datapath: Add support for RHEL-7 / CentOS-7 kernel.
[cascardo/ovs.git] / datapath / datapath.c
index ad445bb..b0de672 100644 (file)
@@ -293,7 +293,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        OVS_CB(skb)->input_vport = p;
 
        /* Extract flow from 'skb' into 'key'. */
-       error = ovs_flow_extract(skb, p->port_no, &key);
+       error = ovs_flow_key_extract(skb, &key);
        if (unlikely(error)) {
                kfree_skb(skb);
                return;
@@ -339,15 +339,19 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
        struct dp_upcall_info later_info;
        struct sw_flow_key later_key;
        struct sk_buff *segs, *nskb;
+       struct ovs_skb_cb ovs_cb;
        int err;
 
+       ovs_cb = *OVS_CB(skb);
        segs = __skb_gso_segment(skb, NETIF_F_SG, false);
+       *OVS_CB(skb) = ovs_cb;
        if (IS_ERR(segs))
                return PTR_ERR(segs);
 
        /* Queue all of the segments. */
        skb = segs;
        do {
+               *OVS_CB(skb) = ovs_cb;
                err = queue_userspace_packet(dp, skb, upcall_info);
                if (err)
                        break;
@@ -429,7 +433,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
        struct sk_buff *user_skb; /* to be queued to userspace */
        struct nlattr *nla;
        struct genl_info info = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+#ifdef HAVE_GENLMSG_NEW_UNICAST
                .dst_sk = ovs_dp_get_net(dp)->genl_sock,
 #endif
                .snd_portid = upcall_info->portid,
@@ -570,13 +574,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(flow))
                goto err_kfree_skb;
 
-       err = ovs_flow_extract(packet, -1, &flow->key);
+       err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
+                                            &flow->key);
        if (err)
                goto err_flow_free;
 
-       err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]);
-       if (err)
-               goto err_flow_free;
        acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
        err = PTR_ERR(acts);
        if (IS_ERR(acts))
@@ -923,8 +925,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
                }
                /* The unmasked key has to be the same for flow updates. */
                if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) {
-                       error = -EEXIST;
-                       goto err_unlock_ovs;
+                       /* Look for any overlapping flow. */
+                       flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+                       if (!flow) {
+                               error = -ENOENT;
+                               goto err_unlock_ovs;
+                       }
                }
                /* Update actions. */
                old_acts = ovsl_dereference(flow->sf_acts);
@@ -1015,16 +1021,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
                goto err_unlock_ovs;
        }
        /* Check that the flow exists. */
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
+       flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
        if (unlikely(!flow)) {
                error = -ENOENT;
                goto err_unlock_ovs;
        }
-       /* The unmasked key has to be the same for flow updates. */
-       if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) {
-               error = -EEXIST;
-               goto err_unlock_ovs;
-       }
+
        /* Update actions, if present. */
        if (likely(acts)) {
                old_acts = ovsl_dereference(flow->sf_acts);
@@ -1096,8 +1098,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
                goto unlock;
        }
 
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
-       if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
+       flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+       if (!flow) {
                err = -ENOENT;
                goto unlock;
        }
@@ -1144,8 +1146,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
                err = ovs_flow_tbl_flush(&dp->table);
                goto unlock;
        }
-       flow = ovs_flow_tbl_lookup(&dp->table, &key);
-       if (unlikely(!flow || !ovs_flow_cmp_unmasked_key(flow, &match))) {
+       flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+       if (unlikely(!flow)) {
                err = -ENOENT;
                goto unlock;
        }