Typos. A bunch of typos I've been collecting.
[vpp.git] / src / vnet / fib / fib_api.c
1 /*
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/mfib/mfib_table.h>
21 #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
42 int
43 fib_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);
53     clib_memset(out, 0, sizeof(*out));
54     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);
59     out->frp_weight = in->weight;
60     out->frp_preference = in->preference;
61
62     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
73     /*
74      * the special INVALID label means 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
172 void
173 fib_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
191 static void
192 fib_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
217 void
218 fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
219                      vl_api_fib_path_t *out)
220 {
221     int ii;
222
223     clib_memset (out, 0, sizeof (*out));
224     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:
233         switch (ip_null_dpo_get_action(api_rpath->dpo.dpoi_index))
234         {
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
257     if (0 != api_rpath->rpath.frp_fib_index)
258     {
259         if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
260             (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto))
261         {
262             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             }
276         }
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     }
288     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     }
323 }
324
325 fib_protocol_t
326 fib_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
340 int
341 fib_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 }