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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <errno.h>
28 #include <byteswap.h>
29 #include <ipxe/dhcp.h>
30 #include <ipxe/dhcpopts.h>
31 #include <ipxe/settings.h>
32 #include <ipxe/device.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/init.h>
35 
36 /** @file
37  *
38  * Network device configuration settings
39  *
40  */
41 
42 /** Network device predefined settings */
43 const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
44  .name = "mac",
45  .description = "MAC address",
46  .type = &setting_type_hex,
47 };
48 const struct setting hwaddr_setting __setting ( SETTING_NETDEV, hwaddr ) = {
49  .name = "hwaddr",
50  .description = "Hardware address",
51  .type = &setting_type_hex,
52 };
53 const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
54  .name = "bustype",
55  .description = "Bus type",
56  .type = &setting_type_string,
57 };
58 const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
59  .name = "busloc",
60  .description = "Bus location",
61  .type = &setting_type_uint32,
62 };
63 const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
64  .name = "busid",
65  .description = "Bus ID",
66  .type = &setting_type_hex,
67 };
68 const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
69  .name = "chip",
70  .description = "Chip",
71  .type = &setting_type_string,
72 };
73 const struct setting ifname_setting __setting ( SETTING_NETDEV, ifname ) = {
74  .name = "ifname",
75  .description = "Interface name",
76  .type = &setting_type_string,
77 };
78 const struct setting mtu_setting __setting ( SETTING_NETDEV, mtu ) = {
79  .name = "mtu",
80  .description = "MTU",
81  .type = &setting_type_int16,
82  .tag = DHCP_MTU,
83 };
84 
85 /**
86  * Store link-layer address setting
87  *
88  * @v netdev Network device
89  * @v data Setting data, or NULL to clear setting
90  * @v len Length of setting data
91  * @ret rc Return status code
92  */
93 static int netdev_store_mac ( struct net_device *netdev,
94  const void *data, size_t len ) {
96 
97  /* Record new MAC address */
98  if ( data ) {
99  if ( len != netdev->ll_protocol->ll_addr_len )
100  return -EINVAL;
101  memcpy ( netdev->ll_addr, data, len );
102  } else {
103  /* Reset MAC address if clearing setting */
105  }
106 
107  return 0;
108 }
109 
110 /**
111  * Fetch link-layer address setting
112  *
113  * @v netdev Network device
114  * @v data Buffer to fill with setting data
115  * @v len Length of buffer
116  * @ret len Length of setting data, or negative error
117  */
118 static int netdev_fetch_mac ( struct net_device *netdev, void *data,
119  size_t len ) {
121 
122  if ( len > max_len )
123  len = max_len;
124  memcpy ( data, netdev->ll_addr, len );
125  return max_len;
126 }
127 
128 /**
129  * Fetch hardware address setting
130  *
131  * @v netdev Network device
132  * @v data Buffer to fill with setting data
133  * @v len Length of buffer
134  * @ret len Length of setting data, or negative error
135  */
136 static int netdev_fetch_hwaddr ( struct net_device *netdev, void *data,
137  size_t len ) {
139 
140  if ( len > max_len )
141  len = max_len;
142  memcpy ( data, netdev->hw_addr, len );
143  return max_len;
144 }
145 
146 /**
147  * Fetch bus type setting
148  *
149  * @v netdev Network device
150  * @v data Buffer to fill with setting data
151  * @v len Length of buffer
152  * @ret len Length of setting data, or negative error
153  */
154 static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
155  size_t len ) {
156  static const char *bustypes[] = {
157  [BUS_TYPE_PCI] = "PCI",
158  [BUS_TYPE_ISAPNP] = "ISAPNP",
159  [BUS_TYPE_EISA] = "EISA",
160  [BUS_TYPE_MCA] = "MCA",
161  [BUS_TYPE_ISA] = "ISA",
162  [BUS_TYPE_TAP] = "TAP",
163  [BUS_TYPE_EFI] = "EFI",
164  [BUS_TYPE_XEN] = "XEN",
165  [BUS_TYPE_HV] = "HV",
166  [BUS_TYPE_USB] = "USB",
167  };
168  struct device_description *desc = &netdev->dev->desc;
169  const char *bustype;
170 
171  assert ( desc->bus_type < ( sizeof ( bustypes ) /
172  sizeof ( bustypes[0] ) ) );
173  bustype = bustypes[desc->bus_type];
174  if ( ! bustype )
175  return -ENOENT;
176  strncpy ( data, bustype, len );
177  return strlen ( bustype );
178 }
179 
180 /**
181  * Fetch bus location setting
182  *
183  * @v netdev Network device
184  * @v data Buffer to fill with setting data
185  * @v len Length of buffer
186  * @ret len Length of setting data, or negative error
187  */
188 static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
189  size_t len ) {
190  struct device_description *desc = &netdev->dev->desc;
191  uint32_t busloc;
192 
193  busloc = cpu_to_be32 ( desc->location );
194  if ( len > sizeof ( busloc ) )
195  len = sizeof ( busloc );
196  memcpy ( data, &busloc, len );
197  return sizeof ( busloc );
198 }
199 
200 /**
201  * Fetch bus ID setting
202  *
203  * @v netdev Network device
204  * @v data Buffer to fill with setting data
205  * @v len Length of buffer
206  * @ret len Length of setting data, or negative error
207  */
208 static int netdev_fetch_busid ( struct net_device *netdev, void *data,
209  size_t len ) {
210  struct device_description *desc = &netdev->dev->desc;
211  struct dhcp_netdev_desc dhcp_desc;
212 
213  dhcp_desc.type = desc->bus_type;
214  dhcp_desc.vendor = htons ( desc->vendor );
215  dhcp_desc.device = htons ( desc->device );
216  if ( len > sizeof ( dhcp_desc ) )
217  len = sizeof ( dhcp_desc );
218  memcpy ( data, &dhcp_desc, len );
219  return sizeof ( dhcp_desc );
220 }
221 
222 /**
223  * Fetch chip setting
224  *
225  * @v netdev Network device
226  * @v data Buffer to fill with setting data
227  * @v len Length of buffer
228  * @ret len Length of setting data, or negative error
229  */
230 static int netdev_fetch_chip ( struct net_device *netdev, void *data,
231  size_t len ) {
232  const char *chip = netdev->dev->driver_name;
233 
234  strncpy ( data, chip, len );
235  return strlen ( chip );
236 }
237 
238 /**
239  * Fetch ifname setting
240  *
241  * @v netdev Network device
242  * @v data Buffer to fill with setting data
243  * @v len Length of buffer
244  * @ret len Length of setting data, or negative error
245  */
246 static int netdev_fetch_ifname ( struct net_device *netdev, void *data,
247  size_t len ) {
248  const char *ifname = netdev->name;
249 
250  strncpy ( data, ifname, len );
251  return strlen ( ifname );
252 }
253 
254 /** A network device setting operation */
256  /** Setting */
257  const struct setting *setting;
258  /** Store setting (or NULL if not supported)
259  *
260  * @v netdev Network device
261  * @v data Setting data, or NULL to clear setting
262  * @v len Length of setting data
263  * @ret rc Return status code
264  */
265  int ( * store ) ( struct net_device *netdev, const void *data,
266  size_t len );
267  /** Fetch setting
268  *
269  * @v netdev Network device
270  * @v data Buffer to fill with setting data
271  * @v len Length of buffer
272  * @ret len Length of setting data, or negative error
273  */
274  int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
275 };
276 
277 /** Network device settings */
279  { &mac_setting, netdev_store_mac, netdev_fetch_mac },
280  { &hwaddr_setting, NULL, netdev_fetch_hwaddr },
281  { &bustype_setting, NULL, netdev_fetch_bustype },
282  { &busloc_setting, NULL, netdev_fetch_busloc },
283  { &busid_setting, NULL, netdev_fetch_busid },
284  { &chip_setting, NULL, netdev_fetch_chip },
285  { &ifname_setting, NULL, netdev_fetch_ifname },
286 };
287 
288 /**
289  * Store value of network device setting
290  *
291  * @v settings Settings block
292  * @v setting Setting to store
293  * @v data Setting data, or NULL to clear setting
294  * @v len Length of setting data
295  * @ret rc Return status code
296  */
297 static int netdev_store ( struct settings *settings,
298  const struct setting *setting,
299  const void *data, size_t len ) {
300  struct net_device *netdev = container_of ( settings, struct net_device,
301  settings.settings );
303  unsigned int i;
304 
305  /* Handle network device-specific settings */
306  for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
307  sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
309  if ( setting_cmp ( setting, op->setting ) == 0 ) {
310  if ( op->store ) {
311  return op->store ( netdev, data, len );
312  } else {
313  return -ENOTSUP;
314  }
315  }
316  }
317 
319 }
320 
321 /**
322  * Fetch value of network device setting
323  *
324  * @v settings Settings block
325  * @v setting Setting to fetch
326  * @v data Buffer to fill with setting data
327  * @v len Length of buffer
328  * @ret len Length of setting data, or negative error
329  */
330 static int netdev_fetch ( struct settings *settings, struct setting *setting,
331  void *data, size_t len ) {
332  struct net_device *netdev = container_of ( settings, struct net_device,
333  settings.settings );
335  unsigned int i;
336 
337  /* Handle network device-specific settings */
338  for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
339  sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
341  if ( setting_cmp ( setting, op->setting ) == 0 )
342  return op->fetch ( netdev, data, len );
343  }
344 
346 }
347 
348 /**
349  * Clear network device settings
350  *
351  * @v settings Settings block
352  */
353 static void netdev_clear ( struct settings *settings ) {
355 }
356 
357 /** Network device configuration settings operations */
359  .store = netdev_store,
360  .fetch = netdev_fetch,
361  .clear = netdev_clear,
362 };
363 
364 /**
365  * Redirect "netX" settings block
366  *
367  * @v settings Settings block
368  * @ret settings Underlying settings block
369  */
370 static struct settings * netdev_redirect ( struct settings *settings ) {
371  struct net_device *netdev;
372 
373  /* Redirect to most recently opened network device */
375  if ( netdev ) {
376  return netdev_settings ( netdev );
377  } else {
378  return settings;
379  }
380 }
381 
382 /** "netX" settings operations */
385 };
386 
387 /** "netX" settings */
389  .refcnt = NULL,
393 };
394 
395 /** Initialise "netX" settings */
396 static void netdev_redirect_settings_init ( void ) {
397  int rc;
398 
400  "netX" ) ) != 0 ) {
401  DBG ( "Could not register netX settings: %s\n",
402  strerror ( rc ) );
403  return;
404  }
405 }
406 
407 /** "netX" settings initialiser */
408 struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
410 };
411 
412 /**
413  * Apply network device settings
414  *
415  * @ret rc Return status code
416  */
417 static int apply_netdev_settings ( void ) {
418  struct net_device *netdev;
419  struct settings *settings;
420  struct ll_protocol *ll_protocol;
421  size_t max_mtu;
422  size_t old_mtu;
423  size_t mtu;
424  int rc;
425 
426  /* Process settings for each network device */
427  for_each_netdev ( netdev ) {
428 
429  /* Get network device settings */
431 
432  /* Get MTU */
433  mtu = fetch_uintz_setting ( settings, &mtu_setting );
434 
435  /* Do nothing unless MTU is specified */
436  if ( ! mtu )
437  continue;
438 
439  /* Limit MTU to maximum supported by hardware */
441  max_mtu = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
442  if ( mtu > max_mtu ) {
443  DBGC ( netdev, "NETDEV %s cannot support MTU %zd (max "
444  "%zd)\n", netdev->name, mtu, max_mtu );
445  mtu = max_mtu;
446  }
447 
448  /* Update maximum packet length */
449  old_mtu = netdev->mtu;
450  netdev->mtu = mtu;
451  if ( mtu != old_mtu ) {
452  DBGC ( netdev, "NETDEV %s MTU is %zd\n",
453  netdev->name, mtu );
454  }
455 
456  /* Close and reopen network device if MTU has increased */
457  if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
458  netdev_close ( netdev );
459  if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
460  DBGC ( netdev, "NETDEV %s could not reopen: "
461  "%s\n", netdev->name, strerror ( rc ) );
462  return rc;
463  }
464  }
465  }
466 
467  return 0;
468 }
469 
470 /** Network device settings applicator */
471 struct settings_applicator netdev_applicator __settings_applicator = {
473 };
static int netdev_fetch_mac(struct net_device *netdev, void *data, size_t len)
Fetch link-layer address setting.
#define EINVAL
Invalid argument.
Definition: errno.h:428
static struct settings netdev_redirect_settings
"netX" settings
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
Dynamic Host Configuration Protocol.
int(* fetch)(struct net_device *netdev, void *data, size_t len)
Fetch setting.
uint8_t ll_header_len
Link-layer header length.
Definition: netdevice.h:200
uint8_t type
Bus type ID.
Definition: dhcp.h:426
static struct netdev_setting_operation netdev_setting_operations[]
Network device settings.
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:198
static struct settings * netdev_redirect(struct settings *settings)
Redirect "netX" settings block.
void(* initialise)(void)
Definition: init.h:15
static struct settings_operations netdev_redirect_settings_operations
"netX" settings operations
const struct setting * setting
Setting.
static void size_t size_t max_len
Definition: entropy.h:153
Error codes.
const struct setting mac_setting __setting(SETTING_NETDEV, mac)
Network device predefined settings.
size_t mtu
Maximum transmission unit length.
Definition: netdevice.h:409
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
A settings applicator.
Definition: settings.h:251
void generic_settings_clear(struct settings *settings)
Clear generic settings block.
Definition: settings.c:207
static int apply_netdev_settings(void)
Apply network device settings.
int generic_settings_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of generic setting.
Definition: settings.c:178
uint8_t mac[ETH_ALEN]
MAC address.
Definition: ena.h:24
unsigned int vendor
Vendor ID.
Definition: device.h:31
void(* init_addr)(const void *hw_addr, void *ll_addr)
Initialise link-layer address.
Definition: netdevice.h:150
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:577
A link-layer protocol.
Definition: netdevice.h:114
static void netdev_clear(struct settings *settings)
Clear network device settings.
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
A hardware device description.
Definition: device.h:19
#define BUS_TYPE_MCA
MCA bus type.
Definition: device.h:52
const char * name
Name.
Definition: settings.h:28
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition: string.c:317
static int netdev_fetch_chip(struct net_device *netdev, void *data, size_t len)
Fetch chip setting.
#define BUS_TYPE_ISA
ISA bus type.
Definition: device.h:55
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define SETTING_NETDEV
Network device settings.
Definition: settings.h:63
static int netdev_fetch_busid(struct net_device *netdev, void *data, size_t len)
Fetch bus ID setting.
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:652
An initialisation function.
Definition: init.h:14
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
uint8_t hw_addr_len
Hardware address length.
Definition: netdevice.h:196
static struct net_device * netdev
Definition: gdbudp.c:52
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition: netdevice.c:973
const char * driver_name
Driver name.
Definition: device.h:77
unsigned int location
Location.
Definition: device.h:29
static int netdev_store(struct settings *settings, const struct setting *setting, const void *data, size_t len)
Store value of network device setting.
#define DHCP_MTU
Maximum transmission unit.
Definition: dhcp.h:87
struct settings_applicator netdev_applicator __settings_applicator
Network device settings applicator.
Configuration settings.
struct settings *(* redirect)(struct settings *settings)
Redirect to underlying settings block (if applicable)
Definition: settings.h:91
#define BUS_TYPE_EISA
EISA bus type.
Definition: device.h:49
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
A network device setting operation.
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:526
uint16_t device
Device ID.
Definition: dhcp.h:430
A network device.
Definition: netdevice.h:348
Network device descriptor.
Definition: dhcp.h:424
size_t strlen(const char *src)
Get length of string.
Definition: string.c:213
Settings block operations.
Definition: settings.h:85
A settings block.
Definition: settings.h:132
unsigned long fetch_uintz_setting(struct settings *settings, const struct setting *setting)
Fetch value of unsigned integer setting, or zero.
Definition: settings.c:1072
static int netdev_fetch_hwaddr(struct net_device *netdev, void *data, size_t len)
Fetch hardware address setting.
#define BUS_TYPE_EFI
EFI bus type.
Definition: device.h:61
unsigned int uint32_t
Definition: stdint.h:12
DHCP options.
struct list_head siblings
Sibling settings blocks.
Definition: settings.h:140
A setting.
Definition: settings.h:23
struct device * dev
Underlying hardware device.
Definition: netdevice.h:360
void netdev_close(struct net_device *netdev)
Close network device.
Definition: netdevice.c:801
Network device management.
#define BUS_TYPE_TAP
TAP bus type.
Definition: device.h:58
#define cpu_to_be32(value)
Definition: byteswap.h:110
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
unsigned int bus_type
Bus type.
Definition: device.h:24
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:358
uint32_t len
Length.
Definition: ena.h:14
static int netdev_fetch_bustype(struct net_device *netdev, void *data, size_t len)
Fetch bus type setting.
struct settings_operations netdev_settings_operations
Network device configuration settings operations.
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:126
unsigned int device
Device ID.
Definition: device.h:33
uint32_t mtu
Maximum MTU.
Definition: ena.h:28
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int netdev_fetch_ifname(struct net_device *netdev, void *data, size_t len)
Fetch ifname setting.
struct device_description desc
Device description.
Definition: device.h:79
static void netdev_redirect_settings_init(void)
Initialise "netX" settings.
int(* apply)(void)
Apply updated settings.
Definition: settings.h:256
Device model.
struct init_fn netdev_redirect_settings_init_fn __init_fn(INIT_LATE)
"netX" settings initialiser
struct list_head children
Child settings blocks.
Definition: settings.h:142
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition: settings.c:478
static int netdev_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of network device setting.
uint16_t vendor
Vendor ID.
Definition: dhcp.h:428
struct arbelprm_port_state_change_st data
Message.
Definition: arbel.h:12
#define BUS_TYPE_XEN
Xen bus type.
Definition: device.h:64
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
size_t max_pkt_len
Maximum packet length.
Definition: netdevice.h:403
#define INIT_LATE
Late initialisation.
Definition: init.h:31
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
#define BUS_TYPE_USB
USB bus type.
Definition: device.h:70
struct generic_settings settings
Configuration settings applicable to this device.
Definition: netdevice.h:422
static int netdev_store_mac(struct net_device *netdev, const void *data, size_t len)
Store link-layer address setting.
int(* store)(struct net_device *netdev, const void *data, size_t len)
Store setting (or NULL if not supported)
int(* store)(struct settings *settings, const struct setting *setting, const void *data, size_t len)
Store value of setting.
Definition: settings.h:108
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition: settings.c:1124
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:375
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
String functions.
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:767
#define htons(value)
Definition: byteswap.h:135
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:366
struct refcnt * refcnt
Reference counter.
Definition: settings.h:134
static int netdev_fetch_busloc(struct net_device *netdev, void *data, size_t len)
Fetch bus location setting.
#define BUS_TYPE_HV
Hyper-V bus type.
Definition: device.h:67
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition: device.h:46