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 |