blob: ada0012ecd09355c16fc41ff953a15ada9fe10bb [file] [log] [blame]
Neale Ranns81458422018-03-12 06:59:36 -07001/*
2 * Copyright (c) 2016 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#include <vnet/vnet.h>
17#include <vlibmemory/api.h>
18#include <vnet/fib/fib_api.h>
19#include <vnet/fib/fib_table.h>
Neale Ranns775f73c2018-12-20 03:01:49 -080020#include <vnet/mfib/mfib_table.h>
Neale Ranns81458422018-03-12 06:59:36 -070021#include <vnet/bier/bier_disp_table.h>
22#include <vnet/dpo/ip_null_dpo.h>
23
24#include <vnet/vnet_msg_enum.h>
25
26#define vl_typedefs /* define message structures */
27#include <vnet/vnet_all_api_h.h>
28#undef vl_typedefs
29
30#define vl_endianfun /* define message structures */
31#include <vnet/vnet_all_api_h.h>
32#undef vl_endianfun
33
34/* instantiate all the print functions we know about */
35#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
36#define vl_printfun
37#include <vnet/vnet_all_api_h.h>
38#undef vl_printfun
39
40#include <vlibapi/api_helper_macros.h>
41
42int
43fib_path_api_parse (const vl_api_fib_path_t *in,
44 fib_route_path_t *out)
45{
46 fib_route_path_flags_t path_flags;
47 mpls_label_t next_hop_via_label;
48 int rv = 0, n_labels;
49 u8 ii;
50
51 path_flags = FIB_ROUTE_PATH_FLAG_NONE;
52 next_hop_via_label = ntohl (in->via_label);
Dave Barachb7b92992018-10-17 10:38:51 -040053 clib_memset(out, 0, sizeof(*out));
Neale Ranns81458422018-03-12 06:59:36 -070054 out->frp_sw_if_index = ~0;
55
56 out->frp_proto = in->afi;
57 // .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
58 out->frp_sw_if_index = ntohl(in->sw_if_index);
Neale Ranns81458422018-03-12 06:59:36 -070059 out->frp_weight = in->weight;
60 out->frp_preference = in->preference;
61
Neale Rannsf726f532019-03-11 05:34:50 -070062 if (DPO_PROTO_IP4 == out->frp_proto ||
63 DPO_PROTO_IP6 == out->frp_proto ||
64 DPO_PROTO_MPLS == out->frp_proto)
65 {
66 out->frp_fib_index = fib_table_find (dpo_proto_to_fib(out->frp_proto),
67 ntohl (in->table_id));
68
69 if (~0 == out->frp_fib_index)
70 return (VNET_API_ERROR_NO_SUCH_FIB);
71 }
72
Neale Ranns81458422018-03-12 06:59:36 -070073 /*
74 * the special INVALID label meams we are not recursing via a
75 * label. Exp-null value is never a valid via-label so that
76 * also means it's not a via-label and means clients that set
77 * it to 0 by default get the expected behaviour
78 */
79 if ((MPLS_LABEL_INVALID != next_hop_via_label) &&
80 (0 != next_hop_via_label))
81 {
82 out->frp_proto = DPO_PROTO_MPLS;
83 out->frp_local_label = next_hop_via_label;
84 out->frp_eos = MPLS_NON_EOS;
85 }
86
87 n_labels = in->n_labels;
88 if (n_labels == 0)
89 ;
90 else
91 {
92 vec_validate (out->frp_label_stack, n_labels - 1);
93 for (ii = 0; ii < n_labels; ii++)
94 {
95 out->frp_label_stack[ii].fml_value =
96 ntohl(in->label_stack[ii].label);
97 out->frp_label_stack[ii].fml_ttl =
98 in->label_stack[ii].ttl;
99 out->frp_label_stack[ii].fml_exp =
100 in->label_stack[ii].exp;
101 out->frp_label_stack[ii].fml_mode =
102 (in->label_stack[ii].is_uniform ?
103 FIB_MPLS_LSP_MODE_UNIFORM :
104 FIB_MPLS_LSP_MODE_PIPE);
105 }
106 }
107
108 if (in->is_dvr)
109 path_flags |= FIB_ROUTE_PATH_DVR;
110 if (in->is_resolve_host)
111 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
112 if (in->is_resolve_attached)
113 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
114 /* if (in->is_interface_rx) */
115 /* path_flags |= FIB_ROUTE_PATH_INTF_RX; */
116 /* if (in->is_rpf_id) */
117 /* path_flags |= FIB_ROUTE_PATH_RPF_ID; */
118 if (in->is_source_lookup)
119 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
120
121 if (in->is_udp_encap)
122 {
123 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
124 out->frp_udp_encap_id = ntohl(in->next_hop_id);
125 }
126 else
127 {
128 if (DPO_PROTO_IP4 == in->afi)
129 {
130 clib_memcpy (&out->frp_addr.ip4,
131 in->next_hop,
132 sizeof (out->frp_addr.ip4));
133 }
134 else if (DPO_PROTO_IP6 == in->afi)
135 {
136 clib_memcpy (&out->frp_addr.ip6,
137 in->next_hop,
138 sizeof (out->frp_addr.ip6));
139 }
140
141 if (ip46_address_is_zero(&out->frp_addr))
142 {
143 if (DPO_PROTO_BIER == in->afi)
144 {
145 index_t bdti;
146
147 bdti = bier_disp_table_find(ntohl(in->table_id));
148
149 if (INDEX_INVALID != bdti)
150 {
151 out->frp_fib_index = bdti;
152 out->frp_proto = DPO_PROTO_BIER;
153 }
154 else
155 {
156 rv = VNET_API_ERROR_NO_SUCH_FIB;
157 }
158 }
159 else if (out->frp_sw_if_index == ~0 &&
160 out->frp_fib_index != ~0)
161 {
162 path_flags |= FIB_ROUTE_PATH_DEAG;
163 }
164 }
165 }
166
167 out->frp_flags = path_flags;
168
169 return (rv);
170}
171
172void
173fib_prefix_to_api (const fib_prefix_t *pfx,
174 u8 address[16],
175 u8 *length,
176 u8 *is_ip6)
177{
178 *length = pfx->fp_len;
179 *is_ip6 = (FIB_PROTOCOL_IP6 == pfx->fp_proto ? 1 : 0);
180
181 if (FIB_PROTOCOL_IP6 == pfx->fp_proto)
182 {
183 memcpy (address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
184 }
185 else
186 {
187 memcpy (address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
188 }
189}
190
191static void
192fib_api_path_copy_next_hop (const fib_route_path_encode_t * api_rpath, void *fp_arg)
193{
194 int is_ip4;
195 vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
196
197 if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
198 fp->afi = IP46_TYPE_IP4;
199 else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
200 fp->afi = IP46_TYPE_IP6;
201 else
202 {
203 is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
204 if (is_ip4)
205 fp->afi = IP46_TYPE_IP4;
206 else
207 fp->afi = IP46_TYPE_IP6;
208 }
209 if (fp->afi == IP46_TYPE_IP4)
210 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
211 sizeof (api_rpath->rpath.frp_addr.ip4));
212 else
213 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
214 sizeof (api_rpath->rpath.frp_addr.ip6));
215}
216
217void
218fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
219 vl_api_fib_path_t *out)
220{
Neale Ranns775f73c2018-12-20 03:01:49 -0800221 int ii;
222
Dave Barachb7b92992018-10-17 10:38:51 -0400223 clib_memset (out, 0, sizeof (*out));
Neale Ranns81458422018-03-12 06:59:36 -0700224 switch (api_rpath->dpo.dpoi_type)
225 {
226 case DPO_RECEIVE:
227 out->is_local = true;
228 break;
229 case DPO_DROP:
230 out->is_drop = true;
231 break;
232 case DPO_IP_NULL:
Dmitry Vakhrushevf38bef42018-03-16 20:26:32 +0300233 switch (ip_null_dpo_get_action(api_rpath->dpo.dpoi_index))
Neale Ranns81458422018-03-12 06:59:36 -0700234 {
235 case IP_NULL_ACTION_NONE:
236 out->is_drop = true;
237 break;
238 case IP_NULL_ACTION_SEND_ICMP_UNREACH:
239 out->is_unreach = true;
240 break;
241 case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
242 out->is_prohibit = true;
243 break;
244 default:
245 break;
246 }
247 break;
248 default:
249 break;
250 }
251 out->weight = api_rpath->rpath.frp_weight;
252 out->preference = api_rpath->rpath.frp_preference;
253 out->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
254 out->afi = api_rpath->rpath.frp_proto;
255 fib_api_path_copy_next_hop (api_rpath, out);
256
Neale Rannsde450cb2018-07-10 03:00:07 -0700257 if (0 != api_rpath->rpath.frp_fib_index)
Neale Ranns81458422018-03-12 06:59:36 -0700258 {
259 if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
Neale Ranns26600e62018-03-19 02:43:28 -0700260 (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto))
Neale Ranns81458422018-03-12 06:59:36 -0700261 {
Neale Ranns775f73c2018-12-20 03:01:49 -0800262 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RPF_ID)
263 {
264 out->table_id =
265 htonl(mfib_table_get_table_id(
266 api_rpath->rpath.frp_fib_index,
267 dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
268 }
269 else
270 {
271 out->table_id =
272 htonl(fib_table_get_table_id(
273 api_rpath->rpath.frp_fib_index,
274 dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
275 }
Neale Ranns81458422018-03-12 06:59:36 -0700276 }
277 }
278
279 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_DVR)
280 {
281 out->is_dvr = 1;
282 }
283 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
284 {
285 out->is_udp_encap = 1;
286 out->next_hop_id = api_rpath->rpath.frp_udp_encap_id;
287 }
Neale Ranns775f73c2018-12-20 03:01:49 -0800288 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_INTF_RX)
289 {
290 out->is_interface_rx = 1;
291 }
292 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_LOCAL)
293 {
294 out->is_local = 1;
295 }
296 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
297 {
298 out->is_resolve_host = 1;
299 }
300 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
301 {
302 out->is_resolve_attached = 1;
303 }
304 /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_ATTACHED) { */
305 /* out->is_attached = 1; */
306 /* } */
307 /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_CONNECTED) { */
308 /* out->is_connected = 1; */
309 /* } */
310 if (api_rpath->rpath.frp_label_stack)
311 {
312 for (ii = 0; ii < vec_len(api_rpath->rpath.frp_label_stack); ii++)
313 {
314 out->label_stack[ii].label =
315 htonl(api_rpath->rpath.frp_label_stack[ii].fml_value);
316 out->label_stack[ii].ttl =
317 api_rpath->rpath.frp_label_stack[ii].fml_ttl;
318 out->label_stack[ii].exp =
319 api_rpath->rpath.frp_label_stack[ii].fml_exp;
320 }
321 out->n_labels = ii;
322 }
Neale Ranns81458422018-03-12 06:59:36 -0700323}
Neale Ranns2303cb12018-02-21 04:57:17 -0800324
Neale Rannsd1e68ab2018-10-01 01:42:13 -0700325fib_protocol_t
326fib_proto_from_api_address_family (int af)
327{
328 switch (clib_net_to_host_u32 (af))
329 {
330 case ADDRESS_IP4:
331 return (FIB_PROTOCOL_IP4);
332 case ADDRESS_IP6:
333 return (FIB_PROTOCOL_IP6);
334 }
335
336 ASSERT(0);
337 return (FIB_PROTOCOL_IP4);
338}
339
340int
341fib_proto_to_api_address_family (fib_protocol_t fproto)
342{
343 switch (fproto)
344 {
345 case FIB_PROTOCOL_IP4:
346 return (clib_net_to_host_u32 (ADDRESS_IP4));
347 case FIB_PROTOCOL_IP6:
348 return (clib_net_to_host_u32 (ADDRESS_IP6));
349 default:
350 break;
351 }
352
353 ASSERT(0);
354 return (clib_net_to_host_u32 (ADDRESS_IP4));
355}