Stefan Schuermans commited on 2012-03-24 13:58:46
              Showing 17 changed files, with 792 additions and 50 deletions.
            
| ... | ... | @@ -1,7 +1,7 @@ | 
| 1 | 1 | #include "arp.h" | 
| 2 | 2 | #include "config.h" | 
| 3 | 3 | #include "ethernet.h" | 
| 4 | -// TODO #include "ip.h" | |
| 4 | +#include "ip.h" | |
| 5 | 5 | #include "macros.h" | 
| 6 | 6 | #include "nethelp.h" | 
| 7 | 7 |  | 
| ... | ... | @@ -30,28 +30,28 @@ struct arp_table | 
| 30 | 30 | */ | 
| 31 | 31 | static void arp_send_request(unsigned char ip[4]) | 
| 32 | 32 |  { | 
| 33 | - struct arp_packet arp_request; | |
| 33 | + struct arp_packet_pad arp_request; | |
| 34 | 34 |  | 
| 35 | 35 | // build ARP request | 
| 36 | - arp_request.arp_hdr.hw_type = htons(0x0001); // ethernet | |
| 37 | - arp_request.arp_hdr.proto_type = htons(0x0800); // IP | |
| 38 | - arp_request.arp_hdr.hw_len = 0x06; // length of a MAC address | |
| 39 | - arp_request.arp_hdr.proto_len = 0x04; // length of an IP address | |
| 40 | - arp_request.arp_hdr.op = htons(0x0001); // ARP request | |
| 41 | - mac_cpy(arp_request.arp_hdr.src_mac, config_mac.mac); // own MAC | |
| 42 | - ip_cpy(arp_request.arp_hdr.src_ip, config_ip.ip); // own IP | |
| 43 | - mac_cpy(arp_request.arp_hdr.dest_mac, | |
| 36 | + arp_request.p.arp_hdr.hw_type = htons(0x0001); // ethernet | |
| 37 | + arp_request.p.arp_hdr.proto_type = htons(0x0800); // IP | |
| 38 | + arp_request.p.arp_hdr.hw_len = 0x06; // length of a MAC address | |
| 39 | + arp_request.p.arp_hdr.proto_len = 0x04; // length of an IP address | |
| 40 | + arp_request.p.arp_hdr.op = htons(0x0001); // ARP request | |
| 41 | + mac_cpy(arp_request.p.arp_hdr.src_mac, config_mac.mac); // own MAC | |
| 42 | + ip_cpy(arp_request.p.arp_hdr.src_ip, config_ip.ip); // own IP | |
| 43 | + mac_cpy(arp_request.p.arp_hdr.dest_mac, | |
| 44 | 44 | "\xFF\xFF\xFF\xFF\xFF\xFF"); // broadcast MAC | 
| 45 | - ip_cpy(arp_request.arp_hdr.dest_ip, ip); // requested IP | |
| 45 | + ip_cpy(arp_request.p.arp_hdr.dest_ip, ip); // requested IP | |
| 46 | 46 |  | 
| 47 | 47 | // send ARP request | 
| 48 | - mac_cpy(arp_request.eth_hdr.dest, arp_request.arp_hdr.dest_mac); | |
| 49 | - arp_request.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP | |
| 50 | - ethernet_send(&arp_request, sizeof(arp_request)); | |
| 48 | + mac_cpy(arp_request.p.eth_hdr.dest, arp_request.p.arp_hdr.dest_mac); | |
| 49 | + arp_request.p.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP | |
| 50 | + ethernet_send(&arp_request.p, sizeof(arp_request.p)); | |
| 51 | 51 | } | 
| 52 | 52 |  | 
| 53 | 53 | /// initialize | 
| 54 | -/* extern */ void arp_init(void) | |
| 54 | +void arp_init(void) | |
| 55 | 55 |  { | 
| 56 | 56 | unsigned int i; | 
| 57 | 57 |  | 
| ... | ... | @@ -61,7 +61,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 61 | 61 | } | 
| 62 | 62 |  | 
| 63 | 63 | /// tick procedure - call every 200ms | 
| 64 | -/* extern */ void arp_tick200(void) | |
| 64 | +void arp_tick200(void) | |
| 65 | 65 |  { | 
| 66 | 66 | unsigned int i; | 
| 67 | 67 |  | 
| ... | ... | @@ -91,7 +91,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 91 | 91 | * @param[in] ptr pointer to data of packet | 
| 92 | 92 | * @param[in] sz size of packet | 
| 93 | 93 | */ | 
| 94 | -/* extern */ void arp_recv(void *ptr, unsigned int sz) | |
| 94 | +void arp_recv(void *ptr, unsigned int sz) | |
| 95 | 95 |  { | 
| 96 | 96 | struct arp_packet *arp_pack; | 
| 97 | 97 |  | 
| ... | ... | @@ -99,7 +99,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 99 | 99 | if (sz < sizeof(struct arp_packet)) | 
| 100 | 100 | return; | 
| 101 | 101 |  | 
| 102 | - arp_pack = (struct arp_packet *)ptr; | |
| 102 | + arp_pack = ptr; | |
| 103 | 103 |  | 
| 104 | 104 | // not IP over ethernet | 
| 105 | 105 | if (arp_pack->arp_hdr.hw_type != htons(0x0001) || // ethernet | 
| ... | ... | @@ -135,7 +135,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 135 | 135 | mac_cpy(arp_reply.p.eth_hdr.dest, | 
| 136 | 136 | arp_reply.p.arp_hdr.dest_mac); // ethernet destination address | 
| 137 | 137 | arp_reply.p.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP | 
| 138 | - ethernet_send(&arp_reply, sizeof(arp_reply)); | |
| 138 | + ethernet_send(&arp_reply.p, sizeof(arp_reply.p)); | |
| 139 | 139 |  | 
| 140 | 140 | return; | 
| 141 | 141 | } | 
| ... | ... | @@ -161,7 +161,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 161 | 161 | mac_cpy(arp_tab[i].mac, arp_pack->arp_hdr.src_mac); | 
| 162 | 162 | // notify IP | 
| 163 | 163 | // - IP might be waiting for the MAC to transmit a packet | 
| 164 | - // TODO ip_got_mac(arp_tab[i].ip, arp_tab[i].mac); | |
| 164 | + ip_got_mac(arp_tab[i].ip, arp_tab[i].mac); | |
| 165 | 165 | } | 
| 166 | 166 | return; | 
| 167 | 167 | } | 
| ... | ... | @@ -174,7 +174,7 @@ static void arp_send_request(unsigned char ip[4]) | 
| 174 | 174 | * @param[out] mac MAC address for this IP address | 
| 175 | 175 | * @return 0 in case of success, 1 if the MAC address is unknown | 
| 176 | 176 | */ | 
| 177 | -/* extern */ int arp_lookup(unsigned char ip[4], unsigned char mac[6]) | |
| 177 | +int arp_lookup(unsigned char ip[4], unsigned char mac[6]) | |
| 178 | 178 |  { | 
| 179 | 179 | unsigned int i, j; | 
| 180 | 180 |  | 
| ... | ... | @@ -28,17 +28,17 @@ struct arp_packet | 
| 28 | 28 | ETHERNET_PAD(arp_packet); | 
| 29 | 29 |  | 
| 30 | 30 | /// initialize | 
| 31 | -extern void arp_init(void); | |
| 31 | +void arp_init(void); | |
| 32 | 32 |  | 
| 33 | 33 | /// tick procedure - call every 200ms | 
| 34 | -extern void arp_tick200(void); | |
| 34 | +void arp_tick200(void); | |
| 35 | 35 |  | 
| 36 | 36 | /** | 
| 37 | 37 | * @brief process a received ARP packet | 
| 38 | 38 | * @param[in] ptr pointer to data of packet | 
| 39 | 39 | * @param[in] sz size of packet | 
| 40 | 40 | */ | 
| 41 | -extern void arp_recv(void *ptr, unsigned int sz); | |
| 41 | +void arp_recv(void *ptr, unsigned int sz); | |
| 42 | 42 |  | 
| 43 | 43 | /** | 
| 44 | 44 | * @brief look up the MAC for an IP address | 
| ... | ... | @@ -46,7 +46,7 @@ extern void arp_recv(void *ptr, unsigned int sz); | 
| 46 | 46 | * @param[out] mac MAC address for this IP address | 
| 47 | 47 | * @return 0 in case of success, 1 if the MAC address is unknown | 
| 48 | 48 | */ | 
| 49 | -extern int arp_lookup(unsigned char ip[4], unsigned char mac[6]); | |
| 49 | +int arp_lookup(unsigned char ip[4], unsigned char mac[6]); | |
| 50 | 50 |  | 
| 51 | 51 | #endif // #ifdef ARP_H | 
| 52 | 52 |  | 
| ... | ... | @@ -0,0 +1,41 @@ | 
| 1 | +#include "checksum.h" | |
| 2 | +#include "macros.h" | |
| 3 | +#include "nethelp.h" | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @brief generate an IP style checksum | |
| 7 | + * @param[in] ptr pointer to data | |
| 8 | + * @param[in] sz size of data | |
| 9 | + * @param[in] pseudo1 additional value to include - set to 0 if not needed | |
| 10 | + * @param[in] preude2 additional value to include - set to 0 if not needed | |
| 11 | + * | |
| 12 | + * can also be used to check a checksum (returns 0 if correct) | |
| 13 | + */ | |
| 14 | +unsigned short checksum(void *ptr, unsigned int sz, | |
| 15 | + unsigned short pseudo1, unsigned short pseudo2) | |
| 16 | +{ | |
| 17 | + unsigned int sum; | |
| 18 | + unsigned short *data; | |
| 19 | + | |
| 20 | + // sum up data of pseudo header | |
| 21 | + sum = pseudo1; | |
| 22 | + sum += pseudo2; | |
| 23 | + | |
| 24 | + // add full 16 bit words in header | |
| 25 | + for (data = ptr; sz >= 2; data++, sz -= 2) | |
| 26 | + sum += ntohs(*data); | |
| 27 | + | |
| 28 | + // add last byte | |
| 29 | + if (sz >= 1) | |
| 30 | + sum += *(unsigned char *)data << 8; | |
| 31 | + | |
| 32 | + // convert sum to one's complement sum | |
| 33 | + // add carries (bits 31..16) to sum (bits 15..0) | |
| 34 | + sum = (sum & 0x0000FFFF) + (sum >> 16); | |
| 35 | + // still a carry possible (from last addition) | |
| 36 | + sum = (sum & 0x0000FFFF) + (sum >> 16); | |
| 37 | + | |
| 38 | + // return complement of one's complement sum | |
| 39 | + return ~(unsigned short)sum; | |
| 40 | +} | |
| 41 | + | 
| ... | ... | @@ -0,0 +1,17 @@ | 
| 1 | +#ifndef CHECKSUM_H | |
| 2 | +#define CHECKSUM_H | |
| 3 | + | |
| 4 | +/** | |
| 5 | + * @brief generate an IP style checksum | |
| 6 | + * @param[in] ptr pointer to data | |
| 7 | + * @param[in] sz size of data | |
| 8 | + * @param[in] pseudo1 additional value to include - set to 0 if not needed | |
| 9 | + * @param[in] preude2 additional value to include - set to 0 if not needed | |
| 10 | + * | |
| 11 | + * can also be used to check a checksum (returns 0 if correct) | |
| 12 | + */ | |
| 13 | +unsigned short checksum(void *ptr, unsigned int sz, | |
| 14 | + unsigned short pseudo1, unsigned short pseudo2); | |
| 15 | + | |
| 16 | +#endif // #ifdef CHECKSUM_H | |
| 17 | + | 
| ... | ... | @@ -8,7 +8,7 @@ | 
| 8 | 8 | #include "config.h" | 
| 9 | 9 | #include "eth.h" | 
| 10 | 10 | #include "ethernet.h" | 
| 11 | -// TODO #include "ip.h" | |
| 11 | +#include "ip.h" | |
| 12 | 12 | #include "macros.h" | 
| 13 | 13 | #include "nethelp.h" | 
| 14 | 14 |  | 
| ... | ... | @@ -17,7 +17,7 @@ | 
| 17 | 17 | * @param[in] ptr pointer to data of packet | 
| 18 | 18 | * @param[in] sz size of packet | 
| 19 | 19 | */ | 
| 20 | -/* extern */ void ethernet_recv(void *ptr, unsigned int sz) | |
| 20 | +void ethernet_recv(void *ptr, unsigned int sz) | |
| 21 | 21 |  { | 
| 22 | 22 | struct ethernet_packet *eth_pack; | 
| 23 | 23 |  | 
| ... | ... | @@ -25,7 +25,7 @@ | 
| 25 | 25 | if (sz < sizeof(struct ethernet_packet)) | 
| 26 | 26 | return; | 
| 27 | 27 |  | 
| 28 | - eth_pack = (struct ethernet_packet *)ptr; | |
| 28 | + eth_pack = ptr; | |
| 29 | 29 |  | 
| 30 | 30 | // branch according to packet type | 
| 31 | 31 | switch (eth_pack->eth_hdr.type) | 
| ... | ... | @@ -36,7 +36,7 @@ | 
| 36 | 36 | break; | 
| 37 | 37 | // IP | 
| 38 | 38 | case htons(0x0800): | 
| 39 | - // TODO ip_recv(ptr, sz); | |
| 39 | + ip_recv(ptr, sz); | |
| 40 | 40 | break; | 
| 41 | 41 | } | 
| 42 | 42 | } | 
| ... | ... | @@ -46,10 +46,10 @@ | 
| 46 | 46 | * @param[in] ptr pointer to data of packet | 
| 47 | 47 | * @param[in] sz size of packet | 
| 48 | 48 | * | 
| 49 | - * ptr must point to a ethernet_packet with eth_hdr.dest and eth_hdr.type | |
| 50 | - * already initialized | |
| 49 | + * ptr must point to a ethernet_packet of sufficient size (ethernet padding) | |
| 50 | + * with eth_hdr.dest and eth_hdr.type already initialized | |
| 51 | 51 | */ | 
| 52 | -/* extern */ void ethernet_send(void *ptr, unsigned int sz) | |
| 52 | +void ethernet_send(void *ptr, unsigned int sz) | |
| 53 | 53 |  { | 
| 54 | 54 | struct ethernet_packet *eth_pack; | 
| 55 | 55 |  | 
| ... | ... | @@ -57,7 +57,7 @@ | 
| 57 | 57 | if (sz < sizeof(struct ethernet_packet)) | 
| 58 | 58 | return; | 
| 59 | 59 |  | 
| 60 | - eth_pack = (struct ethernet_packet *)ptr; | |
| 60 | + eth_pack = ptr; | |
| 61 | 61 |  | 
| 62 | 62 | // fill in source address | 
| 63 | 63 | mac_cpy(eth_pack->eth_hdr.src, config_mac.mac); | 
| ... | ... | @@ -43,8 +43,8 @@ void ethernet_recv(void *ptr, unsigned int sz); | 
| 43 | 43 | * @param[in] ptr pointer to data of packet | 
| 44 | 44 | * @param[in] sz size of packet | 
| 45 | 45 | * | 
| 46 | - * ptr must point to a ethernet_packet with eth_hdr.dest and eth_hdr.type | |
| 47 | - * already initialized | |
| 46 | + * ptr must point to a ethernet_packet of sufficient size (ethernet padding) | |
| 47 | + * with eth_hdr.dest and eth_hdr.type already initialized | |
| 48 | 48 | */ | 
| 49 | 49 | void ethernet_send(void *ptr, unsigned int sz); | 
| 50 | 50 |  | 
| ... | ... | @@ -0,0 +1,101 @@ | 
| 1 | +#include "checksum.h" | |
| 2 | +#include "ethernet.h" | |
| 3 | +#include "icmp.h" | |
| 4 | +#include "ip.h" | |
| 5 | +#include "macros.h" | |
| 6 | +#include "nethelp.h" | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @brief send an ICMP packet | |
| 10 | + * @param[in] ptr pointer to data of packet | |
| 11 | + * @param[in] sz size of packet | |
| 12 | + * | |
| 13 | + * ptr must point to a icmp_packet of sufficient size (ethernet padding) | |
| 14 | + * with icmp_hdr.type, icmp_hdr.code and ip_hdr.sest already initialized | |
| 15 | + */ | |
| 16 | +static void icmp_send(void *ptr, unsigned int sz) | |
| 17 | +{ | |
| 18 | + struct icmp_packet *icmp_pack; | |
| 19 | + unsigned short chk; | |
| 20 | + | |
| 21 | + // packet too short | |
| 22 | + if (sz < sizeof(struct icmp_packet)) | |
| 23 | + return; | |
| 24 | + | |
| 25 | + icmp_pack = ptr; | |
| 26 | + | |
| 27 | + // fill in header values | |
| 28 | + icmp_pack->icmp_hdr.chk = 0x0000; | |
| 29 | + | |
| 30 | + // generate checksum | |
| 31 | + chk = checksum(&icmp_pack->icmp_hdr, | |
| 32 | + sz - sizeof(struct ethernet_header) | |
| 33 | + - sizeof(struct ip_header), | |
| 34 | + 0x0000, 0x0000); | |
| 35 | + icmp_pack->icmp_hdr.chk = htons(chk); | |
| 36 | + | |
| 37 | + // send ICMP packet | |
| 38 | + icmp_pack->ip_hdr.proto = 0x01; // ICMP | |
| 39 | + ip_send(icmp_pack, sz); | |
| 40 | +} | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * @brief process a received ICMP echo request packet | |
| 44 | + * @param[in] ptr pointer to data of packet | |
| 45 | + * @param[in] sz size of packet | |
| 46 | + */ | |
| 47 | +static void icmp_echo_req_recv(void *ptr, unsigned int sz) | |
| 48 | +{ | |
| 49 | + struct icmp_echo_packet *icmp_echo_pack; | |
| 50 | + | |
| 51 | + // packet too short | |
| 52 | + if (sz < sizeof(struct icmp_echo_packet)) | |
| 53 | + return; | |
| 54 | + | |
| 55 | + icmp_echo_pack = ptr; | |
| 56 | + | |
| 57 | + // code not 0 | |
| 58 | + if (icmp_echo_pack->icmp_hdr.code != 0x00) | |
| 59 | + return; | |
| 60 | + | |
| 61 | + // send an ICMP echo reply | |
| 62 | + // - use same buffer to send reply | |
| 63 | + // - this saves us from needing to allocate a new buffer | |
| 64 | + // - this saves us from needing to copy echo_hdr.id, echo_hdr.seq and data | |
| 65 | + icmp_echo_pack->icmp_hdr.type = 0x00; // ICMP echo reply | |
| 66 | + icmp_echo_pack->icmp_hdr.code = 0x00; | |
| 67 | + // destination IP is source IP of request | |
| 68 | + ip_cpy(icmp_echo_pack->ip_hdr.dest, icmp_echo_pack->ip_hdr.src); | |
| 69 | + icmp_send(icmp_echo_pack, sz); | |
| 70 | +} | |
| 71 | + | |
| 72 | +/** | |
| 73 | + * @brief process a received ICMP packet | |
| 74 | + * @param[in] ptr pointer to data of packet | |
| 75 | + * @param[in] sz size of packet | |
| 76 | + */ | |
| 77 | +void icmp_recv(void *ptr, unsigned int sz) | |
| 78 | +{ | |
| 79 | + struct icmp_packet *icmp_pack; | |
| 80 | + | |
| 81 | + // packet too short | |
| 82 | + if (sz < sizeof(struct icmp_packet)) | |
| 83 | + return; | |
| 84 | + | |
| 85 | + icmp_pack = ptr; | |
| 86 | + | |
| 87 | + // test checksum | |
| 88 | + if (checksum(&icmp_pack->icmp_hdr, | |
| 89 | + sz - sizeof(struct ethernet_header) - sizeof(struct ip_header), | |
| 90 | + 0x0000, 0x0000)) | |
| 91 | + return; | |
| 92 | + | |
| 93 | + // branch according to type | |
| 94 | +  switch (icmp_pack->icmp_hdr.type) { | |
| 95 | + // ICMP echo request | |
| 96 | + case 0x08: | |
| 97 | + icmp_echo_req_recv(ptr, sz); | |
| 98 | + break; | |
| 99 | + } | |
| 100 | +} | |
| 101 | + | 
| ... | ... | @@ -0,0 +1,53 @@ | 
| 1 | +#ifndef ICMP_H | |
| 2 | +#define ICMP_H | |
| 3 | + | |
| 4 | +#include "ethernet.h" | |
| 5 | +#include "ip.h" | |
| 6 | + | |
| 7 | +/// header of ICMP packet | |
| 8 | +struct icmp_header | |
| 9 | +{ | |
| 10 | + unsigned char type; | |
| 11 | + unsigned char code; | |
| 12 | + unsigned short chk; | |
| 13 | +} __attribute__((packed)); | |
| 14 | + | |
| 15 | +/// ICMP packet | |
| 16 | +struct icmp_packet | |
| 17 | +{ | |
| 18 | + struct ethernet_header eth_hdr; | |
| 19 | + struct ip_header ip_hdr; | |
| 20 | + struct icmp_header icmp_hdr; | |
| 21 | +} __attribute__((packed)); | |
| 22 | + | |
| 23 | +/// ICMP packet with padding | |
| 24 | +ETHERNET_PAD(icmp_packet); | |
| 25 | + | |
| 26 | +// header of ICMP echo request/reply packet | |
| 27 | +struct icmp_echo_header | |
| 28 | +{ | |
| 29 | + unsigned short id; | |
| 30 | + unsigned short seq; | |
| 31 | +} __attribute__((packed)); | |
| 32 | + | |
| 33 | +/// ICMP echo request/reply packet | |
| 34 | +struct icmp_echo_packet | |
| 35 | +{ | |
| 36 | + struct ethernet_header eth_hdr; | |
| 37 | + struct ip_header ip_hdr; | |
| 38 | + struct icmp_header icmp_hdr; | |
| 39 | + struct icmp_echo_header echo_hdr; | |
| 40 | +} __attribute__((packed)); | |
| 41 | + | |
| 42 | +/// ICMP echo request/reply packet with padding | |
| 43 | +ETHERNET_PAD(icmp_echo_packet); | |
| 44 | + | |
| 45 | +/** | |
| 46 | + * @brief process a received ICMP packet | |
| 47 | + * @param[in] ptr pointer to data of packet | |
| 48 | + * @param[in] sz size of packet | |
| 49 | + */ | |
| 50 | +void icmp_recv(void *ptr, unsigned int sz); | |
| 51 | + | |
| 52 | +#endif // #ifdef ICMP_H | |
| 53 | + | 
| ... | ... | @@ -0,0 +1,307 @@ | 
| 1 | +#include "arp.h" | |
| 2 | +#include "checksum.h" | |
| 3 | +#include "config.h" | |
| 4 | +#include "ethernet.h" | |
| 5 | +#include "icmp.h" | |
| 6 | +#include "ip.h" | |
| 7 | +#include "macros.h" | |
| 8 | +#include "memcpy.h" | |
| 9 | +#include "nethelp.h" | |
| 10 | +#include "udp.h" | |
| 11 | + | |
| 12 | +// timing parameters | |
| 13 | +#define IP_BUFFER_TICKS_MAX 50 // maximum age of buffered IP packet (in 200ms) | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * buffers for IP packets to transmit | |
| 17 | + * - used if MAC is unknown when packet shall be transmitted | |
| 18 | + * - packet is sent when MAC becomes known | |
| 19 | + * - some buffers with different length (packets have different lengths) | |
| 20 | + * - all buffers must be larger than min ethernet frame size (eth padding) | |
| 21 | + */ | |
| 22 | +//@{ | |
| 23 | +unsigned int ip_buffer0[20]; | |
| 24 | +unsigned int ip_buffer1[20]; | |
| 25 | +unsigned int ip_buffer2[40]; | |
| 26 | +unsigned int ip_buffer3[80]; | |
| 27 | +//@} | |
| 28 | +/// table with buffers | |
| 29 | +struct ip_buffer_table | |
| 30 | +{ | |
| 31 | + void *ptr; ///< pointer to buffer for packet | |
| 32 | + unsigned int buf_sz; ///< size of buffer | |
| 33 | + unsigned int pkg_sz; ///< size of packet in buffer, 0 for packet | |
| 34 | + unsigned int ticks; //< age of entry (in 200ms) | |
| 35 | +} ip_buffer_tab[] = | |
| 36 | +{ // put smaller buffers in front of larger buffers | |
| 37 | + // - then short packets will use smaller buffers more often | |
| 38 | +  { ip_buffer0, sizeof(ip_buffer0), 0, 0 }, | |
| 39 | +  { ip_buffer1, sizeof(ip_buffer1), 0, 0 }, | |
| 40 | +  { ip_buffer2, sizeof(ip_buffer2), 0, 0 }, | |
| 41 | +  { ip_buffer3, sizeof(ip_buffer3), 0, 0 }, | |
| 42 | +}; | |
| 43 | + | |
| 44 | +/// initialize | |
| 45 | +void ip_init(void) | |
| 46 | +{ | |
| 47 | + unsigned int i; | |
| 48 | + for (i = 0; i < count(ip_buffer_tab ); i++) | |
| 49 | + ip_buffer_tab[i].pkg_sz = 0; | |
| 50 | +} | |
| 51 | + | |
| 52 | +/// tick procedure - call every 200ms | |
| 53 | +void ip_tick200(void) | |
| 54 | +{ | |
| 55 | + unsigned int i; | |
| 56 | + | |
| 57 | + // increase age of buffered IP packets and remove timed out ones | |
| 58 | +  for (i = 0; i < count( ip_buffer_tab ); i++) { | |
| 59 | +    if (ip_buffer_tab[i].pkg_sz > 0 ) { // buffer in use | |
| 60 | + ip_buffer_tab[i].ticks++; // increase age | |
| 61 | + if (ip_buffer_tab[i].ticks > IP_BUFFER_TICKS_MAX) // too old | |
| 62 | + ip_buffer_tab[i].pkg_sz = 0; // discard packet | |
| 63 | + } | |
| 64 | + } | |
| 65 | +} | |
| 66 | + | |
| 67 | +/** | |
| 68 | + * @brief process a received IP packet | |
| 69 | + * @param[in] ptr pointer to data of packet | |
| 70 | + * @param[in] sz size of packet | |
| 71 | + */ | |
| 72 | +void ip_recv(void *ptr, unsigned int sz) | |
| 73 | +{ | |
| 74 | + struct ip_packet *ip_pack; | |
| 75 | + unsigned int len; | |
| 76 | + | |
| 77 | + // packet too short | |
| 78 | + if (sz < sizeof(struct ip_packet)) | |
| 79 | + return; | |
| 80 | + | |
| 81 | + ip_pack = ptr; | |
| 82 | + | |
| 83 | + // not IPv4 -> drop | |
| 84 | + if (ip_pack->ip_hdr.ver__hdr_len != 0x45) // IPv4 with no options present | |
| 85 | + return; | |
| 86 | + | |
| 87 | + // not to own IP / broadcast -> drop | |
| 88 | +  while (1) { | |
| 89 | + // own IP -> accept | |
| 90 | + if (ip_eq(ip_pack->ip_hdr.dest, config_ip.ip) ) | |
| 91 | + break; | |
| 92 | + // local network's broadcast address -> accept | |
| 93 | + if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) == | |
| 94 | + (config_ip.ip[0] & config_ip.mask[0]) && | |
| 95 | + (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) == | |
| 96 | + (config_ip.ip[1] & config_ip.mask[1]) && | |
| 97 | + (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) == | |
| 98 | + (config_ip.ip[2] & config_ip.mask[2]) && | |
| 99 | + (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) == | |
| 100 | + (config_ip.ip[3] & config_ip.mask[3]) && | |
| 101 | + (ip_pack->ip_hdr.dest[0] & ~config_ip.mask[0]) == | |
| 102 | + ~config_ip.mask[0] && | |
| 103 | + (ip_pack->ip_hdr.dest[1] & ~config_ip.mask[1]) == | |
| 104 | + ~config_ip.mask[1] && | |
| 105 | + (ip_pack->ip_hdr.dest[2] & ~config_ip.mask[2]) == | |
| 106 | + ~config_ip.mask[2] && | |
| 107 | + (ip_pack->ip_hdr.dest[3] & ~config_ip.mask[3]) == | |
| 108 | + ~config_ip.mask[3] ) | |
| 109 | + break; | |
| 110 | + // link local boradcast address -> accept | |
| 111 | + if (ip_pack->ip_hdr.dest[0] == 0xFF && | |
| 112 | + ip_pack->ip_hdr.dest[1] == 0xFF && | |
| 113 | + ip_pack->ip_hdr.dest[2] == 0xFF && | |
| 114 | + ip_pack->ip_hdr.dest[3] == 0xFF ) | |
| 115 | + break; | |
| 116 | + // drop | |
| 117 | + return; | |
| 118 | + } | |
| 119 | + | |
| 120 | + // ignore packets sent from invalid source adresses | |
| 121 | + // - this might be some attack or some router fault | |
| 122 | + if (ip_pack->ip_hdr.src[0] >= 0xE0 || // broadcast, reserved or multicast | |
| 123 | + ip_pack->ip_hdr.src[0] == 0x7F || // loopback network | |
| 124 | + ip_eq(ip_pack->ip_hdr.src, "\x00\x00\x00\x00" )) // IP 0.0.0.0 | |
| 125 | + return; | |
| 126 | + // ignore packets sent from local network or broadcast address | |
| 127 | + if ((ip_pack->ip_hdr.src[0] & config_ip.mask[0]) == | |
| 128 | + (config_ip.ip[0] & config_ip.mask[0]) && // source IP is in own subnet | |
| 129 | + (ip_pack->ip_hdr.src[1] & config_ip.mask[1]) == | |
| 130 | + (config_ip.ip[1] & config_ip.mask[1]) && | |
| 131 | + (ip_pack->ip_hdr.src[2] & config_ip.mask[2]) == | |
| 132 | + (config_ip.ip[2] & config_ip.mask[2]) && | |
| 133 | + (ip_pack->ip_hdr.src[3] & config_ip.mask[3]) == | |
| 134 | + (config_ip.ip[3] & config_ip.mask[3])) | |
| 135 | +  { | |
| 136 | + // local network address | |
| 137 | + if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0x00 && | |
| 138 | + (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0x00 && | |
| 139 | + (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0x00 && | |
| 140 | + (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0x00 ) | |
| 141 | + return; | |
| 142 | + // local broadcast address | |
| 143 | + if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0xFF && | |
| 144 | + (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0xFF && | |
| 145 | + (ip_pack->ip_hdr.src[2] & ~config_ip.mask[2]) == 0xFF && | |
| 146 | + (ip_pack->ip_hdr.src[3] & ~config_ip.mask[3]) == 0xFF ) | |
| 147 | + return; | |
| 148 | + } | |
| 149 | + // ignore packets sent from own IP address | |
| 150 | + if (ip_eq(ip_pack->ip_hdr.src, config_ip.ip)) | |
| 151 | + return; | |
| 152 | + | |
| 153 | + // ignore fragmented packets | |
| 154 | + // BUG: fragmentation must be supported according to RFC781 | |
| 155 | + // but there is not enough RAM for assembling packets with up to 64kB | |
| 156 | + // fragment offset 0, more_frags=0, dont_frag=x, reserved_flag=0 | |
| 157 | + if ((ntohs(ip_pack->ip_hdr.frag_ofs) & 0xBFFF) != 0x0000) | |
| 158 | + return; | |
| 159 | + | |
| 160 | + // check total length | |
| 161 | + len = sizeof(struct ethernet_header ) + ntohs(ip_pack->ip_hdr.total_len); | |
| 162 | + if (sz < len) // packet is truncated | |
| 163 | + return; | |
| 164 | + sz = len; // remove ethernet padding from packet (maybe sz > len) | |
| 165 | + | |
| 166 | + // test header checksum | |
| 167 | + if (checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000)) | |
| 168 | + return; | |
| 169 | + | |
| 170 | + // branch according to protocol | |
| 171 | +  switch(ip_pack->ip_hdr.proto) { | |
| 172 | + // ICMP | |
| 173 | + case 0x01: | |
| 174 | + icmp_recv(ptr, sz); | |
| 175 | + break; | |
| 176 | + // UDP | |
| 177 | + case 0x11: | |
| 178 | + udp_recv(ptr, sz); | |
| 179 | + break; | |
| 180 | + } | |
| 181 | +} | |
| 182 | + | |
| 183 | +/** | |
| 184 | + * @brief send an IP packet | |
| 185 | + * @param[in] ptr pointer to data of packet | |
| 186 | + * @param[in] sz size of packet | |
| 187 | + * | |
| 188 | + * ptr must point to a ip_packet of sufficient size (ethernet padding) | |
| 189 | + * with ip_hdr.proto and ip_hdr.dest already initialized | |
| 190 | + */ | |
| 191 | +void ip_send(void *ptr, unsigned int sz) | |
| 192 | +{ | |
| 193 | + struct ip_packet *ip_pack; | |
| 194 | + unsigned short chk; | |
| 195 | + unsigned int i; | |
| 196 | + | |
| 197 | + // packet too short | |
| 198 | + if (sz < sizeof(struct ip_packet)) | |
| 199 | + return; | |
| 200 | + | |
| 201 | + ip_pack = ptr; | |
| 202 | + | |
| 203 | + // fill in header values | |
| 204 | + ip_pack->ip_hdr.ver__hdr_len = 0x45; | |
| 205 | + ip_pack->ip_hdr.tos = 0x00; | |
| 206 | + ip_pack->ip_hdr.total_len = htons(sz - sizeof(struct ethernet_header)); | |
| 207 | + ip_pack->ip_hdr.id = 0x0000; | |
| 208 | + ip_pack->ip_hdr.frag_ofs = 0x0000; | |
| 209 | + ip_pack->ip_hdr.ttl = 0x40; | |
| 210 | + ip_pack->ip_hdr.hdr_chk = 0x0000; | |
| 211 | + ip_cpy(ip_pack->ip_hdr.src, config_ip.ip); | |
| 212 | + | |
| 213 | + // generate header checksum | |
| 214 | + chk = checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000); | |
| 215 | + ip_pack->ip_hdr.hdr_chk = htons(chk); | |
| 216 | + | |
| 217 | + // destination is in own subnet | |
| 218 | + if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) == | |
| 219 | + (config_ip.ip[0] & config_ip.mask[0]) && | |
| 220 | + (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) == | |
| 221 | + (config_ip.ip[1] & config_ip.mask[1]) && | |
| 222 | + (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) == | |
| 223 | + (config_ip.ip[2] & config_ip.mask[2]) && | |
| 224 | + (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) == | |
| 225 | + (config_ip.ip[3] & config_ip.mask[3]) ) | |
| 226 | + // lookup MAC address of destination | |
| 227 | + i = arp_lookup(ip_pack->ip_hdr.dest, ip_pack->eth_hdr.dest); | |
| 228 | + // destination is not in own subnet | |
| 229 | + else | |
| 230 | + // lookup MAC address of default gateway | |
| 231 | + i = arp_lookup(config_ip.gw, ip_pack->eth_hdr.dest); | |
| 232 | + | |
| 233 | + // MAC available | |
| 234 | +  if (i == 0x00) { | |
| 235 | + // sent IP packet | |
| 236 | + ip_pack->eth_hdr.type = htons(0x0800); // ethernet packet type: IP | |
| 237 | + ethernet_send(ip_pack, sz); | |
| 238 | + return; | |
| 239 | + } | |
| 240 | + | |
| 241 | + // find a buffer to store the packet in | |
| 242 | +  for (i = 0; i < count(ip_buffer_tab); i++) { | |
| 243 | + if (ip_buffer_tab[i].pkg_sz == 0 && // buffer not in use | |
| 244 | +        sz < ip_buffer_tab[i].buf_sz) { // buffer long enough | |
| 245 | + // put packet into buffer | |
| 246 | + memcpy(ip_buffer_tab[i].ptr, ptr, sz); | |
| 247 | + ip_buffer_tab[i].pkg_sz = sz; | |
| 248 | + ip_buffer_tab[i].ticks = 0; | |
| 249 | + break; | |
| 250 | + } | |
| 251 | + } | |
| 252 | + /* if no buffer was found, we cannnot do anything about it | |
| 253 | + and must discard the packet (i.e. do nothing here) */ | |
| 254 | +} | |
| 255 | + | |
| 256 | +/** | |
| 257 | + * @brief a MAC address was discovered | |
| 258 | + * @param[in] ip the IP address the MAC was discovered for | |
| 259 | + * @param[in] mac the MAC address corresponding to the IP address | |
| 260 | + * | |
| 261 | + * called by ARP to notify IP | |
| 262 | + */ | |
| 263 | +void ip_got_mac(unsigned char ip[4], unsigned char mac[6]) | |
| 264 | +{ | |
| 265 | + unsigned char i; | |
| 266 | + struct ip_packet *ip_pack; | |
| 267 | + | |
| 268 | + // search for buffered packets that can be sent now | |
| 269 | +  for (i = 0; i < count(ip_buffer_tab); i++) { | |
| 270 | +    if (ip_buffer_tab[i].pkg_sz > 0) { // buffer in use | |
| 271 | + ip_pack = ip_buffer_tab[i].ptr; | |
| 272 | + | |
| 273 | + // destination is in own subnet | |
| 274 | + if ((ip_pack->ip_hdr.dest[0] & config_ip.mask[0]) == | |
| 275 | + (config_ip.ip[0] & config_ip.mask[0]) && | |
| 276 | + (ip_pack->ip_hdr.dest[1] & config_ip.mask[1]) == | |
| 277 | + (config_ip.ip[1] & config_ip.mask[1]) && | |
| 278 | + (ip_pack->ip_hdr.dest[2] & config_ip.mask[2]) == | |
| 279 | + (config_ip.ip[2] & config_ip.mask[2]) && | |
| 280 | + (ip_pack->ip_hdr.dest[3] & config_ip.mask[3]) == | |
| 281 | +            (config_ip.ip[3] & config_ip.mask[3])) { | |
| 282 | + // packet can be sent to destination | |
| 283 | +        if (ip_eq( ip_pack->ip_hdr.dest, ip)) { | |
| 284 | + // send IP packet | |
| 285 | + ip_pack->eth_hdr.type = htons(0x0800); // ethernet packet type: IP | |
| 286 | + mac_cpy(ip_pack->eth_hdr.dest, mac); | |
| 287 | + ethernet_send(ip_buffer_tab[i].ptr, ip_buffer_tab[i].pkg_sz); | |
| 288 | + // buffer is now free | |
| 289 | + ip_buffer_tab[i].pkg_sz = 0; | |
| 290 | + } | |
| 291 | + } | |
| 292 | + // destination is not in own subnet | |
| 293 | +      else { | |
| 294 | + // packet can be sent to gateway | |
| 295 | +        if (ip_eq(config_ip.gw, ip)) { | |
| 296 | + // send IP packet | |
| 297 | + ip_pack->eth_hdr.type = htons(0x0800); // ethernet packet type: IP | |
| 298 | + mac_cpy(ip_pack->eth_hdr.dest, mac); | |
| 299 | + ethernet_send(ip_buffer_tab[i].ptr, ip_buffer_tab[i].pkg_sz); | |
| 300 | + // buffer is now free | |
| 301 | + ip_buffer_tab[i].pkg_sz = 0; | |
| 302 | + } | |
| 303 | + } | |
| 304 | + } | |
| 305 | + } // for (i ... | |
| 306 | +} | |
| 307 | + | 
| ... | ... | @@ -0,0 +1,64 @@ | 
| 1 | +#ifndef IP_H | |
| 2 | +#define IP_H | |
| 3 | + | |
| 4 | +#include "ethernet.h" | |
| 5 | + | |
| 6 | +/// header of IP packet | |
| 7 | +struct ip_header | |
| 8 | +{ | |
| 9 | + unsigned char ver__hdr_len; | |
| 10 | + unsigned char tos; | |
| 11 | + unsigned short total_len; | |
| 12 | + unsigned short id; | |
| 13 | + unsigned short frag_ofs; | |
| 14 | + unsigned char ttl; | |
| 15 | + unsigned char proto; | |
| 16 | + unsigned short hdr_chk; | |
| 17 | + unsigned char src[4]; | |
| 18 | + unsigned char dest[4]; | |
| 19 | +} __attribute__((packed)); | |
| 20 | + | |
| 21 | +/// IP packet | |
| 22 | +struct ip_packet | |
| 23 | +{ | |
| 24 | + struct ethernet_header eth_hdr; | |
| 25 | + struct ip_header ip_hdr; | |
| 26 | +} __attribute__((packed)); | |
| 27 | + | |
| 28 | +/// IP packet with padding | |
| 29 | +ETHERNET_PAD(ip_packet); | |
| 30 | + | |
| 31 | +/// initialize | |
| 32 | +void ip_init(void); | |
| 33 | + | |
| 34 | +/// tick procedure - call every 200ms | |
| 35 | +void ip_tick200(void); | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * @brief process a received IP packet | |
| 39 | + * @param[in] ptr pointer to data of packet | |
| 40 | + * @param[in] sz size of packet | |
| 41 | + */ | |
| 42 | +void ip_recv(void *ptr, unsigned int sz); | |
| 43 | + | |
| 44 | +/** | |
| 45 | + * @brief send an IP packet | |
| 46 | + * @param[in] ptr pointer to data of packet | |
| 47 | + * @param[in] sz size of packet | |
| 48 | + * | |
| 49 | + * ptr must point to a ip_packet of sufficient size (ethernet padding) | |
| 50 | + * with ip_hdr.proto and ip_hdr.dest already initialized | |
| 51 | + */ | |
| 52 | +void ip_send(void *ptr, unsigned int sz); | |
| 53 | + | |
| 54 | +/** | |
| 55 | + * @brief a MAC address was discovered | |
| 56 | + * @param[in] ip the IP address the MAC was discovered for | |
| 57 | + * @param[in] mac the MAC address corresponding to the IP address | |
| 58 | + * | |
| 59 | + * called by ARP to notify IP | |
| 60 | + */ | |
| 61 | +void ip_got_mac(unsigned char ip[4], unsigned char mac[6]); | |
| 62 | + | |
| 63 | +#endif // #ifdef IP_H | |
| 64 | + | 
| ... | ... | @@ -1,10 +1,12 @@ | 
| 1 | 1 | #include "arp.h" | 
| 2 | 2 | #include "cyc_cnt.h" | 
| 3 | 3 | #include "eth.h" | 
| 4 | +#include "ip.h" | |
| 4 | 5 | #include "lcd.h" | 
| 5 | 6 | #include "leds.h" | 
| 6 | -#include "uart.h" | |
| 7 | 7 | #include "switches.h" | 
| 8 | +#include "uart.h" | |
| 9 | +#include "udp.h" | |
| 8 | 10 |  | 
| 9 | 11 | unsigned char leds_val = 0x88; | 
| 10 | 12 |  | 
| ... | ... | @@ -81,6 +83,8 @@ void tick200(void) | 
| 81 | 83 |  { | 
| 82 | 84 | leds_tick200(); | 
| 83 | 85 | arp_tick200(); | 
| 86 | + ip_tick200(); | |
| 87 | + udp_tick200(); | |
| 84 | 88 | } | 
| 85 | 89 |  | 
| 86 | 90 | int main() | 
| ... | ... | @@ -116,6 +120,7 @@ int main() | 
| 116 | 120 | leds_set_state(0x08); | 
| 117 | 121 |  | 
| 118 | 122 | arp_init(); | 
| 123 | + ip_init(); | |
| 119 | 124 |  | 
| 120 | 125 | leds_set_state(0x10); | 
| 121 | 126 |  | 
| ... | ... | @@ -0,0 +1,35 @@ | 
| 1 | +#include "memcpy.h" | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @brief copy memory | |
| 5 | + * @param[in] dest pointer to destination buffer | |
| 6 | + * @param[in] src pointer to source data | |
| 7 | + * @param[in] sz size of data to copy | |
| 8 | + */ | |
| 9 | +void memcpy(void *dest, const void *src, unsigned int sz) | |
| 10 | +{ | |
| 11 | + unsigned int *dest4; | |
| 12 | + const unsigned int *src4; | |
| 13 | + unsigned int sz4; | |
| 14 | + unsigned char *dest1; | |
| 15 | + const unsigned char *src1; | |
| 16 | + | |
| 17 | + // word aligned memory addresses -> fast copy | |
| 18 | +  if (((unsigned int)dest & 3) == 0 && ((unsigned int)src & 3) == 0) { | |
| 19 | + dest4 = dest; | |
| 20 | + src4 = src; | |
| 21 | + for (sz4 = sz >> 2; sz4 > 0; --sz4) | |
| 22 | + *dest4++ = *src4++; | |
| 23 | + dest = dest4; | |
| 24 | + src = src4; | |
| 25 | + sz -= sz4; | |
| 26 | + // there might still be a few bytes to copy now | |
| 27 | + } | |
| 28 | + | |
| 29 | + // safe and slow fallback: copy byte-wise | |
| 30 | + dest1 = dest; | |
| 31 | + src1 = src; | |
| 32 | + for ( ; sz > 0; --sz) | |
| 33 | + *dest1++ = *src1++; | |
| 34 | +} | |
| 35 | + | 
| ... | ... | @@ -0,0 +1,13 @@ | 
| 1 | +#ifndef MEMCPY_H | |
| 2 | +#define MEMCPY_H | |
| 3 | + | |
| 4 | +/** | |
| 5 | + * @brief copy memory | |
| 6 | + * @param[in] dest pointer to destination buffer | |
| 7 | + * @param[in] src pointer to source data | |
| 8 | + * @param[in] sz size of data to copy | |
| 9 | + */ | |
| 10 | +void memcpy(void *dest, const void *src, unsigned int sz); | |
| 11 | + | |
| 12 | +#endif // #ifdef MEMCPY_H | |
| 13 | + | 
| ... | ... | @@ -0,0 +1,42 @@ | 
| 1 | +#include "config.h" | |
| 2 | +#include "checksum.h" | |
| 3 | +#include "ethernet.h" | |
| 4 | +#include "ip.h" | |
| 5 | +#include "macros.h" | |
| 6 | +#include "nethelp.h" | |
| 7 | +#include "udp.h" | |
| 8 | + | |
| 9 | +/// tick procedure - call every 200ms | |
| 10 | +void udp_tick200(void) | |
| 11 | +{ | |
| 12 | + // TODO | |
| 13 | +} | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * @brief process a received UDP packet | |
| 17 | + * @param[in] ptr pointer to data of packet | |
| 18 | + * @param[in] sz size of packet | |
| 19 | + */ | |
| 20 | +void udp_recv(void *ptr, unsigned int sz) | |
| 21 | +{ | |
| 22 | + // TODO | |
| 23 | + (void)ptr; | |
| 24 | + (void)sz; | |
| 25 | +} | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @brief send a UDP packet | |
| 29 | + * @param[in] ptr pointer to data of packet | |
| 30 | + * @param[in] sz size of packet | |
| 31 | + * | |
| 32 | + * ptr must point to a udp_packet of sufficient size (ethernet padding) | |
| 33 | + * with ip_hdr.proto and udp_hdr.src_port, udp_hdr.dest_port, ip_hdr.dest | |
| 34 | + * already initialized | |
| 35 | + */ | |
| 36 | +void udp_send(void *ptr, unsigned int sz) | |
| 37 | +{ | |
| 38 | + // TODO | |
| 39 | + (void)ptr; | |
| 40 | + (void)sz; | |
| 41 | +} | |
| 42 | + | 
| ... | ... | @@ -0,0 +1,49 @@ | 
| 1 | +#ifndef UDP_H | |
| 2 | +#define UDP_H | |
| 3 | + | |
| 4 | +#include "ethernet.h" | |
| 5 | +#include "ip.h" | |
| 6 | + | |
| 7 | +/// header of UDP packet | |
| 8 | +struct udp_header | |
| 9 | +{ | |
| 10 | + unsigned short src_port; | |
| 11 | + unsigned short dest_port; | |
| 12 | + unsigned short length; | |
| 13 | + unsigned short chk; | |
| 14 | +} __attribute__((packed)); | |
| 15 | + | |
| 16 | +/// UDP packet | |
| 17 | +struct udp_packet | |
| 18 | +{ | |
| 19 | + struct ethernet_header eth_hdr; | |
| 20 | + struct ip_header ip_hdr; | |
| 21 | + struct udp_header udp_hdr; | |
| 22 | +} __attribute__((packed)); | |
| 23 | + | |
| 24 | +/// UDP packet with padding | |
| 25 | +ETHERNET_PAD(udp_packet); | |
| 26 | + | |
| 27 | +/// tick procedure - call every 200ms | |
| 28 | +void udp_tick200(void); | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * @brief process a received UDP packet | |
| 32 | + * @param[in] ptr pointer to data of packet | |
| 33 | + * @param[in] sz size of packet | |
| 34 | + */ | |
| 35 | +void udp_recv(void *ptr, unsigned int sz); | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * @brief send a UDP packet | |
| 39 | + * @param[in] ptr pointer to data of packet | |
| 40 | + * @param[in] sz size of packet | |
| 41 | + * | |
| 42 | + * ptr must point to a udp_packet of sufficient size (ethernet padding) | |
| 43 | + * with ip_hdr.proto and udp_hdr.src_port, udp_hdr.dest_port, ip_hdr.dest | |
| 44 | + * already initialized | |
| 45 | + */ | |
| 46 | +void udp_send(void *ptr, unsigned int sz); | |
| 47 | + | |
| 48 | +#endif // #ifdef UDP_H | |
| 49 | + | 
| ... | ... | @@ -29,22 +29,37 @@ ARCHITECTURE a_testbed OF e_testbed IS | 
| 29 | 29 | ); | 
| 30 | 30 | END COMPONENT e_system; | 
| 31 | 31 |  | 
| 32 | - TYPE t_eth_data IS ARRAY(0 TO 108 - 1) OF std_logic_vector(3 DOWNTO 0); | |
| 32 | + -- ICMP echo request | |
| 33 | + TYPE t_eth_data IS ARRAY(0 TO 220 - 1) OF std_logic_vector(3 DOWNTO 0); | |
| 33 | 34 | CONSTANT eth_data: t_eth_data := ( | 
| 34 | 35 | X"5", X"5", X"5", X"5", X"5", X"5", X"5", X"5", | 
| 35 | 36 | X"5", X"5", X"5", X"5", X"5", X"5", X"5", X"D", | 
| 36 | - X"F", X"F", X"F", X"F", X"F", X"F", X"F", X"F", | |
| 37 | - X"F", X"F", X"F", X"F", X"2", X"0", X"3", X"0", | |
| 38 | - X"4", X"0", X"5", X"0", X"6", X"0", X"7", X"0", | |
| 39 | - X"8", X"0", X"6", X"0", X"0", X"0", X"1", X"0", | |
| 40 | - X"8", X"0", X"0", X"0", X"6", X"0", X"4", X"0", | |
| 41 | - X"0", X"0", X"1", X"0", X"0", X"0", X"d", X"1", | |
| 42 | - X"0", X"6", X"c", X"d", X"5", X"7", X"d", X"2", | |
| 43 | - X"0", X"c", X"8", X"a", X"0", X"0", X"a", X"0", | |
| 44 | - X"f", X"f", X"f", X"f", X"f", X"f", X"f", X"f", | |
| 45 | - X"f", X"f", X"f", X"f", X"0", X"c", X"8", X"a", | |
| 46 | - X"0", X"0", X"9", X"5", X"0", X"E", X"8", X"0", | |
| 47 | - X"8", X"C", X"1", X"B" | |
| 37 | + X"2", X"0", X"D", X"4", X"9", X"4", X"0", X"5", | |
| 38 | + X"3", X"5", X"1", X"0", X"0", X"0", X"D", X"1", | |
| 39 | + X"0", X"6", X"C", X"D", X"5", X"7", X"D", X"2", | |
| 40 | + X"8", X"0", X"0", X"0", X"5", X"4", X"0", X"0", | |
| 41 | + X"0", X"0", X"4", X"5", X"0", X"0", X"0", X"0", | |
| 42 | + X"0", X"4", X"0", X"0", X"0", X"4", X"1", X"0", | |
| 43 | + X"8", X"B", X"5", X"F", X"0", X"C", X"8", X"A", | |
| 44 | + X"0", X"0", X"A", X"0", X"0", X"C", X"8", X"A", | |
| 45 | + X"0", X"0", X"9", X"5", X"8", X"0", X"0", X"0", | |
| 46 | + X"E", X"8", X"7", X"5", X"F", X"0", X"2", X"6", | |
| 47 | + X"0", X"0", X"1", X"0", X"6", X"E", X"4", X"B", | |
| 48 | + X"D", X"6", X"F", X"4", X"0", X"0", X"0", X"0", | |
| 49 | + X"0", X"0", X"0", X"0", X"4", X"4", X"E", X"6", | |
| 50 | + X"3", X"0", X"0", X"0", X"0", X"0", X"0", X"0", | |
| 51 | + X"0", X"0", X"0", X"0", X"0", X"1", X"1", X"1", | |
| 52 | + X"2", X"1", X"3", X"1", X"4", X"1", X"5", X"1", | |
| 53 | + X"6", X"1", X"7", X"1", X"8", X"1", X"9", X"1", | |
| 54 | + X"A", X"1", X"B", X"1", X"C", X"1", X"D", X"1", | |
| 55 | + X"E", X"1", X"F", X"1", X"0", X"2", X"1", X"2", | |
| 56 | + X"2", X"2", X"3", X"2", X"4", X"2", X"5", X"2", | |
| 57 | + X"6", X"2", X"7", X"2", X"8", X"2", X"9", X"2", | |
| 58 | + X"A", X"2", X"B", X"2", X"C", X"2", X"D", X"2", | |
| 59 | + X"E", X"2", X"F", X"2", X"0", X"3", X"1", X"3", | |
| 60 | + X"2", X"3", X"3", X"3", X"4", X"3", X"5", X"3", | |
| 61 | + X"6", X"3", X"7", X"3", X"2", X"9", X"1", X"C", | |
| 62 | + X"0", X"1", X"2", X"C" | |
| 48 | 63 | ); | 
| 49 | 64 |  | 
| 50 | 65 | SIGNAL s_clk: std_logic; | 
| 51 | 66 |