From 5b3a8f73a2eccd20452b8e2d628df024b925b44e Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Fri, 9 Dec 2005 07:16:39 +0000 Subject: [PATCH 1/1] Implementado el checksum de UDP, tanto para paquetes recibidos como para paquetes enviados. --- src/dp8390.c | 25 ++++++++++++++++++++----- src/dp8390.h | 2 +- src/main.c | 22 +++++++++++++++------- src/netdev.h | 9 ++++++++- src/udp.c | 53 ++++++++++++++++++++++++++++++++++++++++++---------- src/udp.h | 20 +++++++++++++------- 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/src/dp8390.c b/src/dp8390.c index c56bb84..5c472a5 100644 --- a/src/dp8390.c +++ b/src/dp8390.c @@ -247,6 +247,10 @@ bool netdev_init() /** Comienza el envío de un nuevo frame */ void netdev_send_start() { + // Wait until pending transmit operation completes. + while (read_reg(CR) & TXP) continue; + write_reg(ISR, PTX); // Limpio bit de interrupción + // Set remote DMA start address registers to indicate where to load packet. write_reg(RSAR0, 0u); write_reg(RSAR1, TX_PAGE_START); @@ -272,15 +276,26 @@ void netdev_send_end(byte len) // Issue command for RTL8019AS to transmit packet from it's local buffer. write_reg(CR, START | TXP); - - // Wait until pending transmit operation completes. - while(read_reg(CR) & TXP) continue; } void netdev_write_start(byte len) { // Set remote DMA byte count registers to indicate length of packet load. - write_reg(RBCR0, len); // Tamaño máximo en principio + write_reg(RBCR0, len); + write_reg(RBCR1, 0u); + + // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS. + write_reg(CR, WRITE); +} + +void netdev_write_start_at(byte offset, byte len) +{ + // Set remote DMA start address registers to packet data. + write_reg(RSAR0, offset); + write_reg(RSAR1, TX_PAGE_START); + + // Set remote DMA byte count registers to indicate length of packet load. + write_reg(RBCR0, len); write_reg(RBCR1, 0u); // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS. @@ -333,7 +348,7 @@ byte netdev_recv_start() printb(read_reg(ISR), 0x01); printb(read_reg(BNRY), 0x02); printb(current, 0x04); - ledsb(0x00, 0x00); + printb(0x00, 0x00); reset(); } return 0; diff --git a/src/dp8390.h b/src/dp8390.h index 7587ec3..dfd19d6 100644 --- a/src/dp8390.h +++ b/src/dp8390.h @@ -30,7 +30,7 @@ sbit NICE = CTRL_PORT^2; // A7, usado para activar placa de red // Configuración de paǵinas de buffers #define TX_PAGE_START 0x40 // 0x4000 Tx buffer: 256 bytes (usamos 128) -#define RX_PAGE_START 0x46 // 0x4600 Rx buffer: 31 * 256 = 7936 bytes +#define RX_PAGE_START 0x41 // 0x4600 Rx buffer: 31 * 256 = 7936 bytes #define RX_PAGE_STOP 0x60 // 0x6000 // Register base address diff --git a/src/main.c b/src/main.c index 18df512..60ed5db 100644 --- a/src/main.c +++ b/src/main.c @@ -32,8 +32,10 @@ void main(void) { byte buf[64]; //XXX byte i; //XXX + byte len; - if (!netdev_recv_start()) // no recibimos nada (válido) + len = netdev_recv_start(); + if (!len) // no recibimos nada (válido) continue; // Probamos de nuevo // Tenemos algo! @@ -72,21 +74,27 @@ void main(void) //printb(udp_dgram_len, 0x40); // TODO // Nuestro protocolo, por ahora un simple echo! - netdev_read_start(udp_dgram_len-UDP_HEADER_SIZE); - for (i = 0; i < udp_dgram_len-UDP_HEADER_SIZE; ++i) - buf[i] = netdev_read_byte(); + len = udp_dgram_len - UDP_HEADER_SIZE; + netdev_read_start(len); + for (i = 0; i < len; ++i) + buf[i] = udp_read_byte(); netdev_read_end(); + if (!udp_checksum_ok()) + goto drop; netdev_recv_end(); // Respuesta netdev_send_start(); eth_write_frame_header(); + //udp_dgram_len = UDP_HEADER_SIZE+len; + //ip_packet_len = IP_HEADER_SIZE+udp_dgram_len; ip_write_packet_header(); udp_write_dgram_header(); - netdev_write_start(udp_dgram_len-UDP_HEADER_SIZE); - for (i = 0; i < udp_dgram_len-UDP_HEADER_SIZE; ++i) - netdev_write_byte(buf[i]); + netdev_write_start(len); + for (i = 0; i < len; ++i) + udp_write_byte(buf[i]); netdev_write_end(); + udp_write_checksum(ETH_HEADER_SIZE+IP_HEADER_SIZE); netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len); } } diff --git a/src/netdev.h b/src/netdev.h index 175313c..27bbb3b 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -23,11 +23,18 @@ void netdev_send_start(); */ void netdev_send_end(byte len); -/** Comienza una transferencia al dispositivo de red +/** Comienza una escritura a los buffers del dispositivo de red * @param len Cantidad de bytes a escribir */ void netdev_write_start(byte len); +/** Comienza una escritura a los buffers del dispositivo de red a partir de un + * offset dado. + * @param offset Offset en donde comenzar a escribir + * @param len Cantidad de bytes a escribir + */ +void netdev_write_start_at(byte offset, byte len); + /** Escribe un byte al buffer de la placa de red para ser enviado * @precond netdev_write_start() debe haber sido ejecutada * @param b Byte a enviar diff --git a/src/udp.c b/src/udp.c index f8264b1..09b9bfc 100644 --- a/src/udp.c +++ b/src/udp.c @@ -1,5 +1,6 @@ // vim: set et sw=4 sts=4 : +#include "debug.h" #include "netdev.h" #include "ip.h" #include "udp.h" @@ -12,6 +13,8 @@ byte udp_dgram_len; /* para calcular checksum */ static uint16 checksum; +static byte byte_count; +static byte last_byte; /* agrega un word al checksum calculado */ static void sum(uint16 w) @@ -28,6 +31,7 @@ bool udp_read_dgram_header() netdev_read_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; + byte_count = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ /* ip de origen */ sum(WORD(ip_addr_remote[0], ip_addr_remote[1])); @@ -66,16 +70,29 @@ bool udp_read_dgram_header() return true; } -uint16 udp_read_word() +byte udp_read_byte() { - uint16 w = netdev_read_word(); - sum(w); - return w; + byte b; + if (byte_count % 2) // impar, tengo 2, sumo + { + b = netdev_read_byte(); + sum(WORD(last_byte, b)); + } + else // par, guardo para sumar cuando tenga 2 + { + b = netdev_read_byte(); + last_byte = b; + } + ++byte_count; + return b; } bool udp_checksum_ok() { - return (uint16)~checksum; + // Verifico si falta sumar algo (UDP debe sumar de a un word) + if (byte_count == (udp_dgram_len - UDP_HEADER_SIZE)) + sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00 + return !(uint16)~checksum; } void udp_write_dgram_header() @@ -83,6 +100,7 @@ void udp_write_dgram_header() netdev_write_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; + byte_count = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ /* ip de origen */ sum(WORD(ip_addr_remote[0], ip_addr_remote[1])); @@ -110,15 +128,30 @@ void udp_write_dgram_header() netdev_write_end(); } -void udp_write_word(uint16 w) +void udp_write_byte(byte b) { - sum(w); - netdev_write_word(w); + if (byte_count % 2) // impar, tengo 2, sumo + { + netdev_write_byte(b); + sum(WORD(last_byte, b)); + } + else // par, guardo para sumar cuando tenga 2 + { + netdev_write_byte(b); + last_byte = b; + } + ++byte_count; } -void udp_write_checksum() +void udp_write_checksum(byte offset) { - // XXX TODO FIXME + // Verifico si falta sumar algo (UDP debe sumar de a un word) + if (byte_count == (udp_dgram_len - UDP_HEADER_SIZE)) + sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00 + // Escribo checksum en el buffer de la placa de red + netdev_write_start_at(offset + 6, 2); // 6 bytes de offset hasta el checksum + netdev_write_word((uint16)~checksum); // Guardo checksum + netdev_write_end(); return; } diff --git a/src/udp.h b/src/udp.h index d636776..d08d03f 100644 --- a/src/udp.h +++ b/src/udp.h @@ -61,7 +61,7 @@ extern uint16 udp_port_local; /** Puerto UDP de destino */ extern uint16 udp_port_remote; -/** Tamaño del datagrama UDP */ +/** Tamaño del datagrama UDP (no soportamos más de 255) */ extern byte udp_dgram_len; /** Lee la cabecera del datagrama UDP. @@ -72,8 +72,10 @@ extern byte udp_dgram_len; */ bool udp_read_dgram_header(); -/** Recibe un word del payload UDP chequeando el checksum. */ -uint16 udp_read_word(); +/** Recibe un word del payload UDP chequeando el checksum. + * @precond Hay que llamar antes a netdev_read_start() + */ +byte udp_read_byte(); /* Indica si el checksum calculado está ok */ bool udp_checksum_ok(); @@ -85,10 +87,14 @@ bool udp_checksum_ok(); */ void udp_write_dgram_header(); -/** Escribe un word al payload UDP chequeando el checksum. */ -void udp_write_word(uint16 w); +/** Escribe un word al payload UDP chequeando el checksum. + * @precond Hay que llamar antes a netdev_write_start() + */ +void udp_write_byte(byte b); -/* Escribe el checksum calculado al frame a enviar */ -void udp_write_checksum(); +/* Escribe el checksum calculado al frame a enviar + * @param offset Offset a partir de donde están las cabeceras UDP. + */ +void udp_write_checksum(byte offset); #endif /* _UDP_H_ */ -- 2.43.0