From c9ea71093067ccf1d8473df257d55da39f8f74da Mon Sep 17 00:00:00 2001 From: Nikhil Chandru Rao Date: Wed, 28 Jun 2006 15:43:08 +0000 Subject: [PATCH] Renamed net/interface.c and include/gpxe/interface.h to net/tcpip_if.c and include/gpxe/tcpip_if.h respectively. Made changes in the other files. --- src/include/gpxe/ip.h | 4 +- src/include/gpxe/tcpip_if.h | 91 ++++++++++++++++++++++++ src/include/gpxe/udp.h | 5 ++ src/net/ipv4.c | 42 ++++++++--- src/net/tcpip_if.c | 136 ++++++++++++++++++++++++++++++++++++ src/net/udp.c | 10 +-- 6 files changed, 273 insertions(+), 15 deletions(-) create mode 100644 src/include/gpxe/tcpip_if.h create mode 100644 src/net/tcpip_if.c diff --git a/src/include/gpxe/ip.h b/src/include/gpxe/ip.h index e497dd79..a6c59064 100644 --- a/src/include/gpxe/ip.h +++ b/src/include/gpxe/ip.h @@ -32,6 +32,7 @@ struct ipv4_pseudo_header { struct pk_buff; struct net_device; struct net_protocol; +struct tcpip_protocol; extern struct net_protocol ipv4_protocol; @@ -41,6 +42,7 @@ extern int add_ipv4_address ( struct net_device *netdev, extern void del_ipv4_address ( struct net_device *netdev ); extern int ipv4_uip_tx ( struct pk_buff *pkb ); -extern int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest ); +extern int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, + struct in_addr *dest ); #endif /* _GPXE_IP_H */ diff --git a/src/include/gpxe/tcpip_if.h b/src/include/gpxe/tcpip_if.h new file mode 100644 index 00000000..bac39699 --- /dev/null +++ b/src/include/gpxe/tcpip_if.h @@ -0,0 +1,91 @@ +#ifndef _GPXE_INTERFACE_H +#define _GPXE_INTERFACE_H + +/** @file + * + * Transport-network layer interface + * + */ + +#include +#include +#include + +struct pk_buff; +struct net_protocol; +struct tcpip_protocol; +struct tcpip_net_protocol; + +/** + * A transport-layer protocol of the TCPIP stack (eg. UDP, TCP, etc) + */ +struct tcpip_protocol { + /** Protocol name */ + const char *name; + /** + * Process received packet + * + * @v pkb Packet buffer + * @v netdev Network device + * @v ll_source Link-layer source address + * + * This method takes ownership of the packet buffer. + */ + void ( * rx ) ( struct pk_buff *pkb, struct in_addr *src_net_addr, struct in_addr *dest_net_addr ); + /** + * Transport-layer protocol number + * + * This is a constant of the type IP_XXX + */ + uint8_t trans_proto; + /** + * Checksum offset + * + * A negative number indicates that the protocol does not require + * checksumming to be performed by the network layer. A positive number is + * the offset of the checksum field in the transport-layer header. + */ + int csum_offset; +}; + +/** + * A TCPIP supporting network-layer protocol + */ +struct tcpip_net_protocol { + /** Network protocol */ + struct net_protocol *net_protocol; + /** Network address family */ + sa_family_t sa_family; + /** Complete transport-layer checksum calculation + * + * @v pkb Packet buffer + * @v tcpip Transport-layer protocol + * + */ + void ( * tx_csum ) ( struct pk_buff *pkb, + struct tcpip_protocol *tcpip ); +}; + +/** + * Register a transport-layer protocol + * + * @v protocol Transport-layer protocol + */ +#define TCPIP_PROTOCOL( protocol ) \ + struct tcpip_protocol protocol __table ( tcpip_protocols, 01 ) + +#define TCPIP_NET_PROTOCOL( protocol ) \ + struct tcpip_net_protocol protocol __table ( tcpip_net_protocols, 01 ) + +extern void trans_rx ( struct pk_buff *pkb, uint8_t trans_proto, + struct in_addr *src, struct in_addr *dest ); + +extern int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, + struct sockaddr *dest ); + +extern uint16_t calc_chksum ( void *data, size_t len ); + +extern struct tcpip_protocol * find_tcpip_protocol ( uint8_t trans_proto ); +extern struct tcpip_net_protocol * find_tcpip_net_protocol ( sa_family_t sa_family ); + +#endif /* _GPXE_INTERFACE_H */ diff --git a/src/include/gpxe/udp.h b/src/include/gpxe/udp.h index faad6c2d..e6511160 100644 --- a/src/include/gpxe/udp.h +++ b/src/include/gpxe/udp.h @@ -74,6 +74,11 @@ struct udp_connection { */ static LIST_HEAD ( udp_conns ); +/** + * UDP protocol + */ +extern struct tcpip_protocol udp_protocol; + /** * Functions provided to the application layer */ diff --git a/src/net/ipv4.c b/src/net/ipv4.c index b770301a..9669b07d 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -12,7 +12,7 @@ #include #include "uip/uip.h" #include -#include +#include /** @file * @@ -103,6 +103,7 @@ void del_ipv4_address ( struct net_device *netdev ) { * @v iphdr IPv4 header */ static void ipv4_dump ( struct iphdr *iphdr __unused ) { + DBG ( "IP4 header at %p+%zx\n", iphdr, sizeof ( *iphdr ) ); DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 ); DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN ); @@ -120,12 +121,19 @@ static void ipv4_dump ( struct iphdr *iphdr __unused ) { /** * Complete the transport-layer checksum + * + * @v pkb Packet buffer + * @v tcpip Transport-layer protocol + * + * This function calculates the tcpip */ -void ipv4_tx_csum ( struct pk_buff *pkb, uint8_t trans_proto ) { +void ipv4_tx_csum ( struct pk_buff *pkb, struct tcpip_protocol *tcpip ) { struct iphdr *iphdr = pkb->data; struct ipv4_pseudo_header pshdr; - void *csum_offset = iphdr + sizeof ( *iphdr ) + ( trans_proto == IP_UDP ? 6 : 16 ); + void *csum_offset = iphdr + sizeof ( *iphdr ) + tcpip->csum_offset; + uint16_t partial_csum = *( ( uint16_t* ) csum_offset ); + uint16_t csum; /* Calculate pseudo header */ pshdr.src = iphdr->src; @@ -135,14 +143,19 @@ void ipv4_tx_csum ( struct pk_buff *pkb, uint8_t trans_proto ) { pshdr.len = htons ( pkb_len ( pkb ) - sizeof ( *iphdr ) ); /* Update the checksum value */ - *( ( uint16_t* ) csum_offset ) = *( ( uint16_t* ) csum_offset ) + calc_chksum ( &pshdr, IP_PSHLEN ); + csum = partial_csum + calc_chksum ( &pshdr, sizeof ( pshdr ) ); + memcpy ( csum_offset, &csum, 2 ); } /** * Calculate the transport-layer checksum while processing packets */ -uint16_t ipv4_rx_csum ( struct pk_buff *pkb __unused, uint8_t trans_proto __unused ) { - /** This function needs to be implemented. Until then, it will return 0xffffffff every time */ +uint16_t ipv4_rx_csum ( struct pk_buff *pkb __unused, + uint8_t trans_proto __unused ) { + /** + * This function needs to be implemented. Until then, it will return + * 0xffffffff every time + */ return 0xffff; } @@ -222,13 +235,14 @@ int ipv4_uip_tx ( struct pk_buff *pkb ) { * Transmit IP packet (without uIP) * * @v pkb Packet buffer - * @v trans_proto Transport-layer protocol number + * @v tcpip Transport-layer protocol * @v dest Destination network-layer address * @ret rc Status * * This function expects a transport-layer segment and prepends the IP header */ -int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest ) { +int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, + struct in_addr *dest ) { struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) ); struct ipv4_miniroute *miniroute; struct net_device *netdev = NULL; @@ -244,7 +258,7 @@ int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest ) iphdr->ident = htons ( next_ident++ ); iphdr->frags = 0; iphdr->ttl = IP_TTL; - iphdr->protocol = trans_proto; + iphdr->protocol = tcpip->trans_proto; /* Copy destination address */ iphdr->dest = *dest; @@ -280,7 +294,7 @@ int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest ) } /* Calculate the transport layer checksum */ - ipv4_tx_csum ( pkb, trans_proto ); + ipv4_tx_csum ( pkb, tcpip ); /* Calculate header checksum, in network byte order */ iphdr->chksum = 0; @@ -477,6 +491,14 @@ struct net_protocol ipv4_protocol = { NET_PROTOCOL ( ipv4_protocol ); +/** IPv4 TCPIP net protocol */ +struct tcpip_net_protocol ipv4_tcpip_protocol = { + .net_protocol = &ipv4_protocol, + .tx_csum = ipv4_tx_csum, +}; + +TCPIP_NET_PROTOCOL ( ipv4_tcpip_protocol ); + /** IPv4 ARP protocol */ struct arp_net_protocol ipv4_arp_protocol = { .net_protocol = &ipv4_protocol, diff --git a/src/net/tcpip_if.c b/src/net/tcpip_if.c new file mode 100644 index 00000000..5c5e5962 --- /dev/null +++ b/src/net/tcpip_if.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * Transport-network layer interface + * + * This file contains functions and utilities for the transport-network layer interface + */ + +/** Registered network-layer protocols that support TCPIP */ +static struct tcpip_net_protocol tcpip_net_protocols[0] __table_start ( tcpip_net_protocols ); +static struct tcpip_net_protocol tcpip_net_protocols_end[0] __table_end ( tcpip_net_protocols ); + +struct tcpip_protocol; + +/** Registered transport-layer protocols that support TCPIP */ +static struct tcpip_protocol tcpip_protocols[0] __table_start ( tcpip_protocols ); +static struct tcpip_protocol tcpip_protocols_end[0] __table_end ( tcpip_protocols ); + +/** Identify TCPIP network-layer protocol + * + * @v sa_family Network address family + * @ret tcpip Protocol supporting TCPIP, or NULL + */ +static struct tcpip_net_protocol * tcpip_find_protocol ( sa_family_t sa_family ) { + struct tcpip_net_protocol *tcpip_net; + + for ( tcpip_net = tcpip_net_protocols; + tcpip_net < tcpip_net_protocols_end; ++tcpip_net ) { + if ( tcpip_net->sa_family == sa_family ) { + return tcpip_net; + } + } + return NULL; +} + +/** Identify TCPIP transport-layer protocol + * + * @v trans_proto Transport-layer protocol number, IP_XXX + * @ret tcpip_protocol Transport-layer protocol, or NULL + */ +struct tcpip_protocol* find_tcpip_protocol ( uint8_t trans_proto ) { + struct tcpip_protocol *tcpip; + + for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; + ++tcpip ) { + if ( tcpip->trans_proto == trans_proto ) { + return tcpip; + } + } + return NULL; +} + +/** Process a received packet + * + * @v pkb Packet buffer + * @v trans_proto Transport-layer protocol number + * @v src Source network-layer address + * @v dest Destination network-layer address + * + * This function expects a transport-layer segment from the network-layer + */ +void trans_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src, + struct in_addr *dest ) { + struct tcpip_protocol *tcpip; + + /* Identify the transport layer protocol */ + for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; ++tcpip ) { + if ( tcpip->trans_proto == trans_proto ) { + DBG ( "Packet sent to %s module", tcpip->name ); + tcpip->rx ( pkb, src, dest ); + } + } +} + +/** Transmit a transport-layer segment + * + * @v pkb Packet buffer + * @v trans_proto Transport-layer protocol + * @v sock Destination socket address + * @ret Status + */ +int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, + struct sockaddr *sock ) { + + /* Identify the network layer protocol and send it using xxx_tx() */ + switch ( sock->sa_family ) { + case AF_INET: /* IPv4 network family */ + return ipv4_tx ( pkb, tcpip, &sock->sin.sin_addr ); + case AF_INET6: /* IPv6 network family */ + return ipv6_tx ( pkb, tcpip, &sock->sin6.sin6_addr ); + } + DBG ( "Network family %d not supported", sock->sa_family ); + return -EAFNOSUPPORT; +} + +/** + * Calculate internet checksum + * + * @v data Pointer to the data + * @v len Length of data to be checksummed + * @ret chksum 16 bit internet checksum + * + * This function calculates the internet checksum (refer RFC1071) for "len" + * bytes beginning at the location "data" + */ +uint16_t calc_chksum ( void *data, size_t len ) { + register long sum = 0; + uint16_t checksum; + unsigned short *temp; + while ( len > 1 ) { + temp = (unsigned short*) data++; + sum += *temp; + len -= 2; + } + if ( len > 0 ) { + sum += *(unsigned char *)data; + } + while ( sum >> 16 ) { + sum = ( sum & 0xffff ) + ( sum >> 16 ); + } + checksum = ~sum; + return checksum; +} + + diff --git a/src/net/udp.c b/src/net/udp.c index abfa7595..4a82e976 100644 --- a/src/net/udp.c +++ b/src/net/udp.c @@ -6,11 +6,12 @@ #include #include #include +#include #include #include #include #include -#include +#include /** @file * @@ -149,7 +150,7 @@ int udp_send ( struct udp_connection *conn, const void *data, size_t len ) { udp_dump ( udphdr ); /* Send it to the next layer for processing */ - return trans_tx ( conn->tx_pkb, IP_UDP, sock ); + return trans_tx ( conn->tx_pkb, &udp_protocol, sock ); } /** @@ -268,10 +269,11 @@ void udp_rx ( struct pk_buff *pkb, struct in_addr *src_net_addr __unused, conn->udp_op->newdata ( conn, pkb->data, ulen - sizeof ( *udphdr ) ); } -struct trans_protocol udp_protocol = { +struct tcpip_protocol udp_protocol = { .name = "UDP", .rx = udp_rx, .trans_proto = IP_UDP, + .csum_offset = 6, }; -TRANS_PROTOCOL ( udp_protocol ); +TCPIP_PROTOCOL ( udp_protocol );