handle padding to minimum ethernet frame size (TX) in HW
Stefan Schuermans

Stefan Schuermans commited on 2012-03-24 16:42:53
Showing 12 changed files, with 82 additions and 85 deletions.

... ...
@@ -30,24 +30,24 @@ struct arp_table
30 30
  */
31 31
 static void arp_send_request(unsigned char ip[4])
32 32
 {
33
-  struct arp_packet_pad arp_request;
33
+  struct arp_packet arp_request;
34 34
 
35 35
   // build ARP request
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,
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,
44 44
           "\xFF\xFF\xFF\xFF\xFF\xFF"); // broadcast MAC
45
-  ip_cpy(arp_request.p.arp_hdr.dest_ip, ip); // requested IP
45
+  ip_cpy(arp_request.arp_hdr.dest_ip, ip); // requested IP
46 46
 
47 47
   // send 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));
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));
51 51
 }
52 52
 
53 53
 /// initialize
... ...
@@ -116,26 +116,26 @@ void arp_recv(void *ptr, unsigned int sz)
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_pad arp_reply;
119
+    struct arp_packet arp_reply;
120 120
 
121 121
     // build ARP reply
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,
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,
130 130
             arp_pack->arp_hdr.src_mac); // requestor's MAC
131
-    ip_cpy(arp_reply.p.arp_hdr.dest_ip,
131
+    ip_cpy(arp_reply.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.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
-    ethernet_send(&arp_reply.p, sizeof(arp_reply.p));
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
138
+    ethernet_send(&arp_reply, sizeof(arp_reply));
139 139
 
140 140
     return;
141 141
   }
... ...
@@ -24,9 +24,6 @@ struct arp_packet
24 24
   struct arp_header arp_hdr;
25 25
 } __attribute__((packed));
26 26
 
27
-/// ARP packet with padding
28
-ETHERNET_PAD(arp_packet);
29
-
30 27
 /// initialize
31 28
 void arp_init(void);
32 29
 
... ...
@@ -116,7 +116,7 @@ int eth_rx(void **pptr, unsigned int *psz)
116 116
  */
117 117
 void eth_tx(const void *ptr, unsigned int sz)
118 118
 {
119
-  while(sz < 60 || sz & 3) /* pad with zeros */
119
+  while(sz & 3) /* pad with zeros */
120 120
     ((unsigned char *)ptr)[sz++] = 0;
121 121
   eth_ptr[8] = (unsigned int)ptr; /* start */
122 122
   eth_ptr[9] = (unsigned int)ptr + sz; /* end */
... ...
@@ -46,7 +46,7 @@ void ethernet_recv(void *ptr, unsigned int sz)
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 of sufficient size (ethernet padding)
49
+ * ptr must point to a ethernet_packet
50 50
  * with eth_hdr.dest and eth_hdr.type already initialized
51 51
  */
52 52
 void ethernet_send(void *ptr, unsigned int sz)
... ...
@@ -1,19 +1,6 @@
1 1
 #ifndef ETHERNET_H
2 2
 #define ETHERNET_H
3 3
 
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 4
 /// header of ethernet packet
18 5
 struct ethernet_header
19 6
 {
... ...
@@ -28,9 +15,6 @@ struct ethernet_packet
28 15
   struct ethernet_header eth_hdr;
29 16
 } __attribute__((packed));
30 17
 
31
-/// ethernet packet with padding
32
-ETHERNET_PAD(ethernet_packet);
33
-
34 18
 /**
35 19
  * @brief process a received ethernet packet
36 20
  * @param[in] ptr pointer to data of packet
... ...
@@ -43,7 +27,7 @@ void ethernet_recv(void *ptr, unsigned int sz);
43 27
  * @param[in] ptr pointer to data of packet
44 28
  * @param[in] sz size of packet
45 29
  *
46
- * ptr must point to a ethernet_packet of sufficient size (ethernet padding)
30
+ * ptr must point to a ethernet_packet
47 31
  * with eth_hdr.dest and eth_hdr.type already initialized
48 32
  */
49 33
 void ethernet_send(void *ptr, unsigned int sz);
... ...
@@ -10,7 +10,7 @@
10 10
  * @param[in] ptr pointer to data of packet
11 11
  * @param[in] sz size of packet
12 12
  *
13
- * ptr must point to a icmp_packet of sufficient size (ethernet padding)
13
+ * ptr must point to a icmp_packet
14 14
  * with icmp_hdr.type, icmp_hdr.code and ip_hdr.sest already initialized
15 15
  */
16 16
 static void icmp_send(void *ptr, unsigned int sz)
... ...
@@ -20,9 +20,6 @@ struct icmp_packet
20 20
   struct icmp_header icmp_hdr;
21 21
 } __attribute__((packed));
22 22
 
23
-/// ICMP packet with padding
24
-ETHERNET_PAD(icmp_packet);
25
-
26 23
 // header of ICMP echo request/reply packet
27 24
 struct icmp_echo_header
28 25
 {
... ...
@@ -39,9 +36,6 @@ struct icmp_echo_packet
39 36
   struct icmp_echo_header echo_hdr;
40 37
 } __attribute__((packed));
41 38
 
42
-/// ICMP echo request/reply packet with padding
43
-ETHERNET_PAD(icmp_echo_packet);
44
-
45 39
 /**
46 40
  * @brief process a received ICMP packet
47 41
  * @param[in] ptr pointer to data of packet
... ...
@@ -17,7 +17,6 @@
17 17
  *  - used if MAC is unknown when packet shall be transmitted
18 18
  *  - packet is sent when MAC becomes known
19 19
  *  - some buffers with different length (packets have different lengths)
20
- *  - all buffers must be larger than min ethernet frame size (eth padding)
21 20
  */
22 21
 //@{
23 22
 unsigned int ip_buffer0[20];
... ...
@@ -185,7 +184,7 @@ void ip_recv(void *ptr, unsigned int sz)
185 184
  * @param[in] ptr pointer to data of packet
186 185
  * @param[in] sz size of packet
187 186
  *
188
- * ptr must point to a ip_packet of sufficient size (ethernet padding)
187
+ * ptr must point to a ip_packet
189 188
  * with ip_hdr.proto and ip_hdr.dest already initialized
190 189
  */
191 190
 void ip_send(void *ptr, unsigned int sz)
... ...
@@ -25,9 +25,6 @@ struct ip_packet
25 25
   struct ip_header ip_hdr;
26 26
 } __attribute__((packed));
27 27
 
28
-/// IP packet with padding
29
-ETHERNET_PAD(ip_packet);
30
-
31 28
 /// initialize
32 29
 void ip_init(void);
33 30
 
... ...
@@ -46,7 +43,7 @@ void ip_recv(void *ptr, unsigned int sz);
46 43
  * @param[in] ptr pointer to data of packet
47 44
  * @param[in] sz size of packet
48 45
  *
49
- * ptr must point to a ip_packet of sufficient size (ethernet padding)
46
+ * ptr must point to a ip_packet
50 47
  * with ip_hdr.proto and ip_hdr.dest already initialized
51 48
  */
52 49
 void ip_send(void *ptr, unsigned int sz);
... ...
@@ -29,7 +29,7 @@ void udp_recv(void *ptr, unsigned int sz)
29 29
  * @param[in] ptr pointer to data of packet
30 30
  * @param[in] sz size of packet
31 31
  *
32
- * ptr must point to a udp_packet of sufficient size (ethernet padding)
32
+ * ptr must point to a udp_packet
33 33
  * with ip_hdr.proto and udp_hdr.src_port, udp_hdr.dest_port, ip_hdr.dest
34 34
  * already initialized
35 35
  */
... ...
@@ -21,9 +21,6 @@ struct udp_packet
21 21
   struct udp_header udp_hdr;
22 22
 } __attribute__((packed));
23 23
 
24
-/// UDP packet with padding
25
-ETHERNET_PAD(udp_packet);
26
-
27 24
 /// tick procedure - call every 200ms
28 25
 void udp_tick200(void);
29 26
 
... ...
@@ -39,7 +36,7 @@ void udp_recv(void *ptr, unsigned int sz);
39 36
  * @param[in] ptr pointer to data of packet
40 37
  * @param[in] sz size of packet
41 38
  *
42
- * ptr must point to a udp_packet of sufficient size (ethernet padding)
39
+ * ptr must point to a udp_packet
43 40
  * with ip_hdr.proto and udp_hdr.src_port, udp_hdr.dest_port, ip_hdr.dest
44 41
  * already initialized
45 42
  */
... ...
@@ -19,9 +19,11 @@ END ENTITY e_io_eth_txframe;
19 19
 
20 20
 ARCHITECTURE a_io_eth_txframe OF e_io_eth_txframe IS
21 21
 
22
-    TYPE t_state IS (st_idle, st_sync, st_start, st_data, st_crc, st_gap);
22
+    TYPE t_state IS (st_idle, st_sync, st_start, st_data,
23
+                     st_pad, st_crc, st_gap);
23 24
 
24
-    SUBTYPE t_data_cnt IS natural RANGE 0 TO 255;
25
+    SUBTYPE t_data_cnt IS natural RANGE 0 TO 3;
26
+    SUBTYPE t_byte_cnt IS natural RANGE 0 TO 255;
25 27
 
26 28
     SIGNAL r_state:     t_state                       := st_idle;
27 29
     SIGNAL n_state:     t_state;
... ...
@@ -29,6 +31,8 @@ ARCHITECTURE a_io_eth_txframe OF e_io_eth_txframe IS
29 31
     SIGNAL n_data_cnt:  t_data_cnt;
30 32
     SIGNAL r_data:      std_logic_vector(31 DOWNTO 0) := (OTHERS => '0');
31 33
     SIGNAL n_data:      std_logic_vector(31 DOWNTO 0);
34
+    SIGNAL r_byte_cnt:  t_byte_cnt                    := 0;
35
+    SIGNAL n_byte_cnt:  t_byte_cnt;
32 36
     SIGNAL r_crc_start: std_logic                     := '0';
33 37
     SIGNAL n_crc_start: std_logic;
34 38
 
... ...
@@ -60,7 +64,7 @@ BEGIN
60 64
             o_crc   => s_crc_crc
61 65
         );
62 66
 
63
-    p_next: PROCESS(r_state, r_data_cnt, r_data, r_crc_start,
67
+    p_next: PROCESS(r_state, r_data_cnt, r_data, r_byte_cnt, r_crc_start,
64 68
                     i_if_data_ack,
65 69
                     i_frame_en, i_frame_data, i_frame_data_en,
66 70
                     s_crc_crc)
... ...
@@ -69,6 +73,7 @@ BEGIN
69 73
         n_state          <= r_state;
70 74
         n_data_cnt       <= r_data_cnt;
71 75
         n_data           <= r_data;
76
+        n_byte_cnt       <= r_byte_cnt;
72 77
         n_crc_start      <= '0';
73 78
         o_if_data        <= X"00";
74 79
         o_if_data_en     <= '0';
... ...
@@ -81,14 +86,14 @@ BEGIN
81 86
             WHEN st_idle =>
82 87
                 IF i_frame_en = '1' THEN
83 88
                     n_state    <= st_sync;
84
-                    n_data_cnt <= 7;
89
+                    n_byte_cnt <= 0;
85 90
                 END IF;
86 91
             WHEN st_sync =>
87 92
                 IF i_if_data_ack = '1' THEN
88
-                    IF r_data_cnt = 1 THEN
93
+                    IF r_byte_cnt = 6 THEN
89 94
                         n_state <= st_start;
90 95
                     ELSE
91
-                        n_data_cnt <= r_data_cnt - 1;
96
+                        n_byte_cnt <= r_byte_cnt + 1;
92 97
                     END IF;
93 98
                 END IF;
94 99
                 o_if_data    <= X"55";
... ...
@@ -97,62 +102,84 @@ BEGIN
97 102
                 IF i_if_data_ack = '1' THEN
98 103
                     IF i_frame_data_en = '1' THEN
99 104
                         n_state          <= st_data;
100
-                        n_data_cnt       <= 4;
105
+                        n_data_cnt       <= 0;
101 106
                         n_data           <= i_frame_data;
107
+                        n_byte_cnt       <= 0;
102 108
                         n_crc_start      <= '1';
103 109
                         o_frame_data_ack <= '1';
104 110
                     ELSE
105 111
                         n_state    <= st_gap;
106
-                        n_data_cnt <= 12 * 8 * 2; -- 12 octets, x2 because of clk
112
+                        n_byte_cnt <= 0;
107 113
                     END IF;
108 114
                 END IF;
109 115
                 o_if_data    <= X"D5";
110 116
                 o_if_data_en <= '1';
111 117
             WHEN st_data =>
112 118
                 IF i_if_data_ack = '1' THEN
113
-                    IF r_data_cnt = 1 THEN
119
+                    IF r_data_cnt = 3 THEN
114 120
                         IF i_frame_data_en = '1' THEN
115 121
                             n_state          <= st_data;
116
-                            n_data_cnt       <= 4;
122
+                            n_data_cnt       <= 0;
117 123
                             n_data           <= i_frame_data;
118 124
                             o_frame_data_ack <= '1';
119 125
                         ELSE
126
+                            IF r_byte_cnt = 59 THEN
120 127
                                 n_state    <= st_crc;
121
-                            n_data_cnt       <= 4;
128
+                                n_data_cnt <= 0;
129
+                            ELSE
130
+                                n_state    <= st_pad;
131
+                            END IF;
122 132
                         END IF;
123 133
                     ELSE
124
-                        n_data_cnt          <= r_data_cnt - 1;
134
+                        n_data_cnt          <= r_data_cnt + 1;
125 135
                         n_data(23 DOWNTO 0) <= r_data(31 DOWNTO 8);
126 136
                     END IF;
137
+                    IF r_byte_cnt /= 59 THEN
138
+                        n_byte_cnt <= r_byte_cnt + 1;
139
+                    END IF;
127 140
                     s_crc_en    <= '1';
128 141
                     s_crc_start <= r_crc_start;
129 142
                     s_crc_data  <= r_data(7 DOWNTO 0);
130 143
                 END IF;
131 144
                 o_if_data    <= r_data(7 DOWNTO 0);
132 145
                 o_if_data_en <= '1';
146
+            WHEN st_pad =>
147
+                IF i_if_data_ack = '1' THEN
148
+                    IF r_byte_cnt = 59 THEN
149
+                        n_state    <= st_crc;
150
+                        n_data_cnt <= 0;
151
+                    ELSE
152
+                        n_byte_cnt <= r_byte_cnt + 1;
153
+                    END IF;
154
+                    s_crc_en   <= '1';
155
+                    s_crc_data <= (OTHERS => '0');
156
+                END IF;
157
+                o_if_data    <= (OTHERS => '0');
158
+                o_if_data_en <= '1';
133 159
             WHEN st_crc =>
134
-                IF r_data_cnt = 4 THEN
160
+                IF r_data_cnt = 0 THEN
135 161
                     v_data := s_crc_crc; -- get CRC value on first CRC byte
136 162
                 ELSE
137 163
                     v_data := r_data;
138 164
                 END IF;
139 165
                 IF i_if_data_ack = '1' THEN
140
-                    IF r_data_cnt = 1 THEN
166
+                    IF r_data_cnt = 3 THEN
141 167
                         n_state    <= st_gap;
142
-                        n_data_cnt <= 12 * 8 * 2; -- 12 octets, x2 because of clk
168
+                        n_byte_cnt <= 0;
143 169
                     ELSE
144
-                        n_data_cnt          <= r_data_cnt - 1;
170
+                        n_data_cnt          <= r_data_cnt + 1;
145 171
                         n_data(23 DOWNTO 0) <= v_data(31 DOWNTO 8);
146 172
                     END IF;
147 173
                 END IF;
148 174
                 o_if_data    <= v_data(7 DOWNTO 0);
149 175
                 o_if_data_en <= '1';
150 176
             WHEN st_gap =>
151
-                IF r_data_cnt = 1 THEN
177
+                 -- 12 octets, *2 because of clk, plus async FIFO len
178
+                IF r_byte_cnt = 12 * 8 * 2 + 16 THEN
152 179
                     n_state      <= st_idle;
153 180
                     o_frame_done <= '1';
154 181
                 ELSE
155
-                    n_data_cnt <= r_data_cnt - 1;
182
+                    n_byte_cnt <= r_byte_cnt + 1;
156 183
                 END IF;
157 184
             WHEN OTHERS => NULL;
158 185
         END CASE;
... ...
@@ -164,11 +191,13 @@ BEGIN
164 191
             r_state     <= st_idle;
165 192
             r_data_cnt  <= 0;
166 193
             r_data      <= (OTHERS => '0');
194
+            r_byte_cnt  <= 0;
167 195
             r_crc_start <= '0';
168 196
         ELSIF rising_edge(clk) THEN
169 197
             r_state     <= n_state;
170 198
             r_data_cnt  <= n_data_cnt;
171 199
             r_data      <= n_data;
200
+            r_byte_cnt  <= n_byte_cnt;
172 201
             r_crc_start <= n_crc_start;
173 202
         END IF;
174 203
     END PROCESS p_sync;
175 204