# Compilador
CC=sdcc
-CFLAGS=-DDEBUG
+#CFLAGS=-DDEBUG
# Assembler
AS=asx8051
SHELL=bash
# Archivos
-cmodules=main dp8390 eth ip udp elp
+cmodules=main dp8390 eth arp ip udp elp
amodules=leds
modules=$(cmodules) $(amodules)
ip.h: types.h
+arp.h: types.h eth.h ip.h
+
udp.h: types.h
elp.h: types.h
eth.asm: eth.c eth.h netdev.h debug.h
eth.rel: eth.asm
+arp.asm: arp.c arp.h netdev.h debug.h
+arp.rel: arp.asm
+
ip.asm: ip.c ip.h netdev.h debug.h
ip.rel: ip.asm
--- /dev/null
+// vim: set et sw=4 sts=4 :
+
+#include "arp.h"
+#include "netdev.h"
+#include "debug.h"
+#include "eth.h"
+#include "ip.h"
+
+bool arp_read_packet()
+{
+ byte i;
+ bit ok = true;
+ netdev_read_start(ARP_HEADER_SIZE);
+ /* hardware type (solo soportamos ethernet: 0x0001)*/
+ if (netdev_read_word() != 0x0001)
+ ok = false;
+ /* protocolo (sólo soportamos IP: 0x0800) */
+ if (netdev_read_word() != 0x0800)
+ ok = false;
+ /* tamaño de dirección de hardware (sólo soportamos ethernet) */
+ if (netdev_read_byte() != ETH_ADDR_SIZE)
+ ok = false;
+ /* tamaño de dirección de protocolo (sólo soportamos IPv4) */
+ if (netdev_read_byte() != IP_ADDR_SIZE)
+ ok = false;
+ /* opcode (sólo le damos bola a los requests: 0x0001) */
+ if (netdev_read_word() != 0x0001)
+ ok = false;
+ netdev_read_end();
+ /* si las cosas no vienen bien a esta altura, ni nos gastamos en seguir */
+ if (!ok)
+ return ok;
+ netdev_read_start(ARP_PAYLOAD_SIZE);
+ /* obtenemos MAC de origen (ya la teníamos pero por las dudas) */
+ for (i = 0; i < ETH_ADDR_SIZE; ++i)
+ eth_addr_remote[i] = netdev_read_byte();
+ /* obtenemos IP de origen */
+ for (i = 0; i < IP_ADDR_SIZE; ++i)
+ ip_addr_remote[i] = netdev_read_byte();
+ /* la MAC de destino no nos importa, seguramente es broadcast */
+ for (i = 0; i < ETH_ADDR_SIZE; ++i)
+ netdev_read_byte();
+ /* sí nos importa qué IP andan buscando */
+ for (i = 0; i < IP_ADDR_SIZE; ++i)
+ if (ip_addr_local[i] != netdev_read_byte())
+ ok = false; /* si no buscan la nuestra, perdemos interés */
+ netdev_read_end();
+ return ok;
+}
+
+void arp_write_packet()
+{
+ byte i;
+ bit ok = true;
+ netdev_write_start(ARP_PACKET_SIZE);
+ /* hardware type (ethernet: 0x0001)*/
+ netdev_write_word(0x0001);
+ /* protocolo type (IP: 0x0800) */
+ netdev_write_word(0x0800);
+ /* tamaño de dirección de hardware */
+ netdev_write_byte(ETH_ADDR_SIZE);
+ /* tamaño de dirección de protocolo */
+ netdev_write_byte(IP_ADDR_SIZE);
+ /* opcode (response: 0x0002) */
+ netdev_write_word(0x0002);
+ /* MAC de origen */
+ for (i = 0; i < ETH_ADDR_SIZE; ++i)
+ netdev_write_byte(eth_addr_local[i]);
+ /* IP de origen */
+ for (i = 0; i < IP_ADDR_SIZE; ++i)
+ netdev_write_byte(ip_addr_local[i]);
+ /* MAC de destino */
+ for (i = 0; i < ETH_ADDR_SIZE; ++i)
+ netdev_write_byte(eth_addr_remote[i]);
+ /* IP de destino */
+ for (i = 0; i < IP_ADDR_SIZE; ++i)
+ netdev_write_byte(ip_addr_remote[i]);
+ netdev_write_end();
+}
+
--- /dev/null
+// vim: set et sw=4 sts=4 :
+
+#ifndef _ARP_H_
+#define _ARP_H_
+
+#include "types.h"
+#include "eth.h"
+#include "ip.h"
+
+/** @file
+ * Paquete ARP.
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Hardware Type | Protocol Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Hardware Size | Protocol Size | Opcode |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Sender MAC (cant. de bytes especificados por Hardware size) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Sender IP (cant. de bytes especificados por Protocol size) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Target MAC (cant. de bytes especificados por Hardware size) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Target IP (cant. de bytes especificados por Protocol size) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Nosotros sólo implementamos la respuesta a un request ARP, ya que sólo
+ * respondemos paquetes, nunca tenemos que enviar un paquete a una IP
+ * arbitraria. De esta manera nos evitamos, además, la necesidad de tener una
+ * tabla de cache ARP y de enviar peticiones ARP.
+ */
+
+/** Tamaño de la cabecera ARP (en bytes) */
+#define ARP_HEADER_SIZE 8
+
+/** Tamaño del payload del paquete ARP que soportamos nosotros (en bytes) */
+#define ARP_PAYLOAD_SIZE (2*ETH_ADDR_SIZE + 2*IP_ADDR_SIZE)
+
+/** Tamaño del paquete ARP que soportamos nosotros (en bytes) */
+#define ARP_PACKET_SIZE (ARP_HEADER_SIZE + ARP_PAYLOAD_SIZE)
+
+/** Lee el paquete ARP.
+ *
+ * Si devuelve false (0) es que hubo un error o es un paquete no soportado, por
+ * lo que hay que descartarlo.
+ */
+bool arp_read_packet();
+
+/** Escribe el paquete ARP.
+ *
+ * Responde al request recibido con la ip de ip_addr_local.
+ */
+void arp_write_packet();
+
+#endif /* _ARP_H_ */
// vim: set et sw=4 sts=4 :
#include "debug.h"
+#include "leds.h"
#include "eth.h"
#include "dp8390.h"
;.db 32
DEFAULT_MATRIX:
-; .dw 0b0000111111110000 ; columna 0
-; .dw 0b0011111111111100 ; columna 1
-; .dw 0b0111000000001110 ; columna 2
-; .dw 0b0110000000000110 ; columna 3
-; .dw 0b1100001100000011 ; columna 4
-; .dw 0b1100011000110011 ; columna 5
-; .dw 0b1100110000110011 ; columna 6
-; .dw 0b1100110000000011 ; columna 7
-; .dw 0b1100110000000011 ; columna 8
-; .dw 0b1100110000110011 ; columna 9
-; .dw 0b1100011000110011 ; columna 10
-; .dw 0b1100001100000011 ; columna 11
-; .dw 0b0110000000000110 ; columna 12
-; .dw 0b0111000000001110 ; columna 13
-; .dw 0b0011111111111100 ; columna 14
-; .dw 0b0000111111110000 ; columna 15
-
- .dw 0b0000011111100000
- .dw 0b0001111111111000
- .dw 0b0011100000011100
- .dw 0b0111110000000110
- .dw 0b0110111000000110
- .dw 0b1100011100000011
- .dw 0b1100001110000011
- .dw 0b1111111111111111
- .dw 0b1111111111111111
- .dw 0b1100001110000011
- .dw 0b1100011100000011
- .dw 0b0110111000000110
- .dw 0b0111110000000110
- .dw 0b0011100000011100
- .dw 0b0001111111111000
- .dw 0b0000011111100000
+ .dw 0b0000111111110000 ; columna 0
+ .dw 0b0011111111111100 ; columna 1
+ .dw 0b0111000000001110 ; columna 2
+ .dw 0b0110000000000110 ; columna 3
+ .dw 0b1100001100000011 ; columna 4
+ .dw 0b1100011000110011 ; columna 5
+ .dw 0b1100110000110011 ; columna 6
+ .dw 0b1100110000000011 ; columna 7
+ .dw 0b1100110000000011 ; columna 8
+ .dw 0b1100110000110011 ; columna 9
+ .dw 0b1100011000110011 ; columna 10
+ .dw 0b1100001100000011 ; columna 11
+ .dw 0b0110000000000110 ; columna 12
+ .dw 0b0111000000001110 ; columna 13
+ .dw 0b0011111111111100 ; columna 14
+ .dw 0b0000111111110000 ; columna 15
+
+; .dw 0b0000011111100000
+; .dw 0b0001111111111000
+; .dw 0b0011100000011100
+; .dw 0b0111110000000110
+; .dw 0b0110111000000110
+; .dw 0b1100011100000011
+; .dw 0b1100001110000011
+; .dw 0b1111111111111111
+; .dw 0b1111111111111111
+; .dw 0b1100001110000011
+; .dw 0b1100011100000011
+; .dw 0b0110111000000110
+; .dw 0b0111110000000110
+; .dw 0b0011100000011100
+; .dw 0b0001111111111000
+; .dw 0b0000011111100000
; .dw 0b1111000000001111 ; columna 0
; .dw 0b1100000000000011 ; columna 1
#include "reg51.h"
#include "netdev.h"
#include "eth.h"
+#include "arp.h"
#include "ip.h"
#include "udp.h"
#include "elp.h"
// Vemos que protocolo transporta
switch (eth_proto)
{
- case ETH_ARP: // TODO: implementar ARP!
- goto drop; // Tiramos el paquete
+ case ETH_ARP:
+ // Obtenemos paquete ARP
+ if (!arp_read_packet) // No es un paquete soportado
+ goto drop; // Tiramos el paquete
+
+ // Terminamos recepción
+ netdev_recv_end();
+
+ // Respondemos
+ netdev_send_start();
+ eth_write_frame_header();
+ arp_write_packet();
+ netdev_send_end(ETH_HEADER_SIZE + ARP_PACKET_SIZE);
+
+ // Seguimos viaje
+ continue;
case ETH_IP:
// Parseamos cabecera IP