iPXE
ethernet.c File Reference

Ethernet protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/if_arp.h>
#include <ipxe/if_ether.h>
#include <ipxe/in.h>
#include <ipxe/netdevice.h>
#include <ipxe/iobuf.h>
#include <ipxe/ethernet.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int eth_is_llc_packet (struct ethhdr *ethhdr)
 Check if Ethernet packet has an 802.3 LLC header.
int eth_push (struct net_device *netdev __unused, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto)
 Add Ethernet link-layer header.
int eth_pull (struct net_device *netdev __unused, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
 Remove Ethernet link-layer header.
void eth_init_addr (const void *hw_addr, void *ll_addr)
 Initialise Ethernet address.
void eth_random_addr (void *hw_addr)
 Generate random Ethernet address.
const char * eth_ntoa (const void *ll_addr)
 Transcribe Ethernet address.
int eth_mc_hash (unsigned int af, const void *net_addr, void *ll_addr)
 Hash multicast address.
int eth_eth_addr (const void *ll_addr, void *eth_addr)
 Generate Ethernet-compatible compressed link-layer address.
int eth_eui64 (const void *ll_addr, void *eui64)
 Generate EUI-64 address.
struct net_devicealloc_etherdev (size_t priv_size)
 Allocate Ethernet device.
 REQUIRING_SYMBOL (ethernet_protocol)
 REQUIRE_OBJECT (config_ethernet)

Variables

uint8_t eth_broadcast [ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
 Ethernet broadcast MAC address.
struct ll_protocol ethernet_protocol __ll_protocol
 Ethernet protocol.

Detailed Description

Ethernet protocol.

Definition in file ethernet.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ eth_is_llc_packet()

int eth_is_llc_packet ( struct ethhdr * ethhdr)
inlinestatic

Check if Ethernet packet has an 802.3 LLC header.

Parameters
ethhdrEthernet header
Return values
is_llcPacket has 802.3 LLC header

Definition at line 56 of file ethernet.c.

56 {
57 uint8_t len_msb;
58
59 /* Check if the protocol field contains a value short enough
60 * to be a frame length. The slightly convoluted form of the
61 * comparison is designed to reduce to a single x86
62 * instruction.
63 */
64 len_msb = *( ( uint8_t * ) &ethhdr->h_protocol );
65 return ( len_msb < 0x06 );
66}
unsigned char uint8_t
Definition stdint.h:10
An Ethernet link-layer header.
Definition if_ether.h:32
uint16_t h_protocol
Protocol ID.
Definition if_ether.h:38

References ethhdr::h_protocol.

Referenced by eth_pull().

◆ eth_push()

int eth_push ( struct net_device *netdev __unused,
struct io_buffer * iobuf,
const void * ll_dest,
const void * ll_source,
uint16_t net_proto )

Add Ethernet link-layer header.

Parameters
netdevNetwork device
iobufI/O buffer
ll_destLink-layer destination address
ll_sourceSource link-layer address
net_protoNetwork-layer protocol, in network-byte order
Return values
rcReturn status code

Definition at line 78 of file ethernet.c.

80 {
81 struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
82
83 /* Build Ethernet header */
84 memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN );
85 memcpy ( ethhdr->h_source, ll_source, ETH_ALEN );
86 ethhdr->h_protocol = net_proto;
87
88 return 0;
89}
#define ETH_ALEN
Definition if_ether.h:9
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define iob_push(iobuf, len)
Definition iobuf.h:89
uint8_t h_dest[ETH_ALEN]
Destination MAC address.
Definition if_ether.h:34
uint8_t h_source[ETH_ALEN]
Source MAC address.
Definition if_ether.h:36

References __unused, ETH_ALEN, ethhdr::h_dest, ethhdr::h_protocol, ethhdr::h_source, iob_push, memcpy(), and netdev.

◆ eth_pull()

int eth_pull ( struct net_device *netdev __unused,
struct io_buffer * iobuf,
const void ** ll_dest,
const void ** ll_source,
uint16_t * net_proto,
unsigned int * flags )

Remove Ethernet link-layer header.

Parameters
netdevNetwork device
iobufI/O buffer
Return values
ll_destLink-layer destination address
ll_sourceSource link-layer address
net_protoNetwork-layer protocol, in network-byte order
flagsPacket flags
rcReturn status code

Definition at line 102 of file ethernet.c.

104 {
105 struct ethhdr *ethhdr = iobuf->data;
106 uint16_t *llc_proto;
107
108 /* Sanity check. While in theory we could receive a one-byte
109 * packet, this will never happen in practice and performing
110 * the combined length check here avoids the need for an
111 * additional comparison if we detect an LLC frame.
112 */
113 if ( iob_len ( iobuf ) < ( sizeof ( *ethhdr ) + sizeof ( *llc_proto ))){
114 DBG ( "Ethernet packet too short (%zd bytes)\n",
115 iob_len ( iobuf ) );
116 return -EINVAL;
117 }
118
119 /* Strip off Ethernet header */
120 iob_pull ( iobuf, sizeof ( *ethhdr ) );
121
122 /* Fill in required fields */
123 *ll_dest = ethhdr->h_dest;
124 *ll_source = ethhdr->h_source;
125 *net_proto = ethhdr->h_protocol;
127 LL_MULTICAST : 0 ) |
129 LL_BROADCAST : 0 ) );
130
131 /* If this is an LLC frame (with a length in place of the
132 * protocol field), then use the next two bytes (which happen
133 * to be the LLC DSAP and SSAP) as the protocol. This allows
134 * for minimal-overhead support for receiving (rare) LLC
135 * frames, without requiring a full LLC protocol layer.
136 */
137 if ( eth_is_llc_packet ( ethhdr ) ) {
138 llc_proto = iobuf->data;
139 *net_proto = *llc_proto;
140 }
141
142 return 0;
143}
unsigned short uint16_t
Definition stdint.h:11
uint8_t flags
Flags.
Definition ena.h:7
static int eth_is_llc_packet(struct ethhdr *ethhdr)
Check if Ethernet packet has an 802.3 LLC header.
Definition ethernet.c:56
static int is_multicast_ether_addr(const void *addr)
Check if Ethernet address is a multicast address.
Definition ethernet.h:38
static int is_broadcast_ether_addr(const void *addr)
Check if Ethernet address is the broadcast address.
Definition ethernet.h:62
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define EINVAL
Invalid argument.
Definition errno.h:429
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_pull(iobuf, len)
Definition iobuf.h:107
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition netdevice.h:106
#define LL_BROADCAST
Packet is a broadcast packet.
Definition netdevice.h:109
void * data
Start of data.
Definition iobuf.h:53

References __unused, io_buffer::data, DBG, EINVAL, eth_is_llc_packet(), flags, ethhdr::h_dest, ethhdr::h_protocol, ethhdr::h_source, iob_len(), iob_pull, is_broadcast_ether_addr(), is_multicast_ether_addr(), LL_BROADCAST, LL_MULTICAST, and netdev.

Referenced by undinet_transmit().

◆ eth_init_addr()

void eth_init_addr ( const void * hw_addr,
void * ll_addr )

Initialise Ethernet address.

Parameters
hw_addrHardware address
ll_addrLink-layer address

Definition at line 151 of file ethernet.c.

151 {
152 memcpy ( ll_addr, hw_addr, ETH_ALEN );
153}

References ETH_ALEN, and memcpy().

◆ eth_random_addr()

void eth_random_addr ( void * hw_addr)

Generate random Ethernet address.

Parameters
hw_addrGenerated hardware address

Definition at line 160 of file ethernet.c.

160 {
161 uint8_t *addr = hw_addr;
162 unsigned int i;
163
164 for ( i = 0 ; i < ETH_ALEN ; i++ )
165 addr[i] = random();
166 addr[0] &= ~0x01; /* Clear multicast bit */
167 addr[0] |= 0x02; /* Set locally-assigned bit */
168}
uint32_t addr
Buffer address.
Definition dwmac.h:9
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32

References addr, ETH_ALEN, and random().

Referenced by igbvf_probe(), intelvf_mbox_reset(), lan78xx_fetch_mac(), smsc95xx_fetch_mac(), and txnic_bgx_mac().

◆ eth_ntoa()

const char * eth_ntoa ( const void * ll_addr)

Transcribe Ethernet address.

Parameters
ll_addrLink-layer address
Return values
stringLink-layer address in human-readable format

Definition at line 176 of file ethernet.c.

176 {
177 static char buf[18]; /* "00:00:00:00:00:00" */
178 const uint8_t *eth_addr = ll_addr;
179
180 sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x",
181 eth_addr[0], eth_addr[1], eth_addr[2],
182 eth_addr[3], eth_addr[4], eth_addr[5] );
183 return buf;
184}
#define sprintf(buf, fmt,...)
Write a formatted string to a buffer.
Definition stdio.h:37

References sprintf.

Referenced by acpimac_extract(), amd8111e_get_mac_address(), b44_probe(), bnx2_probe(), bofm_dummy_harvest(), bofm_dummy_update(), bofm_en(), bofm_test(), corkscrew_probe1(), cs89x0_probe(), davicom_probe(), dmfe_probe(), ecm_fetch_mac(), eepro_probe(), ena_get_device_attributes(), eoib_create(), eoib_rx_av(), eoib_tx_av(), epic100_probe(), eth_probe(), eth_slow_lacp_dump(), eth_slow_marker_dump(), exanic_probe(), fcoe_expired(), fcoe_fip_rx(), fcoe_fip_rx_advertisement(), fcoe_fip_rx_els_response(), fcoe_fip_rx_vlan(), fcoe_rx(), gve_describe(), hermon_bofm_harvest(), hermon_bofm_update(), ibft_fill_nic(), ice_admin_mac_read(), intel_fetch_mac(), intel_fetch_mac_eeprom(), intelvf_mbox_reset(), intelx_try_fetch_mac(), intelxl_admin_mac_read(), ipoib_find_remac(), ipoib_translate_tx_arp(), ipoib_transmit(), iwlist(), lan78xx_fetch_mac(), ne_probe(), net80211_probe_step(), net80211_step_associate(), nv_setup_mac_addr(), pcnet32_probe(), phantom_add_macaddr(), phantom_del_macaddr(), phantom_get_macaddr(), prism2_probe(), smc9000_probe(), smsc95xx_fetch_mac(), smsc95xx_vm3_fetch_mac(), smscusb_eeprom_fetch_mac(), smscusb_fdt_fetch_mac(), smscusb_otp_fetch_mac(), stp_rx(), t595_probe(), t5x9_probe(), tlan_probe(), tulip_probe(), txnic_lmac_probe(), undinet_probe(), virtnet_probe_legacy(), virtnet_probe_modern(), vxge_probe(), w89c840_probe(), wpa_derive_ptk(), xsmp_rx_xve_install(), and xve_create().

◆ eth_mc_hash()

int eth_mc_hash ( unsigned int af,
const void * net_addr,
void * ll_addr )

Hash multicast address.

Parameters
afAddress family
net_addrNetwork-layer address
ll_addrLink-layer address to fill in
Return values
rcReturn status code

Definition at line 194 of file ethernet.c.

194 {
195 const uint8_t *net_addr_bytes = net_addr;
196 uint8_t *ll_addr_bytes = ll_addr;
197
198 switch ( af ) {
199 case AF_INET:
200 ll_addr_bytes[0] = 0x01;
201 ll_addr_bytes[1] = 0x00;
202 ll_addr_bytes[2] = 0x5e;
203 ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f;
204 ll_addr_bytes[4] = net_addr_bytes[2];
205 ll_addr_bytes[5] = net_addr_bytes[3];
206 return 0;
207 case AF_INET6:
208 ll_addr_bytes[0] = 0x33;
209 ll_addr_bytes[1] = 0x33;
210 memcpy ( &ll_addr_bytes[2], &net_addr_bytes[12], 4 );
211 return 0;
212 default:
213 return -ENOTSUP;
214 }
215}
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define AF_INET6
IPv6 Internet addresses.
Definition socket.h:65
#define ENOTSUP
Operation not supported.
Definition errno.h:590

References AF_INET, AF_INET6, ENOTSUP, and memcpy().

◆ eth_eth_addr()

int eth_eth_addr ( const void * ll_addr,
void * eth_addr )

Generate Ethernet-compatible compressed link-layer address.

Parameters
ll_addrLink-layer address
eth_addrEthernet-compatible address to fill in

Definition at line 223 of file ethernet.c.

223 {
224 memcpy ( eth_addr, ll_addr, ETH_ALEN );
225 return 0;
226}

References ETH_ALEN, and memcpy().

◆ eth_eui64()

int eth_eui64 ( const void * ll_addr,
void * eui64 )

Generate EUI-64 address.

Parameters
ll_addrLink-layer address
eui64EUI-64 address to fill in
Return values
rcReturn status code

Definition at line 235 of file ethernet.c.

235 {
236
237 memcpy ( ( eui64 + 0 ), ( ll_addr + 0 ), 3 );
238 memcpy ( ( eui64 + 5 ), ( ll_addr + 3 ), 3 );
239 *( ( uint16_t * ) ( eui64 + 3 ) ) = htons ( 0xfffe );
240 return 0;
241}
#define htons(value)
Definition byteswap.h:136

References htons, and memcpy().

◆ alloc_etherdev()

struct net_device * alloc_etherdev ( size_t priv_size)

Allocate Ethernet device.

Parameters
priv_sizeSize of driver private data
Return values
netdevNetwork device, or NULL

Definition at line 265 of file ethernet.c.

265 {
266 struct net_device *netdev;
267
268 netdev = alloc_netdev ( priv_size );
269 if ( netdev ) {
270 netdev->ll_protocol = &ethernet_protocol;
271 netdev->ll_broadcast = eth_broadcast;
272 netdev->max_pkt_len = ETH_FRAME_LEN;
273 netdev->mtu = ETH_MAX_MTU;
274 }
275 return netdev;
276}
uint8_t eth_broadcast[ETH_ALEN]
Ethernet broadcast MAC address.
Definition ethernet.c:48
static struct net_device * netdev
Definition gdbudp.c:53
#define ETH_FRAME_LEN
Definition if_ether.h:12
#define ETH_MAX_MTU
Definition if_ether.h:15
struct net_device * alloc_netdev(size_t priv_len)
Allocate network device.
Definition netdevice.c:722
A network device.
Definition netdevice.h:353

References alloc_netdev(), eth_broadcast, ETH_FRAME_LEN, ETH_MAX_MTU, and netdev.

Referenced by a3c90x_probe(), af_packet_nic_probe(), alloc_rndis(), atl1e_probe(), atl_probe(), axge_probe(), b44_probe(), bnxt_init_one(), cgem_probe(), dm96xx_probe(), dwmac_probe(), ecm_probe(), efab_probe(), ena_probe(), eoib_create(), exanic_probe_port(), flexboot_nodnic_register_netdev(), forcedeth_probe(), gve_probe(), hermon_probe(), hunt_probe(), ice_probe(), icplus_probe(), ifec_pci_probe(), igbvf_probe(), intel_probe(), intelx_probe(), intelxl_probe(), intelxlvf_probe(), intelxvf_probe(), iphone_probe(), jme_probe(), lan78xx_probe(), legacy_probe(), mnpnet_start(), myri10ge_pci_probe(), myson_probe(), natsemi_probe(), ncm_probe(), netfront_probe(), pcnet32_probe(), phantom_probe(), pnic_probe(), rdc_probe(), realtek_probe(), rhine_probe(), sis190_init_board(), skeleton_probe(), skge_devinit(), sky2_init_netdev(), slirp_probe(), smsc75xx_probe(), smsc95xx_probe(), snpnet_start(), tap_probe(), testnet_okx(), tg3_init_one(), txnic_alloc(), undinet_probe(), velocity_probe(), virtnet_probe_legacy(), virtnet_probe_modern(), vlan_create(), vmxnet3_probe(), and vxge_device_register().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( ethernet_protocol )

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_ethernet )

Variable Documentation

◆ eth_broadcast

uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }

Ethernet broadcast MAC address.

Definition at line 48 of file ethernet.c.

48{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

Referenced by alloc_etherdev(), alloc_ipoibdev(), ath9k_init_misc(), ice_probe(), ipoib_complete_recv(), net80211_alloc(), and net80211_probe_step().

◆ __ll_protocol

struct ll_protocol ethernet_protocol __ll_protocol
Initial value:
= {
.name = "Ethernet",
.ll_proto = htons ( ARPHRD_ETHER ),
.hw_addr_len = ETH_ALEN,
.ll_addr_len = ETH_ALEN,
.ll_header_len = ETH_HLEN,
.push = eth_push,
.pull = eth_pull,
.init_addr = eth_init_addr,
.ntoa = eth_ntoa,
.mc_hash = eth_mc_hash,
.eth_addr = eth_eth_addr,
.eui64 = eth_eui64,
}
int eth_mc_hash(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition ethernet.c:194
int eth_push(struct net_device *netdev __unused, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto)
Add Ethernet link-layer header.
Definition ethernet.c:78
void eth_init_addr(const void *hw_addr, void *ll_addr)
Initialise Ethernet address.
Definition ethernet.c:151
int eth_eui64(const void *ll_addr, void *eui64)
Generate EUI-64 address.
Definition ethernet.c:235
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
int eth_pull(struct net_device *netdev __unused, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
Remove Ethernet link-layer header.
Definition ethernet.c:102
int eth_eth_addr(const void *ll_addr, void *eth_addr)
Generate Ethernet-compatible compressed link-layer address.
Definition ethernet.c:223
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition if_arp.h:17
#define ETH_HLEN
Definition if_ether.h:10

Ethernet protocol.

Definition at line 244 of file ethernet.c.

244 {
245 .name = "Ethernet",
246 .ll_proto = htons ( ARPHRD_ETHER ),
247 .hw_addr_len = ETH_ALEN,
248 .ll_addr_len = ETH_ALEN,
249 .ll_header_len = ETH_HLEN,
250 .push = eth_push,
251 .pull = eth_pull,
252 .init_addr = eth_init_addr,
253 .ntoa = eth_ntoa,
254 .mc_hash = eth_mc_hash,
255 .eth_addr = eth_eth_addr,
256 .eui64 = eth_eui64,
257};