blob: e9a28658523b65725429b05c1a8611c99a2d0f18 [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>
20#include <vnet/bier/bier_disp_table.h>
21#include <vnet/dpo/ip_null_dpo.h>
22
23#include <vnet/vnet_msg_enum.h>
24
25#define vl_typedefs /* define message structures */
26#include <vnet/vnet_all_api_h.h>
27#undef vl_typedefs
28
29#define vl_endianfun /* define message structures */
30#include <vnet/vnet_all_api_h.h>
31#undef vl_endianfun
32
33/* instantiate all the print functions we know about */
34#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
35#define vl_printfun
36#include <vnet/vnet_all_api_h.h>
37#undef vl_printfun
38
39#include <vlibapi/api_helper_macros.h>
40
41int
42fib_path_api_parse (const vl_api_fib_path_t *in,
43 fib_route_path_t *out)
44{
45 fib_route_path_flags_t path_flags;
46 mpls_label_t next_hop_via_label;
47 int rv = 0, n_labels;
48 u8 ii;
49
50 path_flags = FIB_ROUTE_PATH_FLAG_NONE;
51 next_hop_via_label = ntohl (in->via_label);
52 memset(out, 0, sizeof(*out));
53 out->frp_sw_if_index = ~0;
54
55 out->frp_proto = in->afi;
56 // .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
57 out->frp_sw_if_index = ntohl(in->sw_if_index);
58 out->frp_fib_index = ntohl(in->table_id);
59 out->frp_weight = in->weight;
60 out->frp_preference = in->preference;
61
62 /*
63 * the special INVALID label meams we are not recursing via a
64 * label. Exp-null value is never a valid via-label so that
65 * also means it's not a via-label and means clients that set
66 * it to 0 by default get the expected behaviour
67 */
68 if ((MPLS_LABEL_INVALID != next_hop_via_label) &&
69 (0 != next_hop_via_label))
70 {
71 out->frp_proto = DPO_PROTO_MPLS;
72 out->frp_local_label = next_hop_via_label;
73 out->frp_eos = MPLS_NON_EOS;
74 }
75
76 n_labels = in->n_labels;
77 if (n_labels == 0)
78 ;
79 else
80 {
81 vec_validate (out->frp_label_stack, n_labels - 1);
82 for (ii = 0; ii < n_labels; ii++)
83 {
84 out->frp_label_stack[ii].fml_value =
85 ntohl(in->label_stack[ii].label);
86 out->frp_label_stack[ii].fml_ttl =
87 in->label_stack[ii].ttl;
88 out->frp_label_stack[ii].fml_exp =
89 in->label_stack[ii].exp;
90 out->frp_label_stack[ii].fml_mode =
91 (in->label_stack[ii].is_uniform ?
92 FIB_MPLS_LSP_MODE_UNIFORM :
93 FIB_MPLS_LSP_MODE_PIPE);
94 }
95 }
96
97 if (in->is_dvr)
98 path_flags |= FIB_ROUTE_PATH_DVR;
99 if (in->is_resolve_host)
100 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
101 if (in->is_resolve_attached)
102 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
103 /* if (in->is_interface_rx) */
104 /* path_flags |= FIB_ROUTE_PATH_INTF_RX; */
105 /* if (in->is_rpf_id) */
106 /* path_flags |= FIB_ROUTE_PATH_RPF_ID; */
107 if (in->is_source_lookup)
108 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
109
110 if (in->is_udp_encap)
111 {
112 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
113 out->frp_udp_encap_id = ntohl(in->next_hop_id);
114 }
115 else
116 {
117 if (DPO_PROTO_IP4 == in->afi)
118 {
119 clib_memcpy (&out->frp_addr.ip4,
120 in->next_hop,
121 sizeof (out->frp_addr.ip4));
122 }
123 else if (DPO_PROTO_IP6 == in->afi)
124 {
125 clib_memcpy (&out->frp_addr.ip6,
126 in->next_hop,
127 sizeof (out->frp_addr.ip6));
128 }
129
130 if (ip46_address_is_zero(&out->frp_addr))
131 {
132 if (DPO_PROTO_BIER == in->afi)
133 {
134 index_t bdti;
135
136 bdti = bier_disp_table_find(ntohl(in->table_id));
137
138 if (INDEX_INVALID != bdti)
139 {
140 out->frp_fib_index = bdti;
141 out->frp_proto = DPO_PROTO_BIER;
142 }
143 else
144 {
145 rv = VNET_API_ERROR_NO_SUCH_FIB;
146 }
147 }
148 else if (out->frp_sw_if_index == ~0 &&
149 out->frp_fib_index != ~0)
150 {
151 path_flags |= FIB_ROUTE_PATH_DEAG;
152 }
153 }
154 }
155
156 out->frp_flags = path_flags;
157
158 return (rv);
159}
160
161void
162fib_prefix_to_api (const fib_prefix_t *pfx,
163 u8 address[16],
164 u8 *length,
165 u8 *is_ip6)
166{
167 *length = pfx->fp_len;
168 *is_ip6 = (FIB_PROTOCOL_IP6 == pfx->fp_proto ? 1 : 0);
169
170 if (FIB_PROTOCOL_IP6 == pfx->fp_proto)
171 {
172 memcpy (address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
173 }
174 else
175 {
176 memcpy (address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
177 }
178}
179
180static void
181fib_api_path_copy_next_hop (const fib_route_path_encode_t * api_rpath, void *fp_arg)
182{
183 int is_ip4;
184 vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
185
186 if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
187 fp->afi = IP46_TYPE_IP4;
188 else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
189 fp->afi = IP46_TYPE_IP6;
190 else
191 {
192 is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
193 if (is_ip4)
194 fp->afi = IP46_TYPE_IP4;
195 else
196 fp->afi = IP46_TYPE_IP6;
197 }
198 if (fp->afi == IP46_TYPE_IP4)
199 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
200 sizeof (api_rpath->rpath.frp_addr.ip4));
201 else
202 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
203 sizeof (api_rpath->rpath.frp_addr.ip6));
204}
205
206void
207fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
208 vl_api_fib_path_t *out)
209{
210 memset (out, 0, sizeof (*out));
211 switch (api_rpath->dpo.dpoi_type)
212 {
213 case DPO_RECEIVE:
214 out->is_local = true;
215 break;
216 case DPO_DROP:
217 out->is_drop = true;
218 break;
219 case DPO_IP_NULL:
Dmitry Vakhrushevf38bef42018-03-16 20:26:32 +0300220 switch (ip_null_dpo_get_action(api_rpath->dpo.dpoi_index))
Neale Ranns81458422018-03-12 06:59:36 -0700221 {
222 case IP_NULL_ACTION_NONE:
223 out->is_drop = true;
224 break;
225 case IP_NULL_ACTION_SEND_ICMP_UNREACH:
226 out->is_unreach = true;
227 break;
228 case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
229 out->is_prohibit = true;
230 break;
231 default:
232 break;
233 }
234 break;
235 default:
236 break;
237 }
238 out->weight = api_rpath->rpath.frp_weight;
239 out->preference = api_rpath->rpath.frp_preference;
240 out->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
241 out->afi = api_rpath->rpath.frp_proto;
242 fib_api_path_copy_next_hop (api_rpath, out);
243
244 if (~0 == api_rpath->rpath.frp_sw_if_index &&
245 !ip46_address_is_zero(&api_rpath->rpath.frp_addr))
246 {
247 if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
Neale Ranns26600e62018-03-19 02:43:28 -0700248 (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto))
Neale Ranns81458422018-03-12 06:59:36 -0700249 {
250 fib_table_t *fib;
251
252 fib = fib_table_get (api_rpath->rpath.frp_fib_index,
253 dpo_proto_to_fib(api_rpath->rpath.frp_proto));
254
255 out->table_id = htonl (fib->ft_table_id);
256 }
257 }
258
259 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_DVR)
260 {
261 out->is_dvr = 1;
262 }
263 if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
264 {
265 out->is_udp_encap = 1;
266 out->next_hop_id = api_rpath->rpath.frp_udp_encap_id;
267 }
268}
Neale Ranns2303cb12018-02-21 04:57:17 -0800269