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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/vnet.h>
17 #include <vlibmemory/api.h>
18 #include <vnet/fib/fib_api.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/mfib/mfib_table.h>
21 #include <vnet/bier/bier_disp_table.h>
22 #include <vnet/dpo/ip_null_dpo.h>
24 #include <vnet/vnet_msg_enum.h>
26 #define vl_typedefs /* define message structures */
27 #include <vnet/vnet_all_api_h.h>
30 #define vl_endianfun /* define message structures */
31 #include <vnet/vnet_all_api_h.h>
34 /* instantiate all the print functions we know about */
35 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
37 #include <vnet/vnet_all_api_h.h>
40 #include <vlibapi/api_helper_macros.h>
43 fib_path_api_parse (const vl_api_fib_path_t *in,
44 fib_route_path_t *out)
46 fib_route_path_flags_t path_flags;
47 mpls_label_t next_hop_via_label;
51 path_flags = FIB_ROUTE_PATH_FLAG_NONE;
52 next_hop_via_label = ntohl (in->via_label);
53 clib_memset(out, 0, sizeof(*out));
54 out->frp_sw_if_index = ~0;
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);
59 out->frp_fib_index = ntohl(in->table_id);
60 out->frp_weight = in->weight;
61 out->frp_preference = in->preference;
64 * the special INVALID label meams we are not recursing via a
65 * label. Exp-null value is never a valid via-label so that
66 * also means it's not a via-label and means clients that set
67 * it to 0 by default get the expected behaviour
69 if ((MPLS_LABEL_INVALID != next_hop_via_label) &&
70 (0 != next_hop_via_label))
72 out->frp_proto = DPO_PROTO_MPLS;
73 out->frp_local_label = next_hop_via_label;
74 out->frp_eos = MPLS_NON_EOS;
77 n_labels = in->n_labels;
82 vec_validate (out->frp_label_stack, n_labels - 1);
83 for (ii = 0; ii < n_labels; ii++)
85 out->frp_label_stack[ii].fml_value =
86 ntohl(in->label_stack[ii].label);
87 out->frp_label_stack[ii].fml_ttl =
88 in->label_stack[ii].ttl;
89 out->frp_label_stack[ii].fml_exp =
90 in->label_stack[ii].exp;
91 out->frp_label_stack[ii].fml_mode =
92 (in->label_stack[ii].is_uniform ?
93 FIB_MPLS_LSP_MODE_UNIFORM :
94 FIB_MPLS_LSP_MODE_PIPE);
99 path_flags |= FIB_ROUTE_PATH_DVR;
100 if (in->is_resolve_host)
101 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
102 if (in->is_resolve_attached)
103 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
104 /* if (in->is_interface_rx) */
105 /* path_flags |= FIB_ROUTE_PATH_INTF_RX; */
106 /* if (in->is_rpf_id) */
107 /* path_flags |= FIB_ROUTE_PATH_RPF_ID; */
108 if (in->is_source_lookup)
109 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
111 if (in->is_udp_encap)
113 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
114 out->frp_udp_encap_id = ntohl(in->next_hop_id);
118 if (DPO_PROTO_IP4 == in->afi)
120 clib_memcpy (&out->frp_addr.ip4,
122 sizeof (out->frp_addr.ip4));
124 else if (DPO_PROTO_IP6 == in->afi)
126 clib_memcpy (&out->frp_addr.ip6,
128 sizeof (out->frp_addr.ip6));
131 if (ip46_address_is_zero(&out->frp_addr))
133 if (DPO_PROTO_BIER == in->afi)
137 bdti = bier_disp_table_find(ntohl(in->table_id));
139 if (INDEX_INVALID != bdti)
141 out->frp_fib_index = bdti;
142 out->frp_proto = DPO_PROTO_BIER;
146 rv = VNET_API_ERROR_NO_SUCH_FIB;
149 else if (out->frp_sw_if_index == ~0 &&
150 out->frp_fib_index != ~0)
152 path_flags |= FIB_ROUTE_PATH_DEAG;
157 out->frp_flags = path_flags;
163 fib_prefix_to_api (const fib_prefix_t *pfx,
168 *length = pfx->fp_len;
169 *is_ip6 = (FIB_PROTOCOL_IP6 == pfx->fp_proto ? 1 : 0);
171 if (FIB_PROTOCOL_IP6 == pfx->fp_proto)
173 memcpy (address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
177 memcpy (address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
182 fib_api_path_copy_next_hop (const fib_route_path_encode_t * api_rpath, void *fp_arg)
185 vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
187 if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
188 fp->afi = IP46_TYPE_IP4;
189 else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
190 fp->afi = IP46_TYPE_IP6;
193 is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
195 fp->afi = IP46_TYPE_IP4;
197 fp->afi = IP46_TYPE_IP6;
199 if (fp->afi == IP46_TYPE_IP4)
200 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
201 sizeof (api_rpath->rpath.frp_addr.ip4));
203 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
204 sizeof (api_rpath->rpath.frp_addr.ip6));
208 fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
209 vl_api_fib_path_t *out)
213 clib_memset (out, 0, sizeof (*out));
214 switch (api_rpath->dpo.dpoi_type)
217 out->is_local = true;
223 switch (ip_null_dpo_get_action(api_rpath->dpo.dpoi_index))
225 case IP_NULL_ACTION_NONE:
228 case IP_NULL_ACTION_SEND_ICMP_UNREACH:
229 out->is_unreach = true;
231 case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
232 out->is_prohibit = true;
241 out->weight = api_rpath->rpath.frp_weight;
242 out->preference = api_rpath->rpath.frp_preference;
243 out->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
244 out->afi = api_rpath->rpath.frp_proto;
245 fib_api_path_copy_next_hop (api_rpath, out);
247 if (0 != api_rpath->rpath.frp_fib_index)
249 if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
250 (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto))
252 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RPF_ID)
255 htonl(mfib_table_get_table_id(
256 api_rpath->rpath.frp_fib_index,
257 dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
262 htonl(fib_table_get_table_id(
263 api_rpath->rpath.frp_fib_index,
264 dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
269 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_DVR)
273 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
275 out->is_udp_encap = 1;
276 out->next_hop_id = api_rpath->rpath.frp_udp_encap_id;
278 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_INTF_RX)
280 out->is_interface_rx = 1;
282 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_LOCAL)
286 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
288 out->is_resolve_host = 1;
290 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
292 out->is_resolve_attached = 1;
294 /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_ATTACHED) { */
295 /* out->is_attached = 1; */
297 /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_CONNECTED) { */
298 /* out->is_connected = 1; */
300 if (api_rpath->rpath.frp_label_stack)
302 for (ii = 0; ii < vec_len(api_rpath->rpath.frp_label_stack); ii++)
304 out->label_stack[ii].label =
305 htonl(api_rpath->rpath.frp_label_stack[ii].fml_value);
306 out->label_stack[ii].ttl =
307 api_rpath->rpath.frp_label_stack[ii].fml_ttl;
308 out->label_stack[ii].exp =
309 api_rpath->rpath.frp_label_stack[ii].fml_exp;
316 fib_proto_from_api_address_family (int af)
318 switch (clib_net_to_host_u32 (af))
321 return (FIB_PROTOCOL_IP4);
323 return (FIB_PROTOCOL_IP6);
327 return (FIB_PROTOCOL_IP4);
331 fib_proto_to_api_address_family (fib_protocol_t fproto)
335 case FIB_PROTOCOL_IP4:
336 return (clib_net_to_host_u32 (ADDRESS_IP4));
337 case FIB_PROTOCOL_IP6:
338 return (clib_net_to_host_u32 (ADDRESS_IP6));
344 return (clib_net_to_host_u32 (ADDRESS_IP4));