Simplify TX datapath.
authorMichael Brown <mcb30@etherboot.org>
Fri, 16 Jun 2006 00:19:46 +0000 (00:19 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 16 Jun 2006 00:19:46 +0000 (00:19 +0000)
src/include/gpxe/arp.h
src/include/gpxe/ip.h
src/include/gpxe/netdevice.h
src/net/aoe.c
src/net/arp.c
src/net/ethernet.c
src/net/ipv4.c
src/net/netdevice.c
src/net/tcp.c

index 27591d3..a1f9e34 100644 (file)
@@ -8,11 +8,12 @@
  */
 
 struct net_device;
-struct net_header;
-struct ll_header;
+struct net_protocol;
 
 extern int arp_resolve ( struct net_device *netdev,
-                        const struct net_header *nethdr,
-                        struct ll_header *llhdr );
+                        struct net_protocol *net_protocol,
+                        const void *dest_net_addr,
+                        const void *source_net_addr,
+                        void *dest_ll_addr );
 
 #endif /* _GPXE_ARP_H */
index 44aee7d..8eac31a 100644 (file)
@@ -11,4 +11,10 @@ struct net_protocol;
 
 extern struct net_protocol ipv4_protocol;
 
+extern int add_ipv4_address ( struct net_device *netdev,
+                             struct in_addr address, struct in_addr netmask,
+                             struct in_addr gateway );
+extern void del_ipv4_address ( struct net_device *netdev );
+extern int ipv4_uip_transmit ( struct pk_buff *pkb );
+
 #endif /* _GPXE_IP_H */
index 1879bf1..68226dc 100644 (file)
@@ -86,22 +86,6 @@ struct ll_header {
 struct net_protocol {
        /** Protocol name */
        const char *name;
-       /**
-        * Perform network-layer routing
-        *
-        * @v pkb       Packet buffer
-        * @v nethdr    Generic network-layer header
-        * @ret rc      Return status code
-        *
-        * This method should fill in the network header with enough
-        * information to allow the link layer to route the packet.
-        *
-        * For example, in the case of IPv4, this method should fill
-        * in the IP addresses of the local adapter and the next hop
-        * destination (e.g. the gateway).
-        */
-       int ( * route ) ( const struct pk_buff *pkb,
-                         struct net_header *nethdr );
        /**
         * Process received packet
         *
@@ -141,36 +125,21 @@ struct ll_protocol {
        /** Protocol name */
        const char *name;
        /**
-        * Perform link-layer routing
-        *
-        * @v netdev    Network device
-        * @v nethdr    Generic network-layer header
-        * @ret llhdr   Generic link-layer header
-        * @ret rc      Return status code
+        * Transmit network-layer packet via network device
         *
-        * This method should construct the generic link-layer header
-        * based on the generic network-layer header.
         *
-        * If a link-layer header cannot be constructed (e.g. because
-        * of a missing ARP cache entry), then this method should
-        * return an error (after transmitting an ARP request, if
-        * applicable).
-        */
-       int ( * route ) ( struct net_device *netdev,
-                         const struct net_header *nethdr,
-                         struct ll_header *llhdr );
-       /**
-        * Fill media-specific link-layer header
-        *
-        * @v llhdr     Generic link-layer header
-        * @v pkb       Packet buffer
+        * @v pkb               Packet buffer
+        * @v netdev            Network device
+        * @v net_protocol      Network-layer protocol
+        * @v ll_dest           Link-layer destination address
+        * @ret rc              Return status code
         *
-        * This method should fill in the link-layer header in the
-        * packet buffer based on information in the generic
-        * link-layer header.
+        * This method should prepend in the link-layer header
+        * (e.g. the Ethernet DIX header) and transmit the packet.
         */
-       void ( * fill_llh ) ( const struct ll_header *llhdr,
-                             struct pk_buff *pkb );
+       int ( * transmit ) ( struct pk_buff *pkb, struct net_device *netdev,
+                            struct net_protocol *net_protocol,
+                            const void *ll_dest );
        /**
         * Parse media-specific link-layer header
         *
@@ -204,8 +173,8 @@ struct ll_protocol {
        uint16_t ll_proto;
        /** Link-layer address length */
        uint8_t ll_addr_len;
-       /** Link-layer header length */
-       uint8_t ll_header_len;
+       /** Link-layer broadcast address */
+       const uint8_t *ll_broadcast;
 };
 
 /**
@@ -288,31 +257,6 @@ extern struct net_device static_single_netdev;
        static_single_netdev.priv = priv_data;  \
        &static_single_netdev; } )
 
-/**
- * Register network device
- *
- * @v netdev           Network device
- * @ret rc             Return status code
- *
- * Adds the network device to the list of network devices.
- */
-static inline int
-register_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
-       return 0;
-}
-
-/**
- * Unregister network device
- *
- * @v netdev           Network device
- *
- * Removes the network device from the list of network devices.
- */
-static inline void 
-unregister_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
-       /* Nothing to do */
-}
-
 /**
  * Free network device
  *
@@ -339,6 +283,27 @@ static inline int netdev_transmit ( struct net_device *netdev,
        return netdev->transmit ( netdev, pkb );
 }
 
+/**
+ * Transmit network-layer packet
+ *
+ * @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
+ *
+ * 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.
+ */
+static inline int net_transmit ( struct pk_buff *pkb,
+                                struct net_device *netdev,
+                                struct net_protocol *net_protocol,
+                                const void *ll_dest ) {
+       return netdev->ll_protocol->transmit ( pkb, netdev, net_protocol,
+                                              ll_dest );
+}
+
 /**
  * Register a link-layer protocol
  *
@@ -363,14 +328,14 @@ static inline int netdev_transmit ( struct net_device *netdev,
 #define STATIC_SINGLE_NETDEV_ADDRESS( address ) \
        struct net_address address __table ( sgl_netdev_addresses, 01 )
 
+extern int register_netdev ( struct net_device *netdev );
+extern void unregister_netdev ( struct net_device *netdev );
 extern void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb );
 
 extern struct net_protocol *find_net_protocol ( uint16_t net_proto );
 extern struct net_device *
 find_netdev_by_net_addr ( struct net_protocol *net_protocol, void *net_addr );
 
-extern int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev );
-extern int net_transmit ( struct pk_buff *pkb );
 extern int net_poll ( void );
 extern struct pk_buff * net_rx_dequeue ( void );
 extern int net_rx_process ( struct pk_buff *pkb );
index cfb833f..693b360 100644 (file)
@@ -24,6 +24,7 @@
 #include <byteswap.h>
 #include <gpxe/list.h>
 #include <gpxe/if_ether.h>
+#include <gpxe/ethernet.h>
 #include <gpxe/pkbuff.h>
 #include <gpxe/uaccess.h>
 #include <gpxe/ata.h>
@@ -116,7 +117,7 @@ static int aoe_send_command ( struct aoe_session *aoe ) {
 
        /* Send packet */
        start_timer ( &aoe->timer );
-       return net_transmit_via ( pkb, aoe->netdev );
+       return net_transmit ( pkb, aoe->netdev, &aoe_protocol, aoe->target );
 }
 
 /**
@@ -251,38 +252,11 @@ static int aoe_rx ( struct pk_buff *pkb ) {
        return rc;
 }
 
-/**
- * Perform AoE network-layer routing
- *
- * @v pkb      Packet buffer
- * @ret source Network-layer source address
- * @ret dest   Network-layer destination address
- * @ret rc     Return status code
- */
-static int aoe_route ( const struct pk_buff *pkb __unused,
-                      struct net_header *nethdr ) {
-       struct aoehdr *aoehdr = pkb->data;
-       struct aoe_session *aoe;
-
-       list_for_each_entry ( aoe, &aoe_sessions, list ) {
-               if ( ( ntohs ( aoehdr->major ) == aoe->major ) &&
-                    ( aoehdr->minor == aoe->minor ) ) {
-                       nethdr->flags = PKT_FL_RAW_ADDR;
-                       memcpy ( nethdr->dest_net_addr, aoe->target,
-                                sizeof ( aoe->target ) );
-                       return 0;
-               }
-       }
-               
-       return -EHOSTUNREACH;
-}
-
 /** AoE protocol */
 struct net_protocol aoe_protocol = {
        .name = "AoE",
        .net_proto = htons ( ETH_P_AOE ),
        .rx_process = aoe_rx,
-       .route = aoe_route,
 };
 
 NET_PROTOCOL ( aoe_protocol );
@@ -293,7 +267,8 @@ NET_PROTOCOL ( aoe_protocol );
  * @v aoe              AoE session
  */
 void aoe_open ( struct aoe_session *aoe ) {
-       memset ( aoe->target, 0xff, sizeof ( aoe->target ) );
+       memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
+                sizeof ( aoe->target ) );
        aoe->tag = AOE_TAG_MAGIC;
        aoe->timer.expired = aoe_timer_expired;
        list_add ( &aoe->list, &aoe_sessions );
index af7d6e1..66f9bd4 100644 (file)
@@ -92,42 +92,42 @@ arp_find_entry ( struct ll_protocol *ll_protocol,
  * Look up media-specific link-layer address in the ARP cache
  *
  * @v netdev           Network device
- * @v nethdr           Generic network-layer header
- * @ret llhdr          Generic link-layer header
+ * @v net_protocol     Network-layer protocol
+ * @v dest_net_addr    Destination network-layer address
+ * @v source_net_addr  Source network-layer address
+ * @ret dest_ll_addr   Destination link layer address
  * @ret rc             Return status code
  *
  * This function will use the ARP cache to look up the link-layer
- * address for the link-layer protocol specified in @c llhdr and the
- * network-layer protocol and address as specified in @c nethdr.  If
+ * address for the link-layer protocol associated with the network
+ * device and the given network-layer protocol and addresses.  If
  * found, the destination link-layer address will be filled in in @c
- * llhdr.
+ * dest_ll_addr.
  *
  * If no address is found in the ARP cache, an ARP request will be
  * transmitted on the specified network device and -ENOENT will be
  * returned.
  */
-int arp_resolve ( struct net_device *netdev, const struct net_header *nethdr,
-                 struct ll_header *llhdr ) {
-       struct net_protocol *net_protocol = nethdr->net_protocol;
-       struct ll_protocol *ll_protocol = llhdr->ll_protocol;
+int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol,
+                 const void *dest_net_addr, const void *source_net_addr,
+                 void *dest_ll_addr ) {
+       struct ll_protocol *ll_protocol = netdev->ll_protocol;
        const struct arp_entry *arp;
        struct pk_buff *pkb;
        struct arphdr *arphdr;
        int rc;
 
        /* Look for existing entry in ARP table */
-       arp = arp_find_entry ( ll_protocol, net_protocol,
-                              nethdr->dest_net_addr );
+       arp = arp_find_entry ( ll_protocol, net_protocol, dest_net_addr );
        if ( arp ) {
                DBG ( "ARP cache hit: %s %s => %s %s\n",
                      net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
                      ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
-               memcpy ( llhdr->dest_ll_addr, arp->ll_addr,
-                        sizeof ( llhdr->dest_ll_addr ) );
+               memcpy ( dest_ll_addr, arp->ll_addr, ll_protocol->ll_addr_len);
                return 0;
        }
        DBG ( "ARP cache miss: %s %s\n", net_protocol->name,
-             net_protocol->ntoa ( nethdr->dest_net_addr ) );
+             net_protocol->ntoa ( dest_net_addr ) );
 
        /* Allocate ARP packet */
        pkb = alloc_pkb ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
@@ -145,16 +145,17 @@ int arp_resolve ( struct net_device *netdev, const struct net_header *nethdr,
        arphdr->ar_pln = net_protocol->net_addr_len;
        arphdr->ar_op = htons ( ARPOP_REQUEST );
        memcpy ( pkb_put ( pkb, ll_protocol->ll_addr_len ),
-                llhdr->source_ll_addr, ll_protocol->ll_addr_len );
+                netdev->ll_addr, ll_protocol->ll_addr_len );
        memcpy ( pkb_put ( pkb, net_protocol->net_addr_len ),
-                nethdr->source_net_addr, net_protocol->net_addr_len );
+                source_net_addr, net_protocol->net_addr_len );
        memset ( pkb_put ( pkb, ll_protocol->ll_addr_len ),
                 0, ll_protocol->ll_addr_len );
        memcpy ( pkb_put ( pkb, net_protocol->net_addr_len ),
-                nethdr->dest_net_addr, net_protocol->net_addr_len );
+                dest_net_addr, net_protocol->net_addr_len );
 
        /* Transmit ARP request */
-       if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 )
+       if ( ( rc = net_transmit ( pkb, netdev, &arp_protocol, 
+                                  ll_protocol->ll_broadcast ) ) != 0 )
                return rc;
 
        return -ENOENT;
@@ -235,10 +236,10 @@ static int arp_rx ( struct pk_buff *pkb ) {
        arphdr->ar_op = htons ( ARPOP_REPLY );
        memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
                 arphdr->ar_hln + arphdr->ar_pln );
-       memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
+       memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
 
        /* Send reply */
-       net_transmit_via ( pkb, netdev );
+       net_transmit ( pkb, netdev, &arp_protocol, arp_target_ha (arphdr ) );
        pkb = NULL;
 
  done:
@@ -246,29 +247,6 @@ static int arp_rx ( struct pk_buff *pkb ) {
        return 0;
 }
 
-/**
- * Perform ARP network-layer routing
- *
- * @v pkb      Packet buffer
- * @ret source Network-layer source address
- * @ret dest   Network-layer destination address
- * @ret rc     Return status code
- */
-static int arp_route ( const struct pk_buff *pkb,
-                      struct net_header *nethdr ) {
-       struct arphdr *arphdr = pkb->data;
-
-       memcpy ( nethdr->source_net_addr, arp_sender_ha ( arphdr ),
-                arphdr->ar_hln );
-       memcpy ( nethdr->dest_net_addr, arp_target_ha ( arphdr ),
-                arphdr->ar_hln );
-       nethdr->flags = PKT_FL_RAW_ADDR;
-       if ( arphdr->ar_op == htons ( ARPOP_REQUEST ) )
-               nethdr->flags |= PKT_FL_BROADCAST;
-       
-       return 0;
-}
-
 /**
  * Transcribe ARP address
  *
@@ -287,7 +265,6 @@ struct net_protocol arp_protocol = {
        .name = "ARP",
        .net_proto = htons ( ETH_P_ARP ),
        .rx_process = arp_rx,
-       .route = arp_route,
        .ntoa = arp_ntoa,
 };
 
index cadcb67..f10bc60 100644 (file)
@@ -25,7 +25,6 @@
 #include <gpxe/if_ether.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/pkbuff.h>
-#include <gpxe/arp.h>
 #include <gpxe/ethernet.h>
 
 /** @file
 static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 /**
- * Perform Ethernet routing
+ * Transmit Ethernet packet
  *
- * @v nethdr   Generic network-layer header
- * @ret llhdr  Generic link-layer header
- * @ret rc     Return status code
+ * @v pkb              Packet buffer
+ * @v netdev           Network device
+ * @v net_protocol     Network-layer protocol
+ * @v ll_dest          Link-layer destination address
  *
- * Constructs the generic link-layer header based on the generic
- * network-layer header, i.e. maps network-layer addresses (e.g. IPv4
- * addresses) to MAC addresses.
- *
- * If the destination MAC address cannot be determined, an ARP request
- * is sent for the requested network-layer address and -ENOENT is
- * returned.
- */
-static int eth_route ( struct net_device *netdev,
-                      const struct net_header *nethdr,
-                      struct ll_header *llhdr ) {
-       int rc;
-
-       /* Fill in the easy bits */
-       llhdr->net_proto = nethdr->net_protocol->net_proto;
-       memcpy ( llhdr->source_ll_addr, netdev->ll_addr, ETH_ALEN );
-
-       /* Work out the destination MAC address */
-       if ( nethdr->flags & PKT_FL_BROADCAST ) {
-               memcpy ( llhdr->dest_ll_addr, eth_broadcast, ETH_ALEN );
-       } else if ( nethdr->flags & PKT_FL_RAW_ADDR ) {
-               memcpy ( llhdr->dest_ll_addr, nethdr->dest_net_addr, ETH_ALEN);
-       } else if ( nethdr->flags & PKT_FL_MULTICAST ) {
-               /* IP multicast is a special case; there exists a
-                * direct mapping from IP address to MAC address
-                */
-               assert ( nethdr->net_protocol->net_proto == htons(ETH_P_IP) );
-               llhdr->dest_ll_addr[0] = 0x01;
-               llhdr->dest_ll_addr[1] = 0x00;
-               llhdr->dest_ll_addr[2] = 0x5e;
-               llhdr->dest_ll_addr[3] = nethdr->dest_net_addr[1] & 0x7f;
-               llhdr->dest_ll_addr[4] = nethdr->dest_net_addr[2];
-               llhdr->dest_ll_addr[5] = nethdr->dest_net_addr[3];
-       } else {
-               /* Otherwise, look up the address using ARP */
-               if ( ( rc = arp_resolve ( netdev, nethdr, llhdr ) ) != 0 )
-                       return rc;
-       }
-
-       return 0;
-}
-
-/**
- * Fill in Ethernet link-layer header
- *
- * @v pkb      Packet buffer
- * @v llhdr    Generic link-layer header
- *
- * Fills in the Ethernet link-layer header in the packet buffer based
- * on information in the generic link-layer header.
+ * Prepends the Ethernet link-layer header and transmits the packet.
  */
-static void eth_fill_llh ( const struct ll_header *llhdr,
-                          struct pk_buff *pkb ) {
-       struct ethhdr *ethhdr = pkb->data;
-
-       memcpy ( ethhdr->h_dest, llhdr->dest_ll_addr, ETH_ALEN );
-       memcpy ( ethhdr->h_source, llhdr->source_ll_addr, ETH_ALEN );
-       ethhdr->h_protocol = llhdr->net_proto;
+static int eth_transmit ( struct pk_buff *pkb, struct net_device *netdev,
+                         struct net_protocol *net_protocol,
+                         const void *ll_dest ) {
+       struct ethhdr *ethhdr = pkb_push ( pkb, ETH_HLEN );
+
+       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 );
 }
 
 /**
@@ -138,7 +91,7 @@ static void eth_parse_llh ( const struct pk_buff *pkb,
  */
 static const char * eth_ntoa ( const void *ll_addr ) {
        static char buf[18]; /* "00:00:00:00:00:00" */
-       uint8_t *eth_addr = ll_addr;
+       const uint8_t *eth_addr = ll_addr;
 
        sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x",
                  eth_addr[0], eth_addr[1], eth_addr[2],
@@ -148,14 +101,13 @@ static const char * eth_ntoa ( const void *ll_addr ) {
 
 /** Ethernet protocol */
 struct ll_protocol ethernet_protocol = {
-       .name = "Ethernet",
-       .ll_proto = htons ( ARPHRD_ETHER ),
-       .ll_addr_len = ETH_ALEN,
-       .ll_header_len = ETH_HLEN,
-       .route = eth_route,
-       .fill_llh = eth_fill_llh,
-       .parse_llh = eth_parse_llh,
-       .ntoa = eth_ntoa,
+       .name           = "Ethernet",
+       .ll_proto       = htons ( ARPHRD_ETHER ),
+       .ll_addr_len    = ETH_ALEN,
+       .ll_broadcast   = eth_broadcast,
+       .transmit       = eth_transmit,
+       .parse_llh      = eth_parse_llh,
+       .ntoa           = eth_ntoa,
 };
 
 LL_PROTOCOL ( ethernet_protocol );
index ddc8281..ae3404c 100644 (file)
@@ -2,9 +2,11 @@
 #include <stdint.h>
 #include <errno.h>
 #include <byteswap.h>
+#include <malloc.h>
 #include <vsprintf.h>
+#include <gpxe/list.h>
 #include <gpxe/in.h>
-
+#include <gpxe/arp.h>
 
 #include <ip.h>
 
@@ -13,6 +15,7 @@
 #include <gpxe/pkbuff.h>
 #include <gpxe/netdevice.h>
 #include "uip/uip.h"
+#include <gpxe/ip.h>
 
 /** @file
  *
 
 struct net_protocol ipv4_protocol;
 
-/** An IPv4 routing table entry */
-struct ipv4_route {
-       /** Network address */
-       struct in_addr network;
+/** An IPv4 address/routing table entry */
+struct ipv4_miniroute {
+       /** List of miniroutes */
+       struct list_head list;
+       /** Network device */
+       struct net_device *netdev;
+       /** IPv4 address */
+       struct in_addr address;
        /** Subnet mask */
        struct in_addr netmask;
        /** Gateway address */
        struct in_addr gateway;
-       /** Gateway device */
-       struct in_addr gatewaydev;
-};
-
-enum {
-       STATIC_SINGLE_NETDEV_ROUTE = 0,
-       DEFAULT_ROUTE,
-       NUM_ROUTES
 };
 
-/** IPv4 routing table */
-static struct ipv4_route routing_table[NUM_ROUTES];
-
-#define routing_table_end ( routing_table + NUM_ROUTES )
+/** List of IPv4 miniroutes */
+static LIST_HEAD ( miniroutes );
 
-#if 0
 /**
- * Set IP address
+ * Add IPv4 interface
  *
- */
-void set_ipaddr ( struct in_addr address ) {
-       union {
-               struct in_addr address;
-               uint16_t uip_address[2];
-       } u;
-
-       u.address = address;
-       uip_sethostaddr ( u.uip_address );
-}
-
-/**
- * Set netmask
+ * @v netdev   Network device
+ * @v address  IPv4 address
+ * @v netmask  Subnet mask
+ * @v gateway  Gateway address (or @c INADDR_NONE for no gateway)
+ * @ret rc     Return status code
  *
  */
-void set_netmask ( struct in_addr address ) {
-       union {
-               struct in_addr address;
-               uint16_t uip_address[2];
-       } u;
-
-       u.address = address;
-       uip_setnetmask ( u.uip_address );
+int add_ipv4_address ( struct net_device *netdev, struct in_addr address,
+                      struct in_addr netmask, struct in_addr gateway ) {
+       struct ipv4_miniroute *miniroute;
+
+       /* Allocate and populate miniroute structure */
+       miniroute = malloc ( sizeof ( *miniroute ) );
+       if ( ! miniroute )
+               return -ENOMEM;
+       miniroute->netdev = netdev;
+       miniroute->address = address;
+       miniroute->netmask = netmask;
+       miniroute->gateway = gateway;
+       
+       /* Add to end of list if we have a gateway, otherwise to start
+        * of list.
+        */
+       if ( gateway.s_addr != INADDR_NONE ) {
+               list_add_tail ( &miniroute->list, &miniroutes );
+       } else {
+               list_add ( &miniroute->list, &miniroutes );
+       }
+       return 0;
 }
 
 /**
- * Set default gateway
+ * Remove IPv4 interface
  *
+ * @v netdev   Network device
  */
-void set_gateway ( struct in_addr address ) {
-       union {
-               struct in_addr address;
-               uint16_t uip_address[2];
-       } u;
+void del_ipv4_address ( struct net_device *netdev ) {
+       struct ipv4_miniroute *miniroute;
 
-       u.address = address;
-       uip_setdraddr ( u.uip_address );
+       list_for_each_entry ( miniroute, &miniroutes, list ) {
+               if ( miniroute->netdev == netdev ) {
+                       list_del ( &miniroute->list );
+                       break;
+               }
+       }
 }
 
 /**
- * Run the TCP/IP stack
- *
- * Call this function in a loop in order to allow TCP/IP processing to
- * take place.  This call takes the stack through a single iteration;
- * it will typically be used in a loop such as
- *
- * @code
+ * Transmit packet constructed by uIP
  *
- * struct tcp_connection *my_connection;
- * ...
- * tcp_connect ( my_connection );
- * while ( ! my_connection->finished ) {
- *   run_tcpip();
- * }
- *
- * @endcode
+ * @v pkb              Packet buffer
+ * @ret rc             Return status code
  *
- * where @c my_connection->finished is set by one of the connection's
- * #tcp_operations methods to indicate completion.
  */
-void run_tcpip ( void ) {
-       void *data;
-       size_t len;
-       uint16_t type;
-       int i;
-       
-       if ( netdev_poll ( 1, &data, &len ) ) {
-               /* We have data */
-               memcpy ( uip_buf, data, len );
-               uip_len = len;
-               type = ntohs ( *( ( uint16_t * ) ( uip_buf + 12 ) ) );
-               if ( type == UIP_ETHTYPE_ARP ) {
-                       uip_arp_arpin();
-               } else {
-                       uip_arp_ipin();
-                       uip_input();
+int ipv4_uip_transmit ( struct pk_buff *pkb ) {
+       struct iphdr *iphdr = pkb->data;
+       struct ipv4_miniroute *miniroute;
+       struct net_device *netdev = NULL;
+       struct in_addr next_hop;
+       struct in_addr source;
+       uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
+       const uint8_t *ll_dest = ll_dest_buf;
+       int rc;
+
+       /* Use routing table to identify next hop and transmitting netdev */
+       next_hop = iphdr->dest;
+       list_for_each_entry ( miniroute, &miniroutes, list ) {
+               if ( ( ( ( iphdr->dest.s_addr ^ miniroute->address.s_addr ) &
+                        miniroute->netmask.s_addr ) == 0 ) ||
+                    ( miniroute->gateway.s_addr != INADDR_NONE ) ) {
+                       netdev = miniroute->netdev;
+                       source = miniroute->address;
+                       if ( miniroute->gateway.s_addr != INADDR_NONE )
+                               next_hop = miniroute->gateway;
+                       break;
                }
-               if ( uip_len > 0 )
-                       uip_transmit();
+       }
+
+       /* Abort if no network device identified */
+       if ( ! netdev ) {
+               DBG ( "No route to %s\n", inet_ntoa ( iphdr->dest ) );
+               rc = -EHOSTUNREACH;
+               goto err;
+       }
+
+       /* Determine link-layer destination address */
+       if ( next_hop.s_addr == INADDR_BROADCAST ) {
+               /* Broadcast address */
+               ll_dest = netdev->ll_protocol->ll_broadcast;
+       } else if ( IN_MULTICAST ( next_hop.s_addr ) ) {
+               /* Special case: IPv4 multicast over Ethernet.  This
+                * code may need to be generalised once we find out
+                * what happens for other link layers.
+                */
+               uint8_t *next_hop_bytes = ( uint8_t * ) &next_hop;
+               ll_dest_buf[0] = 0x01;
+               ll_dest_buf[0] = 0x00;
+               ll_dest_buf[0] = 0x5e;
+               ll_dest_buf[3] = next_hop_bytes[1] & 0x7f;
+               ll_dest_buf[4] = next_hop_bytes[2];
+               ll_dest_buf[5] = next_hop_bytes[3];
        } else {
-               for ( i = 0 ; i < UIP_CONNS ; i++ ) {
-                       uip_periodic ( i );
-                       if ( uip_len > 0 )
-                               uip_transmit();
+               /* Unicast address: resolve via ARP */
+               if ( ( rc = arp_resolve ( netdev, &ipv4_protocol, &next_hop,
+                                         &source, ll_dest_buf ) ) != 0 ) {
+                       DBG ( "No ARP entry for %s\n",
+                             inet_ntoa ( iphdr->dest ) );
+                       goto err;
                }
        }
+       
+       /* Hand off to link layer */
+       return net_transmit ( pkb, netdev, &ipv4_protocol, ll_dest );
+
+ err:
+       free_pkb ( pkb );
+       return rc;
 }
-#endif
 
 /**
  * Process incoming IP packets
@@ -167,51 +193,25 @@ static int ipv4_rx ( struct pk_buff *pkb ) {
                pkb = alloc_pkb ( MAX_LL_HEADER_LEN + uip_len );
                if ( ! pkb )
                        return -ENOMEM;
-               pkb->net_protocol = &ipv4_protocol;
                pkb_reserve ( pkb, MAX_LL_HEADER_LEN );
                memcpy ( pkb_put ( pkb, uip_len ), uip_buf, uip_len );
-               net_transmit ( pkb );
+               ipv4_uip_transmit ( pkb );
        }
        return 0;
 }
 
 /**
- * Perform IP layer routing
+ * Convert IPv4 address to dotted-quad notation
  *
- * @v pkb      Packet buffer
- * @ret source Network-layer source address
- * @ret dest   Network-layer destination address
- * @ret rc     Return status code
+ * @v in       IP address
+ * @ret string IP address in dotted-quad notation
  */
-static int ipv4_route ( const struct pk_buff *pkb,
-                       struct net_header *nethdr ) {
-       struct iphdr *iphdr = pkb->data;
-       struct in_addr *source = ( struct in_addr * ) nethdr->source_net_addr;
-       struct in_addr *dest = ( struct in_addr * ) nethdr->dest_net_addr;
-       struct ipv4_route *route;
-
-       /* Route IP packet according to routing table */
-       source->s_addr = INADDR_NONE;
-       dest->s_addr = iphdr->dest.s_addr;
-       for ( route = routing_table ; route < routing_table_end ; route++ ) {
-               if ( ( dest->s_addr & route->netmask.s_addr )
-                    == route->network.s_addr ) {
-                       source->s_addr = route->gatewaydev.s_addr;
-                       if ( route->gateway.s_addr )
-                               dest->s_addr = route->gateway.s_addr;
-                       break;
-               }
-       }
-
-       /* Set broadcast and multicast flags as applicable */
-       nethdr->flags = 0;
-       if ( dest->s_addr == htonl ( INADDR_BROADCAST ) ) {
-               nethdr->flags = PKT_FL_BROADCAST;
-       } else if ( IN_MULTICAST ( dest->s_addr ) ) {
-               nethdr->flags = PKT_FL_MULTICAST;
-       }
-
-       return 0;
+char * inet_ntoa ( struct in_addr in ) {
+       static char buf[16]; /* "xxx.xxx.xxx.xxx" */
+       uint8_t *bytes = ( uint8_t * ) &in;
+       
+       sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
+       return buf;
 }
 
 /**
@@ -222,12 +222,7 @@ static int ipv4_route ( const struct pk_buff *pkb,
  *
  */
 static const char * ipv4_ntoa ( const void *net_addr ) {
-       static char buf[16]; /* "xxx.xxx.xxx.xxx" */
-       uint8_t *ip_addr = net_addr;
-
-       sprintf ( buf, "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2],
-                 ip_addr[3] );
-       return buf;
+       return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
 }
 
 /** IPv4 protocol */
@@ -236,7 +231,6 @@ struct net_protocol ipv4_protocol = {
        .net_proto = htons ( ETH_P_IP ),
        .net_addr_len = sizeof ( struct in_addr ),
        .rx_process = ipv4_rx,
-       .route = ipv4_route,
        .ntoa = ipv4_ntoa,
 };
 
@@ -251,12 +245,3 @@ struct net_address static_single_ipv4_address = {
 };
 
 STATIC_SINGLE_NETDEV_ADDRESS ( static_single_ipv4_address );
-
-#warning "Remove this static-IP hack"
-static struct ipv4_route routing_table[NUM_ROUTES] = {
-       { { htonl ( 0x0afefe00 ) }, { htonl ( 0xfffffffc ) },
-         { htonl ( 0x00000000 ) }, { htonl ( 0x0afefe01 ) } },
-       { { htonl ( 0x00000000 ) }, { htonl ( 0x00000000 ) },
-         { htonl ( 0x0afefe02 ) }, { htonl ( 0x0afefe01 ) } },
-};
-
index 3d4640a..1825a55 100644 (file)
@@ -62,6 +62,50 @@ static struct net_address static_single_netdev_addresses_end[0]
 /** Recevied packet queue */
 static LIST_HEAD ( rx_queue );
 
+#warning "Remove this static IP address hack"
+#include <ip.h>
+#include <gpxe/ip.h>
+
+/**
+ * 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 ) {
+       
+#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;
+}
+
+/**
+ * Unregister network device
+ *
+ * @v netdev           Network device
+ *
+ * Removes the network device from the list of network devices.
+ */
+void unregister_netdev ( struct net_device *netdev ) {
+
+#warning "Remove this static IP address hack"
+       del_ipv4_address ( netdev );
+
+}
+
 /**
  * Add packet to receive queue
  *
@@ -128,88 +172,6 @@ find_netdev_by_net_addr ( struct net_protocol *net_protocol,
        return NULL;
 }
 
-/**
- * Transmit packet via a network device
- *
- * @v pkb              Packet buffer
- * @v netdev           Network device, or NULL
- * @ret rc             Return status code
- *
- * Transmits the packet via the specified network device.  The packet
- * must begin with a network-layer header, and the @c net_protocol
- * field must have been filled in.  If @c netdev is NULL, the network
- * device is identified via the packet contents, if possible.  This
- * function takes ownership of the packet buffer.
- */
-int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
-       struct net_protocol *net_protocol;
-       struct net_header nethdr;
-       struct ll_protocol *ll_protocol;
-       struct ll_header llhdr;
-       int rc;
-
-       /* Perform network-layer routing */
-       net_protocol = pkb->net_protocol;
-       nethdr.net_protocol = net_protocol;
-       if ( ( rc = net_protocol->route ( pkb, &nethdr ) ) != 0 ) {
-               DBG ( "Could not route to %s address %s\n",
-                     net_protocol->name,
-                     net_protocol->ntoa ( nethdr.dest_net_addr ) );
-               free_pkb ( pkb );
-               return rc;
-       }
-
-       /* Identify transmitting network device, if not specified */
-       if ( ! netdev ) {
-               netdev = find_netdev_by_net_addr ( net_protocol,
-                                                  nethdr.source_net_addr );
-               if ( ! netdev ) {
-                       DBG ( "No network device for %s address %s\n",
-                             net_protocol->name,
-                             net_protocol->ntoa ( nethdr.source_net_addr ) );
-                       free_pkb ( pkb );
-                       return -EHOSTUNREACH;
-               }
-       }
-
-       /* Perform link-layer routing */
-       ll_protocol = netdev->ll_protocol;
-       llhdr.ll_protocol = ll_protocol;
-       if ( ( rc = ll_protocol->route ( netdev, &nethdr, &llhdr ) ) != 0 ) {
-               DBG ( "No link-layer route to %s address %s\n",
-                     net_protocol->name,
-                     net_protocol->ntoa ( nethdr.dest_net_addr ) );
-               free_pkb ( pkb );
-               return rc;
-       }
-
-       /* Prepend link-layer header */
-       pkb_push ( pkb, ll_protocol->ll_header_len );
-       ll_protocol->fill_llh ( &llhdr, pkb );
-
-       /* Hand off packet to network device */
-       if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
-               DBG ( "Device failed to transmit packet\n" );
-               return rc;
-       }
-       
-       DBG ( "Packet transmitted\n" );
-       return 0;
-}
-
-/**
- * Transmit packet
- *
- * @v pkb              Packet buffer
- * @ret rc             Return status code
- *
- * Transmits the packet via the appropriate network device.  This
- * function takes ownership of the packet buffer.
- */
-int net_transmit ( struct pk_buff *pkb ) {
-       return net_transmit_via ( pkb, NULL );
-}
-
 /**
  * Poll for packet on all network devices
  *
@@ -277,7 +239,8 @@ int net_rx_process ( struct pk_buff *pkb ) {
        pkb->net_protocol = net_protocol;
        
        /* Strip off link-layer header */
-       pkb_pull ( pkb, ll_protocol->ll_header_len );
+#warning "Temporary hack"
+       pkb_pull ( pkb, ETH_HLEN );
        
        /* Hand off to network layer */
        if ( ( rc = net_protocol->rx_process ( pkb ) ) != 0 ) {
index 06ab2ee..5027678 100644 (file)
@@ -176,9 +176,8 @@ static void tcp_periodic ( void ) {
                        pkb_reserve ( pkb, MAX_LL_HEADER_LEN );
                        pkb_put ( pkb, uip_len );
                        memcpy ( pkb->data, uip_buf, uip_len );
-                       pkb->net_protocol = &ipv4_protocol;
-                       
-                       net_transmit ( pkb );
+
+                       ipv4_uip_transmit ( pkb );
                }
        }
 }