datapath: Kernel flow metadata parsing should be less restrictive
[sliver-openvswitch.git] / datapath / flow.c
index 54d7bda..152d9be 100644 (file)
@@ -978,7 +978,7 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
                                goto invalid;
                        swkey->ipv6.label = ipv6_key->ipv6_label;
                        swkey->ip.proto = ipv6_key->ipv6_proto;
-                       swkey->ip.tos = ipv6_key->ipv6_tos;
+                       swkey->ip.tos = ipv6_key->ipv6_tclass;
                        swkey->ip.ttl = ipv6_key->ipv6_hlimit;
                        swkey->ip.frag = ipv6_key->ipv6_frag;
                        memcpy(&swkey->ipv6.addr.src, ipv6_key->ipv6_src,
@@ -1160,43 +1160,35 @@ int flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, __be64 *tun_id,
                               const struct nlattr *attr)
 {
        const struct nlattr *nla;
-       u16 prev_type;
        int rem;
 
        *in_port = USHRT_MAX;
        *tun_id = 0;
        *priority = 0;
 
-       prev_type = OVS_KEY_ATTR_UNSPEC;
        nla_for_each_nested(nla, attr, rem) {
                int type = nla_type(nla);
 
-               if (type > OVS_KEY_ATTR_MAX || nla_len(nla) != ovs_key_lens[type])
-                       return -EINVAL;
-
-               switch (TRANSITION(prev_type, type)) {
-               case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_PRIORITY):
-                       *priority = nla_get_u32(nla);
-                       break;
+               if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] != 0) {
+                       if (nla_len(nla) != ovs_key_lens[type])
+                               return -EINVAL;
 
-               case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_TUN_ID):
-               case TRANSITION(OVS_KEY_ATTR_PRIORITY, OVS_KEY_ATTR_TUN_ID):
-                       *tun_id = nla_get_be64(nla);
-                       break;
+                       switch (type) {
+                       case OVS_KEY_ATTR_PRIORITY:
+                               *priority = nla_get_u32(nla);
+                               break;
 
-               case TRANSITION(OVS_KEY_ATTR_UNSPEC, OVS_KEY_ATTR_IN_PORT):
-               case TRANSITION(OVS_KEY_ATTR_PRIORITY, OVS_KEY_ATTR_IN_PORT):
-               case TRANSITION(OVS_KEY_ATTR_TUN_ID, OVS_KEY_ATTR_IN_PORT):
-                       if (nla_get_u32(nla) >= DP_MAX_PORTS)
-                               return -EINVAL;
-                       *in_port = nla_get_u32(nla);
-                       break;
+                       case OVS_KEY_ATTR_TUN_ID:
+                               *tun_id = nla_get_be64(nla);
+                               break;
 
-               default:
-                       return 0;
+                       case OVS_KEY_ATTR_IN_PORT:
+                               if (nla_get_u32(nla) >= DP_MAX_PORTS)
+                                       return -EINVAL;
+                               *in_port = nla_get_u32(nla);
+                               break;
+                       }
                }
-
-               prev_type = type;
        }
        if (rem)
                return -EINVAL;
@@ -1263,7 +1255,7 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                                sizeof(ipv6_key->ipv6_dst));
                ipv6_key->ipv6_label = swkey->ipv6.label;
                ipv6_key->ipv6_proto = swkey->ip.proto;
-               ipv6_key->ipv6_tos = swkey->ip.tos;
+               ipv6_key->ipv6_tclass = swkey->ip.tos;
                ipv6_key->ipv6_hlimit = swkey->ip.ttl;
                ipv6_key->ipv6_frag = swkey->ip.frag;
        } else if (swkey->eth.type == htons(ETH_P_ARP)) {