diff --git a/src/include/gpxe/tcpip_if.h b/src/include/gpxe/tcpip_if.h index bac39699..ce095efa 100644 --- a/src/include/gpxe/tcpip_if.h +++ b/src/include/gpxe/tcpip_if.h @@ -83,7 +83,7 @@ extern void trans_rx ( struct pk_buff *pkb, uint8_t trans_proto, 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 uint16_t calc_chksum ( void *b, int 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 ); diff --git a/src/include/gpxe/udp.h b/src/include/gpxe/udp.h index e6511160..68034583 100644 --- a/src/include/gpxe/udp.h +++ b/src/include/gpxe/udp.h @@ -41,6 +41,23 @@ struct udp_connection; * */ struct udp_operations { + + /** + * Transmit data + * + * @v conn UDP connection + * @v buf Temporary data buffer + * @v len Length of temporary data buffer + * + * The application may use the temporary data buffer to + * construct the data to be sent. Note that merely filling + * the buffer will do nothing; the application must call + * udp_send() in order to actually transmit the data. Use of + * the buffer is not compulsory; the application may call + * udp_send() on any block of data. + */ + void ( * senddata ) ( struct tcp_connection *conn, void *buf, + size_t len ); /** * New data received * @@ -69,11 +86,6 @@ struct udp_connection { struct udp_operations *udp_op; }; -/** - * List of registered UDP connections - */ -static LIST_HEAD ( udp_conns ); - /** * UDP protocol */ diff --git a/src/net/tcpip_if.c b/src/net/tcpip_if.c index 5c5e5962..80d69268 100644 --- a/src/net/tcpip_if.c +++ b/src/net/tcpip_if.c @@ -107,30 +107,19 @@ int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, /** * 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" + * @v b Pointer to the data + * @v len Length of data to be checksummed + * @ret result 16 bit internet checksum */ -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; +uint16_t calc_chksum(void *b, int len) { + uint16_t *buf = b, result; + uint16_t sum=0; + for ( sum = 0; len > 1; len -= 2 ) /* Sum all 16b words */ + sum += *buf++; + if ( len == 1 ) /* If any stray bytes, */ + sum += *(unsigned char*)buf; /* add to sum */ + sum = (sum >> 16) + (sum & 0xffff); /* Add the carry */ + sum += (sum >> 16); /* (again) */ + result = ~sum; /* Take the one's complement */ + return result; /* Return 16b value */ } - - diff --git a/src/net/udp.c b/src/net/udp.c index b84d5161..0fca99a4 100644 --- a/src/net/udp.c +++ b/src/net/udp.c @@ -18,6 +18,14 @@ * UDP protocol */ +/** + * List of registered UDP connections + */ +static LIST_HEAD ( udp_conns ); + +/** + * Some utility functions + */ static inline void copy_sockaddr ( struct sockaddr *source, struct sockaddr *dest ) { memcpy ( dest, source, sizeof ( *dest ) ); } @@ -98,7 +106,27 @@ int udp_buf_alloc ( struct udp_connection *conn, size_t len ) { } /** - * Send data via a UDP connection + * User request to send data via a UDP connection + * + * @v conn UDP connection + * + * This function allocates buffer space and invokes the function's senddata() + * callback. The callback may use the buffer space + */ +int udp_senddata ( struct udp_connection *conn ) { + conn->tx_pkb = pkb_alloc ( UDP_MAX_TXPKB ); + if ( conn->tx_pkb == NULL ) { + DBG ( "Error allocating packet buffer of length %d\n", + UDP_MAX_TXPKB ); + return -ENOMEM; + } + conn->udp_op->senddata ( conn, conn->tx_pkb, pkb_len ( conn->tx_pkb ) ); + return 0; +} + + +/** + * Transmit data via a UDP connection * * @v conn UDP connection * @v data Data to send @@ -124,7 +152,7 @@ int udp_send ( struct udp_connection *conn, const void *data, size_t len ) { /* Reserve space for the headers and copy contents */ pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN ); - memcpy ( pkb_put ( conn->tx_pkb, len ), data, len ); + memmove ( pkb_put ( conn->tx_pkb, len ), data, len ); } /*