nx-match: Increase upper bound length for an nx_match.
[openvswitch] / datapath / datapath.c
index 11a2a110514c3b7cd714181df0fb32e341f276cd..87056cf8cafde32b7df541fcffa91c81123e250b 100644 (file)
@@ -512,24 +512,29 @@ static int validate_actions(const struct nlattr *attr,
 static int validate_sample(const struct nlattr *attr,
                                const struct sw_flow_key *key, int depth)
 {
-       static const struct nla_policy sample_policy[OVS_SAMPLE_ATTR_MAX + 1] =
-       {
-               [OVS_SAMPLE_ATTR_PROBABILITY] = {.type = NLA_U32 },
-               [OVS_SAMPLE_ATTR_ACTIONS] = {.type = NLA_UNSPEC },
-       };
-       struct nlattr *a[OVS_SAMPLE_ATTR_MAX + 1];
-       int error;
-
-       error = nla_parse_nested(a, OVS_SAMPLE_ATTR_MAX, attr, sample_policy);
-       if (error)
-               return error;
+       const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
+       const struct nlattr *probability, *actions;
+       const struct nlattr *a;
+       int rem;
 
-       if (!a[OVS_SAMPLE_ATTR_PROBABILITY])
+       memset(attrs, 0, sizeof(attrs));
+       nla_for_each_nested (a, attr, rem) {
+               int type = nla_type(a);
+               if (!type || type > OVS_SAMPLE_ATTR_MAX || attrs[type])
+                       return -EINVAL;
+               attrs[type] = a;
+       }
+       if (rem)
                return -EINVAL;
-       if (!a[OVS_SAMPLE_ATTR_ACTIONS])
+
+       probability = attrs[OVS_SAMPLE_ATTR_PROBABILITY];
+       if (!probability || nla_len(probability) != sizeof(u32))
                return -EINVAL;
 
-       return validate_actions(a[OVS_SAMPLE_ATTR_ACTIONS], key, (depth + 1));
+       actions = attrs[OVS_SAMPLE_ATTR_ACTIONS];
+       if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN))
+               return -EINVAL;
+       return validate_actions(actions, key, depth + 1);
 }
 
 static int validate_action_key(const struct nlattr *a,
@@ -547,15 +552,16 @@ static int validate_action_key(const struct nlattr *a,
            nla_len(ovs_key) != ovs_key_lens[key_type])
                return -EINVAL;
 
-#define ACTION(act, key)       ((act << 8) | key)
+#define ACTION(act, key)       (((act) << 8) | (key))
 
        switch(ACTION(act_type, key_type)) {
        const struct ovs_key_ipv4 *ipv4_key;
        const struct ovs_key_8021q *q_key;
 
+       case ACTION(OVS_ACTION_ATTR_SET, OVS_KEY_ATTR_PRIORITY):
        case ACTION(OVS_ACTION_ATTR_SET, OVS_KEY_ATTR_TUN_ID):
        case ACTION(OVS_ACTION_ATTR_SET, OVS_KEY_ATTR_ETHERNET):
-                       break;
+               break;
 
        case ACTION(OVS_ACTION_ATTR_PUSH, OVS_KEY_ATTR_8021Q):
                q_key = nla_data(ovs_key);
@@ -647,8 +653,6 @@ static int validate_actions(const struct nlattr *attr,
                        [OVS_ACTION_ATTR_PUSH] = (u32)-1,
                        [OVS_ACTION_ATTR_POP] = 2,
                        [OVS_ACTION_ATTR_SET] = (u32)-1,
-                       [OVS_ACTION_ATTR_SET_PRIORITY] = 4,
-                       [OVS_ACTION_ATTR_POP_PRIORITY] = 0,
                        [OVS_ACTION_ATTR_SAMPLE] = (u32)-1
                };
                int type = nla_type(a);
@@ -662,11 +666,6 @@ static int validate_actions(const struct nlattr *attr,
                case OVS_ACTION_ATTR_UNSPEC:
                        return -EINVAL;
 
-               case OVS_ACTION_ATTR_SET_PRIORITY:
-               case OVS_ACTION_ATTR_POP_PRIORITY:
-                       /* No validation needed. */
-                       break;
-
                case OVS_ACTION_ATTR_USERSPACE:
                        err = validate_userspace(a);
                        if (err)
@@ -765,8 +764,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto err_flow_put;
 
-       err = flow_metadata_from_nlattrs(&flow->key.eth.in_port,
-                                        &flow->key.eth.tun_id,
+       err = flow_metadata_from_nlattrs(&flow->key.phy.priority,
+                                        &flow->key.phy.in_port,
+                                        &flow->key.phy.tun_id,
                                         a[OVS_PACKET_ATTR_KEY]);
        if (err)
                goto err_flow_put;
@@ -784,6 +784,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        rcu_assign_pointer(flow->sf_acts, acts);
 
        OVS_CB(packet)->flow = flow;
+       packet->priority = flow->key.phy.priority;
 
        rcu_read_lock();
        dp = get_dp(ovs_header->dp_ifindex);
@@ -791,9 +792,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        if (!dp)
                goto err_unlock;
 
-       if (flow->key.eth.in_port < DP_MAX_PORTS)
+       if (flow->key.phy.in_port < DP_MAX_PORTS)
                OVS_CB(packet)->vport = get_vport_protected(dp,
-                                                       flow->key.eth.in_port);
+                                                       flow->key.phy.in_port);
 
        local_bh_disable();
        err = execute_actions(dp, packet);