1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Internet Protocol (IP)                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "nx_api.h"
28 #include "nx_ip.h"
29 #include "nx_system.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_ip_create                                       PORTABLE C      */
37 /*                                                           6.3.0        */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function creates an Internet Protocol instance, including      */
45 /*    setting up all appropriate data structures and calling the supplied */
46 /*    link driver for initialization of the physical interface.           */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    ip_ptr                                Pointer to IP control block   */
51 /*    name                                  Name of this IP instance      */
52 /*    ip_address                            Internet address for this IP  */
53 /*    network_mask                          Network mask for IP address   */
54 /*    default_pool                          Default packet pool           */
55 /*    ip_link_driver                        User supplied IP link driver  */
56 /*    memory_ptr                            Pointer memory area for IP    */
57 /*    memory_size                           Size of IP memory area        */
58 /*    priority                              Priority of IP helper thread  */
59 /*                                                                        */
60 /*  OUTPUT                                                                */
61 /*                                                                        */
62 /*    status                                Completion status             */
63 /*                                                                        */
64 /*  CALLS                                                                 */
65 /*                                                                        */
66 /*    tx_event_flags_create                 Create IP event flags         */
67 /*    tx_event_flags_delete                 Delete IP event flags         */
68 /*    tx_mutex_create                       Create IP protection mutex    */
69 /*    tx_mutex_delete                       Delete IP protection mutex    */
70 /*    tx_thread_create                      Create IP helper thread       */
71 /*    tx_timer_create                       Create IP periodic timer      */
72 /*                                                                        */
73 /*  CALLED BY                                                             */
74 /*                                                                        */
75 /*    Application                                                         */
76 /*                                                                        */
77 /*  RELEASE HISTORY                                                       */
78 /*                                                                        */
79 /*    DATE              NAME                      DESCRIPTION             */
80 /*                                                                        */
81 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
82 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
83 /*                                            resulting in version 6.1    */
84 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
85 /*                                            supported random IP id,     */
86 /*                                            resulting in version 6.3.0  */
87 /*                                                                        */
88 /**************************************************************************/
_nx_ip_create(NX_IP * ip_ptr,CHAR * name,ULONG ip_address,ULONG network_mask,NX_PACKET_POOL * default_pool,VOID (* ip_link_driver)(struct NX_IP_DRIVER_STRUCT *),VOID * memory_ptr,ULONG memory_size,UINT priority)89 UINT  _nx_ip_create(NX_IP *ip_ptr, CHAR *name, ULONG ip_address, ULONG network_mask,
90                     NX_PACKET_POOL *default_pool, VOID (*ip_link_driver)(struct NX_IP_DRIVER_STRUCT *),
91                     VOID *memory_ptr, ULONG memory_size, UINT priority)
92 {
93 
94 TX_INTERRUPT_SAVE_AREA
95 
96 NX_IP     *tail_ptr;
97 UINT       i;
98 UINT       old_threshold = 0;
99 TX_THREAD *current_thread;
100 
101 #ifdef NX_DISABLE_IPV4
102     NX_PARAMETER_NOT_USED(ip_address);
103     NX_PARAMETER_NOT_USED(network_mask);
104 #endif /* NX_DISABLE_IPV4 */
105 
106     /* Reference the version ID and option words to ensure they are linked in.  */
107     if (((ULONG)_nx_system_build_options_1 | (ULONG)_nx_system_build_options_2 | (ULONG)_nx_system_build_options_3 |
108          (ULONG)_nx_system_build_options_4 | (ULONG)_nx_system_build_options_5 | (ULONG)_nx_version_id[0]) == 0)
109     {
110 
111         /* We should never get here!  */
112         return(NX_NOT_IMPLEMENTED);
113     }
114 
115     /* Initialize the IP control block to zero.  */
116     memset((void *)ip_ptr, 0, sizeof(NX_IP));
117 
118     /* Configure the primary interface. */
119     ip_ptr -> nx_ip_interface[0].nx_interface_valid = 1;
120 
121 #ifndef NX_DISABLE_IPV4
122     /* Save the IP address.  */
123     ip_ptr -> nx_ip_interface[0].nx_interface_ip_address =   ip_address;
124 
125     /* Save the network mask.  */
126     ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask =  network_mask;
127 
128     /* Derive the network bits of this IP address.  */
129     ip_ptr -> nx_ip_interface[0].nx_interface_ip_network =  ip_address & network_mask;
130 
131     /* Initialize the ARP defend timeout.  */
132     ip_ptr -> nx_ip_interface[0].nx_interface_arp_defend_timeout = 0;
133 #endif /* !NX_DISABLE_IPV4  */
134 
135     /* Setup the link driver address.  */
136     ip_ptr -> nx_ip_interface[0].nx_interface_link_driver_entry =  ip_link_driver;
137 
138     /* Set the device interface name to "PRI". */
139     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
140     ip_ptr -> nx_ip_interface[0].nx_interface_name = (CHAR *)"PRI";
141 
142     /* Set index of each interface. */
143     for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
144     {
145         ip_ptr -> nx_ip_interface[i].nx_interface_index = (UCHAR)i;
146     }
147 
148 
149 #ifndef NX_DISABLE_LOOPBACK_INTERFACE
150 
151     /* Set the Loopback interface name. */
152     /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary  */
153     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_name = (CHAR *)"Internal IP Loopback";
154 
155 
156     /* Mark the loopback interface as valid. */
157     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_valid = 1;
158 
159 #ifndef NX_DISABLE_IPV4
160     /* Set the loopback interface address. */
161     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_ip_address = 0x7F000001;
162     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_ip_network_mask = 0xFF000000;
163     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_ip_network = 0x7F000000;
164 #endif /* !NX_DISABLE_IPV4  */
165 
166     /* Loopback interface is a special case. Therefore no dedicated link driver needed. */
167     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_link_driver_entry = NX_NULL;
168 
169     /* Loopback interface does not need IP/MAC address mapping. */
170     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_address_mapping_needed = 0;
171 
172     /* There is actually no MTU limit for the loopback interface. */
173     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_ip_mtu_size = 65535;
174 
175     /* Mark the loopback interface as LINK UP */
176     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_link_up = 1;
177 
178     /* Set all the link capability. */
179 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
180     ip_ptr -> nx_ip_interface[NX_LOOPBACK_INTERFACE].nx_interface_capability_flag = (NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM |
181                                                                                      NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM |
182                                                                                      NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM |
183                                                                                      NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM |
184                                                                                      NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM |
185                                                                                      NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM |
186                                                                                      NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM |
187                                                                                      NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM |
188                                                                                      NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM |
189                                                                                      NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM |
190                                                                                      NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM |
191                                                                                      NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM);
192 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
193 
194 #endif /* !NX_DISABLE_LOOPBACK_INTERFACE */
195 
196     /* Save the supplied IP name.  */
197     ip_ptr -> nx_ip_name =  name;
198 
199     /* Set the initial IP packet ID.  */
200 #ifndef NX_ENABLE_IP_ID_RANDOMIZATION
201     ip_ptr -> nx_ip_packet_id =  NX_INIT_PACKET_ID;
202 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
203 
204     /* Setup the default packet pool for this IP instance.  */
205     ip_ptr -> nx_ip_default_packet_pool =  default_pool;
206 
207 #ifdef NX_ENABLE_DUAL_PACKET_POOL
208     /* Setup the auxiliary packet pool for this IP instance. By default it pointers to default pool. */
209     ip_ptr -> nx_ip_auxiliary_packet_pool = default_pool;
210 #endif /* NX_ENABLE_DUAL_PACKET_POOL */
211 
212     /* Create the internal IP protection mutex.  */
213     tx_mutex_create(&(ip_ptr -> nx_ip_protection), name, TX_NO_INHERIT);
214 
215     /* Create the internal IP event flag object.  */
216     tx_event_flags_create(&(ip_ptr -> nx_ip_events), name);
217 
218     /* Pickup current thread pointer.  */
219     current_thread =  tx_thread_identify();
220 
221     /* Disable preemption temporarily.  */
222     if (current_thread)
223     {
224         tx_thread_preemption_change(current_thread, priority, &old_threshold);
225     }
226 
227     /* Create the internal IP thread for handling more processing intensive
228        duties.  */
229     /*lint -e{923} suppress cast of pointer to ULONG.  */
230     tx_thread_create(&(ip_ptr -> nx_ip_thread), name, _nx_ip_thread_entry, (ULONG)(ALIGN_TYPE)(ip_ptr),
231                      memory_ptr, memory_size, priority, priority, 1, TX_AUTO_START);
232 
233     NX_THREAD_EXTENSION_PTR_SET(&(ip_ptr -> nx_ip_thread), ip_ptr)
234 
235     /* Create the periodic timer for this IP instance.  */
236     /*lint -e{923} suppress cast of pointer to ULONG.  */
237     tx_timer_create(&(ip_ptr -> nx_ip_periodic_timer), name,
238                     _nx_ip_periodic_timer_entry, (ULONG)(ALIGN_TYPE)ip_ptr,
239                     NX_IP_PERIODIC_RATE, NX_IP_PERIODIC_RATE, TX_AUTO_ACTIVATE);
240 
241     NX_TIMER_EXTENSION_PTR_SET(&(ip_ptr -> nx_ip_periodic_timer), ip_ptr)
242 
243     /* If trace is enabled, register this object.  */
244     NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_IP, ip_ptr, name, memory_ptr, memory_size);
245 
246     /* If trace is enabled, insert this event into the trace buffer.  */
247     NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_CREATE, ip_ptr, ip_address, network_mask, default_pool, NX_TRACE_IP_EVENTS, 0, 0);
248 
249 #ifndef NX_DISABLE_IPV4
250     /* Install IPv4 packet receive processing function pointer */
251     ip_ptr -> nx_ipv4_packet_receive = _nx_ipv4_packet_receive;
252 #endif
253 
254     /* Otherwise, the IP initialization was successful.  Place the
255        IP control block on the list of created IP instances.  */
256     TX_DISABLE
257 
258     /* Load the IP ID field in the IP control block.  */
259     ip_ptr -> nx_ip_id =  NX_IP_ID;
260 
261     /* Place the new IP control block on the list of created IPs.  First,
262        check for an empty list.  */
263     if (_nx_ip_created_ptr)
264     {
265 
266         /* Pickup tail pointer.  */
267         tail_ptr =  _nx_ip_created_ptr -> nx_ip_created_previous;
268 
269         /* Place the new IP control block in the list.  */
270         _nx_ip_created_ptr -> nx_ip_created_previous =  ip_ptr;
271         tail_ptr -> nx_ip_created_next =  ip_ptr;
272 
273         /* Setup this IP's created links.  */
274         ip_ptr -> nx_ip_created_previous =  tail_ptr;
275         ip_ptr -> nx_ip_created_next =      _nx_ip_created_ptr;
276     }
277     else
278     {
279 
280         /* The created IP list is empty.  Add IP control block to empty list.  */
281         _nx_ip_created_ptr =                ip_ptr;
282         ip_ptr -> nx_ip_created_next =      ip_ptr;
283         ip_ptr -> nx_ip_created_previous =  ip_ptr;
284     }
285 
286     /* Increment the created IP counter.  */
287     _nx_ip_created_count++;
288 
289     /* Restore previous interrupt posture.  */
290     TX_RESTORE
291 
292     /* Restore preemption.  */
293     if (current_thread)
294     {
295 
296         /*lint -e{644} suppress variable might not be initialized, since "old_threshold" was initialized in previous tx_thread_preemption_change call. */
297         tx_thread_preemption_change(current_thread, old_threshold, &old_threshold);
298     }
299 
300     /* Return success to the caller.  */
301     return(NX_SUCCESS);
302 }
303 
304