Thanks for the review.  I applied this to master.

The command does print source and destination IPs.  You can see an
example in the change to the tests.

On Thu, Jan 04, 2018 at 05:27:30AM +0000, Vishal Deep Ajmera wrote:
> 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-boun...@openvswitch.org 
> [mailto:ovs-dev-boun...@openvswitch.org] On Behalf Of Ben Pfaff
> Sent: Friday, December 29, 2017 2:05 AM
> To: d...@openvswitch.org
> Cc: Ben Pfaff <b...@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 <b...@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
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to