You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

netdev_settings.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <byteswap.h>
  27. #include <ipxe/dhcp.h>
  28. #include <ipxe/dhcpopts.h>
  29. #include <ipxe/settings.h>
  30. #include <ipxe/device.h>
  31. #include <ipxe/netdevice.h>
  32. #include <ipxe/init.h>
  33. /** @file
  34. *
  35. * Network device configuration settings
  36. *
  37. */
  38. /** Network device predefined settings */
  39. const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
  40. .name = "mac",
  41. .description = "MAC address",
  42. .type = &setting_type_hex,
  43. };
  44. const struct setting hwaddr_setting __setting ( SETTING_NETDEV, hwaddr ) = {
  45. .name = "hwaddr",
  46. .description = "Hardware address",
  47. .type = &setting_type_hex,
  48. };
  49. const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
  50. .name = "bustype",
  51. .description = "Bus type",
  52. .type = &setting_type_string,
  53. };
  54. const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
  55. .name = "busloc",
  56. .description = "Bus location",
  57. .type = &setting_type_uint32,
  58. };
  59. const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
  60. .name = "busid",
  61. .description = "Bus ID",
  62. .type = &setting_type_hex,
  63. };
  64. const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
  65. .name = "chip",
  66. .description = "Chip",
  67. .type = &setting_type_string,
  68. };
  69. const struct setting ifname_setting __setting ( SETTING_NETDEV, ifname ) = {
  70. .name = "ifname",
  71. .description = "Interface name",
  72. .type = &setting_type_string,
  73. };
  74. const struct setting mtu_setting __setting ( SETTING_NETDEV, mtu ) = {
  75. .name = "mtu",
  76. .description = "MTU",
  77. .type = &setting_type_int16,
  78. .tag = DHCP_MTU,
  79. };
  80. /**
  81. * Store link-layer address setting
  82. *
  83. * @v netdev Network device
  84. * @v data Setting data, or NULL to clear setting
  85. * @v len Length of setting data
  86. * @ret rc Return status code
  87. */
  88. static int netdev_store_mac ( struct net_device *netdev,
  89. const void *data, size_t len ) {
  90. struct ll_protocol *ll_protocol = netdev->ll_protocol;
  91. /* Record new MAC address */
  92. if ( data ) {
  93. if ( len != netdev->ll_protocol->ll_addr_len )
  94. return -EINVAL;
  95. memcpy ( netdev->ll_addr, data, len );
  96. } else {
  97. /* Reset MAC address if clearing setting */
  98. ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
  99. }
  100. return 0;
  101. }
  102. /**
  103. * Fetch link-layer address setting
  104. *
  105. * @v netdev Network device
  106. * @v data Buffer to fill with setting data
  107. * @v len Length of buffer
  108. * @ret len Length of setting data, or negative error
  109. */
  110. static int netdev_fetch_mac ( struct net_device *netdev, void *data,
  111. size_t len ) {
  112. size_t max_len = netdev->ll_protocol->ll_addr_len;
  113. if ( len > max_len )
  114. len = max_len;
  115. memcpy ( data, netdev->ll_addr, len );
  116. return max_len;
  117. }
  118. /**
  119. * Fetch hardware address setting
  120. *
  121. * @v netdev Network device
  122. * @v data Buffer to fill with setting data
  123. * @v len Length of buffer
  124. * @ret len Length of setting data, or negative error
  125. */
  126. static int netdev_fetch_hwaddr ( struct net_device *netdev, void *data,
  127. size_t len ) {
  128. size_t max_len = netdev->ll_protocol->hw_addr_len;
  129. if ( len > max_len )
  130. len = max_len;
  131. memcpy ( data, netdev->hw_addr, len );
  132. return max_len;
  133. }
  134. /**
  135. * Fetch bus type 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. */
  142. static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
  143. size_t len ) {
  144. static const char *bustypes[] = {
  145. [BUS_TYPE_PCI] = "PCI",
  146. [BUS_TYPE_ISAPNP] = "ISAPNP",
  147. [BUS_TYPE_EISA] = "EISA",
  148. [BUS_TYPE_MCA] = "MCA",
  149. [BUS_TYPE_ISA] = "ISA",
  150. [BUS_TYPE_TAP] = "TAP",
  151. [BUS_TYPE_EFI] = "EFI",
  152. [BUS_TYPE_XEN] = "XEN",
  153. [BUS_TYPE_HV] = "HV",
  154. [BUS_TYPE_USB] = "USB",
  155. };
  156. struct device_description *desc = &netdev->dev->desc;
  157. const char *bustype;
  158. assert ( desc->bus_type < ( sizeof ( bustypes ) /
  159. sizeof ( bustypes[0] ) ) );
  160. bustype = bustypes[desc->bus_type];
  161. if ( ! bustype )
  162. return -ENOENT;
  163. strncpy ( data, bustype, len );
  164. return strlen ( bustype );
  165. }
  166. /**
  167. * Fetch bus location setting
  168. *
  169. * @v netdev Network device
  170. * @v data Buffer to fill with setting data
  171. * @v len Length of buffer
  172. * @ret len Length of setting data, or negative error
  173. */
  174. static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
  175. size_t len ) {
  176. struct device_description *desc = &netdev->dev->desc;
  177. uint32_t busloc;
  178. busloc = cpu_to_be32 ( desc->location );
  179. if ( len > sizeof ( busloc ) )
  180. len = sizeof ( busloc );
  181. memcpy ( data, &busloc, len );
  182. return sizeof ( busloc );
  183. }
  184. /**
  185. * Fetch bus ID setting
  186. *
  187. * @v netdev Network device
  188. * @v data Buffer to fill with setting data
  189. * @v len Length of buffer
  190. * @ret len Length of setting data, or negative error
  191. */
  192. static int netdev_fetch_busid ( struct net_device *netdev, void *data,
  193. size_t len ) {
  194. struct device_description *desc = &netdev->dev->desc;
  195. struct dhcp_netdev_desc dhcp_desc;
  196. dhcp_desc.type = desc->bus_type;
  197. dhcp_desc.vendor = htons ( desc->vendor );
  198. dhcp_desc.device = htons ( desc->device );
  199. if ( len > sizeof ( dhcp_desc ) )
  200. len = sizeof ( dhcp_desc );
  201. memcpy ( data, &dhcp_desc, len );
  202. return sizeof ( dhcp_desc );
  203. }
  204. /**
  205. * Fetch chip setting
  206. *
  207. * @v netdev Network device
  208. * @v data Buffer to fill with setting data
  209. * @v len Length of buffer
  210. * @ret len Length of setting data, or negative error
  211. */
  212. static int netdev_fetch_chip ( struct net_device *netdev, void *data,
  213. size_t len ) {
  214. const char *chip = netdev->dev->driver_name;
  215. strncpy ( data, chip, len );
  216. return strlen ( chip );
  217. }
  218. /**
  219. * Fetch ifname setting
  220. *
  221. * @v netdev Network device
  222. * @v data Buffer to fill with setting data
  223. * @v len Length of buffer
  224. * @ret len Length of setting data, or negative error
  225. */
  226. static int netdev_fetch_ifname ( struct net_device *netdev, void *data,
  227. size_t len ) {
  228. const char *ifname = netdev->name;
  229. strncpy ( data, ifname, len );
  230. return strlen ( ifname );
  231. }
  232. /** A network device setting operation */
  233. struct netdev_setting_operation {
  234. /** Setting */
  235. const struct setting *setting;
  236. /** Store setting (or NULL if not supported)
  237. *
  238. * @v netdev Network device
  239. * @v data Setting data, or NULL to clear setting
  240. * @v len Length of setting data
  241. * @ret rc Return status code
  242. */
  243. int ( * store ) ( struct net_device *netdev, const void *data,
  244. size_t len );
  245. /** Fetch setting
  246. *
  247. * @v netdev Network device
  248. * @v data Buffer to fill with setting data
  249. * @v len Length of buffer
  250. * @ret len Length of setting data, or negative error
  251. */
  252. int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
  253. };
  254. /** Network device settings */
  255. static struct netdev_setting_operation netdev_setting_operations[] = {
  256. { &mac_setting, netdev_store_mac, netdev_fetch_mac },
  257. { &hwaddr_setting, NULL, netdev_fetch_hwaddr },
  258. { &bustype_setting, NULL, netdev_fetch_bustype },
  259. { &busloc_setting, NULL, netdev_fetch_busloc },
  260. { &busid_setting, NULL, netdev_fetch_busid },
  261. { &chip_setting, NULL, netdev_fetch_chip },
  262. { &ifname_setting, NULL, netdev_fetch_ifname },
  263. };
  264. /**
  265. * Store value of network device setting
  266. *
  267. * @v settings Settings block
  268. * @v setting Setting to store
  269. * @v data Setting data, or NULL to clear setting
  270. * @v len Length of setting data
  271. * @ret rc Return status code
  272. */
  273. static int netdev_store ( struct settings *settings,
  274. const struct setting *setting,
  275. const void *data, size_t len ) {
  276. struct net_device *netdev = container_of ( settings, struct net_device,
  277. settings.settings );
  278. struct netdev_setting_operation *op;
  279. unsigned int i;
  280. /* Handle network device-specific settings */
  281. for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
  282. sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
  283. op = &netdev_setting_operations[i];
  284. if ( setting_cmp ( setting, op->setting ) == 0 ) {
  285. if ( op->store ) {
  286. return op->store ( netdev, data, len );
  287. } else {
  288. return -ENOTSUP;
  289. }
  290. }
  291. }
  292. return generic_settings_store ( settings, setting, data, len );
  293. }
  294. /**
  295. * Fetch value of network device setting
  296. *
  297. * @v settings Settings block
  298. * @v setting Setting to fetch
  299. * @v data Buffer to fill with setting data
  300. * @v len Length of buffer
  301. * @ret len Length of setting data, or negative error
  302. */
  303. static int netdev_fetch ( struct settings *settings, struct setting *setting,
  304. void *data, size_t len ) {
  305. struct net_device *netdev = container_of ( settings, struct net_device,
  306. settings.settings );
  307. struct netdev_setting_operation *op;
  308. unsigned int i;
  309. /* Handle network device-specific settings */
  310. for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
  311. sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
  312. op = &netdev_setting_operations[i];
  313. if ( setting_cmp ( setting, op->setting ) == 0 )
  314. return op->fetch ( netdev, data, len );
  315. }
  316. return generic_settings_fetch ( settings, setting, data, len );
  317. }
  318. /**
  319. * Clear network device settings
  320. *
  321. * @v settings Settings block
  322. */
  323. static void netdev_clear ( struct settings *settings ) {
  324. generic_settings_clear ( settings );
  325. }
  326. /** Network device configuration settings operations */
  327. struct settings_operations netdev_settings_operations = {
  328. .store = netdev_store,
  329. .fetch = netdev_fetch,
  330. .clear = netdev_clear,
  331. };
  332. /**
  333. * Redirect "netX" settings block
  334. *
  335. * @v settings Settings block
  336. * @ret settings Underlying settings block
  337. */
  338. static struct settings * netdev_redirect ( struct settings *settings ) {
  339. struct net_device *netdev;
  340. /* Redirect to most recently opened network device */
  341. netdev = last_opened_netdev();
  342. if ( netdev ) {
  343. return netdev_settings ( netdev );
  344. } else {
  345. return settings;
  346. }
  347. }
  348. /** "netX" settings operations */
  349. static struct settings_operations netdev_redirect_settings_operations = {
  350. .redirect = netdev_redirect,
  351. };
  352. /** "netX" settings */
  353. static struct settings netdev_redirect_settings = {
  354. .refcnt = NULL,
  355. .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
  356. .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
  357. .op = &netdev_redirect_settings_operations,
  358. };
  359. /** Initialise "netX" settings */
  360. static void netdev_redirect_settings_init ( void ) {
  361. int rc;
  362. if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
  363. "netX" ) ) != 0 ) {
  364. DBG ( "Could not register netX settings: %s\n",
  365. strerror ( rc ) );
  366. return;
  367. }
  368. }
  369. /** "netX" settings initialiser */
  370. struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
  371. .initialise = netdev_redirect_settings_init,
  372. };
  373. /**
  374. * Apply network device settings
  375. *
  376. * @ret rc Return status code
  377. */
  378. static int apply_netdev_settings ( void ) {
  379. struct net_device *netdev;
  380. struct settings *settings;
  381. struct ll_protocol *ll_protocol;
  382. size_t max_mtu;
  383. size_t old_mtu;
  384. size_t mtu;
  385. int rc;
  386. /* Process settings for each network device */
  387. for_each_netdev ( netdev ) {
  388. /* Get network device settings */
  389. settings = netdev_settings ( netdev );
  390. /* Get MTU */
  391. mtu = fetch_uintz_setting ( settings, &mtu_setting );
  392. /* Do nothing unless MTU is specified */
  393. if ( ! mtu )
  394. continue;
  395. /* Limit MTU to maximum supported by hardware */
  396. ll_protocol = netdev->ll_protocol;
  397. max_mtu = ( netdev->max_pkt_len - ll_protocol->ll_header_len );
  398. if ( mtu > max_mtu ) {
  399. DBGC ( netdev, "NETDEV %s cannot support MTU %zd (max "
  400. "%zd)\n", netdev->name, mtu, max_mtu );
  401. mtu = max_mtu;
  402. }
  403. /* Update maximum packet length */
  404. old_mtu = netdev->mtu;
  405. netdev->mtu = mtu;
  406. if ( mtu != old_mtu ) {
  407. DBGC ( netdev, "NETDEV %s MTU is %zd\n",
  408. netdev->name, mtu );
  409. }
  410. /* Close and reopen network device if MTU has increased */
  411. if ( netdev_is_open ( netdev ) && ( mtu > old_mtu ) ) {
  412. netdev_close ( netdev );
  413. if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
  414. DBGC ( netdev, "NETDEV %s could not reopen: "
  415. "%s\n", netdev->name, strerror ( rc ) );
  416. return rc;
  417. }
  418. }
  419. }
  420. return 0;
  421. }
  422. /** Network device settings applicator */
  423. struct settings_applicator netdev_applicator __settings_applicator = {
  424. .apply = apply_netdev_settings,
  425. };