[netdevice] Split multicast hashing out into an mc_hash method
authorMichael Brown <mcb30@etherboot.org>
Wed, 15 Oct 2008 01:00:44 +0000 (02:00 +0100)
committerMichael Brown <mcb30@etherboot.org>
Thu, 16 Oct 2008 04:12:56 +0000 (05:12 +0100)
Multicast hashing is an ugly overlap between network and link layers.
EFI requires us to provide access to this functionality, so move it
out of ipv4.c and expose it as a method of the link layer.

src/drivers/net/ipoib.c
src/include/gpxe/netdevice.h
src/net/ethernet.c
src/net/ipv4.c

index 9c9bc91..47090bb 100644 (file)
@@ -222,6 +222,21 @@ const char * ipoib_ntoa ( const void *ll_addr ) {
        return buf;
 }
 
+/**
+ * Hash multicast address
+ *
+ * @v af               Address family
+ * @v net_addr         Network-layer address
+ * @v ll_addr          Link-layer address to fill in
+ * @ret rc             Return status code
+ */
+static int ipoib_mc_hash ( unsigned int af __unused,
+                          const void *net_addr __unused,
+                          void *ll_addr __unused ) {
+
+       return -ENOTSUP;
+}
+
 /** IPoIB protocol */
 struct ll_protocol ipoib_protocol __ll_protocol = {
        .name           = "IPoIB",
@@ -232,6 +247,7 @@ struct ll_protocol ipoib_protocol __ll_protocol = {
        .push           = ipoib_push,
        .pull           = ipoib_pull,
        .ntoa           = ipoib_ntoa,
+       .mc_hash        = ipoib_mc_hash,
 };
 
 /****************************************************************************
index 9f39e0c..3109db8 100644 (file)
@@ -120,6 +120,16 @@ struct ll_protocol {
         * allocated.
         */
        const char * ( * ntoa ) ( const void * ll_addr );
+       /**
+        * Hash multicast address
+        *
+        * @v af        Address family
+        * @v net_addr  Network-layer address
+        * @v ll_addr   Link-layer address to fill in
+        * @ret rc      Return status code
+        */
+       int ( * mc_hash ) ( unsigned int af, const void *net_addr,
+                           void *ll_addr );
        /** Link-layer protocol
         *
         * This is an ARPHRD_XXX constant, in network byte order.
index 7b1c496..ebb551f 100644 (file)
@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <gpxe/if_arp.h>
 #include <gpxe/if_ether.h>
+#include <gpxe/in.h>
 #include <gpxe/netdevice.h>
 #include <gpxe/iobuf.h>
 #include <gpxe/ethernet.h>
@@ -92,8 +93,8 @@ static int eth_pull ( struct io_buffer *iobuf,
 /**
  * Transcribe Ethernet address
  *
- * @v ll_addr  Link-layer address
- * @ret string Link-layer address in human-readable format
+ * @v ll_addr          Link-layer address
+ * @ret string         Link-layer address in human-readable format
  */
 const char * eth_ntoa ( const void *ll_addr ) {
        static char buf[18]; /* "00:00:00:00:00:00" */
@@ -105,6 +106,32 @@ const char * eth_ntoa ( const void *ll_addr ) {
        return buf;
 }
 
+/**
+ * Hash multicast address
+ *
+ * @v af               Address family
+ * @v net_addr         Network-layer address
+ * @v ll_addr          Link-layer address to fill in
+ * @ret rc             Return status code
+ */
+static int eth_mc_hash ( unsigned int af, const void *net_addr,
+                        void *ll_addr ) {
+       const uint8_t *net_addr_bytes = net_addr;
+       uint8_t *ll_addr_bytes = ll_addr;
+
+       switch ( af ) {
+       case AF_INET:
+               ll_addr_bytes[0] = 0x01;
+               ll_addr_bytes[1] = 0x00;
+               ll_addr_bytes[2] = 0x5e;
+               ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f;
+               ll_addr_bytes[4] = net_addr_bytes[2];
+               ll_addr_bytes[5] = net_addr_bytes[3];
+       default:
+               return -ENOTSUP;
+       }
+}
+
 /** Ethernet protocol */
 struct ll_protocol ethernet_protocol __ll_protocol = {
        .name           = "Ethernet",
@@ -115,4 +142,5 @@ struct ll_protocol ethernet_protocol __ll_protocol = {
        .push           = eth_push,
        .pull           = eth_pull,
        .ntoa           = eth_ntoa,
+       .mc_hash        = eth_mc_hash,
 };
index 82a13c3..e14ed6a 100644 (file)
@@ -266,7 +266,6 @@ static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
 static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
                          struct net_device *netdev, uint8_t *ll_dest ) {
        struct ll_protocol *ll_protocol = netdev->ll_protocol;
-       uint8_t *dest_bytes = ( ( uint8_t * ) &dest );
 
        if ( dest.s_addr == INADDR_BROADCAST ) {
                /* Broadcast address */
@@ -274,17 +273,7 @@ static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
                         ll_protocol->ll_addr_len );
                return 0;
        } else if ( IN_MULTICAST ( ntohl ( dest.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.
-                */
-               ll_dest[0] = 0x01;
-               ll_dest[1] = 0x00;
-               ll_dest[2] = 0x5e;
-               ll_dest[3] = dest_bytes[1] & 0x7f;
-               ll_dest[4] = dest_bytes[2];
-               ll_dest[5] = dest_bytes[3];
-               return 0;
+               return ll_protocol->mc_hash ( AF_INET, &dest, ll_dest );
        } else {
                /* Unicast address: resolve via ARP */
                return arp_resolve ( netdev, &ipv4_protocol, &dest,