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 |