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:176
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#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:160
LACP packet.
Definition eth_slow.h:225
void * data
Start of data.
Definition iobuf.h:53
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 unsigned int interval;
154
155 eth_slow_lacp_dump ( iobuf, netdev, "RX" );
156
157 /* Check for looped-back packets */
158 if ( memcmp ( lacp->actor.system, netdev->ll_addr,
159 sizeof ( lacp->actor.system ) ) == 0 ) {
160 DBGC ( netdev, "SLOW %s RX loopback detected\n",
161 netdev->name );
162 return -ELOOP;
163 }
164
165 /* If partner is not in sync, collecting, and distributing,
166 * then block the link until after the next expected LACP
167 * packet.
168 */
169 if ( ~lacp->actor.state & ( LACP_STATE_IN_SYNC |
172 DBGC ( netdev, "SLOW %s LACP partner is down\n", netdev->name );
173 interval = ( ( lacp->actor.state & LACP_STATE_FAST ) ?
174 ( ( LACP_INTERVAL_FAST + 1 ) * TICKS_PER_SEC ) :
175 ( ( LACP_INTERVAL_SLOW + 1 ) * TICKS_PER_SEC ) );
176 netdev_link_block ( netdev, interval );
177 } else {
178 if ( netdev_link_blocked ( netdev ) ) {
179 DBGC ( netdev, "SLOW %s LACP partner is up\n",
180 netdev->name );
181 }
183 }
184
185 /* Build response */
186 memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
187 memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
188 memset ( &lacp->collector, 0, sizeof ( lacp->collector ) );
189 lacp->collector.tlv.type = ETH_SLOW_TLV_LACP_COLLECTOR;
190 lacp->collector.tlv.length = ETH_SLOW_TLV_LACP_COLLECTOR_LEN;
191 memcpy ( &lacp->partner, &lacp->actor, sizeof ( lacp->partner ) );
192 lacp->partner.tlv.type = ETH_SLOW_TLV_LACP_PARTNER;
193 lacp->partner.tlv.length = ETH_SLOW_TLV_LACP_PARTNER_LEN;
194 memset ( &lacp->partner.reserved, 0,
195 sizeof ( lacp->partner.reserved ) );
196 memset ( &lacp->actor, 0, sizeof ( lacp->actor ) );
197 lacp->actor.tlv.type = ETH_SLOW_TLV_LACP_ACTOR;
198 lacp->actor.tlv.length = ETH_SLOW_TLV_LACP_ACTOR_LEN;
199 lacp->actor.system_priority = htons ( LACP_SYSTEM_PRIORITY_MAX );
200 memcpy ( lacp->actor.system, netdev->ll_addr,
201 sizeof ( lacp->actor.system ) );
202 lacp->actor.key = htons ( 1 );
203 lacp->actor.port_priority = htons ( LACP_PORT_PRIORITY_MAX );
204 lacp->actor.port = htons ( 1 );
205 lacp->actor.state = ( LACP_STATE_AGGREGATABLE |
209 ( lacp->partner.state & LACP_STATE_FAST ) );
210 lacp->header.version = ETH_SLOW_LACP_VERSION;
211
212 /* Send response */
213 eth_slow_lacp_dump ( iobuf, netdev, "TX" );
214 return net_tx ( iobuf, netdev, &eth_slow_protocol, eth_slow_address,
215 netdev->ll_addr );
216}
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
#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:449
#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
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:1074
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:651
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References 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, memcmp(), memcpy(), memset(), net_tx(), netdev, netdev_link_block(), netdev_link_blocked(), netdev_link_unblock(), 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 225 of file eth_slow.c.

227 {
228 union eth_slow_packet *eth_slow = iobuf->data;
229 struct eth_slow_marker *marker = &eth_slow->marker;
230
231 DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n",
232 netdev->name, label,
233 eth_slow_marker_tlv_name ( marker->marker.tlv.type ),
234 ntohs ( marker->marker.port ),
235 eth_ntoa ( marker->marker.system ),
236 ntohl ( marker->marker.xact ) );
237 DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
238}
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 247 of file eth_slow.c.

248 {
249 union eth_slow_packet *eth_slow = iobuf->data;
250 struct eth_slow_marker *marker = &eth_slow->marker;
251
252 eth_slow_marker_dump ( iobuf, netdev, "RX" );
253
254 if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
255 /* Send marker response */
256 marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
257 eth_slow_marker_dump ( iobuf, netdev, "TX" );
258 return net_tx ( iobuf, netdev, &eth_slow_protocol,
259 eth_slow_address, netdev->ll_addr );
260 } else {
261 /* Discard all other marker packets */
262 free_iob ( iobuf );
263 return -EINVAL;
264 }
265}
static void eth_slow_marker_dump(struct io_buffer *iobuf, struct net_device *netdev, const char *label)
Dump marker packet.
Definition eth_slow.c:225
#define EINVAL
Invalid argument.
Definition errno.h:429
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 277 of file eth_slow.c.

281 {
282 union eth_slow_packet *eth_slow = iobuf->data;
283
284 /* Sanity checks */
285 if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
286 free_iob ( iobuf );
287 return -EINVAL;
288 }
289
290 /* Strip any trailing padding */
291 iob_unput ( iobuf, ( sizeof ( *eth_slow ) - iob_len ( iobuf ) ) );
292
293 /* Handle according to subtype */
294 switch ( eth_slow->header.subtype ) {
296 return eth_slow_lacp_rx ( iobuf, netdev );
298 return eth_slow_marker_rx ( iobuf, netdev );
299 default:
300 DBGC ( netdev, "SLOW %s RX unknown subtype %02x\n",
301 netdev->name, eth_slow->header.subtype );
302 free_iob ( iobuf );
303 return -EINVAL;
304 }
305}
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:247
#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:140
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:277
#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.

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

Referenced by eth_slow_lacp_rx(), and eth_slow_marker_rx().