implemented UDP functions
Stefan Schuermans

Stefan Schuermans commited on 2012-03-24 19:03:45
Showing 1 changed files, with 113 additions and 7 deletions.

... ...
@@ -6,10 +6,58 @@
6 6
 #include "nethelp.h"
7 7
 #include "udp.h"
8 8
 
9
+// some kind of "token bucket" for UDP echo
10
+#define UDP_ECHO_TICKS 10 ///< allowed rate of UDP echo replies (in 200ms)
11
+static unsigned int udp_echo_tick_cnt = 0; ///< tick counter
12
+#define UDP_ECHO_REPLIES_MAX 3 ///< maximum value for udp_echo_replies
13
+static unsigned int udp_echo_replies = 0; // # of allowed UDP echo replies
14
+
9 15
 /// tick procedure - call every 200ms
10 16
 void udp_tick200(void)
11 17
 {
12
-  // TODO
18
+  // count ticks
19
+  udp_echo_tick_cnt++;
20
+  // time to allow one reply more
21
+  if (udp_echo_tick_cnt >= UDP_ECHO_TICKS) {
22
+    udp_echo_tick_cnt = 0;
23
+
24
+    // increase reply count if not at maximum
25
+    if (udp_echo_replies < UDP_ECHO_REPLIES_MAX)
26
+      udp_echo_replies++;
27
+  }
28
+}
29
+
30
+/**
31
+ * @brief process a received UDP echo packet
32
+ * @param[in] ptr pointer to data of packet
33
+ * @param[in] sz size of packet
34
+ */
35
+static void udp_echo_recv(void *ptr, unsigned int sz)
36
+{
37
+  struct udp_packet *udp_pack;
38
+
39
+  udp_pack = ptr;
40
+
41
+  // source port is UDP echo port
42
+  if (udp_pack->udp_hdr.src_port == htons(7))
43
+    // ignore this packet
44
+    //  - UDP echo answer to another UDP echo port will result
45
+    //    in endless echoing
46
+    return;
47
+
48
+  // only reply with allowed packet rate
49
+  if (udp_echo_replies <= 0)
50
+    return;
51
+  udp_echo_replies--;
52
+
53
+  // send an UDP echo
54
+  //  - use same buffer to send reply
55
+  //  - this saves us from allocating a new buffer
56
+  //  - this saves us from copying the data
57
+  udp_pack->udp_hdr.dest_port = udp_pack->udp_hdr.src_port; // to source port
58
+  udp_pack->udp_hdr.src_port = htons(7); // UDP echo port
59
+  ip_cpy( udp_pack->ip_hdr.dest, udp_pack->ip_hdr.src); // to source IP
60
+  udp_send(udp_pack, sz);
13 61
 }
14 62
 
15 63
 /**
... ...
@@ -19,9 +67,42 @@ void udp_tick200(void)
19 67
  */
20 68
 void udp_recv(void *ptr, unsigned int sz)
21 69
 {
22
-  // TODO
23
-  (void)ptr;
24
-  (void)sz;
70
+  struct udp_packet *udp_pack;
71
+  unsigned int len;
72
+
73
+  // packet too short
74
+  if (sz < sizeof(struct udp_packet))
75
+    return;
76
+
77
+  udp_pack = ptr;
78
+
79
+  // ignore packets sent from or to port 0 (not allowed by RFC)
80
+  if (udp_pack->udp_hdr.src_port == htons(0) ||
81
+      udp_pack->udp_hdr.dest_port == htons(0))
82
+    return;
83
+
84
+  // check total length
85
+  len = sizeof(struct ethernet_header) + sizeof(struct ip_header) +
86
+        ntohs(udp_pack->udp_hdr.length); // length according to UDP header
87
+  if (sz < len) // packet is truncated
88
+    return;
89
+  sz = len; // remove IP padding from packet (maybe sz > len)
90
+
91
+  // test checksum
92
+  if (checksum(&udp_pack->ip_hdr.src,
93
+                sz - sizeof(struct ethernet_header)
94
+                   - sizeof(struct ip_header ) + 8,
95
+                0x0011,
96
+                ntohs(udp_pack->udp_hdr.length)))
97
+    return;
98
+
99
+  // branch according to destination port
100
+  switch (ntohs(udp_pack->udp_hdr.dest_port)) {
101
+    // UDP echo
102
+    case 7:
103
+      udp_echo_recv(ptr, sz);
104
+      break;
105
+  }
25 106
 }
26 107
 
27 108
 /**
... ...
@@ -35,8 +116,33 @@ void udp_recv(void *ptr, unsigned int sz)
35 116
  */
36 117
 void udp_send(void *ptr, unsigned int sz)
37 118
 {
38
-  // TODO
39
-  (void)ptr;
40
-  (void)sz;
119
+  struct udp_packet *udp_pack;
120
+  unsigned int chk;
121
+
122
+  // packet too short
123
+  if (sz < sizeof(struct udp_packet))
124
+    return;
125
+
126
+  udp_pack = ptr;
127
+
128
+  // fill in header values
129
+  udp_pack->udp_hdr.length = htons(sz - sizeof(struct ethernet_header)
130
+                                      - sizeof(struct ip_header));
131
+  udp_pack->udp_hdr.chk = 0x0000;
132
+  /* put IP already here into IP header
133
+     because it is needed for calculation of UDP checksum */
134
+  ip_cpy(udp_pack->ip_hdr.src, config_ip.ip);
135
+
136
+  // generate checksum
137
+  chk = checksum(&udp_pack->ip_hdr.src,
138
+                 sz - sizeof(struct ethernet_header )
139
+                    - sizeof(struct ip_header ) + 8,
140
+                 0x0011,
141
+                 ntohs(udp_pack->udp_hdr.length));
142
+  udp_pack->udp_hdr.chk = htons(chk);
143
+
144
+  // send UDP packet
145
+  udp_pack->ip_hdr.proto = 0x11; // UDP
146
+  ip_send(udp_pack, sz);
41 147
 }
42 148
 
43 149