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