Skip to content

Commit

Permalink
ofproto-dpif: Propagate may_enable flag as link aliveness.
Browse files Browse the repository at this point in the history
The idea is to use OFPPS_LIVE bit to propagate link aliveness state
towards the controller also when sending port status.  The
ofport->may_enable flag could be used for this purpose, thus any
change in LIVE bit is propagated towards conrtoller in
OFPT_PORT_STATUS message.  OFPPS_LIVE bit is set only when links is
not down not administratively, neither operationally as recommended
in OF papers.  I added 9 new unit tests to verify link state changes
when monitored with cfm, bfd or lacp for OF 1.3, OF 1.4 and OF 1.5.
I updated related unit tests according to the changes of
ofproto-dpif.

Signed-off-by: László Sürü <laszlo.suru at ericsson.com>
Co-authored-by: Zoltán Balogh <zoltan.balogh at ericsson.com>
Signed-off-by: Zoltán Balogh <zoltan.balogh at ericsson.com>
Co-authored-by: Jan Scheurich <jan.scheurich at ericsson.com>
Signed-off-by: Jan Scheurich <jan.scheurich at ericsson.com>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
László Sürü authored and blp committed Apr 21, 2017
1 parent 6405341 commit f73b83f
Show file tree
Hide file tree
Showing 7 changed files with 732 additions and 17 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Post-v2.7.0
* Increased support for OpenFlow 1.6 (draft).
* Bundles now support hashing by just nw_src or nw_dst.
* The "learn" action now supports a "limit" option (see ovs-ofctl(8)).
* The port status bit OFPPS_LIVE now reflects link aliveness.

v2.7.0 - 21 Feb 2017
---------------------
Expand Down
23 changes: 23 additions & 0 deletions ofproto/ofproto-dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,16 @@ port_modified(struct ofport *port_)
bfd_set_netdev(port->bfd, netdev);
}

/* Set liveness, unless the link is administratively or
* operationally down or link monitoring false */
if (!(port->up.pp.config & OFPUTIL_PC_PORT_DOWN) &&
!(port->up.pp.state & OFPUTIL_PS_LINK_DOWN) &&
port->may_enable) {
port->up.pp.state |= OFPUTIL_PS_LIVE;
} else {
port->up.pp.state &= ~OFPUTIL_PS_LIVE;
}

ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
port->lldp, &port->up.pp.hw_addr);

Expand Down Expand Up @@ -3457,6 +3467,19 @@ port_run(struct ofport_dpif *ofport)
if (ofport->rstp_port) {
rstp_port_set_mac_operational(ofport->rstp_port, enable);
}

/* Propagate liveness, unless the link is administratively or
* operationally down. */
if (!(ofport->up.pp.config & OFPUTIL_PC_PORT_DOWN) &&
!(ofport->up.pp.state & OFPUTIL_PS_LINK_DOWN)) {
enum ofputil_port_state of_state = ofport->up.pp.state;
if (enable) {
of_state |= OFPUTIL_PS_LIVE;
} else {
of_state &= ~OFPUTIL_PS_LIVE;
}
ofproto_port_set_state(&ofport->up, of_state);
}
}

ofport->may_enable = enable;
Expand Down
12 changes: 8 additions & 4 deletions ofproto/ofproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2473,9 +2473,6 @@ ofport_modified(struct ofport *port, struct ofputil_phy_port *pp)
port->pp.peer = pp->peer;
port->pp.curr_speed = pp->curr_speed;
port->pp.max_speed = pp->max_speed;

connmgr_send_port_status(port->ofproto->connmgr, NULL,
&port->pp, OFPPR_MODIFY);
}

/* Update OpenFlow 'state' in 'port' and notify controller. */
Expand Down Expand Up @@ -2633,7 +2630,8 @@ update_port(struct ofproto *ofproto, const char *name)
struct netdev *old_netdev = port->netdev;

/* 'name' hasn't changed location. Any properties changed? */
if (!ofport_equal(&port->pp, &pp)) {
bool port_changed = !ofport_equal(&port->pp, &pp);
if (port_changed) {
ofport_modified(port, &pp);
}

Expand All @@ -2649,6 +2647,12 @@ update_port(struct ofproto *ofproto, const char *name)
port->ofproto->ofproto_class->port_modified(port);
}

/* Send status update, if any port property changed */
if (port_changed) {
connmgr_send_port_status(port->ofproto->connmgr, NULL,
&port->pp, OFPPR_MODIFY);
}

netdev_close(old_netdev);
} else {
/* If 'port' is nonnull then its name differs from 'name' and thus
Expand Down
213 changes: 213 additions & 0 deletions tests/bfd.at
Original file line number Diff line number Diff line change
Expand Up @@ -830,3 +830,216 @@ BFD_CHECK([p1], [false], [false], [none], [down], [Control Detection Time Expire

OVS_VSWITCHD_STOP
AT_CLEANUP

# test bfd: liveness propagation - OF1.3.
AT_SETUP([bfd - liveness propagation - OF1.3])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow13 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
printf '\n\n--- check_liveness %d ---\n\n\n' $1
shift

echo >>expout "OFPT_PORT_STATUS (OF1.3): MOD: 1(p0): addr:
config: 0
state: $1
speed: 0 Mbps now, 0 Mbps max"

AT_CHECK(
[[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
[0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
#Create 2 bridges connected by patch ports and enable bfd
AT_CHECK([ovs-vsctl add-br br1 -- \
set bridge br1 datapath-type=dummy \
other-config:hwaddr=aa:55:aa:56:00:00 -- \
add-port br1 p1 -- set Interface p1 type=patch \
options:peer=p0 ofport_request=2 -- \
add-port br0 p0 -- set Interface p0 type=patch \
options:peer=p1 ofport_request=1 -- \
set Interface p0 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100 -- \
set Interface p1 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100])

ovs-appctl time/stop
# Disable the stats update to prevent the race between ovsdb updating
# stats and ovs-vsctl cmd closing the jsonrpc session.
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:stats-update-interval=50000000])

# wait for a while to stablize bfd.
ovs-appctl time/warp 10100 100
BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK_TX([p0], [100ms], [100ms], [100ms])
BFD_CHECK_RX([p0], [100ms], [100ms], [100ms])
# both p0 and p1 should have flap_count = "1". since down->up.
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 1 LIVE

# turn bfd on p1 off, should increment the bfd:flap_count on p0.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=false])
ovs-appctl time/warp 5000 100
BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["2"])
AT_CHECK([ovs-vsctl list interface p1 | sed -n "s/^.*flap_count=\(.*\), forwarding.*$/\1/p"])
check_liveness 2 0

# turn bfd on p1 on again, should increment the bfd:flap_count on p0.
# p1 should still have flap_count = "1", since it is reset.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=true])
ovs-appctl time/warp 5000 100
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["3"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP

# test bfd: liveness propagation - OF1.4.
AT_SETUP([bfd - liveness propagation - OF1.4])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow14 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
printf '\n\n--- check_liveness %d ---\n\n\n' $1
shift

echo >>expout "OFPT_PORT_STATUS (OF1.4): MOD: 1(p0): addr:
config: 0
state: $1
speed: 0 Mbps now, 0 Mbps max"

AT_CHECK(
[[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
[0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0509000c0123456700000080
#Create 2 bridges connected by patch ports and enable bfd
AT_CHECK([ovs-vsctl add-br br1 -- \
set bridge br1 datapath-type=dummy \
other-config:hwaddr=aa:55:aa:56:00:00 -- \
add-port br1 p1 -- set Interface p1 type=patch \
options:peer=p0 ofport_request=2 -- \
add-port br0 p0 -- set Interface p0 type=patch \
options:peer=p1 ofport_request=1 -- \
set Interface p0 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100 -- \
set Interface p1 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100])

ovs-appctl time/stop
# Disable the stats update to prevent the race between ovsdb updating
# stats and ovs-vsctl cmd closing the jsonrpc session.
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:stats-update-interval=50000000])

# wait for a while to stablize bfd.
ovs-appctl time/warp 10100 100
BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK_TX([p0], [100ms], [100ms], [100ms])
BFD_CHECK_RX([p0], [100ms], [100ms], [100ms])
# both p0 and p1 should have flap_count = "1". since down->up.
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 1 LIVE

# turn bfd on p1 off, should increment the bfd:flap_count on p0.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=false])
ovs-appctl time/warp 5000 100
BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["2"])
AT_CHECK([ovs-vsctl list interface p1 | sed -n "s/^.*flap_count=\(.*\), forwarding.*$/\1/p"])
check_liveness 2 0

# turn bfd on p1 on again, should increment the bfd:flap_count on p0.
# p1 should still have flap_count = "1", since it is reset.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=true])
ovs-appctl time/warp 5000 100
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["3"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP

# test bfd: liveness propagation - OF1.5.
AT_SETUP([bfd - liveness propagation - OF1.5])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow15 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
printf '\n\n--- check_liveness %d ---\n\n\n' $1
shift

echo >>expout "OFPT_PORT_STATUS (OF1.5): MOD: 1(p0): addr:
config: 0
state: $1
speed: 0 Mbps now, 0 Mbps max"

AT_CHECK(
[[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
[0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0609000c0123456700000080
#Create 2 bridges connected by patch ports and enable bfd
AT_CHECK([ovs-vsctl add-br br1 -- \
set bridge br1 datapath-type=dummy \
other-config:hwaddr=aa:55:aa:56:00:00 -- \
add-port br1 p1 -- set Interface p1 type=patch \
options:peer=p0 ofport_request=2 -- \
add-port br0 p0 -- set Interface p0 type=patch \
options:peer=p1 ofport_request=1 -- \
set Interface p0 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100 -- \
set Interface p1 bfd:enable=true bfd:min_tx=100 bfd:min_rx=100])

ovs-appctl time/stop
# Disable the stats update to prevent the race between ovsdb updating
# stats and ovs-vsctl cmd closing the jsonrpc session.
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:stats-update-interval=50000000])

# wait for a while to stablize bfd.
ovs-appctl time/warp 10100 100
BFD_CHECK([p0], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK([p1], [true], [false], [none], [up], [No Diagnostic], [none], [up], [No Diagnostic])
BFD_CHECK_TX([p0], [100ms], [100ms], [100ms])
BFD_CHECK_RX([p0], [100ms], [100ms], [100ms])
# both p0 and p1 should have flap_count = "1". since down->up.
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 1 LIVE

# turn bfd on p1 off, should increment the bfd:flap_count on p0.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=false])
ovs-appctl time/warp 5000 100
BFD_CHECK([p0], [false], [false], [none], [down], [Control Detection Time Expired], [none], [down], [No Diagnostic])
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["2"])
AT_CHECK([ovs-vsctl list interface p1 | sed -n "s/^.*flap_count=\(.*\), forwarding.*$/\1/p"])
check_liveness 2 0

# turn bfd on p1 on again, should increment the bfd:flap_count on p0.
# p1 should still have flap_count = "1", since it is reset.
AT_CHECK([ovs-vsctl set interface p1 bfd:enable=true])
ovs-appctl time/warp 5000 100
BFD_VSCTL_LIST_IFACE([p0], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["3"])
BFD_VSCTL_LIST_IFACE([p1], ["s/^.*flap_count=\(.*\), forwarding.*$/\1/p"], ["1"])
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP
Loading

0 comments on commit f73b83f

Please sign in to comment.