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