|
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
27
|
27
|
#include <string.h>
|
28
|
28
|
#include <byteswap.h>
|
29
|
29
|
#include <errno.h>
|
|
30
|
+#include <ipxe/timer.h>
|
30
|
31
|
#include <ipxe/iobuf.h>
|
31
|
32
|
#include <ipxe/netdevice.h>
|
32
|
33
|
#include <ipxe/if_ether.h>
|
|
@@ -148,9 +149,30 @@ static int eth_slow_lacp_rx ( struct io_buffer *iobuf,
|
148
|
149
|
struct net_device *netdev ) {
|
149
|
150
|
union eth_slow_packet *eth_slow = iobuf->data;
|
150
|
151
|
struct eth_slow_lacp *lacp = ð_slow->lacp;
|
|
152
|
+ unsigned int interval;
|
151
|
153
|
|
152
|
154
|
eth_slow_lacp_dump ( iobuf, netdev, "RX" );
|
153
|
155
|
|
|
156
|
+ /* If partner is not in sync, collecting, and distributing,
|
|
157
|
+ * then block the link until after the next expected LACP
|
|
158
|
+ * packet.
|
|
159
|
+ */
|
|
160
|
+ if ( ~lacp->partner.state & ( LACP_STATE_IN_SYNC |
|
|
161
|
+ LACP_STATE_COLLECTING |
|
|
162
|
+ LACP_STATE_DISTRIBUTING ) ) {
|
|
163
|
+ DBGC ( netdev, "SLOW %s LACP partner is down\n", netdev->name );
|
|
164
|
+ interval = ( ( lacp->partner.state & LACP_STATE_FAST ) ?
|
|
165
|
+ ( ( LACP_INTERVAL_FAST + 1 ) * TICKS_PER_SEC ) :
|
|
166
|
+ ( ( LACP_INTERVAL_SLOW + 1 ) * TICKS_PER_SEC ) );
|
|
167
|
+ netdev_link_block ( netdev, interval );
|
|
168
|
+ } else {
|
|
169
|
+ if ( netdev_link_blocked ( netdev ) ) {
|
|
170
|
+ DBGC ( netdev, "SLOW %s LACP partner is up\n",
|
|
171
|
+ netdev->name );
|
|
172
|
+ }
|
|
173
|
+ netdev_link_unblock ( netdev );
|
|
174
|
+ }
|
|
175
|
+
|
154
|
176
|
/* Build response */
|
155
|
177
|
memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
|
156
|
178
|
memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
|