use implicit MAC/IP information in received IP packets
Stefan Schuermans

Stefan Schuermans commited on 2012-03-24 23:11:26
Showing 3 changed files, with 65 additions and 24 deletions.

... ...
@@ -18,11 +18,11 @@
18 18
 #define ARP_TAB_FLAG_MAC_OK (2)
19 19
 struct arp_table
20 20
 {
21
-  unsigned char flags; /// flags - see constants
22
-  unsigned char ticks; /// age of entry in 200ms steps
21
+  unsigned int flags; /// flags - see constants
22
+  unsigned int ticks; /// age of entry in 200ms steps
23 23
   unsigned char mac[6];
24 24
   unsigned char ip[4];
25
-} arp_tab[12];
25
+} arp_tab[16];
26 26
 
27 27
 /**
28 28
  * @brief send an ARP request
... ...
@@ -144,28 +144,16 @@ void arp_recv(void *ptr, unsigned int sz)
144 144
   if (arp_pack->arp_hdr.op == htons(0x0002) && // ARP reply
145 145
       mac_eq(arp_pack->arp_hdr.dest_mac, config_mac.mac) && // own MAC address
146 146
       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
147
-    unsigned int i;
148 147
 
149
-    // search IP in ARP tabale
150
-    for (i = 0; i < count(arp_tab); ++i)
151
-      if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
152
-          ip_eq(arp_pack->arp_hdr.src_ip, arp_tab[i].ip))
153
-        break;
154
-    // if found in ARP table
155
-    // (we do not want to put an entry in the ARP table
156
-    //  if we have not asked for the MAC of this IP)
157
-    if (i < count(arp_tab)) {
158
-      // update ARP table entry
159
-      arp_tab[i].flags = ARP_TAB_FLAG_IN_USE | ARP_TAB_FLAG_MAC_OK;
160
-      arp_tab[i].ticks = 0;
161
-      mac_cpy(arp_tab[i].mac, arp_pack->arp_hdr.src_mac);
148
+    // store MAC for IP
149
+    arp_store(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
150
+
162 151
     // notify IP
163 152
     //  - IP might be waiting for the MAC to transmit a packet
164
-      ip_got_mac(arp_tab[i].ip, arp_tab[i].mac);
165
-    }
153
+    ip_got_mac(arp_pack->arp_hdr.src_ip, arp_pack->arp_hdr.src_mac);
154
+
166 155
     return;
167 156
   }
168
-
169 157
 }
170 158
 
171 159
 /**
... ...
@@ -225,3 +213,47 @@ int arp_lookup(unsigned char ip[4], unsigned char mac[6])
225 213
   return 1;
226 214
 }
227 215
 
216
+/**
217
+ * @brief store the MAC for an IP address
218
+ * @param[in] ip IP address to store MAC for
219
+ * @param[out] mac MAC address for this IP address
220
+ */
221
+void arp_store(unsigned char ip[4], unsigned char mac[6])
222
+{
223
+  unsigned int i, j;
224
+
225
+  // search IP in ARP table
226
+  for (i = 0; i < count(arp_tab); ++i) {
227
+    if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
228
+        ip_eq(ip, arp_tab[i].ip))
229
+      break;
230
+  }
231
+
232
+  // not found
233
+  if (i >= count(arp_tab)) {
234
+    // find a free entry
235
+    for (i = 0; i < count(arp_tab); ++i)
236
+      if (!(arp_tab[i].flags & ARP_TAB_FLAG_IN_USE))
237
+        break;
238
+
239
+    // no free entry
240
+    if (i >= count(arp_tab)) {
241
+      // find oldest entry
242
+      i = 0;
243
+      for (j = 1; j < count(arp_tab); ++j)
244
+        if (arp_tab[j].ticks > arp_tab[i].ticks )
245
+          i = j;
246
+    }
247
+
248
+    // set up this entry
249
+    arp_tab[i].flags = ARP_TAB_FLAG_IN_USE;
250
+    arp_tab[i].ticks = 0;
251
+    ip_cpy(arp_tab[i].ip, ip);
252
+  }
253
+
254
+  // update ARP table entry
255
+  arp_tab[i].flags = ARP_TAB_FLAG_IN_USE | ARP_TAB_FLAG_MAC_OK;
256
+  arp_tab[i].ticks = 0;
257
+  mac_cpy(arp_tab[i].mac, mac);
258
+}
259
+
... ...
@@ -45,5 +45,12 @@ void arp_recv(void *ptr, unsigned int sz);
45 45
  */
46 46
 int arp_lookup(unsigned char ip[4], unsigned char mac[6]);
47 47
 
48
+/**
49
+ * @brief store the MAC for an IP address
50
+ * @param[in] ip IP address to store MAC for
51
+ * @param[out] mac MAC address for this IP address
52
+ */
53
+void arp_store(unsigned char ip[4], unsigned char mac[6]);
54
+
48 55
 #endif // #ifdef ARP_H
49 56
 
... ...
@@ -30,7 +30,7 @@ struct ip_buffer_table
30 30
   void *ptr; ///< pointer to buffer for packet
31 31
   unsigned int buf_sz; ///< size of buffer
32 32
   unsigned int pkg_sz; ///< size of packet in buffer, 0 for packet
33
-  unsigned int ticks; //< age of entry (in 200ms)
33
+  unsigned int ticks; ///< age of entry (in 200ms)
34 34
 } ip_buffer_tab[] =
35 35
 { // put smaller buffers in front of larger buffers
36 36
   //  - then short packets will use smaller buffers more often
... ...
@@ -130,8 +130,7 @@ void ip_recv(void *ptr, unsigned int sz)
130 130
       (ip_pack->ip_hdr.src[2] & config_ip.mask[2]) ==
131 131
         (config_ip.ip[2] & config_ip.mask[2]) &&
132 132
       (ip_pack->ip_hdr.src[3] & config_ip.mask[3]) ==
133
-        (config_ip.ip[3] & config_ip.mask[3]))
134
-  {
133
+        (config_ip.ip[3] & config_ip.mask[3])) {
135 134
     // local network address
136 135
     if ((ip_pack->ip_hdr.src[0] & ~config_ip.mask[0]) == 0x00 &&
137 136
         (ip_pack->ip_hdr.src[1] & ~config_ip.mask[1]) == 0x00 &&
... ...
@@ -166,6 +165,9 @@ void ip_recv(void *ptr, unsigned int sz)
166 165
   if (checksum(&ip_pack->ip_hdr, sizeof(struct ip_header), 0x0000, 0x0000))
167 166
     return;
168 167
 
168
+  // save MAC/IP information in ARP table
169
+  arp_store(ip_pack->ip_hdr.src, ip_pack->eth_hdr.src);
170
+
169 171
   // branch according to protocol
170 172
   switch (ip_pack->ip_hdr.proto) {
171 173
     // ICMP
... ...
@@ -240,7 +242,7 @@ void ip_send(void *ptr, unsigned int sz)
240 242
   // find a buffer to store the packet in
241 243
   for (i = 0; i < count(ip_buffer_tab); i++) {
242 244
     if (ip_buffer_tab[i].pkg_sz == 0 && // buffer not in use
243
-        sz < ip_buffer_tab[i].buf_sz) { // buffer long enough
245
+        sz <= ip_buffer_tab[i].buf_sz) { // buffer long enough
244 246
       // put packet into buffer
245 247
       memcpy(ip_buffer_tab[i].ptr, ptr, sz);
246 248
       ip_buffer_tab[i].pkg_sz = sz;
247 249