1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Address Resolution Protocol (ARP)                                   */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "nx_api.h"
29 #include "nx_arp.h"
30 
31 #ifndef NX_DISABLE_IPV4
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_arp_entry_allocate                              PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function allocates an ARP entry for a specific new IP          */
45 /*    destination.                                                        */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    ip_ptr                                IP instance pointer           */
50 /*    arp_list_ptr                          List head of where to place   */
51 /*                                            the newly allocated ARP     */
52 /*                                            entry                       */
53 /*    is_static                             Entry attribute static/dynamic*/
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    status                                Completion status             */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _nx_arp_dynamic_entry_delete          Delete the dynamic entry      */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    NetX Source Code                                                    */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
72 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_nx_arp_entry_allocate(NX_IP * ip_ptr,NX_ARP ** arp_list_ptr,UINT is_static)76 UINT  _nx_arp_entry_allocate(NX_IP *ip_ptr, NX_ARP **arp_list_ptr, UINT is_static)
77 {
78 
79 TX_INTERRUPT_SAVE_AREA
80 NX_ARP *arp_entry;
81 UINT    status;
82 
83 
84     /* Determine if there is an ARP entry available in the dynamic list.  */
85     if (ip_ptr -> nx_ip_arp_dynamic_list)
86     {
87 
88         /* Yes there are one or more free entries.  */
89 
90         /* Pickup pointer to last used dynamic ARP entry.  */
91         arp_entry =  (ip_ptr -> nx_ip_arp_dynamic_list) -> nx_arp_pool_previous;
92 
93         /* Remove from the dynamic list. */
94         _nx_arp_dynamic_entry_delete(ip_ptr, arp_entry);
95 
96         /* Disable interrupts temporarily.  */
97         TX_DISABLE
98 
99         /* Link the ARP entry at the head of the IP list.  */
100 
101         /* Determine if the ARP entry is being added to an empty list.  */
102         if (*arp_list_ptr)
103         {
104 
105             /* Add the ARP entry to the beginning of the nonempty ARP
106                list.  */
107             arp_entry -> nx_arp_active_list_head =  arp_list_ptr;
108             arp_entry -> nx_arp_active_next =      *arp_list_ptr;
109             arp_entry -> nx_arp_active_previous =  (*arp_list_ptr) -> nx_arp_active_previous;
110             (arp_entry -> nx_arp_active_previous) -> nx_arp_active_next =  arp_entry;
111             (*arp_list_ptr) -> nx_arp_active_previous =  arp_entry;
112         }
113         else
114         {
115             /* Empty list, just put the ARP entry at the beginning.  */
116             arp_entry -> nx_arp_active_list_head =  arp_list_ptr;
117             arp_entry -> nx_arp_active_next =       arp_entry;
118             arp_entry -> nx_arp_active_previous =   arp_entry;
119 
120             /* Now setup the list head.  */
121             *arp_list_ptr =  arp_entry;
122         }
123 
124         /* Determine if this is a static entry. */
125         if (is_static == NX_TRUE)
126         {
127 
128             /* Remove this entry from the ARP dynamic list.  */
129 
130             /* Determine if this is the only ARP entry on the dynamic list.  */
131             if (arp_entry == arp_entry -> nx_arp_pool_next)
132             {
133 
134                 /* Remove the sole entry from the dynamic list head.  */
135                 ip_ptr -> nx_ip_arp_dynamic_list =  NX_NULL;
136             }
137             else
138             {
139 
140                 /* Remove the entry from a list of more than one entry.  */
141 
142                 /* Update the links of the adjacent ARP dynamic pool entries.  */
143                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous = arp_entry -> nx_arp_pool_previous;
144                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry -> nx_arp_pool_next;
145             }
146 
147             /* Add the entry to the ARP static list.  */
148 
149             /* Determine if the ARP static list is empty.  */
150             if (ip_ptr -> nx_ip_arp_static_list == NX_NULL)
151             {
152 
153                 /* Just place this single ARP entry on the list.  */
154                 arp_entry -> nx_arp_pool_next =     arp_entry;
155                 arp_entry -> nx_arp_pool_previous = arp_entry;
156                 ip_ptr -> nx_ip_arp_static_list =   arp_entry;
157             }
158             else
159             {
160 
161                 /* Add to the end of the ARP static list.  */
162                 arp_entry -> nx_arp_pool_next = ip_ptr -> nx_ip_arp_static_list;
163                 arp_entry -> nx_arp_pool_previous = (ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous;
164                 ((ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry;
165                 (ip_ptr -> nx_ip_arp_static_list) -> nx_arp_pool_previous = arp_entry;
166             }
167 
168 #ifndef NX_DISABLE_ARP_INFO
169             /* Increment the ARP static entry count.  */
170             ip_ptr -> nx_ip_arp_static_entries++;
171 #endif
172         }
173         else  /* Allocate entry from dynamic list. */
174         {
175 
176             /* Move this ARP entry to the front of the general ARP dynamic entry pool.  */
177             if (arp_entry != ip_ptr -> nx_ip_arp_dynamic_list)
178             {
179 
180                 /* The current ARP entry is not at the front of the list, so it
181                    must be moved.  */
182 
183                 /* Link up the neighbors first.  */
184                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous = arp_entry -> nx_arp_pool_previous;
185                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next = arp_entry -> nx_arp_pool_next;
186 
187                 /* Now link this ARP entry to the head of the list.  */
188                 arp_entry -> nx_arp_pool_next =  ip_ptr -> nx_ip_arp_dynamic_list;
189                 arp_entry -> nx_arp_pool_previous =    (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous;
190                 (arp_entry -> nx_arp_pool_previous) -> nx_arp_pool_next =  arp_entry;
191                 (arp_entry -> nx_arp_pool_next) -> nx_arp_pool_previous =  arp_entry;
192 
193                 /* Now set the list head to this ARP entry.  */
194                 ip_ptr -> nx_ip_arp_dynamic_list =  arp_entry;
195             }
196 
197             /* Increment the number of active dynamic entries.  */
198             ip_ptr -> nx_ip_arp_dynamic_active_count++;
199         }
200 
201         /* Set the entry type.  */
202         arp_entry -> nx_arp_route_static = is_static;
203 
204         /* Restore interrupts.  */
205         TX_RESTORE
206 
207         /* Setup a successful status return.  */
208         status =  NX_SUCCESS;
209     }
210     else
211     {
212 
213         /* No more ARP entries are available, all the ARP entries must be
214            allocated on the static list.  */
215         status =  NX_NO_MORE_ENTRIES;
216     }
217 
218     /* Return status to the caller.  */
219     return(status);
220 }
221 #endif /* !NX_DISABLE_IPV4  */
222 
223