Skip to content

Commit

Permalink
[lacp] Mark link as blocked if partner is not yet up and running
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Mar 18, 2018
1 parent 0778418 commit 33d79d5
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/include/ipxe/eth_slow.h
Expand Up @@ -190,6 +190,12 @@ struct eth_slow_lacp_entity_tlv {
*/
#define LACP_STATE_EXPIRED 0x80

/** LACP fast interval (1 second) */
#define LACP_INTERVAL_FAST 1

/** LACP slow interval (30 seconds) */
#define LACP_INTERVAL_SLOW 30

/** LACP collector TLV */
struct eth_slow_lacp_collector_tlv {
/** TLV header */
Expand Down
22 changes: 22 additions & 0 deletions src/net/eth_slow.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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 ) );
Expand Down

0 comments on commit 33d79d5

Please sign in to comment.