If VXLAN-GBP and VXLAN are set on the same port, only one of those tunnel types
is going to be created. As other tunnel flags are added, like VXLAN-GPE, and
they are incompatible, reject any configuration that put incompatible tunnels on
the same port.

A manual test has been done as well and the port didn't get an ofport. During a
restart, the other tunnel type was rejected and the right flags were on the
dpif_port.

Signed-off-by: Thadeu Lima de Souza Cascardo <casca...@redhat.com>
---
 lib/netdev-vport.c | 78 ++++++++++++++++++++++++++++++++++++++++++------------
 tests/tunnel.at    | 29 ++++++++++++++++++++
 2 files changed, 90 insertions(+), 17 deletions(-)

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 6016fd8..aaf6bfc 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -38,6 +38,7 @@
 #include "packets.h"
 #include "poll-loop.h"
 #include "route-table.h"
+#include "simap.h"
 #include "smap.h"
 #include "socket-util.h"
 #include "unaligned.h"
@@ -63,6 +64,7 @@ static bool tunnel_check_status_change__(struct netdev_vport 
*);
 struct vport_class {
     const char *dpif_port;
     struct netdev_class netdev_class;
+    struct simap dst_port_to_exts;
 };
 
 bool
@@ -71,7 +73,7 @@ netdev_vport_is_vport_class(const struct netdev_class *class)
     return is_vport_class(class);
 }
 
-static const struct vport_class *
+static struct vport_class *
 vport_class_cast(const struct netdev_class *class)
 {
     ovs_assert(is_vport_class(class));
@@ -404,6 +406,36 @@ parse_tunnel_ip(const char *value, bool accept_mcast, bool 
*flow,
     return 0;
 }
 
+static bool
+netdev_vport_may_add(struct netdev *netdev)
+{
+    char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
+    const char *name;
+    struct simap_node *node;
+    struct vport_class *vclass;
+    const struct netdev_vport *vport;
+    const struct netdev_class *class = netdev_get_class(netdev);
+
+    if (!is_vport_class(class)) {
+        return false;
+    }
+
+    if (!netdev_vport_needs_dst_port(netdev)) {
+        return true;
+    }
+
+    vport = netdev_vport_cast(netdev);
+    vclass = vport_class_cast(class);
+    name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
+
+    node = simap_find(&vclass->dst_port_to_exts, name);
+    if (!node) {
+        simap_put(&vclass->dst_port_to_exts, name, vport->tnl_cfg.exts);
+        return true;
+    }
+    return node->data == vport->tnl_cfg.exts;
+}
+
 static int
 set_tunnel_config(struct netdev *dev_, const struct smap *args)
 {
@@ -615,6 +647,10 @@ set_tunnel_config(struct netdev *dev_, const struct smap 
*args)
     }
     ovs_mutex_unlock(&dev->mutex);
 
+    if (!netdev_vport_may_add(dev_)) {
+        return EEXIST;
+    }
+
     return 0;
 }
 
@@ -883,33 +919,40 @@ get_stats(const struct netdev *netdev, struct 
netdev_stats *stats)
     NULL,                   /* rx_drain */
 
 
-#define TUNNEL_CLASS(NAME, DPIF_PORT, BUILD_HEADER, PUSH_HEADER, POP_HEADER)   
\
-    { DPIF_PORT,                                                               
\
-        { NAME, false,                                                         
\
-          VPORT_FUNCTIONS(get_tunnel_config,                                   
\
-                          set_tunnel_config,                                   
\
-                          get_netdev_tunnel_config,                            
\
-                          tunnel_get_status,                                   
\
-                          BUILD_HEADER, PUSH_HEADER, POP_HEADER) }}
+#define TUNNEL_CLASS(TUNNEL, NAME, DPIF_PORT, BUILD_HEADER, PUSH_HEADER, 
POP_HEADER)   \
+    { DPIF_PORT,                                                               
        \
+        { NAME, false,                                                         
        \
+          VPORT_FUNCTIONS(get_tunnel_config,                                   
        \
+                          set_tunnel_config,                                   
        \
+                          get_netdev_tunnel_config,                            
        \
+                          tunnel_get_status,                                   
        \
+                          BUILD_HEADER, PUSH_HEADER, POP_HEADER) },            
        \
+                          SIMAP_INITIALIZER(&(TUNNEL)->dst_port_to_exts) }
 
 void
 netdev_vport_tunnel_register(void)
 {
     /* The name of the dpif_port should be short enough to accomodate adding
      * a port number to the end if one is necessary. */
-    static const struct vport_class vport_classes[] = {
-        TUNNEL_CLASS("geneve", "genev_sys", netdev_geneve_build_header,
+    static struct vport_class vport_classes[] = {
+        TUNNEL_CLASS(&(vport_classes[0]), "geneve", "genev_sys",
+                                            netdev_geneve_build_header,
                                             netdev_tnl_push_udp_header,
                                             netdev_geneve_pop_header),
-        TUNNEL_CLASS("gre", "gre_sys", netdev_gre_build_header,
+        TUNNEL_CLASS(&(vport_classes[1]), "gre", "gre_sys",
+                                       netdev_gre_build_header,
                                        netdev_gre_push_header,
                                        netdev_gre_pop_header),
-        TUNNEL_CLASS("ipsec_gre", "gre_sys", NULL, NULL, NULL),
-        TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
+        TUNNEL_CLASS(&(vport_classes[2]), "ipsec_gre", "gre_sys",
+                     NULL, NULL, NULL),
+        TUNNEL_CLASS(&(vport_classes[3]),"vxlan", "vxlan_sys",
+                                           netdev_vxlan_build_header,
                                            netdev_tnl_push_udp_header,
                                            netdev_vxlan_pop_header),
-        TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),
-        TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),
+        TUNNEL_CLASS(&(vport_classes[4]), "lisp", "lisp_sys",
+                     NULL, NULL, NULL),
+        TUNNEL_CLASS(&(vport_classes[5]), "stt", "stt_sys",
+                     NULL, NULL, NULL),
     };
     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
 
@@ -936,6 +979,7 @@ netdev_vport_patch_register(void)
               VPORT_FUNCTIONS(get_patch_config,
                               set_patch_config,
                               NULL,
-                              NULL, NULL, NULL, NULL) }};
+                              NULL, NULL, NULL, NULL)},
+                              
SIMAP_INITIALIZER(&(&patch_class)->dst_port_to_exts)};
     netdev_register_provider(&patch_class.netdev_class);
 }
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 7f82785..97af317 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -548,6 +548,35 @@ AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 
set(tunnel(tun_id=0x0,dst=1.1.1.1,ttl=64,flags(df|key))),4789
 ])
 
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([tunnel - concomitant incompatible tunnels on the same port])
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
+                    options:remote_ip=flow ofport_request=1])
+
+AT_CHECK([ovs-vsctl add-port br0 p2 -- set Interface p2 type=vxlan \
+                    options:remote_ip=flow options:exts=gbp ofport_request=2], 
[0],
+  [], [ovs-vsctl: Error detected while setting up 'p2'.  See ovs-vswitchd log 
for details.
+])
+
+AT_CHECK([grep p2 ovs-vswitchd.log | sed "s/^.*\(p2:.*\)$/\1/"], [0],
+  [p2: could not set configuration (File exists)
+])
+
+OVS_VSWITCHD_STOP(["/could not set configuration/d"])
+AT_CLEANUP
+
+AT_SETUP([tunnel - concomitant incompatible tunnels on different ports])
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
+                    options:remote_ip=flow ofport_request=1])
+
+AT_CHECK([ovs-vsctl add-port br0 p2 -- set Interface p2 type=vxlan 
options:dst_port=9000 \
+                    options:remote_ip=flow options:exts=gbp ofport_request=2])
+
+AT_CHECK([grep p2 ovs-vswitchd.log | sed "s/^.*\(bridge br0:.*\)$/\1/"], [0],
+  [bridge br0: added interface p2 on port 2
+])
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
-- 
2.5.5

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

Reply via email to