]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/driver/eth/arp.c
Added an optional second ibl config area to the i2c eeprom
[keystone-rtos/ibl.git] / src / driver / eth / arp.c
1 /** 
2  *   @file  arp.c
3  *
4  *   @brief   
5  *      The file implements the NET Module ARP functionality.
6  *
7  *  \par
8  *  NOTE:
9  *      (C) Copyright 2008, Texas Instruments, Inc.
10  *
11  *  \par
12  */
13 #include "types.h"
14 #include "iblloc.h"
15 #include "net.h"
16 #include "netif.h"
17 #include <string.h>
18 #include "net_osal.h"
20 /**********************************************************************
21  *************************** LOCAL Structures *************************
22  **********************************************************************/
24 /**
25  * @brief 
26  *  The structure describes the ARP Cache 
27  *
28  * @details
29  *  This describes the ARP Cache which keeps track of the IPv4 address and
30  *  the corresponding Layer2 MAC Address. 
31  */
32 typedef struct NET_ARP_CACHE
33 {
34     /**
35      * @brief   This is the MAC Address i.e. Layer2 address matching the
36      * corresponding IP Address.
37      */
38     Uint8       mac_address[6];
40     /**
41      * @brief   This is the IP Address stored in network order.
42      */
43     IPN         ip_address;
45     /**
46      * @brief   When the upper layers tries to send a packet and 
47      * the MAC Address is not resolved; packets are stored in this 
48      * temporary area. The ARP stack sends out an ARP request packet 
49      * and resolves the IP  address. Once the resolution is done pending 
50      * packets are transmitted. 
51      */
52     Uint8      pending_packet[NET_MAX_MTU];
54     /**
55      * @brief   This is the length of the pending packet. A value of 0
56      * indicates that there is no pending packet in the ARP cache.
57      */    
58     Uint16     pending_packet_len;
59 }NET_ARP_CACHE;
61 /**********************************************************************
62  *************************** GLOBAL Variables *************************
63  **********************************************************************/
65 /**
66  * @brief   This is the ARP cache; which keeps track of the IP Address to
67  * MAC Address mapping.
68  */
69 NET_ARP_CACHE      net_arp_cache;
71 /**********************************************************************
72  **************************** ARP Functions ***************************
73  **********************************************************************/
75 /**
76  *  @b Description
77  *  @n  
78  *      This function is called by the IP Layer to resolve the layer3 
79  *      address to a layer2 MAC address. The function checks the ARP cache
80  *      for a match but if no entry exists then the functions sends out
81  *      an ARP request and it places this packet into the pending queue.
82  *
83  *  @param[in]  dst_ip
84  *      This is the destination IP address of the packet.
85  *  @param[in]  ptr_iphdr
86  *      This is the pointer to the IP header
87  *  @param[in]  l3_pkt_size
88  *      This is the size of the packet (including the IP Header)
89  *
90  *  @retval
91  *      Not Applicable.
92  */
93 void arp_resolve (IPN dst_ip, IPHDR* ptr_iphdr, Uint16 l3_pkt_size)
94 {
95     ARPHDR* ptr_arphdr;
96     ETHHDR* ptr_ethhdr;
97     Uint8   BroadcastMac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
99     /* Special Case: Are we sending the packet to 255.255.255.255? */
100     if (dst_ip == (IPN)0xFFFFFFFF)
101     {
102         /* YES. This implies that the destination MAC Address in the packet is the Broadcast address
103          * We dont need to lookup the cache. */
104         ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&BroadcastMac[0], 0x800);
105         if (ptr_ethhdr == NULL)
106             return;
108         /* We now have a completed Ethernet packet; send it across. */
109         net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
111         /* The packet has been transmitted and we can clean it up now. */
112         net_free_tx_packet ((Uint8 *)ptr_iphdr);
113         return;            
114     }
116     /* Check if the destination IP Address matches the ARP cache */
117     if (net_arp_cache.ip_address == dst_ip)
118     {
119         /* Make sure the MAC Address in the CACHE has been resolved i.e. Non-Zero. */
120         if ( (net_arp_cache.mac_address[0] != 0x00) || (net_arp_cache.mac_address[1] != 0x00) ||
121              (net_arp_cache.mac_address[2] != 0x00) || (net_arp_cache.mac_address[3] != 0x00) || 
122              (net_arp_cache.mac_address[4] != 0x00) || (net_arp_cache.mac_address[5] != 0x00) )
123         {
124             /* Perfect; the MAC Address is already resolved. 
125              *  We can simply use the ARP CACHE MAC address to create the layer2 header. */
126             ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_iphdr, (void *)&net_arp_cache.mac_address[0], 0x800);
127             if (ptr_ethhdr == NULL)
128                 return;
130             /* We now have a completed Ethernet packet; send it across. */
131             net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + l3_pkt_size);
133             /* The packet has been transmitted and we can clean it up now. */
134             net_free_tx_packet ((Uint8 *)ptr_iphdr);
135             return;
136         }
137     }
139     /* Initialize the ARP Cache: The cache did not have information for the resolution to work
140      * Reset the cache and start again.  */
141     netMemset ((void *)&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
143     /* Populate the ARP Cache */
144     net_arp_cache.ip_address         = dst_ip;    
145     net_arp_cache.pending_packet_len = l3_pkt_size;
146     netMemcpy ((void *)&net_arp_cache.pending_packet[0], (void *)ptr_iphdr, l3_pkt_size);
148     /* Free up the packet now; we have already stored it in the ARP cache. */
149     net_free_tx_packet ((Uint8 *)ptr_iphdr);
151     /* Allocate a new packet to send out the ARP request. */
152     ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
153     if (ptr_arphdr == NULL)
154         return;
156     /* Populate the ARP Header. */
157     ptr_arphdr->HardType     = htons(0x1);
158     ptr_arphdr->ProtocolType = htons(0x800);
159     ptr_arphdr->HardSize     = 0x6;
160     ptr_arphdr->ProtocolSize = 0x4;
161     ptr_arphdr->Op           = htons(0x1);
163     /* Populate the Source IP/MAC Address */
164     netMemcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
165     netMemcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
167     /* Populate the Target IP/MAC Address: This is set to 0 since the cache has been reset above. */
168     netMemcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
169     netMemcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&dst_ip, 4);
171     /* Create the Ethernet header. */
172     ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &BroadcastMac[0], 0x806);
173     if (ptr_ethhdr == NULL)
174         return;
176     /* Send the packet out. */
177     net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
179     /* The packet has been transmitted and we can clean it up now. */
180     net_free_tx_packet ((Uint8 *)ptr_arphdr);
181     return;
184 /**
185  *  @b Description
186  *  @n  
187  *       The function handles the reception and processing of ARP packets.
188  *
189  *  @param[in]  ptr_arphdr
190  *      This is the pointer to the received ARP header.
191  *  @param[in]  num_bytes
192  *      This is the size of the ARP packet.
193  *
194  *  @retval
195  *      Success -   0
196  *  @retval
197  *      Error   -   <0
198  */
199 Int32 arp_receive (ARPHDR* ptr_arphdr, Int32 num_bytes)
201     Uint32  IPAddress;
202     Uint8*  ptr_pending_pkt;
203     ETHHDR* ptr_ethhdr;
205     /* Extract the intended target and convert it to host format. */
206     IPAddress = READ32(ptr_arphdr->IPDst);
208     /* Ensure that the packet has not been looped back and we received our own frame. */
209     if ((ptr_arphdr->SrcAddr[0] == netmcb.net_device.mac_address[0]) &&
210         (ptr_arphdr->SrcAddr[1] == netmcb.net_device.mac_address[1]) &&
211         (ptr_arphdr->SrcAddr[2] == netmcb.net_device.mac_address[2]) &&
212         (ptr_arphdr->SrcAddr[3] == netmcb.net_device.mac_address[3]) &&
213         (ptr_arphdr->SrcAddr[4] == netmcb.net_device.mac_address[4]) &&
214         (ptr_arphdr->SrcAddr[5] == netmcb.net_device.mac_address[5]))
215     {
216         /* We received our own frame; ignore this. */
217         return -1;
218     }
220     /* Check if the packet is meant for us? If it not meant for us we drop the packet. */
221     if (IPAddress != netmcb.net_device.ip_address)
222         return -1;
224     /* The ARP packet was meant for us; we need to update the ARP cache with the request. */
225     net_arp_cache.ip_address = READ32(ptr_arphdr->IPSrc);
226     netMemcpy ((void *)&net_arp_cache.mac_address[0], (void *)&ptr_arphdr->SrcAddr[0], 6);
228     /* Check if the packet is an ARP request? */
229     if (ptr_arphdr->Op == htons(0x1))
230     {
231         /* YES. We need to send out an ARP Reply; so create the packet. 
232          *  Ensure that the Layer3 headers are aligned on the 4 byte boundary 
233          *  and yet we have sufficient space for the Ethernet header. */
234         ptr_arphdr = (ARPHDR *)net_alloc_tx_packet(sizeof(ARPHDR));
235         if (ptr_arphdr == NULL)
236             return -1;
238         /* Populate the ARP Header. */
239         ptr_arphdr->HardType     = htons(0x1);
240         ptr_arphdr->ProtocolType = htons(0x800);
241         ptr_arphdr->HardSize     = 0x6;
242         ptr_arphdr->ProtocolSize = 0x4;
243         ptr_arphdr->Op           = htons(0x2);
245         /* Populate the Source IP/MAC Address in the ARP Header */
246         netMemcpy ((void *)&ptr_arphdr->SrcAddr[0], (void *)&netmcb.net_device.mac_address[0], 6);
247         netMemcpy ((void *)&ptr_arphdr->IPSrc[0], (void *)&netmcb.net_device.ip_address, 4);
249         /* Populate the Target IP/MAC Address in the ARP Header */
250         netMemcpy ((void *)&ptr_arphdr->DstAddr[0], (void *)&net_arp_cache.mac_address[0], 6);
251         netMemcpy ((void *)&ptr_arphdr->IPDst[0], (void *)&net_arp_cache.ip_address, 4);
253         /* Create the Ethernet header. */
254         ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_arphdr, &net_arp_cache.mac_address[0], 0x806);
255         if (ptr_ethhdr == NULL)
256             return -1;
258         /* Send the packet out. */
259         net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + sizeof(ARPHDR));
261         /* The packet has been transmitted and we can clean it up now. */
262         net_free_tx_packet ((Uint8 *)ptr_arphdr);
263     }
265     /* Check if there are any packet awaiting resolution? */
266     if (net_arp_cache.pending_packet_len != 0)
267     {
268         /* There was a packet in the ARP cache which was awaiting resolution. 
269          * We need to send out the packet now. */
270         ptr_pending_pkt = net_alloc_tx_packet(net_arp_cache.pending_packet_len);
271         if (ptr_pending_pkt == NULL)
272             return -1;
274         /* We now copy the contents of this packet from the ARP cache */
275         netMemcpy ((void *)ptr_pending_pkt, (void *)&net_arp_cache.pending_packet[0], 
276                     net_arp_cache.pending_packet_len);
278         /* We create the Ethernet header. 
279          *  Only IPv4 packets await resolution. */
280         ptr_ethhdr = net_create_eth_header ((Uint8 *)ptr_pending_pkt, &net_arp_cache.mac_address[0], 0x800);
281         if (ptr_ethhdr == NULL)
282             return -1;
284         /* Send the packet out. */
285         net_send_packet (ptr_ethhdr, sizeof(ETHHDR) + net_arp_cache.pending_packet_len);
287         /* The pending packet in the cache has been sent out. */
288         net_arp_cache.pending_packet_len = 0;
290         /* The packet has been transmitted and can be cleaned up. */
291         net_free_tx_packet (ptr_pending_pkt);
292     }
294     /* ARP Packet has been successfully processed. */
295     return 0;
298 /**
299  *  @b Description
300  *  @n  
301  *       The function initializes the ARP Module in the NET Boot module.
302  *
303  *  @retval
304  *      Not Applicable
305  */
306 void arp_init (void)
308     netMemset (&net_arp_cache, 0, sizeof(NET_ARP_CACHE));
309     return;