Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

netdevice.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Copyright (C) 2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stdint.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <byteswap.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <gpxe/if_ether.h>
  26. #include <gpxe/iobuf.h>
  27. #include <gpxe/tables.h>
  28. #include <gpxe/process.h>
  29. #include <gpxe/init.h>
  30. #include <gpxe/device.h>
  31. #include <gpxe/errortab.h>
  32. #include <gpxe/netdevice.h>
  33. /** @file
  34. *
  35. * Network device management
  36. *
  37. */
  38. /** List of network devices */
  39. struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
  40. /** List of open network devices, in reverse order of opening */
  41. static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
  42. /** Default link status code */
  43. #define EUNKNOWN_LINK_STATUS EINPROGRESS
  44. /** Human-readable message for the default link status */
  45. struct errortab netdev_errors[] __errortab = {
  46. { EUNKNOWN_LINK_STATUS, "Unknown" },
  47. };
  48. /**
  49. * Mark network device as having link down
  50. *
  51. * @v netdev Network device
  52. */
  53. void netdev_link_down ( struct net_device *netdev ) {
  54. switch ( netdev->link_rc ) {
  55. case 0:
  56. case -EUNKNOWN_LINK_STATUS:
  57. netdev->link_rc = -ENOTCONN;
  58. break;
  59. default:
  60. /* Avoid clobbering a more detailed link status code,
  61. * if one is already set.
  62. */
  63. break;
  64. }
  65. }
  66. /**
  67. * Record network device statistic
  68. *
  69. * @v stats Network device statistics
  70. * @v rc Status code
  71. */
  72. static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
  73. struct net_device_error *error;
  74. struct net_device_error *least_common_error;
  75. unsigned int i;
  76. /* If this is not an error, just update the good counter */
  77. if ( rc == 0 ) {
  78. stats->good++;
  79. return;
  80. }
  81. /* Update the bad counter */
  82. stats->bad++;
  83. /* Locate the appropriate error record */
  84. least_common_error = &stats->errors[0];
  85. for ( i = 0 ; i < ( sizeof ( stats->errors ) /
  86. sizeof ( stats->errors[0] ) ) ; i++ ) {
  87. error = &stats->errors[i];
  88. /* Update matching record, if found */
  89. if ( error->rc == rc ) {
  90. error->count++;
  91. return;
  92. }
  93. if ( error->count < least_common_error->count )
  94. least_common_error = error;
  95. }
  96. /* Overwrite the least common error record */
  97. least_common_error->rc = rc;
  98. least_common_error->count = 1;
  99. }
  100. /**
  101. * Transmit raw packet via network device
  102. *
  103. * @v netdev Network device
  104. * @v iobuf I/O buffer
  105. * @ret rc Return status code
  106. *
  107. * Transmits the packet via the specified network device. This
  108. * function takes ownership of the I/O buffer.
  109. */
  110. int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
  111. int rc;
  112. DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
  113. netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
  114. list_add_tail ( &iobuf->list, &netdev->tx_queue );
  115. if ( ! ( netdev->state & NETDEV_OPEN ) ) {
  116. rc = -ENETUNREACH;
  117. goto err;
  118. }
  119. if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
  120. goto err;
  121. return 0;
  122. err:
  123. netdev_tx_complete_err ( netdev, iobuf, rc );
  124. return rc;
  125. }
  126. /**
  127. * Complete network transmission
  128. *
  129. * @v netdev Network device
  130. * @v iobuf I/O buffer
  131. * @v rc Packet status code
  132. *
  133. * The packet must currently be in the network device's TX queue.
  134. */
  135. void netdev_tx_complete_err ( struct net_device *netdev,
  136. struct io_buffer *iobuf, int rc ) {
  137. /* Update statistics counter */
  138. netdev_record_stat ( &netdev->tx_stats, rc );
  139. if ( rc == 0 ) {
  140. DBGC ( netdev, "NETDEV %p transmission %p complete\n",
  141. netdev, iobuf );
  142. } else {
  143. DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
  144. netdev, iobuf, strerror ( rc ) );
  145. }
  146. /* Catch data corruption as early as possible */
  147. assert ( iobuf->list.next != NULL );
  148. assert ( iobuf->list.prev != NULL );
  149. /* Dequeue and free I/O buffer */
  150. list_del ( &iobuf->list );
  151. free_iob ( iobuf );
  152. }
  153. /**
  154. * Complete network transmission
  155. *
  156. * @v netdev Network device
  157. * @v rc Packet status code
  158. *
  159. * Completes the oldest outstanding packet in the TX queue.
  160. */
  161. void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
  162. struct io_buffer *iobuf;
  163. list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
  164. netdev_tx_complete_err ( netdev, iobuf, rc );
  165. return;
  166. }
  167. }
  168. /**
  169. * Flush device's transmit queue
  170. *
  171. * @v netdev Network device
  172. */
  173. static void netdev_tx_flush ( struct net_device *netdev ) {
  174. /* Discard any packets in the TX queue */
  175. while ( ! list_empty ( &netdev->tx_queue ) ) {
  176. netdev_tx_complete_next_err ( netdev, -ECANCELED );
  177. }
  178. }
  179. /**
  180. * Add packet to receive queue
  181. *
  182. * @v netdev Network device
  183. * @v iobuf I/O buffer, or NULL
  184. *
  185. * The packet is added to the network device's RX queue. This
  186. * function takes ownership of the I/O buffer.
  187. */
  188. void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
  189. DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
  190. netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
  191. /* Enqueue packet */
  192. list_add_tail ( &iobuf->list, &netdev->rx_queue );
  193. /* Update statistics counter */
  194. netdev_record_stat ( &netdev->rx_stats, 0 );
  195. }
  196. /**
  197. * Discard received packet
  198. *
  199. * @v netdev Network device
  200. * @v iobuf I/O buffer, or NULL
  201. * @v rc Packet status code
  202. *
  203. * The packet is discarded and an RX error is recorded. This function
  204. * takes ownership of the I/O buffer. @c iobuf may be NULL if, for
  205. * example, the net device wishes to report an error due to being
  206. * unable to allocate an I/O buffer.
  207. */
  208. void netdev_rx_err ( struct net_device *netdev,
  209. struct io_buffer *iobuf, int rc ) {
  210. DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
  211. netdev, iobuf, strerror ( rc ) );
  212. /* Discard packet */
  213. free_iob ( iobuf );
  214. /* Update statistics counter */
  215. netdev_record_stat ( &netdev->rx_stats, rc );
  216. }
  217. /**
  218. * Poll for completed and received packets on network device
  219. *
  220. * @v netdev Network device
  221. *
  222. * Polls the network device for completed transmissions and received
  223. * packets. Any received packets will be added to the RX packet queue
  224. * via netdev_rx().
  225. */
  226. void netdev_poll ( struct net_device *netdev ) {
  227. if ( netdev->state & NETDEV_OPEN )
  228. netdev->op->poll ( netdev );
  229. }
  230. /**
  231. * Remove packet from device's receive queue
  232. *
  233. * @v netdev Network device
  234. * @ret iobuf I/O buffer, or NULL
  235. *
  236. * Removes the first packet from the device's RX queue and returns it.
  237. * Ownership of the packet is transferred to the caller.
  238. */
  239. struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
  240. struct io_buffer *iobuf;
  241. list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
  242. list_del ( &iobuf->list );
  243. return iobuf;
  244. }
  245. return NULL;
  246. }
  247. /**
  248. * Flush device's receive queue
  249. *
  250. * @v netdev Network device
  251. */
  252. static void netdev_rx_flush ( struct net_device *netdev ) {
  253. struct io_buffer *iobuf;
  254. /* Discard any packets in the RX queue */
  255. while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
  256. netdev_rx_err ( netdev, iobuf, -ECANCELED );
  257. }
  258. }
  259. /**
  260. * Free network device
  261. *
  262. * @v refcnt Network device reference counter
  263. */
  264. static void free_netdev ( struct refcnt *refcnt ) {
  265. struct net_device *netdev =
  266. container_of ( refcnt, struct net_device, refcnt );
  267. netdev_tx_flush ( netdev );
  268. netdev_rx_flush ( netdev );
  269. clear_settings ( netdev_settings ( netdev ) );
  270. free ( netdev );
  271. }
  272. /**
  273. * Allocate network device
  274. *
  275. * @v priv_size Size of private data area (net_device::priv)
  276. * @ret netdev Network device, or NULL
  277. *
  278. * Allocates space for a network device and its private data area.
  279. */
  280. struct net_device * alloc_netdev ( size_t priv_size ) {
  281. struct net_device *netdev;
  282. size_t total_len;
  283. total_len = ( sizeof ( *netdev ) + priv_size );
  284. netdev = zalloc ( total_len );
  285. if ( netdev ) {
  286. netdev->refcnt.free = free_netdev;
  287. netdev->link_rc = -EUNKNOWN_LINK_STATUS;
  288. INIT_LIST_HEAD ( &netdev->tx_queue );
  289. INIT_LIST_HEAD ( &netdev->rx_queue );
  290. netdev_settings_init ( netdev );
  291. netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
  292. }
  293. return netdev;
  294. }
  295. /**
  296. * Register network device
  297. *
  298. * @v netdev Network device
  299. * @ret rc Return status code
  300. *
  301. * Gives the network device a name and adds it to the list of network
  302. * devices.
  303. */
  304. int register_netdev ( struct net_device *netdev ) {
  305. static unsigned int ifindex = 0;
  306. int rc;
  307. /* Create device name */
  308. snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
  309. ifindex++ );
  310. /* Set initial link-layer address */
  311. netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
  312. /* Register per-netdev configuration settings */
  313. if ( ( rc = register_settings ( netdev_settings ( netdev ),
  314. NULL ) ) != 0 ) {
  315. DBGC ( netdev, "NETDEV %p could not register settings: %s\n",
  316. netdev, strerror ( rc ) );
  317. return rc;
  318. }
  319. /* Add to device list */
  320. netdev_get ( netdev );
  321. list_add_tail ( &netdev->list, &net_devices );
  322. DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
  323. netdev, netdev->name, netdev->dev->name,
  324. netdev_addr ( netdev ) );
  325. return 0;
  326. }
  327. /**
  328. * Open network device
  329. *
  330. * @v netdev Network device
  331. * @ret rc Return status code
  332. */
  333. int netdev_open ( struct net_device *netdev ) {
  334. int rc;
  335. /* Do nothing if device is already open */
  336. if ( netdev->state & NETDEV_OPEN )
  337. return 0;
  338. DBGC ( netdev, "NETDEV %p opening\n", netdev );
  339. /* Open the device */
  340. if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
  341. return rc;
  342. /* Mark as opened */
  343. netdev->state |= NETDEV_OPEN;
  344. /* Add to head of open devices list */
  345. list_add ( &netdev->open_list, &open_net_devices );
  346. return 0;
  347. }
  348. /**
  349. * Close network device
  350. *
  351. * @v netdev Network device
  352. */
  353. void netdev_close ( struct net_device *netdev ) {
  354. /* Do nothing if device is already closed */
  355. if ( ! ( netdev->state & NETDEV_OPEN ) )
  356. return;
  357. DBGC ( netdev, "NETDEV %p closing\n", netdev );
  358. /* Close the device */
  359. netdev->op->close ( netdev );
  360. /* Flush TX and RX queues */
  361. netdev_tx_flush ( netdev );
  362. netdev_rx_flush ( netdev );
  363. /* Mark as closed */
  364. netdev->state &= ~NETDEV_OPEN;
  365. /* Remove from open devices list */
  366. list_del ( &netdev->open_list );
  367. }
  368. /**
  369. * Unregister network device
  370. *
  371. * @v netdev Network device
  372. *
  373. * Removes the network device from the list of network devices.
  374. */
  375. void unregister_netdev ( struct net_device *netdev ) {
  376. /* Ensure device is closed */
  377. netdev_close ( netdev );
  378. /* Unregister per-netdev configuration settings */
  379. unregister_settings ( netdev_settings ( netdev ) );
  380. /* Remove from device list */
  381. list_del ( &netdev->list );
  382. netdev_put ( netdev );
  383. DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
  384. }
  385. /** Enable or disable interrupts
  386. *
  387. * @v netdev Network device
  388. * @v enable Interrupts should be enabled
  389. */
  390. void netdev_irq ( struct net_device *netdev, int enable ) {
  391. netdev->op->irq ( netdev, enable );
  392. }
  393. /**
  394. * Get network device by name
  395. *
  396. * @v name Network device name
  397. * @ret netdev Network device, or NULL
  398. */
  399. struct net_device * find_netdev ( const char *name ) {
  400. struct net_device *netdev;
  401. list_for_each_entry ( netdev, &net_devices, list ) {
  402. if ( strcmp ( netdev->name, name ) == 0 )
  403. return netdev;
  404. }
  405. return NULL;
  406. }
  407. /**
  408. * Get network device by PCI bus:dev.fn address
  409. *
  410. * @v bus_type Bus type
  411. * @v location Bus location
  412. * @ret netdev Network device, or NULL
  413. */
  414. struct net_device * find_netdev_by_location ( unsigned int bus_type,
  415. unsigned int location ) {
  416. struct net_device *netdev;
  417. list_for_each_entry ( netdev, &net_devices, list ) {
  418. if ( ( netdev->dev->desc.bus_type == bus_type ) &&
  419. ( netdev->dev->desc.location == location ) )
  420. return netdev;
  421. }
  422. return NULL;
  423. }
  424. /**
  425. * Get most recently opened network device
  426. *
  427. * @ret netdev Most recently opened network device, or NULL
  428. */
  429. struct net_device * last_opened_netdev ( void ) {
  430. struct net_device *netdev;
  431. list_for_each_entry ( netdev, &open_net_devices, open_list ) {
  432. assert ( netdev->state & NETDEV_OPEN );
  433. return netdev;
  434. }
  435. return NULL;
  436. }
  437. /**
  438. * Transmit network-layer packet
  439. *
  440. * @v iobuf I/O buffer
  441. * @v netdev Network device
  442. * @v net_protocol Network-layer protocol
  443. * @v ll_dest Destination link-layer address
  444. * @ret rc Return status code
  445. *
  446. * Prepends link-layer headers to the I/O buffer and transmits the
  447. * packet via the specified network device. This function takes
  448. * ownership of the I/O buffer.
  449. */
  450. int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
  451. struct net_protocol *net_protocol, const void *ll_dest ) {
  452. struct ll_protocol *ll_protocol = netdev->ll_protocol;
  453. int rc;
  454. /* Force a poll on the netdevice to (potentially) clear any
  455. * backed-up TX completions. This is needed on some network
  456. * devices to avoid excessive losses due to small TX ring
  457. * sizes.
  458. */
  459. netdev_poll ( netdev );
  460. /* Add link-layer header */
  461. if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, netdev->ll_addr,
  462. net_protocol->net_proto ) ) != 0 ) {
  463. free_iob ( iobuf );
  464. return rc;
  465. }
  466. /* Transmit packet */
  467. return netdev_tx ( netdev, iobuf );
  468. }
  469. /**
  470. * Process received network-layer packet
  471. *
  472. * @v iobuf I/O buffer
  473. * @v netdev Network device
  474. * @v net_proto Network-layer protocol, in network-byte order
  475. * @v ll_source Source link-layer address
  476. * @ret rc Return status code
  477. */
  478. int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
  479. uint16_t net_proto, const void *ll_source ) {
  480. struct net_protocol *net_protocol;
  481. /* Hand off to network-layer protocol, if any */
  482. for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
  483. if ( net_protocol->net_proto == net_proto )
  484. return net_protocol->rx ( iobuf, netdev, ll_source );
  485. }
  486. DBGC ( netdev, "NETDEV %p unknown network protocol %04x\n",
  487. netdev, ntohs ( net_proto ) );
  488. free_iob ( iobuf );
  489. return 0;
  490. }
  491. /**
  492. * Single-step the network stack
  493. *
  494. * @v process Network stack process
  495. *
  496. * This polls all interfaces for received packets, and processes
  497. * packets from the RX queue.
  498. */
  499. static void net_step ( struct process *process __unused ) {
  500. struct net_device *netdev;
  501. struct io_buffer *iobuf;
  502. struct ll_protocol *ll_protocol;
  503. const void *ll_dest;
  504. const void *ll_source;
  505. uint16_t net_proto;
  506. int rc;
  507. /* Poll and process each network device */
  508. list_for_each_entry ( netdev, &net_devices, list ) {
  509. /* Poll for new packets */
  510. netdev_poll ( netdev );
  511. /* Process at most one received packet. Give priority
  512. * to getting packets out of the NIC over processing
  513. * the received packets, because we advertise a window
  514. * that assumes that we can receive packets from the
  515. * NIC faster than they arrive.
  516. */
  517. if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
  518. DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
  519. netdev, iobuf, iobuf->data,
  520. iob_len ( iobuf ) );
  521. /* Remove link-layer header */
  522. ll_protocol = netdev->ll_protocol;
  523. if ( ( rc = ll_protocol->pull ( netdev, iobuf,
  524. &ll_dest, &ll_source,
  525. &net_proto ) ) != 0 ) {
  526. free_iob ( iobuf );
  527. continue;
  528. }
  529. net_rx ( iobuf, netdev, net_proto, ll_source );
  530. }
  531. }
  532. }
  533. /** Networking stack process */
  534. struct process net_process __permanent_process = {
  535. .list = LIST_HEAD_INIT ( net_process.list ),
  536. .step = net_step,
  537. };