diff options
| author | Michael Brown | 2006-06-18 00:36:27 +0200 |
|---|---|---|
| committer | Michael Brown | 2006-06-18 00:36:27 +0200 |
| commit | 3c8aafa2099c13799fdb4f42d06f1abd278b14f7 (patch) | |
| tree | dda612574bf0c128cc58ff4f7231b73f019f8e2b /src/net | |
| parent | Remove dependency on arptable[] (which is no longer used). (diff) | |
| download | ipxe-3c8aafa2099c13799fdb4f42d06f1abd278b14f7.tar.gz ipxe-3c8aafa2099c13799fdb4f42d06f1abd278b14f7.tar.xz ipxe-3c8aafa2099c13799fdb4f42d06f1abd278b14f7.zip | |
Simplify RX data path.
Kill off the static single net device and move to proper dynamic
registration (which we need with the new device model).
Break the (flawed) assumption that all network-layer protocols can use
ARP; such network-layer protocols (i.e. IPv4) must now register as an ARP
protocol using ARP_NET_PROTOCOL() and provide a single method for checking
the existence of a local network-layer address.
Diffstat (limited to 'src/net')
| -rw-r--r-- | src/net/aoe.c | 14 | ||||
| -rw-r--r-- | src/net/arp.c | 56 | ||||
| -rw-r--r-- | src/net/ethernet.c | 46 | ||||
| -rw-r--r-- | src/net/ipv4.c | 48 | ||||
| -rw-r--r-- | src/net/netdevice.c | 300 | ||||
| -rw-r--r-- | src/net/tcp.c | 2 |
6 files changed, 260 insertions, 206 deletions
diff --git a/src/net/aoe.c b/src/net/aoe.c index 693b36050..e0954fa55 100644 --- a/src/net/aoe.c +++ b/src/net/aoe.c @@ -87,7 +87,6 @@ static int aoe_send_command ( struct aoe_session *aoe ) { data_out_len ); if ( ! pkb ) return -ENOMEM; - pkb->net_protocol = &aoe_protocol; pkb_reserve ( pkb, ETH_HLEN ); aoehdr = pkb_put ( pkb, sizeof ( *aoehdr ) ); aoecmd = pkb_put ( pkb, sizeof ( *aoecmd ) ); @@ -117,7 +116,7 @@ static int aoe_send_command ( struct aoe_session *aoe ) { /* Send packet */ start_timer ( &aoe->timer ); - return net_transmit ( pkb, aoe->netdev, &aoe_protocol, aoe->target ); + return net_tx ( pkb, aoe->netdev, &aoe_protocol, aoe->target ); } /** @@ -209,13 +208,15 @@ static int aoe_rx_response ( struct aoe_session *aoe, struct aoehdr *aoehdr, * Process incoming AoE packets * * @v pkb Packet buffer + * @v netdev Network device + * @v ll_source Link-layer source address * @ret rc Return status code * */ -static int aoe_rx ( struct pk_buff *pkb ) { +static int aoe_rx ( struct pk_buff *pkb, struct net_device *netdev __unused, + const void *ll_source ) { struct aoehdr *aoehdr = pkb->data; unsigned int len = pkb_len ( pkb ); - struct ethhdr *ethhdr = pkb_push ( pkb, sizeof ( *ethhdr ) ); struct aoe_session *aoe; int rc = 0; @@ -241,8 +242,7 @@ static int aoe_rx ( struct pk_buff *pkb ) { continue; if ( ntohl ( aoehdr->tag ) != aoe->tag ) continue; - memcpy ( aoe->target, ethhdr->h_source, - sizeof ( aoe->target ) ); + memcpy ( aoe->target, ll_source, sizeof ( aoe->target ) ); rc = aoe_rx_response ( aoe, aoehdr, len ); break; } @@ -256,7 +256,7 @@ static int aoe_rx ( struct pk_buff *pkb ) { struct net_protocol aoe_protocol = { .name = "AoE", .net_proto = htons ( ETH_P_AOE ), - .rx_process = aoe_rx, + .rx = aoe_rx, }; NET_PROTOCOL ( aoe_protocol ); diff --git a/src/net/arp.c b/src/net/arp.c index 66f9bd4cf..6293bf95c 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -36,6 +36,12 @@ * */ +/** Registered ARP protocols */ +static struct arp_net_protocol arp_net_protocols[0] + __table_start ( arp_net_protocols ); +static struct arp_net_protocol arp_net_protocols_end[0] + __table_end ( arp_net_protocols ); + /** An ARP cache entry */ struct arp_entry { /** Network-layer protocol */ @@ -134,7 +140,6 @@ int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, 2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) ); if ( ! pkb ) return -ENOMEM; - pkb->net_protocol = &arp_protocol; pkb_reserve ( pkb, MAX_LL_HEADER_LEN ); /* Build up ARP request */ @@ -154,17 +159,38 @@ int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, dest_net_addr, net_protocol->net_addr_len ); /* Transmit ARP request */ - if ( ( rc = net_transmit ( pkb, netdev, &arp_protocol, - ll_protocol->ll_broadcast ) ) != 0 ) + if ( ( rc = net_tx ( pkb, netdev, &arp_protocol, + ll_protocol->ll_broadcast ) ) != 0 ) return rc; return -ENOENT; } /** + * Identify ARP protocol + * + * @v net_proto Network-layer protocol, in network-endian order + * @ret arp_net_protocol ARP protocol, or NULL + * + */ +static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) { + struct arp_net_protocol *arp_net_protocol; + + for ( arp_net_protocol = arp_net_protocols ; + arp_net_protocol < arp_net_protocols_end ; arp_net_protocol++ ) { + if ( arp_net_protocol->net_protocol->net_proto == net_proto ) { + return arp_net_protocol; + } + } + return NULL; +} + +/** * Process incoming ARP packets * * @v pkb Packet buffer + * @v netdev Network device + * @v ll_source Link-layer source address * @ret rc Return status code * * This handles ARP requests and responses as detailed in RFC826. The @@ -173,19 +199,21 @@ int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, * avoiding the need for extraneous ARP requests; read the RFC for * details. */ -static int arp_rx ( struct pk_buff *pkb ) { +static int arp_rx ( struct pk_buff *pkb, struct net_device *netdev, + const void *ll_source __unused ) { struct arphdr *arphdr = pkb->data; - struct ll_protocol *ll_protocol; + struct arp_net_protocol *arp_net_protocol; struct net_protocol *net_protocol; + struct ll_protocol *ll_protocol; struct arp_entry *arp; - struct net_device *netdev; int merge = 0; - /* Identify link-layer and network-layer protocols */ - ll_protocol = pkb->ll_protocol; - net_protocol = find_net_protocol ( arphdr->ar_pro ); - if ( ! net_protocol ) + /* Identify network-layer and link-layer protocols */ + arp_net_protocol = arp_find_protocol ( arphdr->ar_pro ); + if ( ! arp_net_protocol ) goto done; + net_protocol = arp_net_protocol->net_protocol; + ll_protocol = netdev->ll_protocol; /* Sanity checks */ if ( ( arphdr->ar_hrd != ll_protocol->ll_proto ) || @@ -206,9 +234,7 @@ static int arp_rx ( struct pk_buff *pkb ) { } /* See if we own the target protocol address */ - netdev = find_netdev_by_net_addr ( net_protocol, - arp_target_pa ( arphdr ) ); - if ( ! netdev ) + if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0) goto done; /* Create new ARP table entry if necessary */ @@ -239,7 +265,7 @@ static int arp_rx ( struct pk_buff *pkb ) { memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln ); /* Send reply */ - net_transmit ( pkb, netdev, &arp_protocol, arp_target_ha (arphdr ) ); + net_tx ( pkb, netdev, &arp_protocol, arp_target_ha (arphdr ) ); pkb = NULL; done: @@ -264,7 +290,7 @@ arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) { struct net_protocol arp_protocol = { .name = "ARP", .net_proto = htons ( ETH_P_ARP ), - .rx_process = arp_rx, + .rx = arp_rx, .ntoa = arp_ntoa, }; diff --git a/src/net/ethernet.c b/src/net/ethernet.c index ab7d42774..13b3c2dbc 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -46,41 +46,43 @@ static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; * * Prepends the Ethernet link-layer header and transmits the packet. */ -static int eth_transmit ( struct pk_buff *pkb, struct net_device *netdev, - struct net_protocol *net_protocol, - const void *ll_dest ) { +static int eth_tx ( struct pk_buff *pkb, struct net_device *netdev, + struct net_protocol *net_protocol, const void *ll_dest ) { struct ethhdr *ethhdr = pkb_push ( pkb, sizeof ( *ethhdr ) ); + /* Build Ethernet header */ memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN ); memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN ); ethhdr->h_protocol = net_protocol->net_proto; - return netdev_transmit ( netdev, pkb ); + + /* Hand off to network device */ + return netdev_tx ( netdev, pkb ); } /** - * Parse Ethernet link-layer header + * Process received Ethernet packet * * @v pkb Packet buffer - * @v llhdr Generic link-layer header + * @v netdev Network device * - * Fills in the generic link-layer header based on information in the - * Ethernet link-layer header in the packet buffer. + * Strips off the Ethernet link-layer header and passes up to the + * network-layer protocol. */ -static void eth_parse_llh ( const struct pk_buff *pkb, - struct ll_header *llhdr ) { +static void eth_rx ( struct pk_buff *pkb, struct net_device *netdev ) { struct ethhdr *ethhdr = pkb->data; - memcpy ( llhdr->dest_ll_addr, ethhdr->h_dest, ETH_ALEN ); - memcpy ( llhdr->source_ll_addr, ethhdr->h_source, ETH_ALEN ); - llhdr->net_proto = ethhdr->h_protocol; - - if ( memcmp ( ethhdr->h_dest, eth_broadcast, ETH_ALEN ) == 0 ) { - llhdr->flags = PKT_FL_BROADCAST; - } else if ( ethhdr->h_dest[0] & 0x01 ) { - llhdr->flags = PKT_FL_MULTICAST; - } else { - llhdr->flags = 0; + /* Sanity check */ + if ( pkb_len ( pkb ) < sizeof ( *ethhdr ) ) { + DBG ( "Ethernet packet too short (%d bytes)\n", + pkb_len ( pkb ) ); + return; } + + /* Strip off Ethernet header */ + pkb_pull ( pkb, sizeof ( *ethhdr ) ); + + /* Hand off to network-layer protocol */ + net_rx ( pkb, netdev, ethhdr->h_protocol, ethhdr->h_source ); } /** @@ -105,8 +107,8 @@ struct ll_protocol ethernet_protocol = { .ll_proto = htons ( ARPHRD_ETHER ), .ll_addr_len = ETH_ALEN, .ll_broadcast = eth_broadcast, - .transmit = eth_transmit, - .parse_llh = eth_parse_llh, + .tx = eth_tx, + .rx = eth_rx, .ntoa = eth_ntoa, }; diff --git a/src/net/ipv4.c b/src/net/ipv4.c index ae3404ccc..47b8cb7f2 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -7,10 +7,6 @@ #include <gpxe/list.h> #include <gpxe/in.h> #include <gpxe/arp.h> - -#include <ip.h> - - #include <gpxe/if_ether.h> #include <gpxe/pkbuff.h> #include <gpxe/netdevice.h> @@ -104,7 +100,7 @@ void del_ipv4_address ( struct net_device *netdev ) { * @ret rc Return status code * */ -int ipv4_uip_transmit ( struct pk_buff *pkb ) { +int ipv4_uip_tx ( struct pk_buff *pkb ) { struct iphdr *iphdr = pkb->data; struct ipv4_miniroute *miniroute; struct net_device *netdev = NULL; @@ -162,7 +158,7 @@ int ipv4_uip_transmit ( struct pk_buff *pkb ) { } /* Hand off to link layer */ - return net_transmit ( pkb, netdev, &ipv4_protocol, ll_dest ); + return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest ); err: free_pkb ( pkb ); @@ -173,12 +169,15 @@ int ipv4_uip_transmit ( struct pk_buff *pkb ) { * Process incoming IP packets * * @v pkb Packet buffer + * @v netdev Network device + * @v ll_source Link-layer source address * @ret rc Return status code * * This handles IP packets by handing them off to the uIP protocol * stack. */ -static int ipv4_rx ( struct pk_buff *pkb ) { +static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused, + const void *ll_source __unused ) { /* Transfer to uIP buffer. Horrendously space-inefficient, * but will do as a proof-of-concept for now. @@ -195,11 +194,32 @@ static int ipv4_rx ( struct pk_buff *pkb ) { return -ENOMEM; pkb_reserve ( pkb, MAX_LL_HEADER_LEN ); memcpy ( pkb_put ( pkb, uip_len ), uip_buf, uip_len ); - ipv4_uip_transmit ( pkb ); + ipv4_uip_tx ( pkb ); } return 0; } +/** + * Check existence of IPv4 address for ARP + * + * @v netdev Network device + * @v net_addr Network-layer address + * @ret rc Return status code + */ +static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) { + const struct in_addr *address = net_addr; + struct ipv4_miniroute *miniroute; + + list_for_each_entry ( miniroute, &miniroutes, list ) { + if ( ( miniroute->netdev == netdev ) && + ( miniroute->address.s_addr == address->s_addr ) ) { + /* Found matching address */ + return 0; + } + } + return -ENOENT; +} + /** * Convert IPv4 address to dotted-quad notation * @@ -230,18 +250,16 @@ struct net_protocol ipv4_protocol = { .name = "IP", .net_proto = htons ( ETH_P_IP ), .net_addr_len = sizeof ( struct in_addr ), - .rx_process = ipv4_rx, + .rx = ipv4_rx, .ntoa = ipv4_ntoa, }; NET_PROTOCOL ( ipv4_protocol ); -/** IPv4 address for the static single net device */ -struct net_address static_single_ipv4_address = { +/** IPv4 ARP protocol */ +struct arp_net_protocol ipv4_arp_protocol = { .net_protocol = &ipv4_protocol, - -#warning "Remove this static-IP hack" - .net_addr = { 0x0a, 0xfe, 0xfe, 0x01 }, + .check = ipv4_arp_check, }; -STATIC_SINGLE_NETDEV_ADDRESS ( static_single_ipv4_address ); +ARP_NET_PROTOCOL ( ipv4_arp_protocol ); diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 1825a55b2..1197e66cd 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -20,6 +20,7 @@ #include <byteswap.h> #include <string.h> #include <errno.h> +#include <malloc.h> #include <gpxe/if_ether.h> #include <gpxe/pkbuff.h> #include <gpxe/tables.h> @@ -33,175 +34,116 @@ * */ -/** - * Static single instance of a network device - * - * The gPXE API is designed to accommodate multiple network devices. - * However, in the interests of code size, the implementation behind - * the API supports only a single instance of a network device. - * - * No code outside of netdevice.c should ever refer directly to @c - * static_single_netdev. - * - * Callers should always check the return status of alloc_netdev(), - * register_netdev() etc. In the current implementation this code - * will be optimised out by the compiler, so there is no penalty. - */ -struct net_device static_single_netdev; - /** Registered network-layer protocols */ static struct net_protocol net_protocols[0] __table_start ( net_protocols ); static struct net_protocol net_protocols_end[0] __table_end ( net_protocols ); -/** Network-layer addresses for @c static_single_netdev */ -static struct net_address static_single_netdev_addresses[0] - __table_start ( sgl_netdev_addresses ); -static struct net_address static_single_netdev_addresses_end[0] - __table_end ( sgl_netdev_addresses ); - -/** Recevied packet queue */ -static LIST_HEAD ( rx_queue ); +/** List of network devices */ +static LIST_HEAD ( net_devices ); #warning "Remove this static IP address hack" #include <ip.h> #include <gpxe/ip.h> /** - * Register network device + * Transmit raw packet via network device * * @v netdev Network device + * @v pkb Packet buffer * @ret rc Return status code * - * Adds the network device to the list of network devices. + * Transmits the packet via the specified network device. This + * function takes ownership of the packet buffer. */ -int register_netdev ( struct net_device *netdev ) { - -#warning "Remove this static IP address hack" - { - const struct in_addr static_address = { htonl ( 0x0afefe01 ) }; - const struct in_addr static_netmask = { htonl ( 0xffffff00 ) }; - const struct in_addr static_gateway = { INADDR_NONE }; - int rc; - - if ( ( rc = add_ipv4_address ( netdev, static_address, - static_netmask, - static_gateway ) ) != 0 ) - return rc; - } - - return 0; +int netdev_tx ( struct net_device *netdev, struct pk_buff *pkb ) { + DBG ( "%s transmitting %p+%zx\n", netdev_name ( netdev ), + pkb->data, pkb_len ( pkb ) ); + return netdev->transmit ( netdev, pkb ); } /** - * Unregister network device + * Add packet to receive queue * * @v netdev Network device + * @v pkb Packet buffer * - * Removes the network device from the list of network devices. + * The packet is added to the network device's RX queue. This + * function takes ownership of the packet buffer. */ -void unregister_netdev ( struct net_device *netdev ) { - -#warning "Remove this static IP address hack" - del_ipv4_address ( netdev ); - +void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) { + DBG ( "%s received %p+%zx\n", netdev_name ( netdev ), + pkb->data, pkb_len ( pkb ) ); + list_add_tail ( &pkb->list, &netdev->rx_queue ); } /** - * Add packet to receive queue + * Transmit network-layer packet * - * @v netdev Network device * @v pkb Packet buffer + * @v netdev Network device + * @v net_protocol Network-layer protocol + * @v ll_dest Destination link-layer address + * @ret rc Return status code * - * The packet is added to the RX queue. This function takes ownership - * of the packet buffer. + * Prepends link-layer headers to the packet buffer and transmits the + * packet via the specified network device. This function takes + * ownership of the packet buffer. */ -void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) { - DBG ( "Packet received\n" ); - pkb->ll_protocol = netdev->ll_protocol; - list_add_tail ( &pkb->list, &rx_queue ); +int net_tx ( struct pk_buff *pkb, struct net_device *netdev, + struct net_protocol *net_protocol, const void *ll_dest ) { + return netdev->ll_protocol->tx ( pkb, netdev, net_protocol, ll_dest ); } /** - * Identify network protocol + * Process received network-layer packet * + * @v pkb Packet buffer + * @v netdev Network device * @v net_proto Network-layer protocol, in network-byte order - * @ret net_protocol Network-layer protocol, or NULL - * - * Identify a network-layer protocol from a protocol number, which - * must be an ETH_P_XXX constant in network-byte order. + * @v ll_source Source link-layer address */ -struct net_protocol * find_net_protocol ( uint16_t net_proto ) { +void net_rx ( struct pk_buff *pkb, struct net_device *netdev, + uint16_t net_proto, const void *ll_source ) { struct net_protocol *net_protocol; + /* Hand off to network-layer protocol, if any */ for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ; net_protocol++ ) { - if ( net_protocol->net_proto == net_proto ) - return net_protocol; - } - return NULL; -} - -/** - * Identify network device by network-layer address - * - * @v net_protocol Network-layer protocol - * @v net_addr Network-layer address - * @ret netdev Network device, or NULL - * - * Searches through all network devices to find the device with the - * specified network-layer address. - * - * Note that even with a static single network device, this function - * can still return NULL. - */ -struct net_device * -find_netdev_by_net_addr ( struct net_protocol *net_protocol, - void *net_addr ) { - struct net_address *net_address; - struct net_device *netdev = &static_single_netdev; - - for ( net_address = static_single_netdev_addresses ; - net_address < static_single_netdev_addresses_end ; - net_address ++ ) { - if ( ( net_address->net_protocol == net_protocol ) && - ( memcmp ( net_address->net_addr, net_addr, - net_protocol->net_addr_len ) == 0 ) ) - return netdev; + if ( net_protocol->net_proto == net_proto ) { + net_protocol->rx ( pkb, netdev, ll_source ); + break; + } } - - return NULL; } /** - * Poll for packet on all network devices + * Poll for packet on network device * + * @v netdev Network device * @ret True There are packets present in the receive queue * @ret False There are no packets present in the receive queue * - * Polls all network devices for received packets. Any received + * Polls the network device for received packets. Any received * packets will be added to the RX packet queue via netdev_rx(). */ -int net_poll ( void ) { - struct net_device *netdev = &static_single_netdev; - - DBG ( "Polling network\n" ); +int netdev_poll ( struct net_device *netdev ) { netdev->poll ( netdev ); - - return ( ! list_empty ( &rx_queue ) ); + return ( ! list_empty ( &netdev->rx_queue ) ); } /** - * Remove packet from receive queue + * Remove packet from device's receive queue * + * @v netdev Network device * @ret pkb Packet buffer, or NULL * - * Removes the first packet from the RX queue and returns it. + * Removes the first packet from the device's RX queue and returns it. * Ownership of the packet is transferred to the caller. */ -struct pk_buff * net_rx_dequeue ( void ) { +struct pk_buff * netdev_rx_dequeue ( struct net_device *netdev ) { struct pk_buff *pkb; - list_for_each_entry ( pkb, &rx_queue, list ) { + list_for_each_entry ( pkb, &netdev->rx_queue, list ) { list_del ( &pkb->list ); return pkb; } @@ -209,49 +151,109 @@ struct pk_buff * net_rx_dequeue ( void ) { } /** - * Process received packet + * Allocate network device * - * @v pkb Packet buffer - * @ret rc Return status code + * @v priv_size Size of private data area (net_device::priv) + * @ret netdev Network device, or NULL * - * Processes a packet received from the network (and, usually, removed - * from the RX queue by net_rx_dequeue()). This call takes ownership - * of the packet buffer. + * Allocates space for a network device and its private data area. */ -int net_rx_process ( struct pk_buff *pkb ) { - struct ll_protocol *ll_protocol; - struct ll_header llhdr; - struct net_protocol *net_protocol; - int rc; +struct net_device * alloc_netdev ( size_t priv_size ) { + struct net_device *netdev; - /* Parse link-layer header */ - ll_protocol = pkb->ll_protocol; - ll_protocol->parse_llh ( pkb, &llhdr ); - - /* Identify network-layer protocol */ - net_protocol = find_net_protocol ( llhdr.net_proto ); - if ( ! net_protocol ) { - DBG ( "Unknown network-layer protocol %x\n", - ntohs ( llhdr.net_proto ) ); - free_pkb ( pkb ); - return -EPROTONOSUPPORT; + netdev = calloc ( 1, sizeof ( *netdev ) + priv_size ); + if ( netdev ) { + INIT_LIST_HEAD ( &netdev->rx_queue ); + netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) ); } - pkb->net_protocol = net_protocol; - - /* Strip off link-layer header */ -#warning "Temporary hack" - pkb_pull ( pkb, ETH_HLEN ); + return netdev; +} + +/** + * Register network device + * + * @v netdev Network device + * @ret rc Return status code + * + * Adds the network device to the list of network devices. + */ +int register_netdev ( struct net_device *netdev ) { - /* Hand off to network layer */ - if ( ( rc = net_protocol->rx_process ( pkb ) ) != 0 ) { - DBG ( "Network-layer protocol dropped packet\n" ); - return rc; +#warning "Remove this static IP address hack" + { + const struct in_addr static_address = { htonl ( 0x0afefe01 ) }; + const struct in_addr static_netmask = { htonl ( 0xffffff00 ) }; + const struct in_addr static_gateway = { INADDR_NONE }; + int rc; + + if ( ( rc = add_ipv4_address ( netdev, static_address, + static_netmask, + static_gateway ) ) != 0 ) + return rc; } + /* Add to device list */ + list_add_tail ( &netdev->list, &net_devices ); + DBG ( "%s registered\n", netdev_name ( netdev ) ); + return 0; } /** + * Unregister network device + * + * @v netdev Network device + * + * Removes the network device from the list of network devices. + */ +void unregister_netdev ( struct net_device *netdev ) { + struct pk_buff *pkb; + +#warning "Remove this static IP address hack" + del_ipv4_address ( netdev ); + + /* Discard any packets in the RX queue */ + while ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) { + DBG ( "%s discarding %p+%zx\n", netdev_name ( netdev ), + pkb->data, pkb_len ( pkb ) ); + free_pkb ( pkb ); + } + + /* Remove from device list */ + list_del ( &netdev->list ); + DBG ( "%s unregistered\n", netdev_name ( netdev ) ); +} + +/** + * Free network device + * + * @v netdev Network device + */ +void free_netdev ( struct net_device *netdev ) { + free ( netdev ); +} + +/** + * Iterate through network devices + * + * @ret netdev Network device, or NULL + * + * This returns the registered network devices in the order of + * registration. If no network devices are registered, it will return + * NULL. + */ +struct net_device * next_netdev ( void ) { + struct net_device *netdev; + + list_for_each_entry ( netdev, &net_devices, list ) { + list_del ( &netdev->list ); + list_add_tail ( &netdev->list, &net_devices ); + return netdev; + } + return NULL; +} + +/** * Single-step the network stack * * @v process Network stack process @@ -266,15 +268,21 @@ int net_rx_process ( struct pk_buff *pkb ) { * multiple packets are processed per poll. */ static void net_step ( struct process *process ) { + struct net_device *netdev; struct pk_buff *pkb; - /* Poll for new packets */ - net_poll(); + /* Poll and process each network device */ + list_for_each_entry ( netdev, &net_devices, list ) { + + /* Poll for new packets */ + netdev_poll ( netdev ); - /* Handle at most one received packet */ - if ( ( pkb = net_rx_dequeue () ) ) { - net_rx_process ( pkb ); - DBG ( "Processed received packet\n" ); + /* Handle at most one received packet per poll */ + if ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) { + DBG ( "%s processing %p+%zx\n", netdev_name ( netdev ), + pkb->data, pkb_len ( pkb ) ); + netdev->ll_protocol->rx ( pkb, netdev ); + } } /* Re-schedule ourself */ diff --git a/src/net/tcp.c b/src/net/tcp.c index 5027678b1..e73708dc3 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -177,7 +177,7 @@ static void tcp_periodic ( void ) { pkb_put ( pkb, uip_len ); memcpy ( pkb->data, uip_buf, uip_len ); - ipv4_uip_transmit ( pkb ); + ipv4_uip_tx ( pkb ); } } } |
