From 52182c5f50198d0f985b10677e47a9ac49ee709b Mon Sep 17 00:00:00 2001 From: nickcooper-zhangtonghao Date: Fri, 19 May 2017 00:20:43 -0700 Subject: [PATCH] stp: Add link-state checking support for stp ports. When bridge stp enabled, we can enable the stp ports despite ports are down. When initializing, this patch checks link-state of ports and enable or disable them according to their link-state. This patch also allow user to enable and disable a port when bridge stp is running. If a stp port is in disable state, it can forward packets. If its link is down and this patch sets it to disable, there is no L2 loop. Signed-off-by: nickcooper-zhangtonghao Signed-off-by: Ben Pfaff --- ofproto/ofproto-dpif.c | 38 +++++++++++++++++++++- tests/stp.at | 71 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ba9e1ea4001..afc169db6a5 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -2577,6 +2577,34 @@ update_stp_port_state(struct ofport_dpif *ofport) } } +static void +stp_check_and_update_link_state(struct ofproto_dpif *ofproto) +{ + struct ofport_dpif *ofport; + + HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) { + bool up = netdev_get_carrier(ofport->up.netdev); + + if (ofport->stp_port && + up != (stp_port_get_state(ofport->stp_port) != STP_DISABLED)) { + + VLOG_DBG("bridge %s, port %s is %s, %s it.", + ofproto->up.name, netdev_get_name(ofport->up.netdev), + up ? "up" : "down", + up ? "enabling" : "disabling"); + + if (up) { + stp_port_enable(ofport->stp_port); + stp_port_set_aux(ofport->stp_port, ofport); + } else { + stp_port_disable(ofport->stp_port); + } + + update_stp_port_state(ofport); + } + } +} + /* Configures STP on 'ofport_' using the settings defined in 's'. The * caller is responsible for assigning STP port numbers and ensuring * there are no duplicates. */ @@ -2607,7 +2635,12 @@ set_stp_port(struct ofport *ofport_, /* Set name before enabling the port so that debugging messages can print * the name. */ stp_port_set_name(sp, netdev_get_name(ofport->up.netdev)); - stp_port_enable(sp); + + if (netdev_get_carrier(ofport_->netdev)) { + stp_port_enable(sp); + } else { + stp_port_disable(sp); + } stp_port_set_aux(sp, ofport); stp_port_set_priority(sp, s->priority); @@ -2669,6 +2702,9 @@ stp_run(struct ofproto_dpif *ofproto) stp_tick(ofproto->stp, MIN(INT_MAX, elapsed)); ofproto->stp_last_tick = now; } + + stp_check_and_update_link_state(ofproto); + while (stp_get_changed_port(ofproto->stp, &sp)) { struct ofport_dpif *ofport = stp_port_get_aux(sp); diff --git a/tests/stp.at b/tests/stp.at index bd5d20892b1..e27600ec4ac 100644 --- a/tests/stp.at +++ b/tests/stp.at @@ -420,6 +420,7 @@ AT_CHECK([ovs-vsctl add-port br1 p8 -- \ set port p8 other_config:stp-enable=false -- \ ]) +ovs-appctl netdev-dummy/set-admin-state up ovs-appctl time/stop AT_CHECK([ovs-ofctl add-flow br0 "in_port=7 icmp actions=1"]) @@ -519,7 +520,7 @@ AT_CHECK([ set interface p6 type=dummy options:pstream=punix:$OVS_RUNDIR/p6.sock ofport_request=6 ], [0]) - +ovs-appctl netdev-dummy/set-admin-state up ovs-appctl time/stop # give time for STP to move initially @@ -626,5 +627,73 @@ AT_CHECK([ovs-appctl mdb/show br2], [0], [dnl port VLAN GROUP Age ]) +AT_CLEANUP + +AT_SETUP([STP - check link-state when stp is running]) +OVS_VSWITCHD_START([]) + +AT_CHECK([ + ovs-vsctl -- \ + set port br0 other_config:stp-enable=false -- \ + set bridge br0 datapath-type=dummy stp_enable=true \ + other-config:hwaddr=aa:66:aa:66:00:00 +], [0]) + +AT_CHECK([ + ovs-vsctl add-port br0 p1 -- \ + set interface p1 type=dummy -- \ + set port p1 other_config:stp-port-num=1 + ovs-vsctl add-port br0 p2 -- \ + set interface p2 type=dummy -- \ + set port p2 other_config:stp-port-num=2 +], [0]) + +ovs-appctl netdev-dummy/set-admin-state up +ovs-appctl time/stop + +# give time for STP to move initially +for i in $(seq 0 30); do + ovs-appctl time/warp 1000 +done + +AT_CHECK([ovs-appctl stp/show br0 | grep p1], [0], [dnl + p1 designated forwarding 19 128.1 +]) +AT_CHECK([ovs-appctl stp/show br0 | grep p2], [0], [dnl + p2 designated forwarding 19 128.2 +]) + +# add a stp port +AT_CHECK([ + ovs-vsctl add-port br0 p3 -- \ + set interface p3 type=dummy -- \ + set port p3 other_config:stp-port-num=3 +], [0]) + +ovs-appctl netdev-dummy/set-admin-state p3 down + +# We should not show the p3 because its link-state is down +AT_CHECK([ovs-appctl stp/show br0 | grep p1], [0], [dnl + p1 designated forwarding 19 128.1 +]) +AT_CHECK([ovs-appctl stp/show br0 | grep p2], [0], [dnl + p2 designated forwarding 19 128.2 +]) +AT_CHECK([ovs-appctl stp/show br0 | grep p3], [1], [dnl +]) + +ovs-appctl netdev-dummy/set-admin-state p3 up + +AT_CHECK([ovs-appctl stp/show br0 | grep p1], [0], [dnl + p1 designated forwarding 19 128.1 +]) +AT_CHECK([ovs-appctl stp/show br0 | grep p2], [0], [dnl + p2 designated forwarding 19 128.2 +]) +AT_CHECK([ovs-appctl stp/show br0 | grep p3], [0], [dnl + p3 designated listening 19 128.3 +]) + + OVS_VSWITCHD_STOP AT_CLEANUP