iPXE
eth_slow.c File Reference

Ethernet slow protocols. More...

#include <stdlib.h>
#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>
#include <ipxe/ethernet.h>
#include <ipxe/eth_slow.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static const char * eth_slow_lacp_tlv_name (uint8_t type)
 Name LACP TLV type.
static const char * eth_slow_marker_tlv_name (uint8_t type)
 Name marker TLV type.
static const char * eth_slow_lacp_state_name (uint8_t state)
 Name LACP state.
static void eth_slow_lacp_dump (struct io_buffer *iobuf, struct net_device *netdev, const char *label)
 Dump LACP packet.
static int eth_slow_lacp_rx (struct io_buffer *iobuf, struct net_device *netdev)
 Process incoming LACP packet.
static void eth_slow_marker_dump (struct io_buffer *iobuf, struct net_device *netdev, const char *label)
 Dump marker packet.
static int eth_slow_marker_rx (struct io_buffer *iobuf, struct net_device *netdev)
 Process incoming marker packet.
static int eth_slow_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
 Process incoming slow packet.

Variables

struct net_protocol eth_slow_protocol __net_protocol
 Slow protocol.
static const uint8_t eth_slow_address [ETH_ALEN]
 Slow protocols multicast address.

Detailed Description

Ethernet slow protocols.

We implement a very simple passive LACP entity, that pretends that each port is the only port on an individual system. We avoid the need for timeout logic (and retaining local state about our partner) by requesting the same timeout period (1s or 30s) as our partner requests, and then simply responding to every packet the partner sends us.

Definition in file eth_slow.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ eth_slow_lacp_tlv_name()

const char * eth_slow_lacp_tlv_name ( uint8_t type)
inlinestatic

Name LACP TLV type.

Parameters
typeLACP TLV type
Return values
nameName of LACP TLV type

Definition at line 63 of file eth_slow.c.

63 {
64 switch ( type ) {
65 case ETH_SLOW_TLV_TERMINATOR: return "terminator";
66 case ETH_SLOW_TLV_LACP_ACTOR: return "actor";
67 case ETH_SLOW_TLV_LACP_PARTNER: return "partner";
68 case ETH_SLOW_TLV_LACP_COLLECTOR: return "collector";
69 default: return "<invalid>";
70 }
71}
uint32_t type
Operating system type.
Definition ena.h:1
#define ETH_SLOW_TLV_LACP_COLLECTOR
LACP collector type.
Definition eth_slow.h:69
#define ETH_SLOW_TLV_LACP_ACTOR
LACP actor type.
Definition eth_slow.h:55
#define ETH_SLOW_TLV_LACP_PARTNER
LACP partner type.
Definition eth_slow.h:62
#define ETH_SLOW_TLV_TERMINATOR
Terminator type.
Definition eth_slow.h:49

References ETH_SLOW_TLV_LACP_ACTOR, ETH_SLOW_TLV_LACP_COLLECTOR, ETH_SLOW_TLV_LACP_PARTNER, ETH_SLOW_TLV_TERMINATOR, and type.

◆ eth_slow_marker_tlv_name()

const char * eth_slow_marker_tlv_name ( uint8_t type)
inlinestatic

Name marker TLV type.

Parameters
typeMarker TLV type
Return values
nameName of marker TLV type

Definition at line 80 of file eth_slow.c.

80 {
81 switch ( type ) {
82 case ETH_SLOW_TLV_TERMINATOR: return "terminator";
83 case ETH_SLOW_TLV_MARKER_REQUEST: return "request";
84 case ETH_SLOW_TLV_MARKER_RESPONSE: return "response";
85 default: return "<invalid>";
86 }
87}
#define ETH_SLOW_TLV_MARKER_RESPONSE
Marker response type.
Definition eth_slow.h:83
#define ETH_SLOW_TLV_MARKER_REQUEST
Marker request type.
Definition eth_slow.h:76

References ETH_SLOW_TLV_MARKER_REQUEST, ETH_SLOW_TLV_MARKER_RESPONSE, ETH_SLOW_TLV_TERMINATOR, and type.

Referenced by eth_slow_marker_dump().

◆ eth_slow_lacp_state_name()

const char * eth_slow_lacp_state_name ( uint8_t state)
static

Name LACP state.

Parameters
stateLACP state
Return values
nameLACP state name

Definition at line 95 of file eth_slow.c.

95 {
96 static char state_chars[] = "AFGSCDLX";
97 unsigned int i;
98
99 for ( i = 0 ; i < 8 ; i++ ) {
100 state_chars[i] |= 0x20;
101 if ( state & ( 1 << i ) )
102 state_chars[i] &= ~0x20;
103 }
104 return state_chars;
105}
uint8_t state
State.
Definition eth_slow.h:36

References state.

Referenced by eth_slow_lacp_dump().

◆ eth_slow_lacp_dump()

void eth_slow_lacp_dump ( struct io_buffer * iobuf,
struct net_device * netdev,
const char * label )
static

Dump LACP packet.

Parameters
iobufI/O buffer
netdevNetwork device
label"RX" or "TX"

Definition at line 114 of file eth_slow.c.

116 {
117 union eth_slow_packet *eth_slow = iobuf->data;
118 struct eth_slow_lacp *lacp = &eth_slow->lacp;
119
120 DBGC ( netdev,
121 "SLOW %s %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n",
122 netdev->name, label, ntohs ( lacp->actor.system_priority ),
123 eth_ntoa ( lacp->actor.system ),
124 ntohs ( lacp->actor.key ),
125 ntohs ( lacp->actor.port_priority ),
126 ntohs ( lacp->actor.port ),
127 eth_slow_lacp_state_name ( lacp->actor.state ) );
128 DBGC ( netdev,
129 "SLOW %s %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n",
130 netdev->name, label, ntohs ( lacp->partner.system_priority ),
131 eth_ntoa ( lacp->partner.system ),
132 ntohs ( lacp->partner.key ),
133 ntohs ( lacp->partner.port_priority ),
134 ntohs ( lacp->partner.port ),
135 eth_slow_lacp_state_name ( lacp->partner.state ) );
136 DBGC ( netdev, "SLOW %s %s LACP collector %04x (%d us)\n",
137 netdev->name, label, ntohs ( lacp->collector.max_delay ),
138 ( ntohs ( lacp->collector.max_delay ) * 10 ) );
139 DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
140}
static const char * eth_slow_lacp_state_name(uint8_t state)
Name LACP state.
Definition eth_slow.c:95
struct eth_slow_lacp lacp
LACP packet.
Definition eth_slow.h:3
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:177
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define ntohs(value)
Definition byteswap.h:137
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
LACP packet.
Definition eth_slow.h:225
void * data
Start of data.
Definition iobuf.h:113
A text label widget.
Definition label.h:16
Slow protocols packet.
Definition eth_slow.h:253
struct eth_slow_lacp lacp
LACP packet.
Definition eth_slow.h:257

References io_buffer::data, DBGC, DBGC2_HDA, eth_ntoa(), eth_slow_lacp_state_name(), iob_len(), eth_slow_packet::lacp, lacp, netdev, and ntohs.

Referenced by eth_slow_lacp_rx().

◆ eth_slow_lacp_rx()

int eth_slow_lacp_rx ( struct io_buffer * iobuf,
struct net_device * netdev )
static

Process incoming LACP packet.

Parameters
iobufI/O buffer
netdevNetwork device
Return values
rcReturn status code

Definition at line 149 of file eth_slow.c.

150 {
151 union eth_slow_packet *eth_slow = iobuf->data;
152 struct eth_slow_lacp *lacp = &eth_slow->lacp;
153 struct net_device *system;
154 unsigned int interval;
155
156 eth_slow_lacp_dump ( iobuf, netdev, "RX" );
157
158 /* Obtain system identifier */
160 assert ( system != NULL );
161
162 /* Check for looped-back packets */
163 if ( memcmp ( lacp->actor.system, system->ll_addr,
164 sizeof ( lacp->actor.system ) ) == 0 ) {
165 DBGC ( netdev, "SLOW %s RX loopback detected\n",
166 netdev->name );
167 return -ELOOP;
168 }
169
170 /* If partner is not in sync, collecting, and distributing,
171 * then block the link until after the next expected LACP
172 * packet.
173 */
174 if ( ~lacp->actor.state & ( LACP_STATE_IN_SYNC |
177 DBGC ( netdev, "SLOW %s LACP partner is down\n", netdev->name );
178 interval = ( ( lacp->actor.state & LACP_STATE_FAST ) ?
179 ( ( LACP_INTERVAL_FAST + 1 ) * TICKS_PER_SEC ) :
180 ( ( LACP_INTERVAL_SLOW + 1 ) * TICKS_PER_SEC ) );
181 netdev_link_block ( netdev, interval );
182 } else {
183 if ( netdev_link_blocked ( netdev ) ) {
184 DBGC ( netdev, "SLOW %s LACP partner is up\n",
185 netdev->name );
186 }
188 }
189
190 /* Build response */
191 memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
192 memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
193 memset ( &lacp->collector, 0, sizeof ( lacp->collector ) );
194 lacp->collector.tlv.type = ETH_SLOW_TLV_LACP_COLLECTOR;
195 lacp->collector.tlv.length = ETH_SLOW_TLV_LACP_COLLECTOR_LEN;
196 memcpy ( &lacp->partner, &lacp->actor, sizeof ( lacp->partner ) );
197 lacp->partner.tlv.type = ETH_SLOW_TLV_LACP_PARTNER;
198 lacp->partner.tlv.length = ETH_SLOW_TLV_LACP_PARTNER_LEN;
199 memset ( &lacp->partner.reserved, 0,
200 sizeof ( lacp->partner.reserved ) );
201 memset ( &lacp->actor, 0, sizeof ( lacp->actor ) );
202 lacp->actor.tlv.type = ETH_SLOW_TLV_LACP_ACTOR;
203 lacp->actor.tlv.length = ETH_SLOW_TLV_LACP_ACTOR_LEN;
204 lacp->actor.system_priority = htons ( LACP_SYSTEM_PRIORITY_MAX );
205 memcpy ( lacp->actor.system, system->ll_addr,
206 sizeof ( lacp->actor.system ) );
207 lacp->actor.key = htons ( netdev->scope_id );
208 lacp->actor.port_priority = htons ( LACP_PORT_PRIORITY_MAX );
209 lacp->actor.port = htons ( netdev->scope_id );
210 lacp->actor.state = ( LACP_STATE_AGGREGATABLE |
214 ( lacp->partner.state & LACP_STATE_FAST ) );
215 lacp->header.version = ETH_SLOW_LACP_VERSION;
216
217 /* Send response */
218 eth_slow_lacp_dump ( iobuf, netdev, "TX" );
219 return net_tx ( iobuf, netdev, &eth_slow_protocol, eth_slow_address,
220 netdev->ll_addr );
221}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
static const uint8_t eth_slow_address[ETH_ALEN]
Slow protocols multicast address.
Definition eth_slow.c:53
static void eth_slow_lacp_dump(struct io_buffer *iobuf, struct net_device *netdev, const char *label)
Dump LACP packet.
Definition eth_slow.c:114
#define LACP_STATE_COLLECTING
LACP link is collecting (receiving).
Definition eth_slow.h:174
#define LACP_STATE_AGGREGATABLE
LACP link is aggregateable.
Definition eth_slow.h:162
#define ETH_SLOW_TLV_LACP_COLLECTOR_LEN
LACP collector length.
Definition eth_slow.h:72
#define ETH_SLOW_TLV_LACP_ACTOR_LEN
LACP actor length.
Definition eth_slow.h:58
#define LACP_INTERVAL_FAST
LACP fast interval (1 second).
Definition eth_slow.h:195
#define LACP_SYSTEM_PRIORITY_MAX
Maximum system priority.
Definition eth_slow.h:139
#define ETH_SLOW_LACP_VERSION
LACP version number.
Definition eth_slow.h:25
#define LACP_STATE_FAST
LACP timeout is short.
Definition eth_slow.h:156
#define LACP_INTERVAL_SLOW
LACP slow interval (30 seconds).
Definition eth_slow.h:198
#define LACP_STATE_IN_SYNC
LACP link is in synchronisation.
Definition eth_slow.h:168
uint8_t system[ETH_ALEN]
System identifier.
Definition eth_slow.h:13
#define ETH_SLOW_TLV_LACP_PARTNER_LEN
LACP partner length.
Definition eth_slow.h:65
#define LACP_STATE_DISTRIBUTING
LACP link is distributing (transmitting).
Definition eth_slow.h:180
#define LACP_PORT_PRIORITY_MAX
Maximum port priority.
Definition eth_slow.h:142
#define ELOOP
Too many levels of symbolic links.
Definition errno.h:492
#define htons(value)
Definition byteswap.h:136
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition list.h:334
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition netdevice.c:1078
struct list_head net_devices
List of network devices.
Definition netdevice.c:54
void netdev_link_block(struct net_device *netdev, unsigned long timeout)
Mark network device link as being blocked.
Definition netdevice.c:248
void netdev_link_unblock(struct net_device *netdev)
Mark network device link as being unblocked.
Definition netdevice.c:263
static int netdev_link_blocked(struct net_device *netdev)
Check link block state of network device.
Definition netdevice.h:654
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A network device.
Definition netdevice.h:353
struct list_head list
List of network devices.
Definition netdevice.h:357

References assert, io_buffer::data, DBGC, ELOOP, eth_slow_address, eth_slow_lacp_dump(), ETH_SLOW_LACP_VERSION, ETH_SLOW_TLV_LACP_ACTOR, ETH_SLOW_TLV_LACP_ACTOR_LEN, ETH_SLOW_TLV_LACP_COLLECTOR, ETH_SLOW_TLV_LACP_COLLECTOR_LEN, ETH_SLOW_TLV_LACP_PARTNER, ETH_SLOW_TLV_LACP_PARTNER_LEN, htons, eth_slow_packet::lacp, lacp, LACP_INTERVAL_FAST, LACP_INTERVAL_SLOW, LACP_PORT_PRIORITY_MAX, LACP_STATE_AGGREGATABLE, LACP_STATE_COLLECTING, LACP_STATE_DISTRIBUTING, LACP_STATE_FAST, LACP_STATE_IN_SYNC, LACP_SYSTEM_PRIORITY_MAX, net_device::list, list_first_entry, memcmp(), memcpy(), memset(), net_devices, net_tx(), netdev, netdev_link_block(), netdev_link_blocked(), netdev_link_unblock(), NULL, system, and TICKS_PER_SEC.

Referenced by eth_slow_rx().

◆ eth_slow_marker_dump()

void eth_slow_marker_dump ( struct io_buffer * iobuf,
struct net_device * netdev,
const char * label )
static

Dump marker packet.

Parameters
iobufI/O buffer
netdevNetwork device
label"RX" or "TX"

Definition at line 230 of file eth_slow.c.

232 {
233 union eth_slow_packet *eth_slow = iobuf->data;
234 struct eth_slow_marker *marker = &eth_slow->marker;
235
236 DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n",
237 netdev->name, label,
238 eth_slow_marker_tlv_name ( marker->marker.tlv.type ),
239 ntohs ( marker->marker.port ),
240 eth_ntoa ( marker->marker.system ),
241 ntohl ( marker->marker.xact ) );
242 DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
243}
static const char * eth_slow_marker_tlv_name(uint8_t type)
Name marker TLV type.
Definition eth_slow.c:80
struct eth_slow_marker_tlv marker
Marker information.
Definition eth_slow.h:3
#define ntohl(value)
Definition byteswap.h:135
Marker packet.
Definition eth_slow.h:241
struct eth_slow_marker marker
Marker packet.
Definition eth_slow.h:259

References io_buffer::data, DBGC, DBGC2_HDA, eth_ntoa(), eth_slow_marker_tlv_name(), iob_len(), eth_slow_packet::marker, marker, netdev, ntohl, and ntohs.

Referenced by eth_slow_marker_rx().

◆ eth_slow_marker_rx()

int eth_slow_marker_rx ( struct io_buffer * iobuf,
struct net_device * netdev )
static

Process incoming marker packet.

Parameters
iobufI/O buffer
netdevNetwork device
Return values
rcReturn status code

Definition at line 252 of file eth_slow.c.

253 {
254 union eth_slow_packet *eth_slow = iobuf->data;
255 struct eth_slow_marker *marker = &eth_slow->marker;
256
257 eth_slow_marker_dump ( iobuf, netdev, "RX" );
258
259 if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
260 /* Send marker response */
261 marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
262 eth_slow_marker_dump ( iobuf, netdev, "TX" );
263 return net_tx ( iobuf, netdev, &eth_slow_protocol,
264 eth_slow_address, netdev->ll_addr );
265 } else {
266 /* Discard all other marker packets */
267 free_iob ( iobuf );
268 return -EINVAL;
269 }
270}
static void eth_slow_marker_dump(struct io_buffer *iobuf, struct net_device *netdev, const char *label)
Dump marker packet.
Definition eth_slow.c:230
#define EINVAL
Invalid argument.
Definition errno.h:472
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153

References io_buffer::data, EINVAL, eth_slow_address, eth_slow_marker_dump(), ETH_SLOW_TLV_MARKER_REQUEST, ETH_SLOW_TLV_MARKER_RESPONSE, free_iob(), eth_slow_packet::marker, marker, net_tx(), and netdev.

Referenced by eth_slow_rx().

◆ eth_slow_rx()

int eth_slow_rx ( struct io_buffer * iobuf,
struct net_device * netdev,
const void *ll_dest __unused,
const void *ll_source __unused,
unsigned int flags __unused )
static

Process incoming slow packet.

Parameters
iobufI/O buffer
netdevNetwork device
ll_destLink-layer destination address
ll_sourceLink-layer source address
flagsPacket flags
Return values
rcReturn status code

Definition at line 282 of file eth_slow.c.

286 {
287 union eth_slow_packet *eth_slow;
288
289 /* Sanity checks */
290 if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
291 free_iob ( iobuf );
292 return -EINVAL;
293 }
294 eth_slow = iobuf->data;
295
296 /* Strip any trailing padding */
297 iob_unput ( iobuf, ( iob_len ( iobuf ) - sizeof ( *eth_slow ) ) );
298
299 /* Handle according to subtype */
300 switch ( eth_slow->header.subtype ) {
302 return eth_slow_lacp_rx ( iobuf, netdev );
304 return eth_slow_marker_rx ( iobuf, netdev );
305 default:
306 DBGC ( netdev, "SLOW %s RX unknown subtype %02x\n",
307 netdev->name, eth_slow->header.subtype );
308 free_iob ( iobuf );
309 return -EINVAL;
310 }
311}
static int eth_slow_lacp_rx(struct io_buffer *iobuf, struct net_device *netdev)
Process incoming LACP packet.
Definition eth_slow.c:149
static int eth_slow_marker_rx(struct io_buffer *iobuf, struct net_device *netdev)
Process incoming marker packet.
Definition eth_slow.c:252
#define ETH_SLOW_SUBTYPE_LACP
LACP subtype.
Definition eth_slow.h:22
#define ETH_SLOW_SUBTYPE_MARKER
Marker subtype.
Definition eth_slow.h:28
#define iob_unput(iobuf, len)
Definition iobuf.h:200
uint8_t subtype
Slow protocols subtype.
Definition eth_slow.h:16
struct eth_slow_header header
Slow protocols header.
Definition eth_slow.h:255

References __unused, io_buffer::data, DBGC, EINVAL, eth_slow_lacp_rx(), eth_slow_marker_rx(), ETH_SLOW_SUBTYPE_LACP, ETH_SLOW_SUBTYPE_MARKER, flags, free_iob(), eth_slow_packet::header, iob_len(), iob_unput, netdev, and eth_slow_header::subtype.

Variable Documentation

◆ __net_protocol

struct net_protocol eth_slow_protocol __net_protocol
Initial value:
= {
.name = "Slow",
.net_proto = htons ( ETH_P_SLOW ),
.rx = eth_slow_rx,
}
static int eth_slow_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
Process incoming slow packet.
Definition eth_slow.c:282
#define ETH_P_SLOW
Definition if_ether.h:24

Slow protocol.

AoE protocol.

Definition at line 50 of file eth_slow.c.

◆ eth_slow_address

const uint8_t eth_slow_address[ETH_ALEN]
static
Initial value:
=
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }

Slow protocols multicast address.

Definition at line 53 of file eth_slow.c.

53 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };

Referenced by eth_slow_lacp_rx(), and eth_slow_marker_rx().