From 08fdcc1205be10e9ca6e7d5f0fcca57e01511e02 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Wed, 18 Jun 2014 22:14:33 -0300 Subject: [PATCH] ofproto-dpif: Add mcast snooping db show and flush cmds This patch adds the command 'ovs-appctl mdb/show bridge' to show learned groups on a bridge from the multicast snooping database. It also adds the command 'ovs-appctl mdb/flush [bridge]' to flush learned groups on a bridge or on all bridges. Acked-by: Thomas Graf Acked-by: Daniel Borkmann Signed-off-by: Flavio Leitner Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif.c | 89 ++++++++++++++++++++++++++++++++++++++ vswitchd/ovs-vswitchd.8.in | 7 +++ 2 files changed, 96 insertions(+) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index d623ee74391..8c130e1e40b 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -3883,6 +3883,36 @@ ofproto_unixctl_fdb_flush(struct unixctl_conn *conn, int argc, unixctl_command_reply(conn, "table successfully flushed"); } +static void +ofproto_unixctl_mcast_snooping_flush(struct unixctl_conn *conn, int argc, + const char *argv[], void *aux OVS_UNUSED) +{ + struct ofproto_dpif *ofproto; + + if (argc > 1) { + ofproto = ofproto_dpif_lookup(argv[1]); + if (!ofproto) { + unixctl_command_reply_error(conn, "no such bridge"); + return; + } + + if (!mcast_snooping_enabled(ofproto->ms)) { + unixctl_command_reply_error(conn, "multicast snooping is disabled"); + return; + } + mcast_snooping_mdb_flush(ofproto->ms); + } else { + HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) { + if (!mcast_snooping_enabled(ofproto->ms)) { + continue; + } + mcast_snooping_mdb_flush(ofproto->ms); + } + } + + unixctl_command_reply(conn, "table successfully flushed"); +} + static struct ofport_dpif * ofbundle_get_a_port(const struct ofbundle *bundle) { @@ -3921,6 +3951,61 @@ ofproto_unixctl_fdb_show(struct unixctl_conn *conn, int argc OVS_UNUSED, ds_destroy(&ds); } +static void +ofproto_unixctl_mcast_snooping_show(struct unixctl_conn *conn, + int argc OVS_UNUSED, + const char *argv[], + void *aux OVS_UNUSED) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + const struct ofproto_dpif *ofproto; + const struct ofbundle *bundle; + const struct mcast_group *grp; + struct mcast_group_bundle *b; + struct mcast_mrouter_bundle *mrouter; + + ofproto = ofproto_dpif_lookup(argv[1]); + if (!ofproto) { + unixctl_command_reply_error(conn, "no such bridge"); + return; + } + + if (!mcast_snooping_enabled(ofproto->ms)) { + unixctl_command_reply_error(conn, "multicast snooping is disabled"); + return; + } + + ds_put_cstr(&ds, " port VLAN GROUP Age\n"); + ovs_rwlock_rdlock(&ofproto->ms->rwlock); + LIST_FOR_EACH (grp, group_node, &ofproto->ms->group_lru) { + LIST_FOR_EACH(b, bundle_node, &grp->bundle_lru) { + char name[OFP_MAX_PORT_NAME_LEN]; + + bundle = b->port; + ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, + name, sizeof name); + ds_put_format(&ds, "%5s %4d "IP_FMT" %3d\n", + name, grp->vlan, IP_ARGS(grp->ip4), + mcast_bundle_age(ofproto->ms, b)); + } + } + + /* ports connected to multicast routers */ + LIST_FOR_EACH(mrouter, mrouter_node, &ofproto->ms->mrouter_lru) { + char name[OFP_MAX_PORT_NAME_LEN]; + + bundle = mrouter->port; + ofputil_port_to_string(ofbundle_get_a_port(bundle)->up.ofp_port, + name, sizeof name); + ds_put_format(&ds, "%5s %4d querier %3d\n", + name, mrouter->vlan, + mcast_mrouter_age(ofproto->ms, mrouter)); + } + ovs_rwlock_unlock(&ofproto->ms->rwlock); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); +} + struct trace_ctx { struct xlate_out xout; struct xlate_in xin; @@ -4601,6 +4686,10 @@ ofproto_dpif_unixctl_init(void) ofproto_unixctl_fdb_flush, NULL); unixctl_command_register("fdb/show", "bridge", 1, 1, ofproto_unixctl_fdb_show, NULL); + unixctl_command_register("mdb/flush", "[bridge]", 0, 1, + ofproto_unixctl_mcast_snooping_flush, NULL); + unixctl_command_register("mdb/show", "bridge", 1, 1, + ofproto_unixctl_mcast_snooping_show, NULL); unixctl_command_register("dpif/dump-dps", "", 0, 0, ofproto_unixctl_dpif_dump_dps, NULL); unixctl_command_register("dpif/show", "", 0, 0, ofproto_unixctl_dpif_show, diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in index e9dc48397b3..e5713e760d2 100644 --- a/vswitchd/ovs-vswitchd.8.in +++ b/vswitchd/ovs-vswitchd.8.in @@ -140,6 +140,13 @@ if no \fIbridge\fR is given. Lists each MAC address/VLAN pair learned by the specified \fIbridge\fR, along with the port on which it was learned and the age of the entry, in seconds. +.IP "\fBmdb/flush\fR [\fIbridge\fR]" +Flushes \fIbridge\fR multicast snooping table, or all snooping tables +if no \fIbridge\fR is given. +.IP "\fBmdb/show\fR \fIbridge\fR" +Lists each multicast group/VLAN pair learned by the specified \fIbridge\fR, +along with the port on which it was learned and the age of the entry, +in seconds. .IP "\fBbridge/reconnect\fR [\fIbridge\fR]" Makes \fIbridge\fR drop all of its OpenFlow controller connections and reconnect. If \fIbridge\fR is not specified, then all bridges drop