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