mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-26 03:09:12 +00:00
Network layer now works as a proof of concept
This commit is contained in:
parent
1488cd3b73
commit
129c6c3968
@ -7,10 +7,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
struct net_device;
|
||||
struct net_header;
|
||||
struct ll_header;
|
||||
|
||||
extern int arp_resolve ( const struct net_header *nethdr,
|
||||
extern int arp_resolve ( struct net_device *netdev,
|
||||
const struct net_header *nethdr,
|
||||
struct ll_header *llhdr );
|
||||
|
||||
#endif /* _GPXE_ARP_H */
|
||||
|
@ -11,12 +11,16 @@
|
||||
#include <gpxe/tables.h>
|
||||
|
||||
struct pk_buff;
|
||||
struct net_device;
|
||||
struct net_protocol;
|
||||
struct ll_protocol;
|
||||
|
||||
/** Maximum length of a link-layer address */
|
||||
#define MAX_LL_ADDR_LEN 6
|
||||
|
||||
/** Maximum length of a link-layer header */
|
||||
#define MAX_LL_HEADER_LEN 16
|
||||
|
||||
/** Maximum length of a network-layer address */
|
||||
#define MAX_NET_ADDR_LEN 4
|
||||
|
||||
@ -32,37 +36,37 @@ struct ll_protocol;
|
||||
struct net_header {
|
||||
/** Network-layer protocol */
|
||||
struct net_protocol *net_protocol;
|
||||
/** Destination address flags
|
||||
/** Flags
|
||||
*
|
||||
* This is the bitwise OR of zero or more NETADDR_FL_XXX
|
||||
* This is the bitwise OR of zero or more PKT_FL_XXX
|
||||
* values.
|
||||
*/
|
||||
int dest_flags;
|
||||
int flags;
|
||||
/** Network-layer destination address */
|
||||
uint8_t dest_net_addr[MAX_NET_ADDR_LEN];
|
||||
/** Network-layer source address */
|
||||
uint8_t source_net_addr[MAX_NET_ADDR_LEN];
|
||||
};
|
||||
|
||||
/** Address is a broadcast address */
|
||||
#define NETADDR_FL_BROADCAST 0x01
|
||||
/** Packet is a broadcast packet */
|
||||
#define PKT_FL_BROADCAST 0x01
|
||||
|
||||
/** Address is a multicast address */
|
||||
#define NETADDR_FL_MULTICAST 0x02
|
||||
/** Packet is a multicast packet */
|
||||
#define PKT_FL_MULTICAST 0x02
|
||||
|
||||
/** Address is a raw hardware address */
|
||||
#define NETADDR_FL_RAW 0x04
|
||||
/** Addresses are raw hardware addresses */
|
||||
#define PKT_FL_RAW_ADDR 0x04
|
||||
|
||||
/** A generic link-layer header */
|
||||
struct ll_header {
|
||||
/** Link-layer protocol */
|
||||
struct ll_protocol *ll_protocol;
|
||||
/** Destination address flags
|
||||
/** Flags
|
||||
*
|
||||
* This is the bitwise OR of zero or more NETADDR_FL_XXX
|
||||
* This is the bitwise OR of zero or more PKT_FL_XXX
|
||||
* values.
|
||||
*/
|
||||
int dest_flags;
|
||||
int flags;
|
||||
/** Link-layer destination address */
|
||||
uint8_t dest_ll_addr[MAX_LL_ADDR_LEN];
|
||||
/** Link-layer source address */
|
||||
@ -80,21 +84,21 @@ struct ll_header {
|
||||
*
|
||||
*/
|
||||
struct net_protocol {
|
||||
/** Protocol name */
|
||||
const char *name;
|
||||
/**
|
||||
* Perform network-layer routing
|
||||
*
|
||||
* @v pkb Packet buffer
|
||||
* @ret source Network-layer source address
|
||||
* @ret dest Network-layer destination address
|
||||
* @v nethdr Generic network-layer header
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* This method should fill in the source and destination
|
||||
* addresses with enough information to allow the link layer
|
||||
* to route the packet.
|
||||
* 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 @c source with the IP addresses of the local adapter and
|
||||
* @c dest with the next hop destination (e.g. the gateway).
|
||||
* 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 );
|
||||
@ -108,6 +112,19 @@ struct net_protocol {
|
||||
* the packet buffer.
|
||||
*/
|
||||
int ( * rx ) ( struct pk_buff *pkb );
|
||||
/**
|
||||
* Transcribe network-layer address
|
||||
*
|
||||
* @v net_addr Network-layer address
|
||||
* @ret string Human-readable transcription of address
|
||||
*
|
||||
* This method should convert the network-layer address into a
|
||||
* human-readable format (e.g. dotted quad notation for IPv4).
|
||||
*
|
||||
* The buffer used to hold the transcription is statically
|
||||
* allocated.
|
||||
*/
|
||||
const char * ( *ntoa ) ( const void * net_addr );
|
||||
/** Network-layer protocol
|
||||
*
|
||||
* This is an ETH_P_XXX constant, in network-byte order
|
||||
@ -122,9 +139,12 @@ struct net_protocol {
|
||||
*
|
||||
*/
|
||||
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
|
||||
@ -137,7 +157,8 @@ struct ll_protocol {
|
||||
* return an error (after transmitting an ARP request, if
|
||||
* applicable).
|
||||
*/
|
||||
int ( * route ) ( const struct net_header *nethdr,
|
||||
int ( * route ) ( struct net_device *netdev,
|
||||
const struct net_header *nethdr,
|
||||
struct ll_header *llhdr );
|
||||
/**
|
||||
* Fill media-specific link-layer header
|
||||
@ -164,6 +185,19 @@ struct ll_protocol {
|
||||
void ( * parse_llh ) ( const struct pk_buff *pkb,
|
||||
struct ll_header *llhdr );
|
||||
|
||||
/**
|
||||
* Transcribe link-layer address
|
||||
*
|
||||
* @v ll_addr Link-layer address
|
||||
* @ret string Human-readable transcription of address
|
||||
*
|
||||
* This method should convert the link-layer address into a
|
||||
* human-readable format.
|
||||
*
|
||||
* The buffer used to hold the transcription is statically
|
||||
* allocated.
|
||||
*/
|
||||
const char * ( *ntoa ) ( const void * ll_addr );
|
||||
/** Link-layer protocol
|
||||
*
|
||||
* This is an ARPHRD_XXX constant, in network byte order.
|
||||
@ -290,13 +324,30 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit raw packet via network device
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v pkb Packet buffer
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Transmits the packet via the specified network device. The
|
||||
* link-layer header must already have been filled in. If this
|
||||
* function returns success, it has taken ownership of the packet
|
||||
* buffer.
|
||||
*/
|
||||
static inline int netdev_transmit ( struct net_device *netdev,
|
||||
struct pk_buff *pkb ) {
|
||||
return netdev->transmit ( netdev, pkb );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a link-layer protocol
|
||||
*
|
||||
* @v protocol Link-layer protocol
|
||||
*/
|
||||
#define LL_PROTOCOL( protocol ) \
|
||||
struct ll_protocol protocol __table ( ll_protocols, 00 )
|
||||
struct ll_protocol protocol __table ( ll_protocols, 01 )
|
||||
|
||||
/**
|
||||
* Register a network-layer protocol
|
||||
@ -304,7 +355,7 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
|
||||
* @v protocol Network-layer protocol
|
||||
*/
|
||||
#define NET_PROTOCOL( protocol ) \
|
||||
struct net_protocol protocol __table ( net_protocols, 00 )
|
||||
struct net_protocol protocol __table ( net_protocols, 01 )
|
||||
|
||||
/**
|
||||
* Register a network-layer address for the static single network device
|
||||
@ -312,15 +363,17 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
|
||||
* @v net_address Network-layer address
|
||||
*/
|
||||
#define STATIC_SINGLE_NETDEV_ADDRESS( address ) \
|
||||
struct net_address address __table ( sgl_netdev_addresses, 00 )
|
||||
struct net_address address __table ( sgl_netdev_addresses, 01 )
|
||||
|
||||
extern struct net_protocol *net_find_protocol ( uint16_t net_proto );
|
||||
extern struct net_device * net_find_address ( struct net_protocol *net_proto,
|
||||
void *net_addr );
|
||||
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 void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb );
|
||||
extern struct pk_buff * net_rx_dequeue ( void );
|
||||
|
||||
#endif /* _GPXE_NETDEVICE_H */
|
||||
|
@ -91,6 +91,7 @@ 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
|
||||
* @ret rc Return status code
|
||||
@ -102,9 +103,11 @@ arp_find_entry ( struct ll_protocol *ll_protocol,
|
||||
* llhdr.
|
||||
*
|
||||
* If no address is found in the ARP cache, an ARP request will be
|
||||
* transmitted and -ENOENT will be returned.
|
||||
* transmitted on the specified network device and -ENOENT will be
|
||||
* returned.
|
||||
*/
|
||||
int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) {
|
||||
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;
|
||||
const struct arp_entry *arp;
|
||||
@ -116,17 +119,23 @@ int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) {
|
||||
arp = arp_find_entry ( ll_protocol, net_protocol,
|
||||
nethdr->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 ) );
|
||||
return 0;
|
||||
}
|
||||
DBG ( "ARP cache miss: %s %s\n", net_protocol->name,
|
||||
net_protocol->ntoa ( nethdr->dest_net_addr ) );
|
||||
|
||||
/* Allocate ARP packet */
|
||||
pkb = alloc_pkb ( sizeof ( *arphdr ) +
|
||||
pkb = alloc_pkb ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
|
||||
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 */
|
||||
arphdr = pkb_put ( pkb, sizeof ( *arphdr ) );
|
||||
@ -145,7 +154,7 @@ int arp_resolve ( const struct net_header *nethdr, struct ll_header *llhdr ) {
|
||||
nethdr->dest_net_addr, net_protocol->net_addr_len );
|
||||
|
||||
/* Transmit ARP request */
|
||||
if ( ( rc = net_transmit ( pkb ) ) != 0 ) {
|
||||
if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 ) {
|
||||
free_pkb ( pkb );
|
||||
return rc;
|
||||
}
|
||||
@ -175,7 +184,7 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
|
||||
/* Identify link-layer and network-layer protocols */
|
||||
ll_protocol = pkb->ll_protocol;
|
||||
net_protocol = net_find_protocol ( arphdr->ar_pro );
|
||||
net_protocol = find_net_protocol ( arphdr->ar_pro );
|
||||
if ( ! net_protocol )
|
||||
goto done;
|
||||
|
||||
@ -192,10 +201,14 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ),
|
||||
arphdr->ar_hln );
|
||||
merge = 1;
|
||||
DBG ( "ARP cache update: %s %s => %s %s\n",
|
||||
net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
|
||||
ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
|
||||
}
|
||||
|
||||
/* See if we own the target protocol address */
|
||||
netdev = net_find_address ( net_protocol, arp_target_pa ( arphdr ) );
|
||||
netdev = find_netdev_by_net_addr ( net_protocol,
|
||||
arp_target_pa ( arphdr ) );
|
||||
if ( ! netdev )
|
||||
goto done;
|
||||
|
||||
@ -208,6 +221,9 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
arphdr->ar_hln );
|
||||
memcpy ( arp->net_addr, arp_sender_pa ( arphdr ),
|
||||
arphdr->ar_pln);
|
||||
DBG ( "ARP cache add: %s %s => %s %s\n",
|
||||
net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
|
||||
ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
|
||||
}
|
||||
|
||||
/* If it's not a request, there's nothing more to do */
|
||||
@ -215,11 +231,14 @@ static int arp_rx ( struct pk_buff *pkb ) {
|
||||
goto done;
|
||||
|
||||
/* Change request to a reply, and send it */
|
||||
DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
|
||||
net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
|
||||
ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
|
||||
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 );
|
||||
if ( net_transmit ( pkb ) == 0 )
|
||||
if ( net_transmit_via ( pkb, netdev ) == 0 )
|
||||
pkb = NULL;
|
||||
|
||||
done:
|
||||
@ -243,18 +262,33 @@ static int arp_route ( const struct pk_buff *pkb,
|
||||
arphdr->ar_hln );
|
||||
memcpy ( nethdr->dest_net_addr, arp_target_ha ( arphdr ),
|
||||
arphdr->ar_hln );
|
||||
nethdr->dest_flags = NETADDR_FL_RAW;
|
||||
nethdr->flags = PKT_FL_RAW_ADDR;
|
||||
if ( arphdr->ar_op == htons ( ARPOP_REQUEST ) )
|
||||
nethdr->dest_flags |= NETADDR_FL_BROADCAST;
|
||||
nethdr->flags |= PKT_FL_BROADCAST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transcribe ARP address
|
||||
*
|
||||
* @v net_addr ARP address
|
||||
* @ret string "<ARP>"
|
||||
*
|
||||
* This operation is meaningless for the ARP protocol.
|
||||
*/
|
||||
static const char *
|
||||
arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
|
||||
return "<ARP>";
|
||||
}
|
||||
|
||||
/** ARP protocol */
|
||||
struct net_protocol arp_protocol = {
|
||||
.name = "ARP",
|
||||
.net_proto = htons ( ETH_P_ARP ),
|
||||
.rx = arp_rx,
|
||||
.route = arp_route,
|
||||
.ntoa = arp_ntoa,
|
||||
};
|
||||
|
||||
NET_PROTOCOL ( arp_protocol );
|
||||
|
@ -51,16 +51,21 @@ static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
* is sent for the requested network-layer address and -ENOENT is
|
||||
* returned.
|
||||
*/
|
||||
static int eth_route ( const struct net_header *nethdr,
|
||||
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->dest_flags & NETADDR_FL_RAW ) {
|
||||
memcpy ( llhdr->dest_ll_addr, nethdr->dest_net_addr, ETH_ALEN);
|
||||
} else if ( nethdr->dest_flags & NETADDR_FL_BROADCAST ) {
|
||||
if ( nethdr->flags & PKT_FL_BROADCAST ) {
|
||||
memcpy ( llhdr->dest_ll_addr, eth_broadcast, ETH_ALEN );
|
||||
} else if ( nethdr->dest_flags & NETADDR_FL_MULTICAST ) {
|
||||
} 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
|
||||
*/
|
||||
@ -73,7 +78,7 @@ static int eth_route ( const struct net_header *nethdr,
|
||||
llhdr->dest_ll_addr[5] = nethdr->dest_net_addr[3];
|
||||
} else {
|
||||
/* Otherwise, look up the address using ARP */
|
||||
if ( ( rc = arp_resolve ( nethdr, llhdr ) ) != 0 )
|
||||
if ( ( rc = arp_resolve ( netdev, nethdr, llhdr ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -116,22 +121,40 @@ static void eth_parse_llh ( const struct pk_buff *pkb,
|
||||
llhdr->net_proto = ethhdr->h_protocol;
|
||||
|
||||
if ( memcmp ( ethhdr->h_dest, eth_broadcast, ETH_ALEN ) == 0 ) {
|
||||
llhdr->dest_flags = NETADDR_FL_BROADCAST;
|
||||
llhdr->flags = PKT_FL_BROADCAST;
|
||||
} else if ( ethhdr->h_dest[0] & 0x01 ) {
|
||||
llhdr->dest_flags = NETADDR_FL_MULTICAST;
|
||||
llhdr->flags = PKT_FL_MULTICAST;
|
||||
} else {
|
||||
llhdr->dest_flags = 0;
|
||||
llhdr->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transcribe Ethernet address
|
||||
*
|
||||
* @v ll_addr Link-layer address
|
||||
* @ret string Link-layer address in human-readable format
|
||||
*/
|
||||
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;
|
||||
|
||||
sprintf ( buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
eth_addr[0], eth_addr[1], eth_addr[2],
|
||||
eth_addr[3], eth_addr[4], eth_addr[5] );
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** 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,
|
||||
};
|
||||
|
||||
LL_PROTOCOL ( ethernet_protocol );
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <byteswap.h>
|
||||
#include <vsprintf.h>
|
||||
#include <gpxe/in.h>
|
||||
|
||||
|
||||
@ -153,7 +154,8 @@ static int ipv4_rx ( struct pk_buff *pkb ) {
|
||||
/* Transfer to uIP buffer. Horrendously space-inefficient,
|
||||
* but will do as a proof-of-concept for now.
|
||||
*/
|
||||
memcpy ( uip_buf, pkb->data, pkb_len ( pkb ) );
|
||||
uip_len = pkb_len ( pkb );
|
||||
memcpy ( uip_buf, pkb->data, uip_len );
|
||||
|
||||
/* Hand to uIP for processing */
|
||||
uip_input ();
|
||||
@ -198,22 +200,40 @@ static int ipv4_route ( const struct pk_buff *pkb,
|
||||
}
|
||||
|
||||
/* Set broadcast and multicast flags as applicable */
|
||||
nethdr->dest_flags = 0;
|
||||
nethdr->flags = 0;
|
||||
if ( dest->s_addr == htonl ( INADDR_BROADCAST ) ) {
|
||||
nethdr->dest_flags = NETADDR_FL_BROADCAST;
|
||||
nethdr->flags = PKT_FL_BROADCAST;
|
||||
} else if ( IN_MULTICAST ( dest->s_addr ) ) {
|
||||
nethdr->dest_flags = NETADDR_FL_MULTICAST;
|
||||
nethdr->flags = PKT_FL_MULTICAST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transcribe IP address
|
||||
*
|
||||
* @v net_addr IP address
|
||||
* @ret string IP address in dotted-quad notation
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/** IPv4 protocol */
|
||||
struct net_protocol ipv4_protocol = {
|
||||
.net_proto = ETH_P_IP,
|
||||
.name = "IP",
|
||||
.net_proto = htons ( ETH_P_IP ),
|
||||
.net_addr_len = sizeof ( struct in_addr ),
|
||||
.rx = ipv4_rx,
|
||||
.route = ipv4_route,
|
||||
.ntoa = ipv4_ntoa,
|
||||
};
|
||||
|
||||
NET_PROTOCOL ( ipv4_protocol );
|
||||
@ -221,6 +241,18 @@ NET_PROTOCOL ( ipv4_protocol );
|
||||
/** IPv4 address for the static single net device */
|
||||
struct net_address static_single_ipv4_address = {
|
||||
.net_protocol = &ipv4_protocol,
|
||||
|
||||
#warning "Remove this static-IP hack"
|
||||
.net_addr = { 0x0a, 0xfe, 0xfe, 0x01 },
|
||||
};
|
||||
|
||||
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 ) } },
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,22 @@ static struct net_address static_single_netdev_addresses_end[0]
|
||||
/** Recevied packet queue */
|
||||
static LIST_HEAD ( rx_queue );
|
||||
|
||||
/**
|
||||
* Add packet to receive queue
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v pkb Packet buffer
|
||||
*
|
||||
* The packet is added to the RX queue. Ownership of the packet is
|
||||
* transferred to the RX queue; the caller must not touch the packet
|
||||
* buffer after calling netdev_rx().
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify network protocol
|
||||
*
|
||||
@ -69,7 +85,7 @@ static LIST_HEAD ( rx_queue );
|
||||
* Identify a network-layer protocol from a protocol number, which
|
||||
* must be an ETH_P_XXX constant in network-byte order.
|
||||
*/
|
||||
struct net_protocol * net_find_protocol ( uint16_t net_proto ) {
|
||||
struct net_protocol * find_net_protocol ( uint16_t net_proto ) {
|
||||
struct net_protocol *net_protocol;
|
||||
|
||||
for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
|
||||
@ -93,8 +109,9 @@ struct net_protocol * net_find_protocol ( uint16_t net_proto ) {
|
||||
* Note that even with a static single network device, this function
|
||||
* can still return NULL.
|
||||
*/
|
||||
struct net_device * net_find_address ( struct net_protocol *net_protocol,
|
||||
void *net_addr ) {
|
||||
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;
|
||||
|
||||
@ -106,9 +123,77 @@ struct net_device * net_find_address ( struct net_protocol *net_protocol,
|
||||
net_protocol->net_addr_len ) == 0 ) )
|
||||
return netdev;
|
||||
}
|
||||
|
||||
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. If this
|
||||
* function returns success, it has taken 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 ) );
|
||||
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 ) );
|
||||
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 ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Prepend link-layer header */
|
||||
pkb_push ( pkb, ll_protocol->ll_header_len );
|
||||
ll_protocol->fill_llh ( &llhdr, pkb );
|
||||
|
||||
/* Transmit packet */
|
||||
if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
|
||||
DBG ( "Device failed to transmit packet\n" );
|
||||
return rc;
|
||||
}
|
||||
|
||||
DBG ( "Packet transmitted\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit packet
|
||||
*
|
||||
@ -120,46 +205,7 @@ struct net_device * net_find_address ( struct net_protocol *net_protocol,
|
||||
* buffer.
|
||||
*/
|
||||
int net_transmit ( struct pk_buff *pkb ) {
|
||||
struct net_protocol *net_protocol;
|
||||
struct net_header nethdr;
|
||||
struct ll_protocol *ll_protocol;
|
||||
struct ll_header llhdr;
|
||||
struct net_device *netdev;
|
||||
int rc;
|
||||
|
||||
/* Perform network-layer routing */
|
||||
net_protocol = pkb->net_protocol;
|
||||
nethdr.net_protocol = net_protocol;
|
||||
if ( ( rc = net_protocol->route ( pkb, &nethdr ) ) != 0 )
|
||||
goto err;
|
||||
|
||||
/* Identify transmitting network device */
|
||||
netdev = net_find_address ( net_protocol, nethdr.source_net_addr );
|
||||
if ( ! netdev )
|
||||
goto err;
|
||||
|
||||
/* Perform link-layer routing */
|
||||
ll_protocol = netdev->ll_protocol;
|
||||
llhdr.ll_protocol = ll_protocol;
|
||||
llhdr.net_proto = net_protocol->net_proto;
|
||||
memcpy ( llhdr.source_ll_addr, netdev->ll_addr,
|
||||
ll_protocol->ll_addr_len);
|
||||
if ( ( rc = ll_protocol->route ( &nethdr, &llhdr ) ) != 0 )
|
||||
goto err;
|
||||
|
||||
/* Prepend link-layer header */
|
||||
pkb_push ( pkb, ll_protocol->ll_header_len );
|
||||
ll_protocol->fill_llh ( &llhdr, pkb );
|
||||
|
||||
/* Transmit packet */
|
||||
if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 )
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free_pkb ( pkb );
|
||||
return rc;
|
||||
return net_transmit_via ( pkb, NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,26 +220,12 @@ int net_transmit ( struct pk_buff *pkb ) {
|
||||
int net_poll ( void ) {
|
||||
struct net_device *netdev = &static_single_netdev;
|
||||
|
||||
DBG ( "Polling network\n" );
|
||||
netdev->poll ( netdev );
|
||||
|
||||
return ( ! list_empty ( &rx_queue ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add packet to receive queue
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v pkb Packet buffer
|
||||
*
|
||||
* The packet is added to the RX queue. Ownership of the packet is
|
||||
* transferred to the RX queue; the caller must not touch the packet
|
||||
* buffer after calling netdev_rx().
|
||||
*/
|
||||
void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
|
||||
pkb->ll_protocol = netdev->ll_protocol;
|
||||
list_add_tail ( &pkb->list, &rx_queue );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove packet from receive queue
|
||||
*
|
||||
@ -225,22 +257,26 @@ void net_run ( void ) {
|
||||
ll_protocol->parse_llh ( pkb, &llhdr );
|
||||
|
||||
/* Identify network-layer protocol */
|
||||
net_protocol = net_find_protocol ( llhdr.net_proto );
|
||||
net_protocol = find_net_protocol ( llhdr.net_proto );
|
||||
if ( ! net_protocol ) {
|
||||
DBG ( "Unknown network-layer protocol %02x\n",
|
||||
DBG ( "Unknown network-layer protocol %x\n",
|
||||
ntohs ( llhdr.net_proto ) );
|
||||
free_pkb ( pkb );
|
||||
continue;
|
||||
}
|
||||
pkb->net_protocol = net_protocol;
|
||||
|
||||
/* Strip off link-layer header */
|
||||
pkb_pull ( pkb, ll_protocol->ll_header_len );
|
||||
|
||||
/* Hand off to network layer */
|
||||
if ( net_protocol->rx ( pkb ) != 0 ) {
|
||||
DBG ( "Network-layer protocol refused packet\n" );
|
||||
free_pkb ( pkb );
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG ( "Processed received packet\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user