added padding of ethernet packets to 60 bytes data min ARP is working now
Stefan Schuermans

Stefan Schuermans commited on 2012-03-21 21:43:38
Showing 6 changed files, with 101 additions and 32 deletions.

... ...
@@ -116,25 +116,25 @@ static void arp_send_request(unsigned char ip[4])
116 116
   // ARP request for own IP address
117 117
   if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request
118 118
       ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
119
-    struct arp_packet arp_reply;
119
+    struct arp_packet_pad arp_reply;
120 120
 
121 121
     // build ARP reply
122
-    arp_reply.arp_hdr.hw_type = htons(0x0001); // ethernet
123
-    arp_reply.arp_hdr.proto_type = htons(0x0800); // IP
124
-    arp_reply.arp_hdr.hw_len = 0x06; // length of a MAC address
125
-    arp_reply.arp_hdr.proto_len = 0x04; // length of an IP address
126
-    arp_reply.arp_hdr.op = htons(0x0002); // ARP reply
127
-    mac_cpy(arp_reply.arp_hdr.src_mac, config_mac.mac); // own MAC
128
-    ip_cpy(arp_reply.arp_hdr.src_ip, config_ip.ip); // own IP
129
-    mac_cpy(arp_reply.arp_hdr.dest_mac,
122
+    arp_reply.p.arp_hdr.hw_type = htons(0x0001); // ethernet
123
+    arp_reply.p.arp_hdr.proto_type = htons(0x0800); // IP
124
+    arp_reply.p.arp_hdr.hw_len = 0x06; // length of a MAC address
125
+    arp_reply.p.arp_hdr.proto_len = 0x04; // length of an IP address
126
+    arp_reply.p.arp_hdr.op = htons(0x0002); // ARP reply
127
+    mac_cpy(arp_reply.p.arp_hdr.src_mac, config_mac.mac); // own MAC
128
+    ip_cpy(arp_reply.p.arp_hdr.src_ip, config_ip.ip); // own IP
129
+    mac_cpy(arp_reply.p.arp_hdr.dest_mac,
130 130
             arp_pack->arp_hdr.src_mac); // requestor's MAC
131
-    ip_cpy(arp_reply.arp_hdr.dest_ip,
131
+    ip_cpy(arp_reply.p.arp_hdr.dest_ip,
132 132
            arp_pack->arp_hdr.src_ip); // requestor's IP
133 133
 
134 134
     // send ARP reply
135
-    mac_cpy(arp_reply.eth_hdr.dest,
136
-            arp_reply.arp_hdr.dest_mac); // ethernet destination address
137
-    arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
135
+    mac_cpy(arp_reply.p.eth_hdr.dest,
136
+            arp_reply.p.arp_hdr.dest_mac); // ethernet destination address
137
+    arp_reply.p.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
138 138
     ethernet_send(&arp_reply, sizeof(arp_reply));
139 139
 
140 140
     return;
... ...
@@ -3,7 +3,7 @@
3 3
 
4 4
 #include "ethernet.h"
5 5
 
6
-/// header of an ARP packet
6
+/// header of ARP packet
7 7
 struct arp_header
8 8
 {
9 9
   unsigned short hw_type;
... ...
@@ -17,13 +17,16 @@ struct arp_header
17 17
   unsigned char dest_ip[4];
18 18
 } __attribute__((packed));
19 19
 
20
-/// an ARP packet
20
+/// ARP packet
21 21
 struct arp_packet
22 22
 {
23 23
   struct ethernet_header eth_hdr;
24 24
   struct arp_header arp_hdr;
25 25
 } __attribute__((packed));
26 26
 
27
+/// ARP packet with padding
28
+ETHERNET_PAD(arp_packet);
29
+
27 30
 /// initialize
28 31
 extern void arp_init(void);
29 32
 
... ...
@@ -5,9 +5,13 @@ static volatile unsigned int *const eth_ptr =
5 5
   (volatile unsigned int *)0x80000400;
6 6
 
7 7
 static unsigned int eth_idx_hw;
8
-static unsigned int eth_rx_buf[2][381]; // max frame len: 1522 byte = 380.5 int
8
+static unsigned int eth_rx_buf[2][381]; /* max frame: 1522 byte = 380.5 int */
9 9
 static unsigned int *eth_rx_pos;
10 10
 
11
+static unsigned int eth_rx_cnt;
12
+
13
+static unsigned int eth_tx_cnt;
14
+
11 15
 /**
12 16
  * @brief set MAC address
13 17
  * @param[in] mac MAC address
... ...
@@ -52,12 +56,21 @@ void eth_mac_init(void)
52 56
 /** initialize receiver */
53 57
 void eth_rx_init(void)
54 58
 {
55
-  // give buffer 0 to HW
59
+  /* give buffer 0 to HW */
56 60
   eth_idx_hw = 0;
57 61
   eth_rx_new_buf(eth_rx_buf[0], sizeof(eth_rx_buf[0]));
58
-  // buffer 1 owned by SW is empty
62
+  /* buffer 1 owned by SW is empty */
59 63
   eth_rx_buf[1][0] = 0;
60 64
   eth_rx_pos = eth_rx_buf[1];
65
+  /* no packets received yet */
66
+  eth_rx_cnt = 0;
67
+}
68
+
69
+/** initialize transmitter */
70
+void eth_tx_init(void)
71
+{
72
+  /* no packets transmitted yet */
73
+  eth_tx_cnt = 0;
61 74
 }
62 75
 
63 76
 /**
... ...
@@ -68,42 +81,59 @@ void eth_rx_init(void)
68 81
  */
69 82
 int eth_rx(void **pptr, unsigned int *psz)
70 83
 {
71
-  // current SW buffer is empty and HW buffer contains a packet
84
+  /* current SW buffer is empty and HW buffer contains a packet */
72 85
   if (*eth_rx_pos == 0 && eth_rx_get_pos() != eth_rx_buf[eth_idx_hw]) {
73
-    // swap buffers
86
+    /* swap buffers */
74 87
     eth_idx_hw = 1 - eth_idx_hw;
75
-    // give new HW buffer to HW
88
+    /* give new HW buffer to HW */
76 89
     eth_rx_new_buf(eth_rx_buf[eth_idx_hw], sizeof(eth_rx_buf[eth_idx_hw]));
77
-    // start reading packet data at begin of new SW buffer
90
+    /* start reading packet data at begin of new SW buffer */
78 91
     eth_rx_pos = eth_rx_buf[1 - eth_idx_hw];
79 92
   }
80 93
 
81
-  // SW buffer contains a packet
94
+  /* SW buffer contains a packet */
82 95
   if (*eth_rx_pos > 0) {
83
-    // return size and pointer, advance position
96
+    /* return size and pointer, advance position */
84 97
     *psz = *eth_rx_pos;
85 98
     eth_rx_pos++;
86 99
     *pptr = eth_rx_pos;
87 100
     eth_rx_pos += *psz >> 2;
101
+    ++eth_rx_cnt; /* count received packets */
88 102
     return 1;
89 103
   }
90 104
 
91
-  // no packet received
105
+  /* no packet received */
92 106
   return 0;
93 107
 }
94 108
 
95 109
 /**
96 110
  * @brief transmit packet
97
- * @param[out] ptr pointer to packet data
98
- * @param[out] sz size of packet
111
+ * @param[in] ptr pointer to packet data
112
+ * @param[in] sz size of packet
113
+ *
114
+ * Padding will be appended if sz is not a multiple of 4 or smaller 60 bytes.
115
+ * The buffer pointed to by ptr must be sufficiently large.
99 116
  */
100 117
 void eth_tx(const void *ptr, unsigned int sz)
101 118
 {
102
-  while(sz & 3) /* pad with zeros up to next 4 byte boundary */
119
+  while(sz < 60 || sz & 3) /* pad with zeros */
103 120
     ((unsigned char *)ptr)[sz++] = 0;
104 121
   eth_ptr[8] = (unsigned int)ptr; /* start */
105 122
   eth_ptr[9] = (unsigned int)ptr + sz; /* end */
106 123
   eth_ptr[10] = 1; /* set flag */
107 124
   while (eth_ptr[10] == 1); /* wait until processed */
125
+  ++eth_tx_cnt; /* count transmitted packets */
126
+}
127
+
128
+/** get number of received packets */
129
+unsigned int eth_rx_get_cnt(void)
130
+{
131
+  return eth_rx_cnt;
132
+}
133
+
134
+/** get number of transmitted packets */
135
+unsigned int eth_tx_get_cnt(void)
136
+{
137
+  return eth_tx_cnt;
108 138
 }
109 139
 
... ...
@@ -7,6 +7,9 @@ void eth_mac_init(void);
7 7
 /** initialize receiver */
8 8
 void eth_rx_init(void);
9 9
 
10
+/** initialize transmitter */
11
+void eth_tx_init(void);
12
+
10 13
 /**
11 14
  * @brief get next received packet
12 15
  * @param[out] *pptr pointer to packet data
... ...
@@ -17,10 +20,19 @@ int eth_rx(void **pptr, unsigned int *psz);
17 20
 
18 21
 /**
19 22
  * @brief transmit packet
20
- * @param[out] ptr pointer to packet data
21
- * @param[out] sz size of packet
23
+ * @param[in] ptr pointer to packet data
24
+ * @param[in] sz size of packet
25
+ *
26
+ * Padding will be appended if sz is not a multiple of 4 or smaller 60 bytes.
27
+ * The buffer pointed to by ptr must be sufficiently large.
22 28
  */
23 29
 void eth_tx(const void *ptr, unsigned int sz);
24 30
 
31
+/** get number of received packets */
32
+unsigned int eth_rx_get_cnt(void);
33
+
34
+/** get number of transmitted packets */
35
+unsigned int eth_tx_get_cnt(void);
36
+
25 37
 #endif /* #ifndef ETH_H */
26 38
 
... ...
@@ -1,7 +1,20 @@
1 1
 #ifndef ETHERNET_H
2 2
 #define ETHERNET_H
3 3
 
4
-/// header of an ethernet packet
4
+/** padding at end of packet
5
+    to reach next size divisible by 4 and at least 60 bytes */
6
+#define ETHERNET_PADDING_SIZE(packet) \
7
+        (sizeof(struct packet) >= 60 ? 0 : 60 - sizeof(struct packet))
8
+#define ETHERNET_PADDING(packet) \
9
+        unsigned char padding[ETHERNET_PADDING_SIZE(packet)]
10
+#define ETHERNET_PAD(packet) \
11
+        struct packet ## _pad \
12
+        { \
13
+          struct packet p; \
14
+          ETHERNET_PADDING(packet); \
15
+        } __attribute__((packed))
16
+
17
+/// header of ethernet packet
5 18
 struct ethernet_header
6 19
 {
7 20
   unsigned char dest[6];
... ...
@@ -15,6 +28,9 @@ struct ethernet_packet
15 28
   struct ethernet_header eth_hdr;
16 29
 } __attribute__((packed));
17 30
 
31
+/// ethernet packet with padding
32
+ETHERNET_PAD(ethernet_packet);
33
+
18 34
 /**
19 35
  * @brief process a received ethernet packet
20 36
  * @param[in] ptr pointer to data of packet
... ...
@@ -55,6 +55,13 @@ void eth_task(void)
55 55
       uart_tx(ptr[i]);
56 56
     ethernet_recv(vptr, sz);
57 57
   }
58
+
59
+  i = eth_rx_get_cnt();
60
+  lcd_chr(0, 11, '0' + (i >> 3 & 0x7));
61
+  lcd_chr(0, 12, '0' + (i & 0x7));
62
+  i = eth_tx_get_cnt();
63
+  lcd_chr(0, 14, '0' + (i >> 3 & 0x7));
64
+  lcd_chr(0, 15, '0' + (i & 0x7));
58 65
 }
59 66
 
60 67
 void tasks(void)
... ...
@@ -84,11 +91,12 @@ int main()
84 91
 
85 92
   eth_mac_init();
86 93
   eth_rx_init();
94
+  eth_tx_init();
87 95
 
88 96
   leds_set_state(0x02);
89 97
 
90 98
   lcd_init();
91
-  lcd_str(0, "MIPS I system");
99
+  lcd_str(0, "MIPS I");
92 100
   lcd_str(1, "");
93 101
 
94 102
   leds_set_state(0x04);
95 103