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