OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [boot-loader-ethmac/] [packet.c] - Blame information for rev 85

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 61 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  boot-loader-ethmac.c                                        //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  The main functions for the boot loader application. This    //
10 80 csantifort
//  application is embedded in the FPGA's SRAM and is used      //
11 61 csantifort
//  to load larger applications into the DDR3 memory on         //
12
//  the development board.                                      //
13
//                                                              //
14
//  Author(s):                                                  //
15
//      - Conor Santifort, csantifort.amber@gmail.com           //
16
//                                                              //
17
//////////////////////////////////////////////////////////////////
18
//                                                              //
19
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
20
//                                                              //
21
// This source file may be used and distributed without         //
22
// restriction provided that this copyright statement is not    //
23
// removed from the file and that any derivative work contains  //
24
// the original copyright notice and the associated disclaimer. //
25
//                                                              //
26
// This source file is free software; you can redistribute it   //
27
// and/or modify it under the terms of the GNU Lesser General   //
28
// Public License as published by the Free Software Foundation; //
29
// either version 2.1 of the License, or (at your option) any   //
30
// later version.                                               //
31
//                                                              //
32
// This source is distributed in the hope that it will be       //
33
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
34
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
35
// PURPOSE.  See the GNU Lesser General Public License for more //
36
// details.                                                     //
37
//                                                              //
38
// You should have received a copy of the GNU Lesser General    //
39
// Public License along with this source; if not, download it   //
40
// from http://www.opencores.org/lgpl.shtml                     //
41
//                                                              //
42
----------------------------------------------------------------*/
43
 
44
 
45
#include "amber_registers.h"
46
#include "address_map.h"
47
#include "line-buffer.h"
48
#include "timer.h"
49
#include "utilities.h"
50
#include "packet.h"
51
#include "tcp.h"
52
 
53
 
54
/* Global variables */
55
mac_ip_t self_g = { {0x00, 0x0e, 0x70, 0x70, 0x70, 0x70},  /* MAC Address  */
56
                    {192, 168, 0, 17}                      /* IPv4 address */
57
                  };
58
 
59
packet_t*   rx_packet_g;
60
 
61
 
62 80 csantifort
void init_packet()
63 61 csantifort
{
64 80 csantifort
    /* receive packet buffer */
65
    rx_packet_g = malloc(sizeof(packet_t));
66 81 csantifort
    rx_packet_g->tcp_window_scale = 0;
67 61 csantifort
}
68
 
69
 
70 81 csantifort
void ethernet_header(char *buf, mac_t* target_mac, unsigned short type)
71 61 csantifort
{
72
    /* ethernet header */
73
    /* DA */
74 81 csantifort
    strncpy(&buf[0], target_mac, 6);
75
    // print_serial("%s:L%d ethernet header target mac %x:%x:%x:%x:%x:%x\n\r",
76
    //    __FILE__, __LINE__,
77
    //    target_mac->mac[0], target_mac->mac[1], target_mac->mac[2],
78
    //    target_mac->mac[3], target_mac->mac[4], target_mac->mac[5]
79
    //    );
80 80 csantifort
 
81 61 csantifort
    /* SA */
82 81 csantifort
    strncpy(&buf[6], &self_g.mac[0], 6);
83 61 csantifort
    buf[ 6] = self_g.mac[0];
84
    buf[ 7] = self_g.mac[1];
85
    buf[ 8] = self_g.mac[2];
86
    buf[ 9] = self_g.mac[3];
87
    buf[10] = self_g.mac[4];
88
    buf[11] = self_g.mac[5];
89 80 csantifort
 
90 61 csantifort
    /* type */
91
    buf[12] = type>>8;
92
    buf[13] = type&0xff;
93
}
94
 
95
 
96 81 csantifort
void ip_header(char *buf, ip_t* target_ip, unsigned short ip_len, char ip_proto)
97 61 csantifort
{
98
    unsigned short header_checksum;
99
    static unsigned short ip_id = 0;
100
 
101
    /* Version, Header length */
102 80 csantifort
    buf[0] = 0x45;
103
 
104 61 csantifort
    /* dscp */
105
    buf[1] = 0;
106 80 csantifort
 
107 61 csantifort
    /* ip len */
108 80 csantifort
    buf[2] = ip_len>>8;
109 61 csantifort
    buf[3] = ip_len&0xff;
110 80 csantifort
 
111 61 csantifort
    /* ID */
112
    buf[4] = (ip_id>>8)&0xff;
113 80 csantifort
    buf[5] = ip_id&0xff;
114 61 csantifort
    //ip_id++;
115 80 csantifort
 
116 61 csantifort
    /* Fragment */
117
    buf[6] = 0;
118
    buf[7] = 0;
119 80 csantifort
 
120 61 csantifort
    /* ttl */
121
    buf[8] = 64;
122 80 csantifort
 
123 61 csantifort
    /* Protocol */
124
    buf[9] = ip_proto;
125 80 csantifort
 
126 61 csantifort
    /* header checksum */
127
    buf[10] = 0;
128
    buf[11] = 0;
129 80 csantifort
 
130 61 csantifort
    /* Source IP */
131 81 csantifort
    strncpy(&buf[12], &self_g.ip[0], 4);
132 80 csantifort
 
133 61 csantifort
    /* Destination IP */
134 81 csantifort
    strncpy(&buf[16], target_ip, 4);
135 80 csantifort
 
136 61 csantifort
    /* header checksum */
137
    header_checksum = header_checksum16(buf, 20, 0);
138
    buf[10] = (header_checksum>>8)&0xff;
139
    buf[11] = header_checksum&0xff;
140
}
141
 
142
 
143 81 csantifort
 
144
void arp_reply(mac_t* arp_sender_mac, ip_t* arp_sender_ip)
145 61 csantifort
{
146 81 csantifort
    char buf [44];
147
    ethernet_header(buf, arp_sender_mac, 0x0806);
148 61 csantifort
 
149
    /* Hardware Type */
150
    buf[14] = 0x00;
151
    buf[15] = 0x01;
152
    /* Protocol Type */
153
    buf[16] = 0x08;
154
    buf[17] = 0x00;
155
    /* HLEN */
156
    buf[18] = 0x06;
157
    /* PLEN */
158
    buf[19] = 0x04;
159 80 csantifort
 
160 61 csantifort
    /* Operation = Reply */
161
    buf[20] = 0x00;
162
    buf[21] = 0x02;
163 80 csantifort
 
164 61 csantifort
    /* Sender MAC */
165
    buf[22] = self_g.mac[0];
166
    buf[23] = self_g.mac[1];
167
    buf[24] = self_g.mac[2];
168
    buf[25] = self_g.mac[3];
169
    buf[26] = self_g.mac[4];
170
    buf[27] = self_g.mac[5];
171 80 csantifort
 
172 61 csantifort
    /* Sender IP */
173
    buf[28] = self_g.ip[0];
174
    buf[29] = self_g.ip[1];
175
    buf[30] = self_g.ip[2];
176
    buf[31] = self_g.ip[3];
177 80 csantifort
 
178 61 csantifort
    /* Target MAC */
179 81 csantifort
    buf[32] = arp_sender_mac->mac[0];
180
    buf[33] = arp_sender_mac->mac[1];
181
    buf[34] = arp_sender_mac->mac[2];
182
    buf[35] = arp_sender_mac->mac[3];
183
    buf[36] = arp_sender_mac->mac[4];
184
    buf[37] = arp_sender_mac->mac[5];
185 80 csantifort
 
186 61 csantifort
    /* Target IP */
187 81 csantifort
    buf[38] = arp_sender_ip->ip[0];
188
    buf[39] = arp_sender_ip->ip[1];
189
    buf[40] = arp_sender_ip->ip[2];
190
    buf[41] = arp_sender_ip->ip[3];
191
    ethmac_tx_packet(buf, 42);
192 61 csantifort
}
193
 
194
 
195
void ping_reply(packet_t* rx_packet, int ping_id, int ping_seq, char * rxbuf)
196
{
197
 
198
    int i;
199
    unsigned short header_checksum;
200 81 csantifort
    // mac_ip_t target;
201
    char buf [96];  // not sure how long this needs  to be = (char*)ETHMAC_TX_BUFFER;
202 80 csantifort
 
203 81 csantifort
    ethernet_header(buf, (mac_t*) rx_packet->src_mac, 0x0800);  /*bytes 0 to 13*/
204
    ip_header(&buf[14], (ip_t*) rx_packet->src_ip, rx_packet->ip_len, 1); /* bytes 14 to 33, ip_proto = 1, ICMP*/
205 80 csantifort
 
206 61 csantifort
    /* ICMP */
207
    /* Type = reply */
208
    buf[34] = 0;
209 80 csantifort
 
210 61 csantifort
    /* Code = 0 */
211
    buf[35] = 0;
212 80 csantifort
 
213 61 csantifort
    /* checksum */
214
    buf[36] = 0;
215
    buf[37] = 0;
216 80 csantifort
 
217 61 csantifort
    /* ID */
218
    buf[38] = ping_id>>8;
219
    buf[39] = ping_id&0xff;
220 80 csantifort
 
221 61 csantifort
    /* SEQ */
222
    buf[40] = ping_seq>>8;
223
    buf[41] = ping_seq&0xff;
224
 
225
    for (i=8; i< rx_packet->ip_len - rx_packet->ip_header_len*4; i++) {
226
        buf[34+i] = rxbuf[i];
227
        }
228
 
229
    header_checksum = header_checksum16(&buf[34], (rx_packet->ip_len)-20, 0);
230
    buf[36] = (header_checksum>>8)&0xff;
231
    buf[37] = header_checksum&0xff;
232 81 csantifort
    ethmac_tx_packet(buf, rx_packet->ip_len+14);
233 61 csantifort
}
234
 
235
 
236
void parse_rx_packet(char * buf, packet_t* rx_packet)
237
{
238
    int i;
239 80 csantifort
 
240 85 csantifort
    for (i=0;i<6;i++)
241
        rx_packet->dst_mac[i] = buf[i];
242 61 csantifort
 
243 85 csantifort
    for (i=0;i<6;i++)
244
        rx_packet->src_mac[i] = buf[i+6];
245
 
246 61 csantifort
    rx_packet->eth_type   = (buf[12]<<8) + buf[13];
247 80 csantifort
 
248
 
249 61 csantifort
    /* ARP */
250
    if (rx_packet->eth_type == 0x0806) {
251
        parse_arp_packet(&buf[14]);
252
        }
253
 
254
    /* Internet Protocol  */
255
    else if (rx_packet->eth_type == 0x0800){
256
        parse_ip_packet(&buf[14], rx_packet);
257
        }
258
}
259
 
260
 
261
void parse_arp_packet(char * buf)
262
{
263
    /* ARP is a broadcast message (mac broadcast address)
264
      asking 'does this IP address belong to you?"
265
    */
266
    int arp_op;
267 81 csantifort
    //mac_ip_t arp_sender, arp_target;
268
    mac_t arp_sender_mac;
269
    ip_t arp_sender_ip;
270 80 csantifort
 
271 61 csantifort
    arp_op = buf[6]<<8 | buf[7];
272
 
273 81 csantifort
    strncpy(&arp_sender_mac, &buf[8], 6);
274
    strncpy(&arp_sender_ip, &buf[14], 4);
275 80 csantifort
 
276 81 csantifort
    // arp_sender.mac[0] = buf[8];
277
    // arp_sender.mac[1] = buf[9];
278
    // arp_sender.mac[2] = buf[10];
279
    // arp_sender.mac[3] = buf[11];
280
    // arp_sender.mac[4] = buf[12];
281
    // arp_sender.mac[5] = buf[13];
282 80 csantifort
 
283 81 csantifort
    // arp_sender.ip [0] = buf[14];
284
    // arp_sender.ip [1] = buf[15];
285
    // arp_sender.ip [2] = buf[16];
286
    // arp_sender.ip [3] = buf[17];
287 80 csantifort
 
288 81 csantifort
    // arp_target.mac[0] = buf[18];
289
    // arp_target.mac[1] = buf[19];
290
    // arp_target.mac[2] = buf[20];
291
    // arp_target.mac[3] = buf[21];
292
    // arp_target.mac[4] = buf[22];
293
    // arp_target.mac[5] = buf[23];
294 80 csantifort
 
295 81 csantifort
    // arp_target.ip [0] = buf[24];
296
    // arp_target.ip [1] = buf[25];
297
    // arp_target.ip [2] = buf[26];
298
    // arp_target.ip [3] = buf[27];
299
 
300 61 csantifort
    /* Send a reply ? */
301 80 csantifort
    if (arp_op==1 &&
302 81 csantifort
        buf[24]==self_g.ip[0] &&
303
        buf[25]==self_g.ip[1] &&
304
        buf[26]==self_g.ip[2] &&
305
        buf[27]==self_g.ip[3]) {
306 80 csantifort
 
307 61 csantifort
        // ARP reply
308 81 csantifort
        arp_reply(&arp_sender_mac, &arp_sender_ip);
309 61 csantifort
        }
310
}
311
 
312
 
313
 
314
void parse_ip_packet(char * buf, packet_t* rx_packet)
315
{
316
    unsigned int ip_version;
317 80 csantifort
 
318 61 csantifort
    ip_version = buf[0]>>4;
319
    if (ip_version != 4) {
320 81 csantifort
        print_serial("%s:L%d IP version %d not supported\n\r", __FILE__, __LINE__, ip_version);
321 61 csantifort
        return;
322
        }
323 80 csantifort
 
324 61 csantifort
    /* Get destination IP address */
325
    rx_packet->dst_ip[0] = buf[16];
326
    rx_packet->dst_ip[1] = buf[17];
327
    rx_packet->dst_ip[2] = buf[18];
328
    rx_packet->dst_ip[3] = buf[19];
329
 
330
    /* If its not my address then ignore the packet */
331 80 csantifort
    if (rx_packet->dst_ip[0] != self_g.ip[0] ||
332
        rx_packet->dst_ip[1] != self_g.ip[1] ||
333
        rx_packet->dst_ip[2] != self_g.ip[2] ||
334 61 csantifort
        rx_packet->dst_ip[3] != self_g.ip[3] ) {
335
        return;
336
        }
337 80 csantifort
 
338 61 csantifort
    rx_packet->ip_len         = buf[ 2]<<8|buf[ 3];
339
    rx_packet->ip_header_len  = buf[0] & 0xf;
340
    rx_packet->ip_proto       = buf[9];
341
    rx_packet->src_ip[0]      = buf[12];
342
    rx_packet->src_ip[1]      = buf[13];
343
    rx_packet->src_ip[2]      = buf[14];
344
    rx_packet->src_ip[3]      = buf[15];
345
 
346 80 csantifort
 
347
    /* Ping packets */
348 61 csantifort
    if (rx_packet->ip_proto == 1){
349
        parse_ping_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
350
        }
351 80 csantifort
 
352 61 csantifort
    /* TCP packets */
353
    else if (rx_packet->ip_proto == 6){
354
        parse_tcp_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
355
        }
356 80 csantifort
 
357 61 csantifort
    /* UDP packets */
358
    else if (rx_packet->ip_proto == 17){
359
        parse_udp_packet(&buf[(rx_packet->ip_header_len)*4], rx_packet);
360
        }
361
}
362
 
363
 
364
void parse_ping_packet(char * buf, packet_t* rx_packet)
365
{
366
    int ping_id;
367
    int ping_seq;
368
 
369
    ping_id     = buf[4]<<8|buf[5];
370
    ping_seq    = buf[6]<<8|buf[7];
371 80 csantifort
 
372 61 csantifort
    ping_reply(rx_packet, ping_id, ping_seq, buf);
373
}
374
 
375
 
376
unsigned short header_checksum16(unsigned char *buf, unsigned short len, unsigned int sum)
377
 {
378
     // build the sum of 16bit words
379
     while(len>1) {
380
         sum += 0xFFFF & (*buf<<8|*(buf+1));
381
         buf+=2;
382
         len-=2;
383
         }
384
     // if there is a byte left then add it (padded with zero)
385
     if (len) {
386
         sum += (0xFF & *buf)<<8;
387
         }
388
     // now calculate the sum over the bytes in the sum
389
     // until the result is only 16bit long
390
     while (sum>>16) {
391
         sum = (sum & 0xFFFF)+(sum >> 16);
392
         }
393 80 csantifort
 
394 61 csantifort
     // build 1's complement:
395
     return( (unsigned short ) sum ^ 0xFFFF);
396
}
397
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.