Signed-off-by: Jarno Rajahalme <jarno.rajaha...@nsn.com>
---
v3 restores compatibility with old userspace/kernel by
unconditionally sending flags (as expected by old code),
but making flags optional when received.
---
 datapath/tunnel.c            |   39 +++++++++++++++++++++++++--------------
 include/openvswitch/tunnel.h |    7 ++++---
 lib/netdev-vport.c           |   35 +++++++++++++++++++++--------------
 3 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 26d9014..08501ab 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -1067,11 +1067,21 @@ static int tnl_set_config(struct net *net, struct 
nlattr *options,
        if (err)
                return err;
 
-       if (!a[OVS_TUNNEL_ATTR_FLAGS] || !a[OVS_TUNNEL_ATTR_DST_IPV4])
-               return -EINVAL;
+       /* Process attributes possibly useful for null_ports first */
+       if (a[OVS_TUNNEL_ATTR_DST_PORT])
+               mutable->dst_port =
+                       htons(nla_get_u16(a[OVS_TUNNEL_ATTR_DST_PORT]));
+
+       if (a[OVS_TUNNEL_ATTR_DST_IPV4])
+               mutable->key.daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
 
-       mutable->flags = nla_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_PUBLIC;
-       mutable->key.daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
+       /* Skip the rest if configuring a null_port */
+       if (!mutable->key.daddr)
+               goto out;
+
+       if (a[OVS_TUNNEL_ATTR_FLAGS])
+               mutable->flags = nla_get_u32(a[OVS_TUNNEL_ATTR_FLAGS])
+                       & TNL_F_PUBLIC;
 
        if (a[OVS_TUNNEL_ATTR_SRC_IPV4]) {
                if (ipv4_is_multicast(mutable->key.daddr))
@@ -1089,10 +1099,6 @@ static int tnl_set_config(struct net *net, struct nlattr 
*options,
        if (a[OVS_TUNNEL_ATTR_TTL])
                mutable->ttl = nla_get_u8(a[OVS_TUNNEL_ATTR_TTL]);
 
-       if (a[OVS_TUNNEL_ATTR_DST_PORT])
-               mutable->dst_port =
-                       htons(nla_get_u16(a[OVS_TUNNEL_ATTR_DST_PORT]));
-
        if (!a[OVS_TUNNEL_ATTR_IN_KEY]) {
                mutable->key.tunnel_type |= TNL_T_KEY_MATCH;
                mutable->flags |= TNL_F_IN_KEY_MATCH;
@@ -1230,11 +1236,19 @@ int ovs_tnl_get_options(const struct vport *vport, 
struct sk_buff *skb)
        const struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
        const struct tnl_mutable_config *mutable = 
rcu_dereference_rtnl(tnl_vport->mutable);
 
-       if (nla_put_u32(skb, OVS_TUNNEL_ATTR_FLAGS,
-                     mutable->flags & TNL_F_PUBLIC) ||
-           nla_put_be32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->key.daddr))
+       if (mutable->dst_port && nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT,
+                                            ntohs(mutable->dst_port)))
                goto nla_put_failure;
 
+       /* Skip the rest for null_ports */
+       if (!mutable->key.daddr)
+               return 0;
+
+       if (nla_put_be32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->key.daddr))
+               goto nla_put_failure;
+       if (nla_put_u32(skb, OVS_TUNNEL_ATTR_FLAGS,
+                       mutable->flags & TNL_F_PUBLIC))
+               goto nla_put_failure;
        if (!(mutable->flags & TNL_F_IN_KEY_MATCH) &&
            nla_put_be64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->key.in_key))
                goto nla_put_failure;
@@ -1248,9 +1262,6 @@ int ovs_tnl_get_options(const struct vport *vport, struct 
sk_buff *skb)
                goto nla_put_failure;
        if (mutable->ttl && nla_put_u8(skb, OVS_TUNNEL_ATTR_TTL, mutable->ttl))
                goto nla_put_failure;
-       if (mutable->dst_port && nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT,
-                                            ntohs(mutable->dst_port)))
-               goto nla_put_failure;
 
        return 0;
 
diff --git a/include/openvswitch/tunnel.h b/include/openvswitch/tunnel.h
index 23d8ba7..8a53ef8 100644
--- a/include/openvswitch/tunnel.h
+++ b/include/openvswitch/tunnel.h
@@ -45,14 +45,15 @@
 
 /* OVS_VPORT_ATTR_OPTIONS attributes for tunnels.
  *
- * OVS_TUNNEL_ATTR_FLAGS and OVS_TUNNEL_ATTR_DST_IPV4 are required.  All other
+ * OVS_TUNNEL_ATTR_DST_IPV4 is required for kernel tunnel ports, all other
  * attributes are optional.
+ * For flow-based tunnels, only the OVS_TUNNEL_ATTR_DST_PORT is useful.
  */
 enum {
        OVS_TUNNEL_ATTR_UNSPEC,
        OVS_TUNNEL_ATTR_FLAGS,    /* 32-bit TNL_F_*. */
-       OVS_TUNNEL_ATTR_DST_IPV4, /* IPv4 destination address. */
-       OVS_TUNNEL_ATTR_SRC_IPV4, /* IPv4 source address. */
+       OVS_TUNNEL_ATTR_DST_IPV4, /* Remote IPv4 address. */
+       OVS_TUNNEL_ATTR_SRC_IPV4, /* Local IPv4 address. */
        OVS_TUNNEL_ATTR_OUT_KEY,  /* __be64 key to use on output. */
        OVS_TUNNEL_ATTR_IN_KEY,   /* __be64 key to match on input. */
        OVS_TUNNEL_ATTR_TOS,      /* 8-bit TOS value. */
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 2b493a7..3374c31 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -139,6 +139,12 @@ netdev_vport_get_vport_type(const struct netdev *netdev)
             : OVS_VPORT_TYPE_UNSPEC);
 }
 
+static uint64_t
+get_u32_or_zero(const struct nlattr *a)
+{
+    return a ? nl_attr_get_u32(a) : 0;
+}
+
 const char *
 netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
 {
@@ -162,7 +168,7 @@ netdev_vport_get_netdev_type(const struct dpif_linux_vport 
*vport)
                                         a)) {
             break;
         }
-        return (nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
+        return (get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
                 ? "ipsec_gre" : "gre");
 
     case OVS_VPORT_TYPE_GRE64:
@@ -170,7 +176,7 @@ netdev_vport_get_netdev_type(const struct dpif_linux_vport 
*vport)
                                         a)) {
             break;
         }
-        return (nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
+        return (get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
                 ? "ipsec_gre64" : "gre64");
 
     case OVS_VPORT_TYPE_CAPWAP:
@@ -529,7 +535,6 @@ static const char *
 netdev_vport_get_tnl_iface(const struct netdev *netdev)
 {
     struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1];
-    ovs_be32 route;
     struct netdev_dev_vport *ndv;
     static char name[IFNAMSIZ];
 
@@ -538,12 +543,13 @@ netdev_vport_get_tnl_iface(const struct netdev *netdev)
                                     a)) {
         return NULL;
     }
-    route = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
+    if (a[OVS_TUNNEL_ATTR_DST_IPV4]) {
+        ovs_be32 route = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
 
-    if (route_table_get_name(route, name)) {
-        return name;
+        if (route_table_get_name(route, name)) {
+            return name;
+        }
     }
-
     return NULL;
 }
 
@@ -768,8 +774,8 @@ tnl_port_config_from_nlattr(const struct nlattr *options, 
size_t options_len,
                             struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1])
 {
     static const struct nl_policy ovs_tunnel_policy[] = {
-        [OVS_TUNNEL_ATTR_FLAGS] = { .type = NL_A_U32 },
-        [OVS_TUNNEL_ATTR_DST_IPV4] = { .type = NL_A_BE32 },
+        [OVS_TUNNEL_ATTR_FLAGS] = { .type = NL_A_U32, .optional = true },
+        [OVS_TUNNEL_ATTR_DST_IPV4] = { .type = NL_A_BE32, .optional = true },
         [OVS_TUNNEL_ATTR_SRC_IPV4] = { .type = NL_A_BE32, .optional = true },
         [OVS_TUNNEL_ATTR_IN_KEY] = { .type = NL_A_BE64, .optional = true },
         [OVS_TUNNEL_ATTR_OUT_KEY] = { .type = NL_A_BE64, .optional = true },
@@ -799,7 +805,6 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const 
char *type OVS_UNUSED,
                       struct smap *args)
 {
     struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1];
-    ovs_be32 daddr;
     uint32_t flags;
     int error;
 
@@ -808,9 +813,10 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const 
char *type OVS_UNUSED,
         return error;
     }
 
-
-    daddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
-    smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(daddr));
+    if (a[OVS_TUNNEL_ATTR_DST_IPV4]) {
+        ovs_be32 daddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
+        smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(daddr));
+    }
 
     if (a[OVS_TUNNEL_ATTR_SRC_IPV4]) {
         ovs_be32 saddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_SRC_IPV4]);
@@ -840,7 +846,8 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const 
char *type OVS_UNUSED,
         }
     }
 
-    flags = nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]);
+    flags = get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]);
+
     if (flags & TNL_F_TTL_INHERIT) {
         smap_add(args, "ttl", "inherit");
     } else if (a[OVS_TUNNEL_ATTR_TTL]) {
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to