iPXE
netdev_settings.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <errno.h>
29#include <byteswap.h>
30#include <ipxe/dhcp.h>
31#include <ipxe/dhcpopts.h>
32#include <ipxe/settings.h>
33#include <ipxe/device.h>
34#include <ipxe/netdevice.h>
35#include <ipxe/init.h>
36
37/** @file
38 *
39 * Network device configuration settings
40 *
41 */
42
43/** Network device predefined settings */
44const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
45 .name = "mac",
46 .description = "MAC address",
47 .type = &setting_type_hex,
48};
49const struct setting hwaddr_setting __setting ( SETTING_NETDEV, hwaddr ) = {
50 .name = "hwaddr",
51 .description = "Hardware address",
52 .type = &setting_type_hex,
53};
54const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
55 .name = "bustype",
56 .description = "Bus type",
57 .type = &setting_type_string,
58};
59const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
60 .name = "busloc",
61 .description = "Bus location",
62 .type = &setting_type_uint32,
63};
64const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
65 .name = "busid",
66 .description = "Bus ID",
67 .type = &setting_type_hex,
68};
69const struct setting linktype_setting __setting ( SETTING_NETDEV, linktype ) = {
70 .name = "linktype",
71 .description = "Link-layer type",
72 .type = &setting_type_string,
73};
74const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
75 .name = "chip",
76 .description = "Chip",
77 .type = &setting_type_string,
78};
79const struct setting ifname_setting __setting ( SETTING_NETDEV, ifname ) = {
80 .name = "ifname",
81 .description = "Interface name",
82 .type = &setting_type_string,
83};
84const struct setting mtu_setting __setting ( SETTING_NETDEV, mtu ) = {
85 .name = "mtu",
86 .description = "MTU",
87 .type = &setting_type_int16,
88 .tag = DHCP_MTU,
89};
90
91/**
92 * Store link-layer address setting
93 *
94 * @v netdev Network device
95 * @v data Setting data, or NULL to clear setting
96 * @v len Length of setting data
97 * @ret rc Return status code
98 */
99static int netdev_store_mac ( struct net_device *netdev,
100 const void *data, size_t len ) {
101 struct ll_protocol *ll_protocol = netdev->ll_protocol;
102
103 /* Record new MAC address */
104 if ( data ) {
105 if ( len != netdev->ll_protocol->ll_addr_len )
106 return -EINVAL;
107 memcpy ( netdev->ll_addr, data, len );
108 } else {
109 /* Reset MAC address if clearing setting */
110 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
111 }
112
113 return 0;
114}
115
116/**
117 * Fetch link-layer address setting
118 *
119 * @v netdev Network device
120 * @v data Buffer to fill with setting data
121 * @v len Length of buffer
122 * @ret len Length of setting data, or negative error
123 */
124static int netdev_fetch_mac ( struct net_device *netdev, void *data,
125 size_t len ) {
126 size_t max_len = netdev->ll_protocol->ll_addr_len;
127
128 if ( len > max_len )
129 len = max_len;
130 memcpy ( data, netdev->ll_addr, len );
131 return max_len;
132}
133
134/**
135 * Fetch hardware address setting
136 *
137 * @v netdev Network device
138 * @v data Buffer to fill with setting data
139 * @v len Length of buffer
140 * @ret len Length of setting data, or negative error
141 */
142static int netdev_fetch_hwaddr ( struct net_device *netdev, void *data,
143 size_t len ) {
144 size_t max_len = netdev->ll_protocol->hw_addr_len;
145
146 if ( len > max_len )
147 len = max_len;
148 memcpy ( data, netdev->hw_addr, len );
149 return max_len;
150}
151
152/**
153 * Fetch bus type setting
154 *
155 * @v netdev Network device
156 * @v data Buffer to fill with setting data
157 * @v len Length of buffer
158 * @ret len Length of setting data, or negative error
159 */
160static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
161 size_t len ) {
162 static const char *bustypes[] = {
163 [BUS_TYPE_PCI] = "PCI",
164 [BUS_TYPE_ISAPNP] = "ISAPNP",
165 [BUS_TYPE_EISA] = "EISA",
166 [BUS_TYPE_MCA] = "MCA",
167 [BUS_TYPE_ISA] = "ISA",
168 [BUS_TYPE_TAP] = "TAP",
169 [BUS_TYPE_EFI] = "EFI",
170 [BUS_TYPE_XEN] = "XEN",
171 [BUS_TYPE_HV] = "HV",
172 [BUS_TYPE_USB] = "USB",
173 [BUS_TYPE_DT] = "DT",
174 };
175 struct device_description *desc = &netdev->dev->desc;
176 const char *bustype;
177
178 assert ( desc->bus_type < ( sizeof ( bustypes ) /
179 sizeof ( bustypes[0] ) ) );
180 bustype = bustypes[desc->bus_type];
181 if ( ! bustype )
182 return -ENOENT;
183 strncpy ( data, bustype, len );
184 return strlen ( bustype );
185}
186
187/**
188 * Fetch bus location setting
189 *
190 * @v netdev Network device
191 * @v data Buffer to fill with setting data
192 * @v len Length of buffer
193 * @ret len Length of setting data, or negative error
194 */
195static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
196 size_t len ) {
197 struct device_description *desc = &netdev->dev->desc;
198 uint32_t busloc;
199
200 busloc = cpu_to_be32 ( desc->location );
201 if ( len > sizeof ( busloc ) )
202 len = sizeof ( busloc );
203 memcpy ( data, &busloc, len );
204 return sizeof ( busloc );
205}
206
207/**
208 * Fetch bus ID setting
209 *
210 * @v netdev Network device
211 * @v data Buffer to fill with setting data
212 * @v len Length of buffer
213 * @ret len Length of setting data, or negative error
214 */
215static int netdev_fetch_busid ( struct net_device *netdev, void *data,
216 size_t len ) {
217 struct device_description *desc = &netdev->dev->desc;
218 struct dhcp_netdev_desc dhcp_desc;
219
220 dhcp_desc.type = desc->bus_type;
221 dhcp_desc.vendor = htons ( desc->vendor );
222 dhcp_desc.device = htons ( desc->device );
223 if ( len > sizeof ( dhcp_desc ) )
224 len = sizeof ( dhcp_desc );
225 memcpy ( data, &dhcp_desc, len );
226 return sizeof ( dhcp_desc );
227}
228
229/**
230 * Fetch link layer type setting
231 *
232 * @v netdev Network device
233 * @v data Buffer to fill with setting data
234 * @v len Length of buffer
235 * @ret len Length of setting data, or negative error
236 */
237static int netdev_fetch_linktype ( struct net_device *netdev, void *data,
238 size_t len ) {
239 const char *linktype = netdev->ll_protocol->name;
240
241 strncpy ( data, linktype, len );
242 return strlen ( linktype );
243}
244
245/**
246 * Fetch chip setting
247 *
248 * @v netdev Network device
249 * @v data Buffer to fill with setting data
250 * @v len Length of buffer
251 * @ret len Length of setting data, or negative error
252 */
253static int netdev_fetch_chip ( struct net_device *netdev, void *data,
254 size_t len ) {
255 const char *chip = netdev->dev->driver_name;
256
257 strncpy ( data, chip, len );
258 return strlen ( chip );
259}
260
261/**
262 * Fetch ifname setting
263 *
264 * @v netdev Network device
265 * @v data Buffer to fill with setting data
266 * @v len Length of buffer
267 * @ret len Length of setting data, or negative error
268 */
269static int netdev_fetch_ifname ( struct net_device *netdev, void *data,
270 size_t len ) {
271 const char *ifname = netdev->name;
272
273 strncpy ( data, ifname, len );
274 return strlen ( ifname );
275}
276
277/** A network device setting operation */
279 /** Setting */
280 const struct setting *setting;
281 /** Store setting (or NULL if not supported)
282 *
283 * @v netdev Network device
284 * @v data Setting data, or NULL to clear setting
285 * @v len Length of setting data
286 * @ret rc Return status code
287 */
288 int ( * store ) ( struct net_device *netdev, const void *data,
289 size_t len );
290 /** Fetch setting
291 *
292 * @v netdev Network device
293 * @v data Buffer to fill with setting data
294 * @v len Length of buffer
295 * @ret len Length of setting data, or negative error
296 */
297 int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
298};
299
300/** Network device settings */
302 { &mac_setting, netdev_store_mac, netdev_fetch_mac },
303 { &hwaddr_setting, NULL, netdev_fetch_hwaddr },
304 { &bustype_setting, NULL, netdev_fetch_bustype },
305 { &busloc_setting, NULL, netdev_fetch_busloc },
306 { &busid_setting, NULL, netdev_fetch_busid },
307 { &linktype_setting, NULL, netdev_fetch_linktype },
308 { &chip_setting, NULL, netdev_fetch_chip },
309 { &ifname_setting, NULL, netdev_fetch_ifname },
310};
311
312/**
313 * Store value of network device setting
314 *
315 * @v settings Settings block
316 * @v setting Setting to store
317 * @v data Setting data, or NULL to clear setting
318 * @v len Length of setting data
319 * @ret rc Return status code
320 */
321static int netdev_store ( struct settings *settings,
322 const struct setting *setting,
323 const void *data, size_t len ) {
325 settings.settings );
327 unsigned int i;
328
329 /* Handle network device-specific settings */
330 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
331 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
333 if ( setting_cmp ( setting, op->setting ) == 0 ) {
334 if ( op->store ) {
335 return op->store ( netdev, data, len );
336 } else {
337 return -ENOTSUP;
338 }
339 }
340 }
341
343}
344
345/**
346 * Fetch value of network device setting
347 *
348 * @v settings Settings block
349 * @v setting Setting to fetch
350 * @v data Buffer to fill with setting data
351 * @v len Length of buffer
352 * @ret len Length of setting data, or negative error
353 */
354static int netdev_fetch ( struct settings *settings, struct setting *setting,
355 void *data, size_t len ) {
357 settings.settings );
359 unsigned int i;
360
361 /* Handle network device-specific settings */
362 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
363 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
365 if ( setting_cmp ( setting, op->setting ) == 0 )
366 return op->fetch ( netdev, data, len );
367 }
368
370}
371
372/**
373 * Clear network device settings
374 *
375 * @v settings Settings block
376 */
377static void netdev_clear ( struct settings *settings ) {
379}
380
381/** Network device configuration settings operations */
383 .store = netdev_store,
384 .fetch = netdev_fetch,
385 .clear = netdev_clear,
386};
387
388/**
389 * Redirect "netX" settings block
390 *
391 * @v settings Settings block
392 * @ret settings Underlying settings block
393 */
394static struct settings * netdev_redirect ( struct settings *settings ) {
395 struct net_device *netdev;
396
397 /* Redirect to "netX" network device */
399 if ( netdev ) {
400 return netdev_settings ( netdev );
401 } else {
402 return settings;
403 }
404}
405
406/** "netX" settings operations */
410
411/** "netX" settings */
413 .refcnt = NULL,
414 .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
415 .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
417};
418
419/** Initialise "netX" settings */
420static void netdev_redirect_settings_init ( void ) {
421 int rc;
422
424 "netX" ) ) != 0 ) {
425 DBG ( "Could not register netX settings: %s\n",
426 strerror ( rc ) );
427 return;
428 }
429}
430
431/** "netX" settings initialiser */
432struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
433 .name = "netX",
434 .initialise = netdev_redirect_settings_init,
435};
436
437/**
438 * Apply network device settings
439 *
440 * @ret rc Return status code
441 */
442static int apply_netdev_settings ( void ) {
443 struct net_device *netdev;
444 struct settings *settings;
445 struct ll_protocol *ll_protocol;
446 size_t max_mtu;
447 size_t old_mtu;
448 size_t mtu;
449 int rc;
450
451 /* Process settings for each network device */
453
454 /* Get network device settings */
456
457 /* Get MTU */
458 mtu = fetch_uintz_setting ( settings, &mtu_setting );
459
460 /* Do nothing unless MTU is specified */
461 if ( ! mtu )
462 continue;
463
464 /* Limit MTU to maximum supported by hardware */
465 ll_protocol = netdev->ll_protocol;
466 max_mtu = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
467 if ( mtu > max_mtu ) {
468 DBGC ( netdev, "NETDEV %s cannot support MTU %zd (max "
469 "%zd)\n", netdev->name, mtu, max_mtu );
470 mtu = max_mtu;
471 }
472
473 /* Update maximum packet length */
474 old_mtu = netdev->mtu;
475 netdev->mtu = mtu;
476 if ( mtu != old_mtu ) {
477 DBGC ( netdev, "NETDEV %s MTU is %zd\n",
478 netdev->name, mtu );
479 }
480
481 /* Close and reopen network device if MTU has increased */
482 if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
484 if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
485 DBGC ( netdev, "NETDEV %s could not reopen: "
486 "%s\n", netdev->name, strerror ( rc ) );
487 return rc;
488 }
489 }
490 }
491
492 return 0;
493}
494
495/** Network device settings applicator */
496struct settings_applicator netdev_applicator __settings_applicator = {
497 .apply = apply_netdev_settings,
498};
linktype
Definition 3c90x.h:240
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Device model.
#define BUS_TYPE_PCI
PCI bus type.
Definition device.h:44
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition device.h:47
#define BUS_TYPE_EISA
EISA bus type.
Definition device.h:50
#define BUS_TYPE_USB
USB bus type.
Definition device.h:71
#define BUS_TYPE_EFI
EFI bus type.
Definition device.h:62
#define BUS_TYPE_ISA
ISA bus type.
Definition device.h:56
#define BUS_TYPE_MCA
MCA bus type.
Definition device.h:53
#define BUS_TYPE_TAP
TAP bus type.
Definition device.h:59
#define BUS_TYPE_XEN
Xen bus type.
Definition device.h:65
#define BUS_TYPE_DT
Devicetree bus type.
Definition device.h:74
#define BUS_TYPE_HV
Hyper-V bus type.
Definition device.h:68
DHCP options.
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint32_t mtu
Maximum MTU.
Definition ena.h:17
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:505
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define DHCP_MTU
Maximum transmission unit.
Definition dhcp.h:87
#define INIT_LATE
Late initialisation.
Definition init.h:33
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define SETTING_NETDEV
Network device settings.
Definition settings.h:64
#define htons(value)
Definition byteswap.h:136
#define cpu_to_be32(value)
Definition byteswap.h:111
Dynamic Host Configuration Protocol.
Configuration settings.
#define __setting(setting_order, name)
Declare a configuration setting.
Definition settings.h:57
#define __settings_applicator
Declare a settings applicator.
Definition settings.h:265
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition list.h:31
static int netdev_fetch_busid(struct net_device *netdev, void *data, size_t len)
Fetch bus ID setting.
static struct settings_operations netdev_redirect_settings_operations
"netX" settings operations
static struct settings netdev_redirect_settings
"netX" settings
static int netdev_fetch_mac(struct net_device *netdev, void *data, size_t len)
Fetch link-layer address setting.
static struct settings * netdev_redirect(struct settings *settings)
Redirect "netX" settings block.
struct settings_operations netdev_settings_operations
Network device configuration settings operations.
static int netdev_fetch_bustype(struct net_device *netdev, void *data, size_t len)
Fetch bus type setting.
static void netdev_redirect_settings_init(void)
Initialise "netX" settings.
static int netdev_fetch_hwaddr(struct net_device *netdev, void *data, size_t len)
Fetch hardware address setting.
static int netdev_store_mac(struct net_device *netdev, const void *data, size_t len)
Store link-layer address setting.
static int netdev_store(struct settings *settings, const struct setting *setting, const void *data, size_t len)
Store value of network device setting.
static int netdev_fetch_chip(struct net_device *netdev, void *data, size_t len)
Fetch chip setting.
static int netdev_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of network device setting.
static int netdev_fetch_busloc(struct net_device *netdev, void *data, size_t len)
Fetch bus location setting.
static void netdev_clear(struct settings *settings)
Clear network device settings.
static struct netdev_setting_operation netdev_setting_operations[]
Network device settings.
static int netdev_fetch_linktype(struct net_device *netdev, void *data, size_t len)
Fetch link layer type setting.
static int apply_netdev_settings(void)
Apply network device settings.
static int netdev_fetch_ifname(struct net_device *netdev, void *data, size_t len)
Fetch ifname setting.
int netdev_open(struct net_device *netdev)
Open network device.
Definition netdevice.c:862
void netdev_close(struct net_device *netdev)
Close network device.
Definition netdevice.c:896
struct net_device * find_netdev(const char *name)
Get network device by name.
Definition netdevice.c:989
Network device management.
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition netdevice.h:547
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition settings.c:476
unsigned long fetch_uintz_setting(struct settings *settings, const struct setting *setting)
Fetch value of unsigned integer setting, or zero.
Definition settings.c:1069
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition settings.c:1121
int generic_settings_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of generic setting.
Definition settings.c:179
void generic_settings_clear(struct settings *settings)
Clear generic settings block.
Definition settings.c:208
int generic_settings_store(struct settings *settings, const struct setting *setting, const void *data, size_t len)
Store value of generic setting.
Definition settings.c:127
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:361
A hardware device description.
Definition device.h:20
Network device descriptor.
Definition dhcp.h:449
uint8_t type
Bus type ID.
Definition dhcp.h:451
uint16_t device
Device ID.
Definition dhcp.h:455
uint16_t vendor
Vendor ID.
Definition dhcp.h:453
An initialisation function.
Definition init.h:15
A link-layer protocol.
Definition netdevice.h:115
void(* init_addr)(const void *hw_addr, void *ll_addr)
Initialise link-layer address.
Definition netdevice.h:151
uint8_t ll_header_len
Link-layer header length.
Definition netdevice.h:201
A network device.
Definition netdevice.h:353
A network device setting operation.
int(* store)(struct net_device *netdev, const void *data, size_t len)
Store setting (or NULL if not supported)
int(* fetch)(struct net_device *netdev, void *data, size_t len)
Fetch setting.
const struct setting * setting
Setting.
A setting.
Definition settings.h:24
A settings applicator.
Definition settings.h:252
Settings block operations.
Definition settings.h:86
A settings block.
Definition settings.h:133
const char * name
Name.
Definition settings.h:137