]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/openvswitch/datapath.c
vlan: introduce *vlan_hwaccel_push_inside helpers
[mirror_ubuntu-artful-kernel.git] / net / openvswitch / datapath.c
index 65561ebb489ea6bdcacc8bac20c293c2915a662c..f37ca3e5824c66df5e0e31afb88a0637b08ccfd3 100644 (file)
@@ -425,11 +425,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
                if (!nskb)
                        return -ENOMEM;
 
-               nskb = __vlan_put_tag(nskb, nskb->vlan_proto, vlan_tx_tag_get(nskb));
+               nskb = __vlan_hwaccel_push_inside(nskb);
                if (!nskb)
                        return -ENOMEM;
 
-               nskb->vlan_tci = 0;
                skb = nskb;
        }
 
@@ -526,6 +525,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        struct vport *input_vport;
        int len;
        int err;
+       bool log = !a[OVS_FLOW_ATTR_PROBE];
 
        err = -EINVAL;
        if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] ||
@@ -559,12 +559,12 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
                goto err_kfree_skb;
 
        err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
-                                            &flow->key);
+                                            &flow->key, log);
        if (err)
                goto err_flow_free;
 
        err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS],
-                                  &flow->key, &acts);
+                                  &flow->key, &acts, log);
        if (err)
                goto err_flow_free;
 
@@ -855,15 +855,16 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
        struct sw_flow_actions *acts;
        struct sw_flow_match match;
        int error;
+       bool log = !a[OVS_FLOW_ATTR_PROBE];
 
        /* Must have key and actions. */
        error = -EINVAL;
        if (!a[OVS_FLOW_ATTR_KEY]) {
-               OVS_NLERR("Flow key attribute not present in new flow.\n");
+               OVS_NLERR(log, "Flow key attr not present in new flow.");
                goto error;
        }
        if (!a[OVS_FLOW_ATTR_ACTIONS]) {
-               OVS_NLERR("Flow actions attribute not present in new flow.\n");
+               OVS_NLERR(log, "Flow actions attr not present in new flow.");
                goto error;
        }
 
@@ -878,8 +879,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
        /* Extract key. */
        ovs_match_init(&match, &new_flow->unmasked_key, &mask);
-       error = ovs_nla_get_match(&match,
-                                 a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
+       error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY],
+                                 a[OVS_FLOW_ATTR_MASK], log);
        if (error)
                goto err_kfree_flow;
 
@@ -887,9 +888,9 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
        /* Validate actions. */
        error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key,
-                                    &acts);
+                                    &acts, log);
        if (error) {
-               OVS_NLERR("Flow actions may not be safe on all matching packets.\n");
+               OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
                goto err_kfree_flow;
        }
 
@@ -942,6 +943,7 @@ 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))) {
+                       /* Look for any overlapping flow. */
                        flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
                        if (!flow) {
                                error = -ENOENT;
@@ -984,16 +986,18 @@ error:
 /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
 static struct sw_flow_actions *get_flow_actions(const struct nlattr *a,
                                                const struct sw_flow_key *key,
-                                               const struct sw_flow_mask *mask)
+                                               const struct sw_flow_mask *mask,
+                                               bool log)
 {
        struct sw_flow_actions *acts;
        struct sw_flow_key masked_key;
        int error;
 
        ovs_flow_mask_key(&masked_key, key, mask);
-       error = ovs_nla_copy_actions(a, &masked_key, &acts);
+       error = ovs_nla_copy_actions(a, &masked_key, &acts, log);
        if (error) {
-               OVS_NLERR("Actions may not be safe on all matching packets.\n");
+               OVS_NLERR(log,
+                         "Actions may not be safe on all matching packets");
                return ERR_PTR(error);
        }
 
@@ -1012,23 +1016,25 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
        struct sw_flow_actions *old_acts = NULL, *acts = NULL;
        struct sw_flow_match match;
        int error;
+       bool log = !a[OVS_FLOW_ATTR_PROBE];
 
        /* Extract key. */
        error = -EINVAL;
        if (!a[OVS_FLOW_ATTR_KEY]) {
-               OVS_NLERR("Flow key attribute not present in set flow.\n");
+               OVS_NLERR(log, "Flow key attribute not present in set flow.");
                goto error;
        }
 
        ovs_match_init(&match, &key, &mask);
-       error = ovs_nla_get_match(&match,
-                                 a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
+       error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY],
+                                 a[OVS_FLOW_ATTR_MASK], log);
        if (error)
                goto error;
 
        /* Validate actions. */
        if (a[OVS_FLOW_ATTR_ACTIONS]) {
-               acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask);
+               acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask,
+                                       log);
                if (IS_ERR(acts)) {
                        error = PTR_ERR(acts);
                        goto error;
@@ -1109,14 +1115,16 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct sw_flow_match match;
        int err;
+       bool log = !a[OVS_FLOW_ATTR_PROBE];
 
        if (!a[OVS_FLOW_ATTR_KEY]) {
-               OVS_NLERR("Flow get message rejected, Key attribute missing.\n");
+               OVS_NLERR(log,
+                         "Flow get message rejected, Key attribute missing.");
                return -EINVAL;
        }
 
        ovs_match_init(&match, &key, NULL);
-       err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
+       err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, log);
        if (err)
                return err;
 
@@ -1157,10 +1165,12 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct sw_flow_match match;
        int err;
+       bool log = !a[OVS_FLOW_ATTR_PROBE];
 
        if (likely(a[OVS_FLOW_ATTR_KEY])) {
                ovs_match_init(&match, &key, NULL);
-               err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
+               err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL,
+                                       log);
                if (unlikely(err))
                        return err;
        }
@@ -1250,8 +1260,10 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
        [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
+       [OVS_FLOW_ATTR_MASK] = { .type = NLA_NESTED },
        [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
        [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
+       [OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG },
 };
 
 static const struct genl_ops dp_flow_genl_ops[] = {