datapath: backport: allow output of MPLS packets on tunnel vports
[cascardo/ovs.git] / datapath / flow_netlink.c
index cbfa233..0f32664 100644 (file)
@@ -263,7 +263,7 @@ size_t ovs_tun_key_attr_size(void)
        /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
         * updating this function.
         */
-       return    nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
+       return    nla_total_size_64bit(8) /* OVS_TUNNEL_KEY_ATTR_ID */
                + nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
                + nla_total_size(16)   /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
                + nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
@@ -722,7 +722,8 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb,
                              unsigned short tun_proto)
 {
        if (output->tun_flags & TUNNEL_KEY &&
-           nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
+           nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id,
+                        OVS_TUNNEL_KEY_ATTR_PAD))
                return -EMSGSIZE;
        switch (tun_proto) {
        case AF_INET:
@@ -1254,7 +1255,7 @@ int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
                        /* The userspace does not send tunnel attributes that
                         * are 0, but we should not wildcard them nonetheless.
                         */
-                       if (match->key->tun_key.u.ipv4.dst)
+                       if (match->key->tun_proto)
                                SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
                                                         0xff, true);
 
@@ -1405,7 +1406,6 @@ int ovs_nla_get_flow_metadata(struct net *net, const struct nlattr *attr,
        memset(&match, 0, sizeof(match));
        match.key = key;
 
-       memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE);
        memset(&key->ct, 0, sizeof(key->ct));
        key->phy.in_port = DP_MAX_PORTS;
 
@@ -1800,10 +1800,8 @@ int ovs_nla_add_action(struct sw_flow_actions **sfa, int attrtype, void *data,
        struct nlattr *a;
 
        a = __add_action(sfa, attrtype, data, len, log);
-       if (IS_ERR(a))
-               return PTR_ERR(a);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(a);
 }
 
 static inline int add_nested_action_start(struct sw_flow_actions **sfa,
@@ -1964,6 +1962,11 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
        if (!tun_dst)
                return -ENOMEM;
 
+       err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
+       if (err) {
+               dst_release((struct dst_entry *)tun_dst);
+               return err;
+       }
        a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
                         sizeof(*ovs_tun), log);
        if (IS_ERR(a)) {
@@ -2043,9 +2046,10 @@ static int validate_set(const struct nlattr *a,
                break;
 
        case OVS_KEY_ATTR_TUNNEL:
+#ifndef USE_UPSTREAM_TUNNEL
                if (eth_p_mpls(eth_type))
                        return -EINVAL;
-
+#endif
                if (masked)
                        return -EINVAL; /* Masked tunnel set not supported. */
 
@@ -2448,7 +2452,10 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
                if (!start)
                        return -EMSGSIZE;
 
-               err = ovs_nla_put_tunnel_info(skb, tun_info);
+               err =  ip_tun_to_nlattr(skb, &tun_info->key,
+                                       ip_tunnel_info_opts(tun_info),
+                                       tun_info->options_len,
+                                       ip_tunnel_info_af(tun_info));
                if (err)
                        return err;
                nla_nest_end(skb, start);