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 /** NetX Component */
16 /** */
17 /** Internet Control Message Protocol (ICMP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26 #include "nx_api.h"
27 #include "nx_ipv6.h"
28 #include "nx_icmpv6.h"
29
30 #ifdef FEATURE_NX_IPV6
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_icmpv6_dest_table_add PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function searches for a matching destination in the table entry*/
46 /* and if no match is found, it creates one. If a match is */
47 /* found, the next hop field is updated if the data is changed, and a */
48 /* pointer returned to that entry. If path MTU discovery is enabled, */
49 /* the path MTU and time out are set to supplied values. If none are */
50 /* NetX Duo applies default values. */
51 /* */
52 /* INPUT */
53 /* */
54 /* ip_ptr IP interface thread task */
55 /* destination_address Destination IP address. */
56 /* dest_entry_ptr Pointer to location of matching*/
57 /* table entry, if any */
58 /* next_hop Pointer to next hop address */
59 /* path_mtu Optional path mtu update. */
60 /* Note: caller shall make sure */
61 /* MTU does not exceed physical */
62 /* link MTU size. */
63 /* mtu_timeout Optional entry timeout update */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* NX_SUCCESS Found matching entry */
68 /* NX_NOT_SUCCESSFUL Error searching table */
69 /* */
70 /* CALLS */
71 /* */
72 /* tx_mutex_get Obtain destination table lock */
73 /* tx_mutex_put Release destination table lock */
74 /* memset Clear memory block */
75 /* _nx_nd_cache_find_entry Find next hop in the ND cache */
76 /* _nx_nd_cache_add_entry Create an entry in ND cache */
77 /* */
78 /* CALLED BY */
79 /* */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
86 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
87 /* resulting in version 6.1 */
88 /* */
89 /**************************************************************************/
90
_nx_icmpv6_dest_table_add(NX_IP * ip_ptr,ULONG * destination_address,NX_IPV6_DESTINATION_ENTRY ** dest_entry_ptr,ULONG * next_hop,ULONG path_mtu,ULONG mtu_timeout,NXD_IPV6_ADDRESS * ipv6_address)91 UINT _nx_icmpv6_dest_table_add(NX_IP *ip_ptr, ULONG *destination_address,
92 NX_IPV6_DESTINATION_ENTRY **dest_entry_ptr, ULONG *next_hop,
93 ULONG path_mtu, ULONG mtu_timeout, NXD_IPV6_ADDRESS *ipv6_address)
94 {
95
96 UINT i, table_size;
97 UINT status;
98
99 /* Pointers must not be NULL. */
100 NX_ASSERT((destination_address != NX_NULL) && (dest_entry_ptr != NX_NULL) && (next_hop != NX_NULL));
101
102 /* Check if destination table already exist. */
103 status = _nx_icmpv6_dest_table_find(ip_ptr, destination_address, dest_entry_ptr, path_mtu, mtu_timeout);
104
105 /* Check status. */
106 if (status == NX_SUCCESS)
107 {
108
109 /* Check if the next hop address is same. */
110 if (CHECK_IPV6_ADDRESSES_SAME(next_hop, (*dest_entry_ptr) -> nx_ipv6_destination_entry_next_hop))
111 {
112
113 /* Same next hop address. Return success. */
114 return(NX_SUCCESS);
115 }
116 else
117 {
118
119 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
120 /* Get MTU from original destination table. */
121 path_mtu = (*dest_entry_ptr) -> nx_ipv6_destination_entry_path_mtu;
122 mtu_timeout = (*dest_entry_ptr) -> nx_ipv6_destination_entry_MTU_timer_tick;
123 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
124
125 /* Next hop is different. Delete this destination table and add new entry. */
126 (*dest_entry_ptr) -> nx_ipv6_destination_entry_valid = 0;
127
128 /* Decrease the count of available destinations. */
129 ip_ptr -> nx_ipv6_destination_table_size--;
130 }
131 }
132
133 /* Set a local variable for convenience. */
134 table_size = ip_ptr -> nx_ipv6_destination_table_size;
135
136 /* There is no invalid destination in table. */
137 if (table_size == NX_IPV6_DESTINATION_TABLE_SIZE)
138 {
139 return(NX_NOT_SUCCESSFUL);
140 }
141
142 /* Initialize the pointer to the table location where we will update/add information. */
143 *dest_entry_ptr = NX_NULL;
144
145 /* Go through the table to find an empty slot. */
146 for (i = 0; i < NX_IPV6_DESTINATION_TABLE_SIZE; i++)
147 {
148
149 /* Is this slot empty? */
150 if (!ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_valid)
151 {
152 /* Yes; we can use it for adding a new entry. */
153 /* Have found an empty slot. */
154 break;
155 }
156 }
157
158 /* Destination is not empty so i must be less than table size. */
159 NX_ASSERT(i < NX_IPV6_DESTINATION_TABLE_SIZE);
160
161 /*
162 If we are here, we did not find a match and are adding a new entry.
163 The process is slightly different from updating a previously existing
164 matching entry, so we handle it separately.
165 */
166
167 /* Clear out any previous data from this slot. */
168 /*lint -e{669} -e{826} suppress cast of pointer to pointer, since it is necessary */
169 memset(&ip_ptr -> nx_ipv6_destination_table[i], 0, sizeof(NX_IPV6_DESTINATION_ENTRY));
170
171 /* Fill in the newly created table entry with the supplied and/or default information. */
172 COPY_IPV6_ADDRESS(destination_address, ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_destination_address);
173
174 /* Add next hop information to the entry. */
175 COPY_IPV6_ADDRESS(next_hop, ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_next_hop);
176
177 /* Attempt to find the matching entry in the cache table. NetX Duo will need to know
178 how to get a packet to the next hop, not just the destination! */
179 status = _nx_nd_cache_find_entry(ip_ptr, next_hop, &ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_nd_entry);
180
181 /* Did not find the matching entry. Try to add one. */
182 if (status)
183 {
184 status = _nx_nd_cache_add_entry(ip_ptr, next_hop, ipv6_address, &ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_nd_entry);
185
186 /* Failed to add new entry. Return. */
187 if (status)
188 {
189 return(NX_NOT_SUCCESSFUL);
190 }
191 }
192
193
194 /* Validate this entry to ensure it will not be overwritten with new entries. */
195 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_valid = 1;
196
197 /* Update the count of destinations currently in the table. */
198 ip_ptr -> nx_ipv6_destination_table_size++;
199
200 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
201
202 /* Is a valid path mtu is given? */
203 if (path_mtu > 0)
204 {
205
206 /* Update the destination path MTU with this supplied data. */
207 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_path_mtu = path_mtu;
208 }
209 else
210 {
211
212 /* No; set the path MTU to the IP task MTU (on link path MTU).*/
213 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_path_mtu = ipv6_address -> nxd_ipv6_address_attached -> nx_interface_ip_mtu_size;
214 }
215
216 /* Is a valid entry timeout is supplied? */
217 if (mtu_timeout > 0)
218 {
219
220 /* Yes; Update the table entry timeout to the supplied data. */
221 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_MTU_timer_tick = mtu_timeout;
222 }
223 else
224 {
225
226 /* No; have we defaulted to our own IP task MTU?*/
227 if (ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_path_mtu == ipv6_address -> nxd_ipv6_address_attached -> nx_interface_ip_mtu_size)
228 {
229
230 /* Yes; This is our optimal path MTU. So there is no need to age this table entry
231 and attempt to increase the path MTU; ok set it to infinity. */
232 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_MTU_timer_tick = NX_WAIT_FOREVER;
233 }
234 else
235 {
236 /* No, this is less than our optimal path MTU. Wait the required interval
237 before probing for a higher path MTU. */
238 ip_ptr -> nx_ipv6_destination_table[i].nx_ipv6_destination_entry_MTU_timer_tick = NX_PATH_MTU_INCREASE_WAIT_INTERVAL_TICKS;
239 }
240 }
241 #else
242 NX_PARAMETER_NOT_USED(path_mtu);
243 NX_PARAMETER_NOT_USED(mtu_timeout);
244 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
245
246 /* Set the table location pointer to the entry we just added/updated. */
247 *dest_entry_ptr = &ip_ptr -> nx_ipv6_destination_table[i];
248
249 return(NX_SUCCESS);
250 }
251
252 #endif /* FEATURE_NX_IPV6 */
253
254