source: edk_user_repository/WARP/sw_services/WARPxilnet_v3_04_a/src/xilnet_ip.c

Last change on this file was 4388, checked in by welsh, 9 years ago

Updated comments about fragmented IP packets.

File size: 7.8 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
3//
4// Xilinx, Inc.
5// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS FOR A PARTICULAR PURPOSE.
16//
17// File   : ip.c
18// Date   : 2002, March 20.
19// Author : Sathya Thammanur
20// Company: Xilinx
21// Group  : Emerging Software Technologies
22//
23// Summary:
24// IP layer specific functions
25//
26// $Id: ip.c,v 1.2.8.6 2005/11/15 23:41:10 salindac Exp $
27//
28////////////////////////////////////////////////////////////////////////////////
29
30////////////////////////////////////////////////////////////////////////////////
31// see copyright.txt for Rice University/Mango Communications modifications
32////////////////////////////////////////////////////////////////////////////////
33
34#include <xilnet_xilsock.h>
35
36
37/*
38 * initialize xilnet ip address
39 */
40void xilnet_ip_init(unsigned char* addr, unsigned int eth_dev_num) {
41    int k = 0;
42    int j;
43    int sum = 0;
44
45    for (j = 0; j < 3; j++) {
46
47        // parse input for dotted decimal notation of ip address
48        while(addr[k] != '.') {
49            sum = sum * 10 + addr[k] - 48;
50            k++;
51        }
52
53        k++; // move over the dot
54        eth_device[eth_dev_num].node_ip_addr[j] = (unsigned char) sum;
55        sum = 0;
56    }
57
58    // read last byte of ip address
59    while (addr[k] != '\0') {
60        sum = sum * 10 + addr[k] - 48;
61        k++;
62    }
63    eth_device[eth_dev_num].node_ip_addr[3] = (unsigned char) sum;
64}
65
66
67/*
68 * ip datagram handler:
69 * checks for the source ip address and calls the corr protocol handler
70 * no checksum calc is done to detect any errors
71 */
72
73int xilnet_ip(unsigned char*buf, int len, unsigned int eth_dev_num) {
74
75    int iplen = 0;
76    struct xilnet_ip_hdr *iph = (struct xilnet_ip_hdr *) (buf+ETH_HDR_LEN);
77
78#ifdef _DEBUG_
79    xil_printf("BEGIN xilnet_ip(): \n");
80    xil_printf("  Packet IP Address: %d.%d.%d.%d \n", (buf+ETH_HDR_LEN)[IP_DADDR_BASE],   (buf+ETH_HDR_LEN)[IP_DADDR_BASE+1],
81                                                      (buf+ETH_HDR_LEN)[IP_DADDR_BASE+2], (buf+ETH_HDR_LEN)[IP_DADDR_BASE+3]);
82    xil_printf("  Device IP Address: %d.%d.%d.%d \n", eth_device[eth_dev_num].node_ip_addr[0], eth_device[eth_dev_num].node_ip_addr[1],
83                                                      eth_device[eth_dev_num].node_ip_addr[2], eth_device[eth_dev_num].node_ip_addr[3]);
84#endif
85
86    unsigned char * ip_hdr  = (unsigned char *) buf + ETH_HDR_LEN;
87    unsigned char addr_pass = 0;
88
89    // If the node has not been initialized (ie address is 10.0.0.0)   
90    if ( eth_device[eth_dev_num].node_ip_addr[3] == 0 ) {
91
92        // Accept broadcast packets from 10.0.X.255
93        if ( ip_hdr[IP_DADDR_BASE]   == eth_device[eth_dev_num].node_ip_addr[0] &&
94             ip_hdr[IP_DADDR_BASE+1] == eth_device[eth_dev_num].node_ip_addr[1] &&
95             ip_hdr[IP_DADDR_BASE+3] == 255 ) {
96
97             addr_pass = 1;
98        }
99    } else {
100        // Accept unicast packets and broadcast packets on the given subnet
101        if ( ip_hdr[IP_DADDR_BASE]   == eth_device[eth_dev_num].node_ip_addr[0] &&
102             ip_hdr[IP_DADDR_BASE+1] == eth_device[eth_dev_num].node_ip_addr[1] &&
103             ip_hdr[IP_DADDR_BASE+2] == eth_device[eth_dev_num].node_ip_addr[2] &&
104            (ip_hdr[IP_DADDR_BASE+3] == eth_device[eth_dev_num].node_ip_addr[3] || ip_hdr[IP_DADDR_BASE+3] == 255 )) {
105
106            addr_pass = 1;
107        }
108    }
109
110    if (addr_pass == 1) {
111   
112        // WARP hardware does not support fragmented packets.  However, we will still pass
113        // the first fragment of a packet up to the transport for processing so that the
114        // OS fragmenting packets does not result in a transport timeout in initNodes.  If
115        // this behavior needs to change the below code will cause the transport to discard
116        // packet fragments.
117        //         
118        // The 'fragment offset field' is 16 bits (see http://en.wikipedia.org/wiki/IPv4#Packet_structure
119        // for more information).  The 'DF' flag can be legitimately set to '1' so we need to mask that
120        // bit before we decide if we can discard the packet.  This means that the frag_off field can
121        // have valid values of either 0x0000 or 0x4000 (big endian).  However, we have to convert to
122        // little endian so the valid values are 0x0000 and 0x0040 (ie byte swapped).
123        //
124        // if ((iph->frag_off & 0xFFBF) != IP_FRAG_OFF) {
125        //     xil_printf("ERROR:  WARPxilnet does not support fragmented packets.\n");
126        //     return 0;
127        // }
128
129        // update hw addr table
130        xilnet_eth_update_hw_tbl(buf, ETH_PROTO_IP, eth_dev_num);
131
132        iplen = (unsigned short)( ((((unsigned short)buf[ETH_HDR_LEN+2]) << 8) & 0xFF00) +
133                                   (((unsigned short)buf[ETH_HDR_LEN+3]) & 0x00FF) );
134
135#ifdef _DEBUG_
136    xil_printf("  IP protocol: %d \n", iph->prot);
137#endif
138
139    // call corr protocol handler with the ip datagram
140        switch (iph->prot) {
141            case IP_PROTO_UDP:
142                return (xilnet_udp(buf+ETH_HDR_LEN, iplen, eth_dev_num));
143            break;
144            case IP_PROTO_TCP:
145                xil_printf("ERROR:  WARPxilnet does not support TCP\n");
146                return 0;
147            break;
148            case IP_PROTO_ICMP:
149                return (xilnet_icmp(buf+ETH_HDR_LEN, iplen, eth_dev_num));
150            break;
151            default:
152                xil_printf("ERROR:  Unknown IP protocol\n");
153                return 0;
154            break;
155        }
156    }
157
158#ifdef _DEBUG_
159    xil_printf("END xilnet_ip(): \n");
160#endif
161
162    return 0;
163}
164
165
166/*
167 * xilnet_ip_header: fills in the ip header for proto
168 */
169int ip_id_cnt = 0;
170
171void xilnet_ip_header(unsigned char* buf, int len, int proto, unsigned char *peer_ip_addr, unsigned int eth_dev_num) {
172
173   struct xilnet_ip_hdr *iph = (struct xilnet_ip_hdr*) buf;
174
175#ifdef _DEBUG_
176   xil_printf("In xilnet_ip_header(): \n");
177#endif
178
179   buf[0]               = IP_VERSION << 4;
180   buf[0]              |= IP_HDR_LEN;
181   iph->tos             = IP_TOS;
182   iph->total_len       = Xil_Htons(len);
183   iph->ident           = Xil_Htons(ip_id_cnt++);
184   iph->frag_off        = Xil_Htons(IP_FRAG_OFF);
185   iph->ttl             = IP_TTL;
186   iph->prot            = proto;
187   iph->check_sum       = 0;
188   buf[IP_SADDR_BASE]   = eth_device[eth_dev_num].node_ip_addr[0];
189   buf[IP_SADDR_BASE+1] = eth_device[eth_dev_num].node_ip_addr[1];
190   buf[IP_SADDR_BASE+2] = eth_device[eth_dev_num].node_ip_addr[2];
191   buf[IP_SADDR_BASE+3] = eth_device[eth_dev_num].node_ip_addr[3];
192   buf[IP_DADDR_BASE]   = peer_ip_addr[0];
193   buf[IP_DADDR_BASE+1] = peer_ip_addr[1];
194   buf[IP_DADDR_BASE+2] = peer_ip_addr[2];
195   buf[IP_DADDR_BASE+3] = peer_ip_addr[3];
196   iph->check_sum = Xil_Htons(xilnet_ip_calc_chksum(buf, IP_HDR_LEN*4));
197
198}
199
200
201/*
202 * xilnet_ip_calc_chksum: compute checksum for ip header
203 */
204
205unsigned short xilnet_ip_calc_chksum(unsigned char* buf, int len) {
206
207   unsigned int sum = 0;
208   unsigned short w16 = 0;
209   int i;
210
211   for (i = 0; i < len; i = i + 2) {
212      w16 = ((buf[i] << 8) & 0xFF00) + (buf[i+1] & 0x00FF);
213      sum = sum + (unsigned int) w16;
214   }
215
216   while (sum >> 16)
217      sum = (sum & 0xFFFF) + (sum >> 16);
218
219   return (unsigned short) (~sum);
220}
Note: See TracBrowser for help on using the repository browser.