Greg Hartman | 76d05dc | 2016-11-23 15:51:27 -0800 | [diff] [blame] | 1 | #ifndef _GPXE_NETDEVICE_H |
| 2 | #define _GPXE_NETDEVICE_H |
| 3 | |
| 4 | /** @file |
| 5 | * |
| 6 | * Network device management |
| 7 | * |
| 8 | */ |
| 9 | |
| 10 | FILE_LICENCE ( GPL2_OR_LATER ); |
| 11 | |
| 12 | #include <stdint.h> |
| 13 | #include <gpxe/list.h> |
| 14 | #include <gpxe/tables.h> |
| 15 | #include <gpxe/refcnt.h> |
| 16 | #include <gpxe/settings.h> |
| 17 | |
| 18 | struct io_buffer; |
| 19 | struct net_device; |
| 20 | struct net_protocol; |
| 21 | struct ll_protocol; |
| 22 | struct device; |
| 23 | |
| 24 | /** Maximum length of a hardware address |
| 25 | * |
| 26 | * The longest currently-supported link-layer address is for IPoIB. |
| 27 | */ |
| 28 | #define MAX_HW_ADDR_LEN 8 |
| 29 | |
| 30 | /** Maximum length of a link-layer address |
| 31 | * |
| 32 | * The longest currently-supported link-layer address is for IPoIB. |
| 33 | */ |
| 34 | #define MAX_LL_ADDR_LEN 20 |
| 35 | |
| 36 | /** Maximum length of a link-layer header |
| 37 | * |
| 38 | * The longest currently-supported link-layer header is for 802.11: a |
| 39 | * 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header. (The |
| 40 | * IPoIB link-layer pseudo-header doesn't actually include link-layer |
| 41 | * addresses; see ipoib.c for details). |
| 42 | */ |
| 43 | #define MAX_LL_HEADER_LEN 32 |
| 44 | |
| 45 | /** Maximum length of a network-layer address */ |
| 46 | #define MAX_NET_ADDR_LEN 4 |
| 47 | |
| 48 | /** |
| 49 | * A network-layer protocol |
| 50 | * |
| 51 | */ |
| 52 | struct net_protocol { |
| 53 | /** Protocol name */ |
| 54 | const char *name; |
| 55 | /** |
| 56 | * Process received packet |
| 57 | * |
| 58 | * @v iobuf I/O buffer |
| 59 | * @v netdev Network device |
| 60 | * @v ll_source Link-layer source address |
| 61 | * |
| 62 | * This method takes ownership of the I/O buffer. |
| 63 | */ |
| 64 | int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev, |
| 65 | const void *ll_source ); |
| 66 | /** |
| 67 | * Transcribe network-layer address |
| 68 | * |
| 69 | * @v net_addr Network-layer address |
| 70 | * @ret string Human-readable transcription of address |
| 71 | * |
| 72 | * This method should convert the network-layer address into a |
| 73 | * human-readable format (e.g. dotted quad notation for IPv4). |
| 74 | * |
| 75 | * The buffer used to hold the transcription is statically |
| 76 | * allocated. |
| 77 | */ |
| 78 | const char * ( *ntoa ) ( const void * net_addr ); |
| 79 | /** Network-layer protocol |
| 80 | * |
| 81 | * This is an ETH_P_XXX constant, in network-byte order |
| 82 | */ |
| 83 | uint16_t net_proto; |
| 84 | /** Network-layer address length */ |
| 85 | uint8_t net_addr_len; |
| 86 | }; |
| 87 | |
| 88 | /** |
| 89 | * A link-layer protocol |
| 90 | * |
| 91 | */ |
| 92 | struct ll_protocol { |
| 93 | /** Protocol name */ |
| 94 | const char *name; |
| 95 | /** |
| 96 | * Add link-layer header |
| 97 | * |
| 98 | * @v netdev Network device |
| 99 | * @v iobuf I/O buffer |
| 100 | * @v ll_dest Link-layer destination address |
| 101 | * @v ll_source Source link-layer address |
| 102 | * @v net_proto Network-layer protocol, in network-byte order |
| 103 | * @ret rc Return status code |
| 104 | */ |
| 105 | int ( * push ) ( struct net_device *netdev, struct io_buffer *iobuf, |
| 106 | const void *ll_dest, const void *ll_source, |
| 107 | uint16_t net_proto ); |
| 108 | /** |
| 109 | * Remove link-layer header |
| 110 | * |
| 111 | * @v netdev Network device |
| 112 | * @v iobuf I/O buffer |
| 113 | * @ret ll_dest Link-layer destination address |
| 114 | * @ret ll_source Source link-layer address |
| 115 | * @ret net_proto Network-layer protocol, in network-byte order |
| 116 | * @ret rc Return status code |
| 117 | */ |
| 118 | int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf, |
| 119 | const void **ll_dest, const void **ll_source, |
| 120 | uint16_t *net_proto ); |
| 121 | /** |
| 122 | * Initialise link-layer address |
| 123 | * |
| 124 | * @v hw_addr Hardware address |
| 125 | * @v ll_addr Link-layer address to fill in |
| 126 | */ |
| 127 | void ( * init_addr ) ( const void *hw_addr, void *ll_addr ); |
| 128 | /** |
| 129 | * Transcribe link-layer address |
| 130 | * |
| 131 | * @v ll_addr Link-layer address |
| 132 | * @ret string Human-readable transcription of address |
| 133 | * |
| 134 | * This method should convert the link-layer address into a |
| 135 | * human-readable format. |
| 136 | * |
| 137 | * The buffer used to hold the transcription is statically |
| 138 | * allocated. |
| 139 | */ |
| 140 | const char * ( * ntoa ) ( const void *ll_addr ); |
| 141 | /** |
| 142 | * Hash multicast address |
| 143 | * |
| 144 | * @v af Address family |
| 145 | * @v net_addr Network-layer address |
| 146 | * @v ll_addr Link-layer address to fill in |
| 147 | * @ret rc Return status code |
| 148 | */ |
| 149 | int ( * mc_hash ) ( unsigned int af, const void *net_addr, |
| 150 | void *ll_addr ); |
| 151 | /** |
| 152 | * Generate Ethernet-compatible compressed link-layer address |
| 153 | * |
| 154 | * @v ll_addr Link-layer address |
| 155 | * @v eth_addr Ethernet-compatible address to fill in |
| 156 | */ |
| 157 | int ( * eth_addr ) ( const void *ll_addr, void *eth_addr ); |
| 158 | /** Link-layer protocol |
| 159 | * |
| 160 | * This is an ARPHRD_XXX constant, in network byte order. |
| 161 | */ |
| 162 | uint16_t ll_proto; |
| 163 | /** Hardware address length */ |
| 164 | uint8_t hw_addr_len; |
| 165 | /** Link-layer address length */ |
| 166 | uint8_t ll_addr_len; |
| 167 | /** Link-layer header length */ |
| 168 | uint8_t ll_header_len; |
| 169 | }; |
| 170 | |
| 171 | /** Network device operations */ |
| 172 | struct net_device_operations { |
| 173 | /** Open network device |
| 174 | * |
| 175 | * @v netdev Network device |
| 176 | * @ret rc Return status code |
| 177 | * |
| 178 | * This method should allocate RX I/O buffers and enable |
| 179 | * the hardware to start transmitting and receiving packets. |
| 180 | */ |
| 181 | int ( * open ) ( struct net_device *netdev ); |
| 182 | /** Close network device |
| 183 | * |
| 184 | * @v netdev Network device |
| 185 | * |
| 186 | * This method should stop the flow of packets, and free up |
| 187 | * any packets that are currently in the device's TX queue. |
| 188 | */ |
| 189 | void ( * close ) ( struct net_device *netdev ); |
| 190 | /** Transmit packet |
| 191 | * |
| 192 | * @v netdev Network device |
| 193 | * @v iobuf I/O buffer |
| 194 | * @ret rc Return status code |
| 195 | * |
| 196 | * This method should cause the hardware to initiate |
| 197 | * transmission of the I/O buffer. |
| 198 | * |
| 199 | * If this method returns success, the I/O buffer remains |
| 200 | * owned by the net device's TX queue, and the net device must |
| 201 | * eventually call netdev_tx_complete() to free the buffer. |
| 202 | * If this method returns failure, the I/O buffer is |
| 203 | * immediately released; the failure is interpreted as |
| 204 | * "failure to enqueue buffer". |
| 205 | * |
| 206 | * This method is guaranteed to be called only when the device |
| 207 | * is open. |
| 208 | */ |
| 209 | int ( * transmit ) ( struct net_device *netdev, |
| 210 | struct io_buffer *iobuf ); |
| 211 | /** Poll for completed and received packets |
| 212 | * |
| 213 | * @v netdev Network device |
| 214 | * |
| 215 | * This method should cause the hardware to check for |
| 216 | * completed transmissions and received packets. Any received |
| 217 | * packets should be delivered via netdev_rx(). |
| 218 | * |
| 219 | * This method is guaranteed to be called only when the device |
| 220 | * is open. |
| 221 | */ |
| 222 | void ( * poll ) ( struct net_device *netdev ); |
| 223 | /** Enable or disable interrupts |
| 224 | * |
| 225 | * @v netdev Network device |
| 226 | * @v enable Interrupts should be enabled |
| 227 | */ |
| 228 | void ( * irq ) ( struct net_device *netdev, int enable ); |
| 229 | }; |
| 230 | |
| 231 | /** Network device error */ |
| 232 | struct net_device_error { |
| 233 | /** Error status code */ |
| 234 | int rc; |
| 235 | /** Error count */ |
| 236 | unsigned int count; |
| 237 | }; |
| 238 | |
| 239 | /** Maximum number of unique errors that we will keep track of */ |
| 240 | #define NETDEV_MAX_UNIQUE_ERRORS 4 |
| 241 | |
| 242 | /** Network device statistics */ |
| 243 | struct net_device_stats { |
| 244 | /** Count of successful completions */ |
| 245 | unsigned int good; |
| 246 | /** Count of error completions */ |
| 247 | unsigned int bad; |
| 248 | /** Error breakdowns */ |
| 249 | struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS]; |
| 250 | }; |
| 251 | |
| 252 | /** |
| 253 | * A network device |
| 254 | * |
| 255 | * This structure represents a piece of networking hardware. It has |
| 256 | * properties such as a link-layer address and methods for |
| 257 | * transmitting and receiving raw packets. |
| 258 | * |
| 259 | * Note that this structure must represent a generic network device, |
| 260 | * not just an Ethernet device. |
| 261 | */ |
| 262 | struct net_device { |
| 263 | /** Reference counter */ |
| 264 | struct refcnt refcnt; |
| 265 | /** List of network devices */ |
| 266 | struct list_head list; |
| 267 | /** List of open network devices */ |
| 268 | struct list_head open_list; |
| 269 | /** Name of this network device */ |
| 270 | char name[8]; |
| 271 | /** Underlying hardware device */ |
| 272 | struct device *dev; |
| 273 | |
| 274 | /** Network device operations */ |
| 275 | struct net_device_operations *op; |
| 276 | |
| 277 | /** Link-layer protocol */ |
| 278 | struct ll_protocol *ll_protocol; |
| 279 | /** Hardware address |
| 280 | * |
| 281 | * This is an address which is an intrinsic property of the |
| 282 | * hardware, e.g. an address held in EEPROM. |
| 283 | * |
| 284 | * Note that the hardware address may not be the same length |
| 285 | * as the link-layer address. |
| 286 | */ |
| 287 | uint8_t hw_addr[MAX_HW_ADDR_LEN]; |
| 288 | /** Link-layer address |
| 289 | * |
| 290 | * This is the current link-layer address assigned to the |
| 291 | * device. It can be changed at runtime. |
| 292 | */ |
| 293 | uint8_t ll_addr[MAX_LL_ADDR_LEN]; |
| 294 | /** Link-layer broadcast address */ |
| 295 | const uint8_t *ll_broadcast; |
| 296 | |
| 297 | /** Current device state |
| 298 | * |
| 299 | * This is the bitwise-OR of zero or more NETDEV_XXX constants. |
| 300 | */ |
| 301 | unsigned int state; |
| 302 | /** Link status code |
| 303 | * |
| 304 | * Zero indicates that the link is up; any other value |
| 305 | * indicates the error preventing link-up. |
| 306 | */ |
| 307 | int link_rc; |
| 308 | /** Maximum packet length |
| 309 | * |
| 310 | * This length includes any link-layer headers. |
| 311 | */ |
| 312 | size_t max_pkt_len; |
| 313 | /** TX packet queue */ |
| 314 | struct list_head tx_queue; |
| 315 | /** RX packet queue */ |
| 316 | struct list_head rx_queue; |
| 317 | /** TX statistics */ |
| 318 | struct net_device_stats tx_stats; |
| 319 | /** RX statistics */ |
| 320 | struct net_device_stats rx_stats; |
| 321 | |
| 322 | /** Configuration settings applicable to this device */ |
| 323 | struct generic_settings settings; |
| 324 | |
| 325 | /** Driver private data */ |
| 326 | void *priv; |
| 327 | }; |
| 328 | |
| 329 | /** Network device is open */ |
| 330 | #define NETDEV_OPEN 0x0001 |
| 331 | |
| 332 | /** Link-layer protocol table */ |
| 333 | #define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" ) |
| 334 | |
| 335 | /** Declare a link-layer protocol */ |
| 336 | #define __ll_protocol __table_entry ( LL_PROTOCOLS, 01 ) |
| 337 | |
| 338 | /** Network-layer protocol table */ |
| 339 | #define NET_PROTOCOLS __table ( struct net_protocol, "net_protocols" ) |
| 340 | |
| 341 | /** Declare a network-layer protocol */ |
| 342 | #define __net_protocol __table_entry ( NET_PROTOCOLS, 01 ) |
| 343 | |
| 344 | extern struct list_head net_devices; |
| 345 | extern struct net_device_operations null_netdev_operations; |
| 346 | extern struct settings_operations netdev_settings_operations; |
| 347 | |
| 348 | /** |
| 349 | * Initialise a network device |
| 350 | * |
| 351 | * @v netdev Network device |
| 352 | * @v op Network device operations |
| 353 | */ |
| 354 | static inline void netdev_init ( struct net_device *netdev, |
| 355 | struct net_device_operations *op ) { |
| 356 | netdev->op = op; |
| 357 | } |
| 358 | |
| 359 | /** |
| 360 | * Stop using a network device |
| 361 | * |
| 362 | * @v netdev Network device |
| 363 | * |
| 364 | * Drivers should call this method immediately before the final call |
| 365 | * to netdev_put(). |
| 366 | */ |
| 367 | static inline void netdev_nullify ( struct net_device *netdev ) { |
| 368 | netdev->op = &null_netdev_operations; |
| 369 | } |
| 370 | |
| 371 | /** |
| 372 | * Get printable network device link-layer address |
| 373 | * |
| 374 | * @v netdev Network device |
| 375 | * @ret name Link-layer address |
| 376 | */ |
| 377 | static inline const char * netdev_addr ( struct net_device *netdev ) { |
| 378 | return netdev->ll_protocol->ntoa ( netdev->ll_addr ); |
| 379 | } |
| 380 | |
| 381 | /** Iterate over all network devices */ |
| 382 | #define for_each_netdev( netdev ) \ |
| 383 | list_for_each_entry ( (netdev), &net_devices, list ) |
| 384 | |
| 385 | /** There exist some network devices |
| 386 | * |
| 387 | * @ret existence Existence of network devices |
| 388 | */ |
| 389 | static inline int have_netdevs ( void ) { |
| 390 | return ( ! list_empty ( &net_devices ) ); |
| 391 | } |
| 392 | |
| 393 | /** |
| 394 | * Get reference to network device |
| 395 | * |
| 396 | * @v netdev Network device |
| 397 | * @ret netdev Network device |
| 398 | */ |
| 399 | static inline __attribute__ (( always_inline )) struct net_device * |
| 400 | netdev_get ( struct net_device *netdev ) { |
| 401 | ref_get ( &netdev->refcnt ); |
| 402 | return netdev; |
| 403 | } |
| 404 | |
| 405 | /** |
| 406 | * Drop reference to network device |
| 407 | * |
| 408 | * @v netdev Network device |
| 409 | */ |
| 410 | static inline __attribute__ (( always_inline )) void |
| 411 | netdev_put ( struct net_device *netdev ) { |
| 412 | ref_put ( &netdev->refcnt ); |
| 413 | } |
| 414 | |
| 415 | /** |
| 416 | * Get driver private area for this network device |
| 417 | * |
| 418 | * @v netdev Network device |
| 419 | * @ret priv Driver private area for this network device |
| 420 | */ |
| 421 | static inline __attribute__ (( always_inline )) void * |
| 422 | netdev_priv ( struct net_device *netdev ) { |
| 423 | return netdev->priv; |
| 424 | } |
| 425 | |
| 426 | /** |
| 427 | * Get per-netdevice configuration settings block |
| 428 | * |
| 429 | * @v netdev Network device |
| 430 | * @ret settings Settings block |
| 431 | */ |
| 432 | static inline __attribute__ (( always_inline )) struct settings * |
| 433 | netdev_settings ( struct net_device *netdev ) { |
| 434 | return &netdev->settings.settings; |
| 435 | } |
| 436 | |
| 437 | /** |
| 438 | * Initialise a per-netdevice configuration settings block |
| 439 | * |
| 440 | * @v generics Generic settings block |
| 441 | * @v refcnt Containing object reference counter, or NULL |
| 442 | * @v name Settings block name |
| 443 | */ |
| 444 | static inline __attribute__ (( always_inline )) void |
| 445 | netdev_settings_init ( struct net_device *netdev ) { |
| 446 | generic_settings_init ( &netdev->settings, |
| 447 | &netdev->refcnt, netdev->name ); |
| 448 | netdev->settings.settings.op = &netdev_settings_operations; |
| 449 | } |
| 450 | |
| 451 | /** |
| 452 | * Mark network device as having link up |
| 453 | * |
| 454 | * @v netdev Network device |
| 455 | */ |
| 456 | static inline __attribute__ (( always_inline )) void |
| 457 | netdev_link_up ( struct net_device *netdev ) { |
| 458 | netdev->link_rc = 0; |
| 459 | } |
| 460 | |
| 461 | /** |
| 462 | * Mark network device as having link down due to a specific error |
| 463 | * |
| 464 | * @v netdev Network device |
| 465 | * @v rc Link status code |
| 466 | */ |
| 467 | static inline __attribute__ (( always_inline )) void |
| 468 | netdev_link_err ( struct net_device *netdev, int rc ) { |
| 469 | netdev->link_rc = rc; |
| 470 | } |
| 471 | |
| 472 | /** |
| 473 | * Check link state of network device |
| 474 | * |
| 475 | * @v netdev Network device |
| 476 | * @ret link_up Link is up |
| 477 | */ |
| 478 | static inline __attribute__ (( always_inline )) int |
| 479 | netdev_link_ok ( struct net_device *netdev ) { |
| 480 | return ( netdev->link_rc == 0 ); |
| 481 | } |
| 482 | |
| 483 | extern void netdev_link_down ( struct net_device *netdev ); |
| 484 | extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); |
| 485 | extern void netdev_tx_complete_err ( struct net_device *netdev, |
| 486 | struct io_buffer *iobuf, int rc ); |
| 487 | extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ); |
| 488 | extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ); |
| 489 | extern void netdev_rx_err ( struct net_device *netdev, |
| 490 | struct io_buffer *iobuf, int rc ); |
| 491 | extern void netdev_poll ( struct net_device *netdev ); |
| 492 | extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ); |
| 493 | extern struct net_device * alloc_netdev ( size_t priv_size ); |
| 494 | extern int register_netdev ( struct net_device *netdev ); |
| 495 | extern int netdev_open ( struct net_device *netdev ); |
| 496 | extern void netdev_close ( struct net_device *netdev ); |
| 497 | extern void unregister_netdev ( struct net_device *netdev ); |
| 498 | extern void netdev_irq ( struct net_device *netdev, int enable ); |
| 499 | extern struct net_device * find_netdev ( const char *name ); |
| 500 | extern struct net_device * find_netdev_by_location ( unsigned int bus_type, |
| 501 | unsigned int location ); |
| 502 | extern struct net_device * last_opened_netdev ( void ); |
| 503 | extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, |
| 504 | struct net_protocol *net_protocol, const void *ll_dest ); |
| 505 | extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, |
| 506 | uint16_t net_proto, const void *ll_source ); |
| 507 | |
| 508 | /** |
| 509 | * Complete network transmission |
| 510 | * |
| 511 | * @v netdev Network device |
| 512 | * @v iobuf I/O buffer |
| 513 | * |
| 514 | * The packet must currently be in the network device's TX queue. |
| 515 | */ |
| 516 | static inline void netdev_tx_complete ( struct net_device *netdev, |
| 517 | struct io_buffer *iobuf ) { |
| 518 | netdev_tx_complete_err ( netdev, iobuf, 0 ); |
| 519 | } |
| 520 | |
| 521 | /** |
| 522 | * Complete network transmission |
| 523 | * |
| 524 | * @v netdev Network device |
| 525 | * |
| 526 | * Completes the oldest outstanding packet in the TX queue. |
| 527 | */ |
| 528 | static inline void netdev_tx_complete_next ( struct net_device *netdev ) { |
| 529 | netdev_tx_complete_next_err ( netdev, 0 ); |
| 530 | } |
| 531 | |
| 532 | #endif /* _GPXE_NETDEVICE_H */ |