From 2cf7241a2ec32fd51b6d859c2eb0317b23739609 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Fri, 9 Dec 2005 02:55:32 +0000 Subject: [PATCH] =?utf8?q?Nueva=20manejo=20de=20buffers,=20un=20poco=20m?= =?utf8?q?=C3=A1s=20modular.=20El=20proyecto=20qued=C3=B3=20como=20un=20ec?= =?utf8?q?ho=20server=20de=20UDP=20en=20el=20puerto=209876,=20es=20decir,?= =?utf8?q?=20recibe=20un=20paquete=20y=20lo=20contesta=20con=20el=20mismo?= =?utf8?q?=20contenido=20a=20qui=C3=A9n=20lo=20envi=C3=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/dp8390.c | 207 +++++++++++++++++++++++---------------------------- src/dp8390.h | 10 +-- src/eth.c | 17 +++-- src/eth.h | 3 + src/ip.c | 70 +++++++++-------- src/ip.h | 3 + src/main.c | 40 ++++++---- src/netdev.h | 53 +++++++++---- src/udp.c | 35 +++++---- src/udp.h | 3 + 10 files changed, 242 insertions(+), 199 deletions(-) diff --git a/src/dp8390.c b/src/dp8390.c index 2943554..c56bb84 100644 --- a/src/dp8390.c +++ b/src/dp8390.c @@ -7,22 +7,17 @@ /** Tamaño del frame */ byte netdev_len; -/// Datos persistentes del módulo -static union // Unión porque nunca se usan ambos juntos +// Próximo frame a obtener +static struct { - byte send_len; ///> Tamaño del frame que será enviado - byte next_pkt; ///> Próximo frame a obtener + byte next_buf; + byte curr_buf; + byte curr_off; } -persistent; - -/// Estructura de la cabecera del buffer de la placa de red. -struct buf_hdr_t -{ - byte status; ///> Estado del frame recibido - byte next; ///> Offset del próximo frame - uint16 len; ///> Tamaño del frame -}; +recv_state; +/// Tamaño de la cabecera de los buffers de la placa de red +#define BUF_HDR_SIZE 4 /// Cambia de página sin modificar los demás bits del CR #define SELECT_REG_PAGE(page) \ @@ -249,21 +244,43 @@ bool netdev_init() } -/** Comienza el envío de un nuevo frame - * @param len Tamaño del frame a enviar - */ +/** Comienza el envío de un nuevo frame */ void netdev_send_start() { - persistent.send_len = 0; - // Wait until pending transmit operation completes. - while(read_reg(CR) & TXP) continue; - // Set remote DMA start address registers to indicate where to load packet. write_reg(RSAR0, 0u); write_reg(RSAR1, TX_PAGE_START); +} + +/** Finaliza el envío del frame + * @precond netdev_send_start() debe haber sido ejecutada + * @precond se copiaron datos al dispositivo para enviar + * @param len Cantidad de bytes a transmitir + */ +void netdev_send_end(byte len) +{ + // Set transmit page start to indicate packet start. + write_reg(TPSR, TX_PAGE_START); + + // Ethernet packets must be > 60 bytes, otherwise are rejected as runts. + if (len < MIN_PACKET_LEN) + len = MIN_PACKET_LEN; + + // Set transmit byte count registers to indicate packet length. + write_reg(TBCR0, len); + write_reg(TBCR1, 0u); + + // 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, MAX_PACKET_LEN); // Tamaño máximo en principio + write_reg(RBCR0, len); // Tamaño máximo en principio write_reg(RBCR1, 0u); // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS. @@ -274,9 +291,8 @@ void netdev_send_start() * @precond netdev_send_start() debe haber sido ejecutada * @param b Byte a enviar */ -void netdev_send_byte(byte b) +void netdev_write_byte(byte b) { - persistent.send_len++; write_reg(RDMA, b); } @@ -284,46 +300,23 @@ void netdev_send_byte(byte b) * @precond netdev_send_start() debe haber sido ejecutada * @param w Word a enviar */ -void netdev_send_word(uint16 w) +void netdev_write_word(uint16 w) { - persistent.send_len += 2; write_reg(RDMA, HIGH(w)); write_reg(RDMA, LOW(w)); } -/** Finaliza el envío del frame - * @precond netdev_send_start() debe haber sido ejecutada - */ -void netdev_send_end() +void netdev_write_end() { // Abort/ complete DMA operation. ABORT_DMA(START); - - // Set transmit page start to indicate packet start. - write_reg(TPSR, TX_PAGE_START); - - // Ethernet packets must be > 60 bytes, otherwise are rejected as runts. - if (persistent.send_len < MIN_PACKET_LEN) - { - persistent.send_len = MIN_PACKET_LEN; - } - - // Set transmit byte count registers to indicate packet length. - write_reg(TBCR0, LOW(persistent.send_len)); - write_reg(TBCR1, 0u); - - // Issue command for RTL8019AS to transmit packet from it's local buffer. - write_reg(CR, START | TXP); } /** Comienza la lectura de un nuevo frame - * @precond netdev_recv_start() debe haber sido ejecutada + * @return Cantidad de bytes a recibir */ -void netdev_recv_start() +byte netdev_recv_start() { - // Limpio tamaño del frame - netdev_len = 0; - // Check if the rx buffer has overflowed. if (read_reg(ISR) & OVW) { @@ -340,25 +333,24 @@ void netdev_recv_start() printb(read_reg(ISR), 0x01); printb(read_reg(BNRY), 0x02); printb(current, 0x04); + ledsb(0x00, 0x00); reset(); } - return; + return 0; } // Check if there is a packet in the rx buffer. else if (read_reg(ISR) & PRX) { - struct buf_hdr_t buf_hdr; + byte status; + byte len; byte current; - byte bnry; // Retrieve packet header. (status, next_ptr, length_l, length_h) - // Set remote DMA start address registers to packet header. - bnry = read_reg(BNRY) + 1; - if (bnry >= RX_PAGE_STOP) - bnry = RX_PAGE_START; - write_reg(RSAR0, 0u); - write_reg(RSAR1, bnry); + // Obtiene el buffer a leer actualmente + recv_state.curr_buf = read_reg(BNRY) + 1; + if (recv_state.curr_buf >= RX_PAGE_STOP) + recv_state.curr_buf = RX_PAGE_START; // Select RTL8019AS register page 1. SELECT_REG_PAGE(1); @@ -370,70 +362,74 @@ void netdev_recv_start() SELECT_REG_PAGE(0); // Check if last packet has been removed from rx buffer. - if(bnry == current) + if(recv_state.curr_buf == current) { // Clear packet received interrupt flag. write_reg(ISR, PRX | RXE); - return; + return 0; } // Set remote DMA byte count registers to packet header length. - write_reg(RBCR0, sizeof(struct buf_hdr_t)); - write_reg(RBCR1, 0x00); - - // Clear remote DMA complete interrupt status register bit. - write_reg(ISR, RDC); - - // Initiate DMA transfer of packet header. - write_reg(CR, READ); + recv_state.curr_off = 0; + netdev_read_start(BUF_HDR_SIZE); // Packet status. - buf_hdr.status = read_reg(RDMA); + status = netdev_read_byte(); // Save next packet pointer. - buf_hdr.next = read_reg(RDMA); - - // Indicamos cual es el próximo paquete para cuando termine - // FIXME poner más lindo para que consuma menos memoria - persistent.next_pkt = buf_hdr.next - 1; + recv_state.next_buf = netdev_read_byte() - 1; // Retrieve packet data length and subtract CRC bytes. - buf_hdr.len = read_reg(RDMA) - sizeof(struct buf_hdr_t); + len = netdev_read_byte() - BUF_HDR_SIZE; // Si es muy grande, muy chico o hubo error, lo descartamos - if ((buf_hdr.len < MIN_PACKET_LEN) || (buf_hdr.len > MAX_PACKET_LEN) - || ((buf_hdr.status & 0x0F) != RXSOK) - || read_reg(RDMA)) // Parte alta del tamaño + if ((len < MIN_PACKET_LEN) || (len > MAX_PACKET_LEN) + || ((status & 0x0F) != RXSOK) + || netdev_read_byte()) // Parte alta del tamaño { // Terminamos DMA y pasamos al próximo frame - ABORT_DMA(START); - write_reg(BNRY, persistent.next_pkt); - return; + netdev_read_end(); + write_reg(BNRY, recv_state.next_buf); + return 0; } // Abort/ complete DMA operation. - ABORT_DMA(START); + netdev_read_end(); - // Todo OK, empezamos a recibir así que ponemos bien el tamaño del frame - netdev_len = buf_hdr.len; + return len; + } - // Set remote DMA start address registers to packet data. - write_reg(RSAR0, sizeof(struct buf_hdr_t)); - write_reg(RSAR1, bnry); + return 0; +} - // Set remote DMA byte count registers to packet data length. - write_reg(RBCR0, buf_hdr.len); - write_reg(RBCR1, 0u); +/** Finaliza la recepción del frame + * @precond netdev_recv_start() debe haber sido ejecutada + */ +void netdev_recv_end() +{ + // Pasa el próximo frame + write_reg(BNRY, recv_state.next_buf); +} - // Initiate DMA transfer of packet data. - write_reg(CR, READ); - } +void netdev_read_start(byte len) +{ + // Set remote DMA start address registers to packet data. + write_reg(RSAR0, recv_state.curr_off); + write_reg(RSAR1, recv_state.curr_buf); + recv_state.curr_off += len; + + // Set remote DMA byte count registers to packet data length. + write_reg(RBCR0, len); + write_reg(RBCR1, 0); + + // Initiate DMA transfer of packet data. + write_reg(CR, READ); } /** Lee un byte del buffer de la placa de red * @precond netdev_recv_start() debe haber sido ejecutada */ -byte netdev_recv_byte() +byte netdev_read_byte() { return read_reg(RDMA); } @@ -441,31 +437,18 @@ byte netdev_recv_byte() /** Lee un word del buffer de la placa de red * @precond netdev_recv_start() debe haber sido ejecutada */ -uint16 netdev_recv_word() +uint16 netdev_read_word() { - uint16 w = netdev_recv_byte() << 8; - return w + netdev_recv_byte(); + uint16 w = read_reg(RDMA) << 8; + return w + read_reg(RDMA); } /** Finaliza la lectura del frame * @precond netdev_recv_start() debe haber sido ejecutada */ -void netdev_recv_end() +void netdev_read_end() { - // Termina de leer bytes de padding (si hay) - netdev_len += sizeof(struct buf_hdr_t); - if (read_reg(CRDA0) < netdev_len) - { - netdev_len -= read_reg(CRDA0) - 1; // El puntero está adelantado en 1 - while (netdev_len--) - { - //printb(read_reg(CRDA0), netdev_len); - netdev_recv_byte(); - } - } // Completa DMA ABORT_DMA(START); - // Pasa el próximo frame - write_reg(BNRY, persistent.next_pkt); } diff --git a/src/dp8390.h b/src/dp8390.h index a11854c..7587ec3 100644 --- a/src/dp8390.h +++ b/src/dp8390.h @@ -24,15 +24,15 @@ sbit IOR = CTRL_PORT^5; // ISA slot pin B14, RTL8019AS pin 29, active low sbit NICE = CTRL_PORT^2; // A7, usado para activar placa de red #endif -// Configuración de paǵinas de buffers -#define TX_PAGE_START 0x40 // 0x4000 Tx buffer: 6 * 256 = 1536 bytes -#define RX_PAGE_START 0x46 // 0x4600 Rx buffer: 26 * 256 = 6656 bytes -#define RX_PAGE_STOP 0x60 // 0x6000 - // Límites de tamaño de paquete #define MIN_PACKET_LEN 60u // Mínimo permitido por 802.3 #define MAX_PACKET_LEN 128u // Mínimo permitido por nuestra escasa memoria =) +// 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_STOP 0x60 // 0x6000 + // Register base address #define REG_BASE 0x0000 // Hardwired to 0x0300 diff --git a/src/eth.c b/src/eth.c index 9085dbb..ee40aac 100644 --- a/src/eth.c +++ b/src/eth.c @@ -17,15 +17,16 @@ bool eth_read_frame_header() { /* variable para iterar */ byte i; + netdev_read_start(ETH_HEADER_SIZE); /* descarto MAC de destino, acepto broadcasts */ for (i = 0; i < ETH_ADDR_SIZE; ++i) - netdev_recv_byte(); + netdev_read_byte(); /* obtenemos MAC de origen */ for (i = 0; i < ETH_ADDR_SIZE; ++i) - eth_addr_remote[i] = netdev_recv_byte(); + eth_addr_remote[i] = netdev_read_byte(); /* obtenemos tipo de protocolo transportado por el frame, (sólo * aceptamos IP y ARP) */ - switch (netdev_recv_word()) + switch (netdev_read_word()) { case IP: eth_proto = ETH_IP; @@ -34,8 +35,10 @@ bool eth_read_frame_header() eth_proto = ETH_ARP; break; default: + netdev_read_end(); return false; /* drop */ } + netdev_read_end(); return true; } @@ -43,13 +46,15 @@ void eth_write_frame_header() { /* variable para iterar */ byte i; + netdev_write_start(ETH_HEADER_SIZE); /* mandamos como MAC de destino la remota */ for (i = 0; i < ETH_ADDR_SIZE; ++i) - netdev_send_byte(eth_addr_remote[i]); + netdev_write_byte(eth_addr_remote[i]); /* y como fuente la nuestra */ for (i = 0; i < ETH_ADDR_SIZE; ++i) - netdev_send_byte(eth_addr_local[i]); + netdev_write_byte(eth_addr_local[i]); /* escribimos el tipo de paquete que transporta el frame */ - netdev_send_word((eth_proto == ETH_IP) ? IP : ARP); + netdev_write_word((eth_proto == ETH_IP) ? IP : ARP); + netdev_write_end(); } diff --git a/src/eth.h b/src/eth.h index 9a640de..f65f5d2 100644 --- a/src/eth.h +++ b/src/eth.h @@ -23,6 +23,9 @@ /** Tamaño de dirección MAC (en bytes) */ #define ETH_ADDR_SIZE 6 +/** Tamaño de cabecera ethernet */ +#define ETH_HEADER_SIZE 14 + /** Tipos de frame ethernet */ typedef enum { ETH_IP, ETH_ARP } eth_proto_t; diff --git a/src/ip.c b/src/ip.c index 0b4b2e2..f60c3d4 100644 --- a/src/ip.c +++ b/src/ip.c @@ -1,6 +1,7 @@ // vim: set et sw=4 sts=4 : #include "netdev.h" +#include "debug.h" #include "ip.h" /** protocolos soportados */ @@ -29,41 +30,43 @@ bool ip_read_packet_header() { /* variables utilitarias (iterar y/o buffer) */ byte h, l; + bit ok = true; + netdev_read_start(IP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; /* versión y tamaño de cabecera vienen en el 1er byte */ - h = netdev_recv_byte(); + h = netdev_read_byte(); /* sólo soportamos versión 4 */ if ((h >> 4) != 4) - return false; /* drop */ + ok = false; /* tamaño de cabecera */ if ((h & 0x0F) != 5) /* no aceptamos opciones raras =) */ - return false; /* drop */ + ok = false; /* ignoramos el TOS y vamos calculando checksum */ - sum(WORD(h, netdev_recv_byte())); + sum(WORD(h, netdev_read_byte())); /* obtenemos tamaño del paquete */ - if (h = netdev_recv_byte()) /* tiene más de 255 bytes (no lo soportamos) */ - return false; /* drop */ - ip_packet_len = netdev_recv_byte(); /* hasta 255 bytes tienen los nuestros */ + if (h = netdev_read_byte()) /* tiene más de 255 bytes (no lo soportamos) */ + ok = false; + ip_packet_len = netdev_read_byte(); /* hasta 255 bytes tienen los nuestros */ /* vamos calculando checksum */ sum(WORD(h, ip_packet_len)); /* ignoramos identificación (2 bytes) y vamos calculando checksum */ - sum(netdev_recv_word()); + sum(netdev_read_word()); /* si tiene prendido el bit de MF (More Fragments, bit 5 del byte, bit 2 * de los flags de la cabecera) o si tiene un offset de fragmento (bits * del 4 al 0 y todos los bits del byte siguiente), dropeamos (no * soportamos fragmentación) */ - h = netdev_recv_byte(); - l = netdev_recv_byte(); + h = netdev_read_byte(); + l = netdev_read_byte(); if ((h & 0x3F) || l) - return false; /* drop */ + ok = false; /* seguimos calculando checksum */ sum(WORD(h, l)); /* no le damos bola al TTL (no le vamos a hacer lío si ya llegó hasta * acá el pobre =) */ - h = netdev_recv_byte(); + h = netdev_read_byte(); /* protocolo (sólo soportamos UDP e ICMP) */ - l = netdev_recv_byte(); + l = netdev_read_byte(); switch (l) { case ICMP: @@ -73,16 +76,16 @@ bool ip_read_packet_header() ip_proto = IP_UDP; break; default: - return false; /* drop */ + ok = false; } /* sigo calculando checksum */ sum(WORD(h, l)); /* obtenemos checksum y seguimos el cálculo */ - sum(netdev_recv_word()); + sum(netdev_read_word()); /* obtenemos IP de origen (mientras seguimos calculando el checksum) */ for (l = 0; l < IP_ADDR_SIZE; ++l) { - ip_addr_remote[l] = netdev_recv_byte(); + ip_addr_remote[l] = netdev_read_byte(); if (l % 2) sum(WORD(h, ip_addr_remote[l])); else @@ -93,8 +96,8 @@ bool ip_read_packet_header() // TODO si soportamos DHCP hay que aceptar broadcasts! for (l = 0; l < IP_ADDR_SIZE; ++l) { - if (ip_addr_local[l] != netdev_recv_byte()) - return false; /* drop (no es para nosotros) */ + if (ip_addr_local[l] != netdev_read_byte()) + ok = false; if (l % 2) sum(WORD(h, ip_addr_local[l])); else @@ -102,8 +105,9 @@ bool ip_read_packet_header() } /* verificamos checksum */ if ((uint16)~checksum) - return false; /* checksum malo, drop */ - return true; + ok = false; + netdev_read_end(); + return ok; } void ip_write_packet_header() @@ -114,28 +118,29 @@ void ip_write_packet_header() static uint16 id; /* reseteamos checksum */ checksum = 0; + netdev_write_start(IP_HEADER_SIZE); /* versión (4) y tamaño de cabecera (5 words de 4 bytes = 20 bytes) */ - netdev_send_byte(h = 0x45); + netdev_write_byte(h = 0x45); /* TOS (0xc0 = Internetwork Control, 0x00 = normal) */ l = (ip_proto == IP_ICMP) ? 0xc0 : 0x00; - netdev_send_byte(l); + netdev_write_byte(l); sum(WORD(h, l)); /* actualizamos checksum */ /* escribimos tamaño del paquete */ - netdev_send_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */ - netdev_send_byte(ip_packet_len); + netdev_write_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */ + netdev_write_byte(ip_packet_len); sum(WORD(h, ip_packet_len)); /* actualizamos checksum */ /* identificación (sirve para reensamblar paquetes) */ - netdev_send_word(id); + netdev_write_word(++id); sum(id); /* actualizamos checksum */ /* pedimos que no se fragmente */ - netdev_send_byte(h = 0x40); /* Don't Fragment (DF) = 1 */ - netdev_send_byte(l = 0x00); /* offset de fragmento = 0 */ + netdev_write_byte(h = 0x40); /* Don't Fragment (DF) = 1 */ + netdev_write_byte(l = 0x00); /* offset de fragmento = 0 */ sum(WORD(h, l)); /* actualizamos checksum */ /* TTL de 64 saltos porque está de moda */ - netdev_send_byte(h = 0x40); + netdev_write_byte(h = 0x40); /* protocolo (sólo soportamos UDP e ICMP) */ l = (ip_proto == IP_ICMP) ? ICMP : UDP; - netdev_send_byte(l); + netdev_write_byte(l); sum(WORD(h, l)); /* actualizamos checksum */ /* checksum: antes de poder escribir el checksum hay que terminar de * calcularlo según las direcciones IP de origen y destino, así que eso @@ -151,13 +156,14 @@ void ip_write_packet_header() else h = ip_addr_remote[l]; /* ahora sí grabamos el checksum */ - netdev_send_word(~checksum); + netdev_write_word(~checksum); /* ahora sí, continuamos poniendo las direcciones */ /* ponemos como dirección IP de origen la nuestra */ for (l = 0; l < IP_ADDR_SIZE; ++l) - netdev_send_byte(ip_addr_local[l]); + netdev_write_byte(ip_addr_local[l]); /* IP de destino, la remota */ for (l = 0; l < IP_ADDR_SIZE; ++l) - netdev_send_byte(ip_addr_remote[l]); + netdev_write_byte(ip_addr_remote[l]); + netdev_write_end(); } diff --git a/src/ip.h b/src/ip.h index 0b3fff1..a40693a 100644 --- a/src/ip.h +++ b/src/ip.h @@ -35,6 +35,9 @@ /** Tamaño de dirección IP (en bytes) */ #define IP_ADDR_SIZE 4 +/** Tamaño de cabecera IP (en bytes) */ +#define IP_HEADER_SIZE 20 + /** Tipos de paquete IP */ typedef enum { IP_UDP, IP_ICMP } ip_proto_t; diff --git a/src/main.c b/src/main.c index 787f025..18df512 100644 --- a/src/main.c +++ b/src/main.c @@ -26,14 +26,14 @@ void main(void) ip_addr_local[3] = 100; // Inicializo puerto UDP - udp_port_local = 9000; + udp_port_local = 9876; while (1) // Forever { - byte i; - netdev_recv_start(); - printb(netdev_len, 0x1); - if (!netdev_len) // no recibimos nada (válido) + byte buf[64]; //XXX + byte i; //XXX + + if (!netdev_recv_start()) // no recibimos nada (válido) continue; // Probamos de nuevo // Tenemos algo! @@ -47,7 +47,7 @@ void main(void) // Vemos que protocolo transporta switch (eth_proto) { - case ETH_ARP: // FIXME, implementar ARP! + case ETH_ARP: // TODO: implementar ARP! goto drop; // Tiramos el paquete case ETH_IP: @@ -60,7 +60,7 @@ void main(void) // Vemos que protocolo transporta switch (ip_proto) { - case IP_ICMP: // FIXME, implementar ICMP! + case IP_ICMP: // TODO: implementar ICMP! goto drop; // Tiramos el paquete case IP_UDP: @@ -69,16 +69,30 @@ void main(void) if (!udp_read_dgram_header()) // No es un buen header goto drop; // Tiramos el paquete - printb(udp_dgram_len, 0x40); + //printb(udp_dgram_len, 0x40); + // TODO // Nuestro protocolo, por ahora un simple echo! - for (i = 8; i < udp_dgram_len; ++i) // 8 por la cabecera UDP - { - printb(netdev_recv_byte(), 0x00); - } -drop: + 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(); + netdev_read_end(); netdev_recv_end(); + + // Respuesta + netdev_send_start(); + eth_write_frame_header(); + 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_end(); + netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len); } } + continue; +drop: + netdev_recv_end(); } } diff --git a/src/netdev.h b/src/netdev.h index e824666..175313c 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -13,46 +13,67 @@ extern byte netdev_len; */ bool netdev_init(); -/** Comienza el envío de un nuevo frame - * @param len Tamaño del frame a enviar - */ +/** Comienza el envío de un nuevo frame */ void netdev_send_start(); -/** Escribe un byte al buffer de la placa de red para ser enviado +/** Finaliza el envío del frame * @precond netdev_send_start() debe haber sido ejecutada + * @precond se copiaron datos al dispositivo para enviar + * @param len Cantidad de bytes a transmitir + */ +void netdev_send_end(byte len); + +/** Comienza una transferencia al dispositivo de red + * @param len Cantidad de bytes a escribir + */ +void netdev_write_start(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 */ -void netdev_send_byte(byte b); +void netdev_write_byte(byte b); /** Escribe un word al buffer de la placa de red para ser enviado - * @precond netdev_send_start() debe haber sido ejecutada + * @precond netdev_write_start() debe haber sido ejecutada * @param w Word a enviar */ -void netdev_send_word(uint16 w); +void netdev_write_word(uint16 w); -/** Finaliza el envío del frame - * @precond netdev_send_start() debe haber sido ejecutada +/** Finaliza una transferencia al dispositivo de red + * @precond netdev_write_start() fue llamada y se ecribió la cantidad de bytes + * en ella especificada */ -void netdev_send_end(); +void netdev_write_end(); -/** Comienza la lectura de un nuevo frame - * @postcond Deja en netdev_len el tamaño del frame recibido +/** Comienza la recepción de un nuevo frame + * @return Cantidad de bytes a recibir */ -void netdev_recv_start(); +byte netdev_recv_start(); + +/** Finaliza la lectura del frame + * @precond netdev_recv_start() debe haber sido ejecutada + */ +void netdev_recv_end(); + +/** Comienza a leer bytes del dispositivo de red + * @param len Cantidad de bytes a leer + */ +void netdev_read_start(byte len); /** Lee un byte del buffer de la placa de red * @precond netdev_recv_start() debe haber sido ejecutada */ -byte netdev_recv_byte(); +byte netdev_read_byte(); /** Lee un word del buffer de la placa de red * @precond netdev_recv_start() debe haber sido ejecutada */ -uint16 netdev_recv_word(); +uint16 netdev_read_word(); /** Finaliza la lectura del frame * @precond netdev_recv_start() debe haber sido ejecutada */ -void netdev_recv_end(); +void netdev_read_end(); #endif // _NETDEV_H_ diff --git a/src/udp.c b/src/udp.c index 9738341..f8264b1 100644 --- a/src/udp.c +++ b/src/udp.c @@ -24,6 +24,8 @@ static void sum(uint16 w) bool udp_read_dgram_header() { byte tmp; + bit ok = true; + netdev_read_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ @@ -39,33 +41,34 @@ bool udp_read_dgram_header() sum(ip_packet_len - 20); /* de ahora en más todos los datos del checksum corresponden a UDP */ /* puerto origen (remoto) */ - udp_port_remote = netdev_recv_word(); + udp_port_remote = netdev_read_word(); /* agregamos puerto de origen al checksum */ sum(udp_port_remote); /* sólo aceptamos datagramas a nuestro puerto */ - if (netdev_recv_word() != udp_port_local) - return false; /* drop */ + if (netdev_read_word() != udp_port_local) + ok = false; /* drop */ /* agregamos puerto de destino al checksum */ sum(udp_port_local); /* tamaño del datagrama */ - if (tmp = netdev_recv_byte()) /* no soportamos más de 255 bytes */ - return false; /* drop */ - udp_dgram_len = netdev_recv_byte(); /* parte baja */ + if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */ + ok = false; /* drop */ + udp_dgram_len = netdev_read_byte(); /* parte baja */ if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */ - return false; /* drop */ + ok = false; /* drop */ /* agregamos tamaño al checksum */ sum(WORD(tmp, udp_dgram_len)); /* agregamos checksum al checksum */ - sum(netdev_recv_word()); + sum(netdev_read_word()); /* falta agregar el cuerpo del mensaje para verificar la suma * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo * los datos de la placa de red byte a byte */ + netdev_read_end(); return true; } uint16 udp_read_word() { - uint16 w = netdev_recv_word(); + uint16 w = netdev_read_word(); sum(w); return w; } @@ -77,6 +80,7 @@ bool udp_checksum_ok() void udp_write_dgram_header() { + netdev_write_start(UDP_HEADER_SIZE); /* reseteamos checksum */ checksum = 0; /* el UDP tiene un checksum que incluye parte de la cabecera IP */ @@ -91,24 +95,25 @@ void udp_write_dgram_header() /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */ sum(ip_packet_len - 20); // FIXME /* puerto origen */ - netdev_send_word(udp_port_local); + netdev_write_word(udp_port_local); sum(udp_port_local); /* puerto destino */ - netdev_send_word(udp_port_remote); + netdev_write_word(udp_port_remote); sum(udp_port_remote); /* tamaño del datagrama */ - netdev_send_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */ - netdev_send_byte(udp_dgram_len); + netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */ + netdev_write_byte(udp_dgram_len); sum(WORD(0x00, udp_dgram_len)); /* indicamos que no se usa checksum */ - netdev_send_word(0x0000); + netdev_write_word(0x0000); sum(0x0000); + netdev_write_end(); } void udp_write_word(uint16 w) { sum(w); - netdev_send_word(w); + netdev_write_word(w); } void udp_write_checksum() diff --git a/src/udp.h b/src/udp.h index e9092f7..d636776 100644 --- a/src/udp.h +++ b/src/udp.h @@ -52,6 +52,9 @@ * */ +/** Tamaño de la cabecera UDP */ +#define UDP_HEADER_SIZE 8 + /** Puerto UDP nuestro */ extern uint16 udp_port_local; -- 2.43.0