Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[netdevice] Split multicast hashing out into an mc_hash method
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.
  • Loading branch information
Michael Brown committed Oct 16, 2008
1 parent 8326681 commit 6b9cc25
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 14 deletions.
16 changes: 16 additions & 0 deletions src/drivers/net/ipoib.c
Expand Up @@ -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",
Expand All @@ -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,
};

/****************************************************************************
Expand Down
10 changes: 10 additions & 0 deletions src/include/gpxe/netdevice.h
Expand Up @@ -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.
Expand Down
32 changes: 30 additions & 2 deletions src/net/ethernet.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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" */
Expand All @@ -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",
Expand All @@ -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,
};
13 changes: 1 addition & 12 deletions src/net/ipv4.c
Expand Up @@ -266,25 +266,14 @@ 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 */
memcpy ( ll_dest, ll_protocol->ll_broadcast,
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,
Expand Down

0 comments on commit 6b9cc25

Please sign in to comment.