summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
authorMichael Brown2018-03-18 16:11:16 +0100
committerMichael Brown2018-03-18 16:16:35 +0100
commit33d79d5d2b6cfd57fbe0733f66784fac658cb360 (patch)
treea0e4a7c6e33e9a15e29be4a43c5ca07e5dc9252b /src/net
parent[golan] Do not assume all devices are identical (diff)
downloadipxe-33d79d5d2b6cfd57fbe0733f66784fac658cb360.tar.gz
ipxe-33d79d5d2b6cfd57fbe0733f66784fac658cb360.tar.xz
ipxe-33d79d5d2b6cfd57fbe0733f66784fac658cb360.zip
[lacp] Mark link as blocked if partner is not yet up and running
Mark the link as blocked if the LACP partner is not reporting itself as being in sync, collecting, and distributing. This matches the behaviour for STP: we mark the link as blocked if we detect that the switch is actively blocking traffic, in order to extend the DHCP discovery period and so prevent boot failures on switches that take an excessively long time to enable ports. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net')
-rw-r--r--src/net/eth_slow.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/net/eth_slow.c b/src/net/eth_slow.c
index 049c26cb..41ce79fe 100644
--- a/src/net/eth_slow.c
+++ b/src/net/eth_slow.c
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <byteswap.h>
#include <errno.h>
+#include <ipxe/timer.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/if_ether.h>
@@ -148,9 +149,30 @@ static int eth_slow_lacp_rx ( struct io_buffer *iobuf,
struct net_device *netdev ) {
union eth_slow_packet *eth_slow = iobuf->data;
struct eth_slow_lacp *lacp = &eth_slow->lacp;
+ unsigned int interval;
eth_slow_lacp_dump ( iobuf, netdev, "RX" );
+ /* If partner is not in sync, collecting, and distributing,
+ * then block the link until after the next expected LACP
+ * packet.
+ */
+ if ( ~lacp->partner.state & ( LACP_STATE_IN_SYNC |
+ LACP_STATE_COLLECTING |
+ LACP_STATE_DISTRIBUTING ) ) {
+ DBGC ( netdev, "SLOW %s LACP partner is down\n", netdev->name );
+ interval = ( ( lacp->partner.state & LACP_STATE_FAST ) ?
+ ( ( LACP_INTERVAL_FAST + 1 ) * TICKS_PER_SEC ) :
+ ( ( LACP_INTERVAL_SLOW + 1 ) * TICKS_PER_SEC ) );
+ netdev_link_block ( netdev, interval );
+ } else {
+ if ( netdev_link_blocked ( netdev ) ) {
+ DBGC ( netdev, "SLOW %s LACP partner is up\n",
+ netdev->name );
+ }
+ netdev_link_unblock ( netdev );
+ }
+
/* Build response */
memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );