Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : /**
17 : * @brief FIB Source Address selection
18 : *
19 : * Use the FIB for source address selection on an interface
20 : */
21 :
22 : #include <vnet/fib/fib_sas.h>
23 : #include <vnet/adj/adj_glean.h>
24 : #include <vnet/ip/ip6_link.h>
25 :
26 :
27 : bool
28 0 : fib_sas_get (u32 sw_if_index,
29 : ip_address_family_t af,
30 : const ip46_address_t *dst,
31 : ip46_address_t *src)
32 : {
33 0 : switch (af)
34 : {
35 0 : case AF_IP4:
36 0 : if (dst)
37 0 : return (fib_sas4_get(sw_if_index, &dst->ip4, &src->ip4));
38 : else
39 0 : return (fib_sas4_get(sw_if_index, NULL, &src->ip4));
40 0 : case AF_IP6:
41 0 : if (dst)
42 0 : return (fib_sas6_get(sw_if_index, &dst->ip6, &src->ip6));
43 : else
44 0 : return (fib_sas6_get(sw_if_index, NULL, &src->ip6));
45 : }
46 0 : return (false);
47 : }
48 :
49 : bool
50 1118 : fib_sas4_get (u32 sw_if_index,
51 : const ip4_address_t *dst,
52 : ip4_address_t *src)
53 : {
54 1118 : ip46_address_t d_tmp, *d_tmpp = NULL;
55 : const ip46_address_t *s_tmp;
56 : vnet_sw_interface_t *swif;
57 :
58 1118 : if (dst)
59 : {
60 1050 : d_tmpp = &d_tmp;
61 1050 : d_tmp.ip4 = *dst;
62 : }
63 :
64 1118 : if (vnet_sw_interface_is_p2p(vnet_get_main(), sw_if_index))
65 : {
66 : ip4_address_t *ip4;
67 0 : ip4 = ip_interface_get_first_ip (sw_if_index, 1);
68 0 : if (ip4) {
69 0 : src->as_u32 = ip4->as_u32;
70 0 : return (true);
71 : } else {
72 0 : return (false);
73 : }
74 : }
75 :
76 : /*
77 : * If the interface is unnumbered then use the IP interface
78 : */
79 1118 : swif = vnet_get_sw_interface (vnet_get_main(), sw_if_index);
80 :
81 1118 : if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
82 2 : sw_if_index = swif->unnumbered_sw_if_index;
83 :
84 : /*
85 : * get the source address from the glean adjacency
86 : */
87 1118 : s_tmp = adj_glean_get_src (FIB_PROTOCOL_IP4, sw_if_index, d_tmpp);
88 :
89 1118 : if (NULL != s_tmp)
90 : {
91 1065 : src->as_u32 = s_tmp->ip4.as_u32;
92 1065 : return (true);
93 : }
94 :
95 53 : return (false);
96 : }
97 :
98 : bool
99 57 : fib_sas6_get (u32 sw_if_index,
100 : const ip6_address_t *dst,
101 : ip6_address_t *src)
102 : {
103 57 : ip46_address_t d_tmp, *d_tmpp = NULL;
104 : const ip46_address_t *s_tmp;
105 :
106 57 : if (dst)
107 : {
108 57 : d_tmpp = &d_tmp;
109 57 : d_tmp.ip6 = *dst;
110 : }
111 :
112 : /*
113 : * if the dst is v6 and link local, use the source link local
114 : */
115 57 : if (dst && ip6_address_is_link_local_unicast (dst))
116 : {
117 2 : const ip6_address_t *ll = ip6_get_link_local_address (sw_if_index);
118 2 : if (NULL == ll)
119 : {
120 0 : return (false);
121 : }
122 2 : ip6_address_copy (src, ll);
123 2 : return (true);
124 : }
125 :
126 55 : if (vnet_sw_interface_is_p2p(vnet_get_main(), sw_if_index))
127 : {
128 : ip6_address_t *ip6;
129 0 : ip6 = ip_interface_get_first_ip (sw_if_index, 0);
130 0 : if (ip6) {
131 0 : ip6_address_copy(src, ip6);
132 0 : return (true);
133 : } else {
134 0 : return (false);
135 : }
136 : }
137 :
138 : /*
139 : * get the source address from the glean adjacency
140 : */
141 55 : s_tmp = adj_glean_get_src (FIB_PROTOCOL_IP6, sw_if_index, d_tmpp);
142 :
143 55 : if (NULL != s_tmp)
144 : {
145 50 : ip6_address_copy(src, &s_tmp->ip6);
146 50 : return (true);
147 : }
148 :
149 5 : return (false);
150 : }
|