@@ -2006,7 +2006,7 @@ bool net_if_ipv6_prefix_rm(struct net_if *iface, struct in6_addr *addr,
20062006}
20072007
20082008struct net_if_ipv6_prefix * net_if_ipv6_prefix_get (struct net_if * iface ,
2009- struct in6_addr * addr )
2009+ const struct in6_addr * addr )
20102010{
20112011 struct net_if_ipv6_prefix * prefix = NULL ;
20122012 struct net_if_ipv6 * ipv6 ;
@@ -2269,25 +2269,53 @@ static inline bool is_proper_ipv6_address(struct net_if_addr *addr)
22692269 return false;
22702270}
22712271
2272+ static bool use_public_address (bool prefer_public , bool is_temporary )
2273+ {
2274+ if (IS_ENABLED (CONFIG_NET_IPV6_PE_ENABLE )) {
2275+ if (!prefer_public && is_temporary ) {
2276+ return false;
2277+ }
2278+ }
2279+
2280+ return true;
2281+ }
2282+
22722283static struct in6_addr * net_if_ipv6_get_best_match (struct net_if * iface ,
22732284 const struct in6_addr * dst ,
2285+ u8_t prefix_len ,
22742286 u8_t * best_so_far )
22752287{
22762288 struct net_if_ipv6 * ipv6 = iface -> config .ip .ipv6 ;
2289+ struct net_if_addr * public_addr = NULL ;
22772290 struct in6_addr * src = NULL ;
2278- u8_t len ;
2291+ u8_t public_addr_len = 0 ;
2292+ struct in6_addr * temp_addr ;
2293+ u8_t len , temp_addr_len ;
2294+ bool ret ;
22792295 int i ;
22802296
22812297 if (!ipv6 ) {
22822298 return NULL ;
22832299 }
22842300
2301+ if (IS_ENABLED (CONFIG_NET_IPV6_PE_ENABLE )) {
2302+ temp_addr = NULL ;
2303+ temp_addr_len = 0 ;
2304+ } else {
2305+ ARG_UNUSED (temp_addr );
2306+ ARG_UNUSED (temp_addr_len );
2307+ }
2308+
22852309 for (i = 0 ; i < NET_IF_MAX_IPV6_ADDR ; i ++ ) {
22862310 if (!is_proper_ipv6_address (& ipv6 -> unicast [i ])) {
22872311 continue ;
22882312 }
22892313
22902314 len = get_diff_ipv6 (dst , & ipv6 -> unicast [i ].address .in6_addr );
2315+ if (len >= prefix_len ) {
2316+ len = prefix_len ;
2317+ }
2318+
22912319 if (len >= * best_so_far ) {
22922320 /* Mesh local address can only be selected for the same
22932321 * subnet.
@@ -2296,11 +2324,39 @@ static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface,
22962324 continue ;
22972325 }
22982326
2327+ ret = use_public_address (iface -> pe_prefer_public ,
2328+ ipv6 -> unicast [i ].is_temporary );
2329+ if (!ret ) {
2330+ temp_addr = & ipv6 -> unicast [i ].address .in6_addr ;
2331+ temp_addr_len = len ;
2332+ continue ;
2333+ }
2334+
2335+ if (!ipv6 -> unicast [i ].is_temporary ) {
2336+ public_addr = & ipv6 -> unicast [i ];
2337+ public_addr_len = len ;
2338+ }
2339+
22992340 * best_so_far = len ;
23002341 src = & ipv6 -> unicast [i ].address .in6_addr ;
23012342 }
23022343 }
23032344
2345+ if (IS_ENABLED (CONFIG_NET_IPV6_PE_ENABLE ) &&
2346+ !iface -> pe_prefer_public && temp_addr ) {
2347+ if (temp_addr_len >= * best_so_far ) {
2348+ * best_so_far = temp_addr_len ;
2349+ src = temp_addr ;
2350+ }
2351+ } else {
2352+ /* By default prefer always public address if found */
2353+ if (public_addr &&
2354+ !net_ipv6_addr_cmp (& public_addr -> address .in6_addr , src )) {
2355+ src = & public_addr -> address .in6_addr ;
2356+ * best_so_far = public_addr_len ;
2357+ }
2358+ }
2359+
23042360 return src ;
23052361}
23062362
@@ -2312,13 +2368,21 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
23122368 struct net_if * iface ;
23132369
23142370 if (!net_ipv6_is_ll_addr (dst ) && !net_ipv6_is_addr_mcast (dst )) {
2371+ struct net_if_ipv6_prefix * prefix ;
2372+ u8_t prefix_len = 128 ;
2373+
2374+ prefix = net_if_ipv6_prefix_get (dst_iface , dst );
2375+ if (prefix ) {
2376+ prefix_len = prefix -> len ;
2377+ }
23152378
23162379 for (iface = __net_if_start ;
23172380 !dst_iface && iface != __net_if_end ;
23182381 iface ++ ) {
23192382 struct in6_addr * addr ;
23202383
23212384 addr = net_if_ipv6_get_best_match (iface , dst ,
2385+ prefix_len ,
23222386 & best_match );
23232387 if (addr ) {
23242388 src = addr ;
@@ -2328,6 +2392,7 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
23282392 /* If caller has supplied interface, then use that */
23292393 if (dst_iface ) {
23302394 src = net_if_ipv6_get_best_match (dst_iface , dst ,
2395+ prefix_len ,
23312396 & best_match );
23322397 }
23332398
0 commit comments