@@ -2574,6 +2574,37 @@ update_stp_port_state(struct ofport_dpif *ofport)
}
}
+static void
+stp_check_and_update_link_state(struct ofproto_dpif *ofproto)
+{
+ struct ofport *ofport_;
+ struct ofport_dpif *ofport;
+ bool up;
+
+ HMAP_FOR_EACH (ofport_, hmap_node, &ofproto->up.ports) {
+ ofport = ofport_dpif_cast(ofport_);
+ up = netdev_get_carrier(ofport_->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. */
@@ -2604,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);
@@ -2666,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);
@@ -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
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 <nic@opencloud.tech> --- ofproto/ofproto-dpif.c | 41 ++++++++++++++++++++++++++++- tests/stp.at | 71 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 2 deletions(-)