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 /** NetX Component                                                        */
15 /**                                                                       */
16 /**   Internet Protocol version 6 Default Router Table (IPv6 router)      */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 #define NX_SOURCE_CODE
21 
22 
23 /* Include necessary system files.  */
24 
25 #include "nx_api.h"
26 #include "nx_ipv6.h"
27 #include "nx_nd_cache.h"
28 #include "nx_icmpv6.h"
29 
30 
31 #ifdef FEATURE_NX_IPV6
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nxd_ipv6_router_lookup                             PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function finds a valid router from the default router table,   */
45 /*    and this function also return the pointer to the router's cache     */
46 /*    entry in the NetX Duo cache table.                                  */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    ip_ptr                                IP instance pointer           */
51 /*    if_ptr                                Pointer to interface          */
52 /*    router_address                        Pointer to default router     */
53 /*    nd_cache_entry                        Pointer to associated ND entry*/
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    status                                Non zero status               */
58 /*                                            router not found            */
59 /*                                          Zero status, router found     */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    None                                                                */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _nx_icmpv6_process_redirect                                         */
68 /*    _nx_ipv6_packet_send                                                */
69 /*                                                                        */
70 /*  NOTE                                                                  */
71 /*                                                                        */
72 /*    Internal Function.  Caller must have acquired IP protection mutex.  */
73 /*    This function should not be called from ISR.  Although it has no    */
74 /*    blocking calls it will slow down response time.                     */
75 /*                                                                        */
76 /*  RELEASE HISTORY                                                       */
77 /*                                                                        */
78 /*    DATE              NAME                      DESCRIPTION             */
79 /*                                                                        */
80 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
81 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
82 /*                                            resulting in version 6.1    */
83 /*                                                                        */
84 /**************************************************************************/
_nxd_ipv6_router_lookup(NX_IP * ip_ptr,NX_INTERFACE * if_ptr,ULONG * router_address,void ** nd_cache_entry)85 UINT  _nxd_ipv6_router_lookup(NX_IP *ip_ptr, NX_INTERFACE *if_ptr, ULONG *router_address, void **nd_cache_entry)
86 {
87 
88 UINT                          i;
89 UINT                          table_size;
90 UINT                          routers_checked;
91 NX_IPV6_DEFAULT_ROUTER_ENTRY *rt_entry;
92 ND_CACHE_ENTRY               *NDCacheEntry;
93 
94     NX_ASSERT(nd_cache_entry != NX_NULL)
95 
96     /* Initialize cache pointer to NULL (if no router found). */
97     *nd_cache_entry = NULL;
98 
99     /* Set a local variable for convenience. */
100     table_size = ip_ptr -> nx_ipv6_default_router_table_size;
101 
102     /* Check if there have been any routers added to the table. */
103     if (table_size == 0)
104     {
105 
106         /* Return a non zero (e.g. unsuccessful) error status. */
107         return(NX_NOT_SUCCESSFUL);
108     }
109 
110     /* Loop to check the router table.  */
111     for (i = 0; table_size && (i < NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE); i++)
112     {
113 
114         /* Local pointer for convenience. */
115         rt_entry = &(ip_ptr -> nx_ipv6_default_router_table[i]);
116 
117         /* Does this slot contain a valid router? */
118         if ((rt_entry -> nx_ipv6_default_router_entry_flag & NX_IPV6_ROUTE_TYPE_VALID) &&
119             (rt_entry -> nx_ipv6_default_router_entry_interface_ptr == if_ptr))
120         {
121 
122             /* Keep track of valid entries we have checked. */
123             NDCacheEntry = rt_entry -> nx_ipv6_default_router_entry_neighbor_cache_ptr;
124 
125             /* Is this router reachable? */
126             if (!NDCacheEntry ||
127                 (NDCacheEntry -> nx_nd_cache_nd_status < ND_CACHE_STATE_REACHABLE) ||
128                 (NDCacheEntry -> nx_nd_cache_nd_status > ND_CACHE_STATE_PROBE))
129             {
130 
131                 /* No, skip over. */
132                 table_size--;
133                 continue;
134             }
135 
136             /* Yes, copy this router address into the return pointer. */
137             COPY_IPV6_ADDRESS(ip_ptr -> nx_ipv6_default_router_table[i].nx_ipv6_default_router_entry_router_address, router_address);
138 
139             /* Copy the router's cache entry pointer to the supplied cache table pointer. */
140             *nd_cache_entry = ip_ptr -> nx_ipv6_default_router_table[i].nx_ipv6_default_router_entry_neighbor_cache_ptr;
141 
142             /* We're done. Break out of the search. */
143             return(NX_SUCCESS);
144         }
145     }
146 
147     /* If we are here, we did not find a suitable default router. Do a search
148        of routers previously reachable. */
149 
150     /* Start at the round robin index so we don't always choose the first
151        less-than-reachable router in the table. */
152     i = ip_ptr -> nx_ipv6_default_router_table_round_robin_index;
153 
154     /* Find a router with previously known reachability. */
155     for (routers_checked = 0; routers_checked < NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE; routers_checked++)
156     {
157 
158         /* Local pointer for convenience. */
159         rt_entry = &(ip_ptr -> nx_ipv6_default_router_table[i]);
160 
161         /* Does this slot contain a valid router? */
162         if ((rt_entry -> nx_ipv6_default_router_entry_flag & NX_IPV6_ROUTE_TYPE_VALID) &&
163             (rt_entry -> nx_ipv6_default_router_entry_interface_ptr == if_ptr))
164         {
165 
166             /* Yes, copy this router to the return pointer. */
167             COPY_IPV6_ADDRESS(rt_entry -> nx_ipv6_default_router_entry_router_address, router_address);
168 
169             /* Copy the router's cache entry pointer to the supplied cache table pointer. */
170             *nd_cache_entry = rt_entry -> nx_ipv6_default_router_entry_neighbor_cache_ptr;
171 
172             /* Update the index so the same router is not chosen again if there
173                any other less-than-reachable routers we can choose, RFC 2461 6.3.6. */
174             ip_ptr -> nx_ipv6_default_router_table_round_robin_index++;
175 
176             /* Do we need wrap the index? */
177             if (ip_ptr -> nx_ipv6_default_router_table_round_robin_index == NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE)
178             {
179 
180                 /* Yes, start back at the first slot. */
181                 ip_ptr -> nx_ipv6_default_router_table_round_robin_index = 0;
182             }
183 
184             /* We're done. Return successful outcome status. */
185             return(NX_SUCCESS);
186         }
187 
188         /* Are we past the end of the table? */
189         if (i == NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE - 1)
190         {
191             /* Yes, wrap to the first slot.*/
192             i = 0;
193         }
194         else
195         {
196             i++;
197         }
198     }
199 
200     /* Router not found. */
201     return(NX_NOT_SUCCESSFUL);
202 }
203 
204 
205 #endif /* FEATURE_NX_IPV6 */
206 
207