[ovs-dev] [PATCH 3/3] tunnel: Add ofproto/list-tunnels command for troubleshooting.

Vishal Deep Ajmera vishal.deep.ajmera at ericsson.com
Thu Jan 4 05:27:30 UTC 2018


Thanks Ben. This indeed is a very useful command to have. Would it also make sense
to print the Source IP and Destination IP fields as part of list command ? This might help 
in identifying the tunnel quickly.

Warm Regards,
Vishal Ajmera

-----Original Message-----
From: ovs-dev-bounces at openvswitch.org [mailto:ovs-dev-bounces at openvswitch.org] On Behalf Of Ben Pfaff
Sent: Friday, December 29, 2017 2:05 AM
To: dev at openvswitch.org
Cc: Ben Pfaff <blp at ovn.org>
Subject: [ovs-dev] [PATCH 3/3] tunnel: Add ofproto/list-tunnels command for troubleshooting.

I've recently had to debug some issues related to tunnel implementation.
This command would make it easier to have some confidence in how tunnels are actually set up inside OVS.

Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 ofproto/tunnel.c | 74 +++++++++++++++++++++++++++++++++++++++++---------------
 tests/cfm.at     |  3 +++
 2 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index f6d266a00607..770e0103476a 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -37,6 +37,7 @@
 #include "tunnel.h"
 #include "openvswitch/vlog.h"
 #include "unaligned.h"
+#include "unixctl.h"
 #include "ofproto-dpif.h"
 #include "netdev-vport.h"
 
@@ -121,7 +122,10 @@ static struct tnl_port *tnl_find_ofport(const struct ofport_dpif *)
 
 static uint32_t tnl_hash(struct tnl_match *);  static void tnl_match_fmt(const struct tnl_match *, struct ds *); -static char *tnl_port_fmt(const struct tnl_port *) OVS_REQ_RDLOCK(rwlock);
+static char *tnl_port_to_string(const struct tnl_port *)
+    OVS_REQ_RDLOCK(rwlock);
+static void tnl_port_format(const struct tnl_port *, struct ds *)
+    OVS_REQ_RDLOCK(rwlock);
 static void tnl_port_mod_log(const struct tnl_port *, const char *action)
     OVS_REQ_RDLOCK(rwlock);
 static const char *tnl_port_get_name(const struct tnl_port *) @@ -129,6 +133,8 @@ static const char *tnl_port_get_name(const struct tnl_port *)  static void tnl_port_del__(const struct ofport_dpif *, odp_port_t)
     OVS_REQ_WRLOCK(rwlock);
 
+static unixctl_cb_func tnl_unixctl_list;
+
 void
 ofproto_tunnel_init(void)
 {
@@ -136,6 +142,8 @@ ofproto_tunnel_init(void)
 
     if (ovsthread_once_start(&once)) {
         fat_rwlock_init(&rwlock);
+        unixctl_command_register("ofproto/list-tunnels", "", 0, 0,
+                                 tnl_unixctl_list, NULL);
         ovsthread_once_done(&once);
     }
 }
@@ -318,7 +326,7 @@ tnl_port_receive(const struct flow *flow) OVS_EXCLUDED(rwlock)
 
     if (!VLOG_DROP_DBG(&dbg_rl)) {
         char *flow_str = flow_to_string(flow, NULL);
-        char *tnl_str = tnl_port_fmt(tnl_port);
+        char *tnl_str = tnl_port_to_string(tnl_port);
         VLOG_DBG("tunnel port %s receive from flow %s", tnl_str, flow_str);
         free(tnl_str);
         free(flow_str);
@@ -467,7 +475,7 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow,
 
     if (pre_flow_str) {
         char *post_flow_str = flow_to_string(flow, NULL);
-        char *tnl_str = tnl_port_fmt(tnl_port);
+        char *tnl_str = tnl_port_to_string(tnl_port);
         VLOG_DBG("flow sent\n"
                  "%s"
                  " pre: %s\n"
@@ -642,53 +650,58 @@ tnl_port_mod_log(const struct tnl_port *tnl_port, const char *action)
     }
 }
 
-static char *
-tnl_port_fmt(const struct tnl_port *tnl_port) OVS_REQ_RDLOCK(rwlock)
+static void OVS_REQ_RDLOCK(rwlock)
+tnl_port_format(const struct tnl_port *tnl_port, struct ds *ds)
 {
     const struct netdev_tunnel_config *cfg =
         netdev_get_tunnel_config(tnl_port->netdev);
-    struct ds ds = DS_EMPTY_INITIALIZER;
 
-    ds_put_format(&ds, "port %"PRIu32": %s (%s: ", tnl_port->match.odp_port,
+    ds_put_format(ds, "port %"PRIu32": %s (%s: ", 
+ tnl_port->match.odp_port,
                   tnl_port_get_name(tnl_port),
                   netdev_get_type(tnl_port->netdev));
-    tnl_match_fmt(&tnl_port->match, &ds);
+    tnl_match_fmt(&tnl_port->match, ds);
 
     if (cfg->out_key != cfg->in_key ||
         cfg->out_key_present != cfg->in_key_present ||
         cfg->out_key_flow != cfg->in_key_flow) {
-        ds_put_cstr(&ds, ", out_key=");
+        ds_put_cstr(ds, ", out_key=");
         if (!cfg->out_key_present) {
-            ds_put_cstr(&ds, "none");
+            ds_put_cstr(ds, "none");
         } else if (cfg->out_key_flow) {
-            ds_put_cstr(&ds, "flow");
+            ds_put_cstr(ds, "flow");
         } else {
-            ds_put_format(&ds, "%#"PRIx64, ntohll(cfg->out_key));
+            ds_put_format(ds, "%#"PRIx64, ntohll(cfg->out_key));
         }
     }
 
     if (cfg->ttl_inherit) {
-        ds_put_cstr(&ds, ", ttl=inherit");
+        ds_put_cstr(ds, ", ttl=inherit");
     } else {
-        ds_put_format(&ds, ", ttl=%"PRIu8, cfg->ttl);
+        ds_put_format(ds, ", ttl=%"PRIu8, cfg->ttl);
     }
 
     if (cfg->tos_inherit) {
-        ds_put_cstr(&ds, ", tos=inherit");
+        ds_put_cstr(ds, ", tos=inherit");
     } else if (cfg->tos) {
-        ds_put_format(&ds, ", tos=%#"PRIx8, cfg->tos);
+        ds_put_format(ds, ", tos=%#"PRIx8, cfg->tos);
     }
 
     if (!cfg->dont_fragment) {
-        ds_put_cstr(&ds, ", df=false");
+        ds_put_cstr(ds, ", df=false");
     }
 
     if (cfg->csum) {
-        ds_put_cstr(&ds, ", csum=true");
+        ds_put_cstr(ds, ", csum=true");
     }
 
-    ds_put_cstr(&ds, ")\n");
+    ds_put_cstr(ds, ")\n");
+}
 
+static char * OVS_REQ_RDLOCK(rwlock)
+tnl_port_to_string(const struct tnl_port *tnl_port) {
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    tnl_port_format(tnl_port, &ds);
     return ds_steal_cstr(&ds);
 }
 
@@ -714,3 +727,26 @@ tnl_port_build_header(const struct ofport_dpif *ofport,
 
     return res;
 }
+
+static void
+tnl_unixctl_list(struct unixctl_conn *conn,
+                 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
+                 void *aux OVS_UNUSED)
+{
+    struct ds reply = DS_EMPTY_INITIALIZER;
+
+    fat_rwlock_rdlock(&rwlock);
+    for (int i = 0; i < N_MATCH_TYPES; i++) {
+        struct hmap *map = tnl_match_maps[i];
+        if (map) {
+            struct tnl_port *tnl_port;
+            HMAP_FOR_EACH (tnl_port, match_node, map) {
+                tnl_port_format(tnl_port, &reply);
+            }
+        }
+    }
+    fat_rwlock_unlock(&rwlock);
+
+    unixctl_command_reply(conn, ds_cstr(&reply));
+    ds_destroy(&reply);
+}
diff --git a/tests/cfm.at b/tests/cfm.at index bcea799f0e26..fa7604c228f7 100644
--- a/tests/cfm.at
+++ b/tests/cfm.at
@@ -52,6 +52,9 @@ OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=gre \
                     set Interface p0 other_config:cfm_interval=300 other_config:cfm_extended=true])
 
 ovs-appctl time/stop
+AT_CHECK([ovs-appctl ofproto/list-tunnels], [0], [dnl port 1: p0 (gre: 
+::->1.2.3.4, key=0, legacy_l2, dp port=1, ttl=64)
+])
 
 AT_CHECK([ovs-vsctl set Interface p0 cfm_mpid=1])  # at beginning, since the first fault check timeout is not reached
--
2.10.2

_______________________________________________
dev mailing list
dev at openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list