blob: 0676a38704f0403951ad1cb7346d56daa58d703a [file] [log] [blame]
Dave Barachb5e8a772016-12-06 12:04:42 -05001/*
2 *------------------------------------------------------------------
3 * ip_api.c - vnet ip api
4 *
5 * Copyright (c) 2016 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vnet/vnet.h>
21#include <vlibmemory/api.h>
22
23#include <vnet/interface.h>
24#include <vnet/api_errno.h>
25#include <vnet/ethernet/ethernet.h>
26#include <vnet/ip/ip.h>
27#include <vnet/ip/ip6_neighbor.h>
28#include <vnet/fib/fib_table.h>
29#include <vnet/fib/fib_api.h>
30#include <vnet/dpo/drop_dpo.h>
31#include <vnet/dpo/receive_dpo.h>
32#include <vnet/dpo/lookup_dpo.h>
33#include <vnet/dpo/classify_dpo.h>
34#include <vnet/dpo/ip_null_dpo.h>
35#include <vnet/ethernet/arp_packet.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080036#include <vnet/mfib/ip6_mfib.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000037#include <vnet/mfib/ip4_mfib.h>
38#include <vnet/mfib/mfib_signal.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080039#include <vnet/mfib/mfib_entry.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050040
41#include <vnet/vnet_msg_enum.h>
42
43#define vl_typedefs /* define message structures */
44#include <vnet/vnet_all_api_h.h>
45#undef vl_typedefs
46
47#define vl_endianfun /* define message structures */
48#include <vnet/vnet_all_api_h.h>
49#undef vl_endianfun
50
51/* instantiate all the print functions we know about */
52#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
53#define vl_printfun
54#include <vnet/vnet_all_api_h.h>
55#undef vl_printfun
56
57#include <vlibapi/api_helper_macros.h>
58
Neale Ranns5a8123b2017-01-26 01:18:23 -080059
Dave Barachb5e8a772016-12-06 12:04:42 -050060#define foreach_ip_api_msg \
61_(IP_FIB_DUMP, ip_fib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050062_(IP6_FIB_DUMP, ip6_fib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080063_(IP_MFIB_DUMP, ip_mfib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080064_(IP6_MFIB_DUMP, ip6_mfib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050065_(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \
Neale Ranns32e1c012016-11-22 17:07:28 +000066_(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080067_(MFIB_SIGNAL_DUMP, mfib_signal_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050068_(IP_ADDRESS_DUMP, ip_address_dump) \
69_(IP_DUMP, ip_dump) \
70_(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
71_(IP_ADD_DEL_ROUTE, ip_add_del_route) \
72_(SET_IP_FLOW_HASH,set_ip_flow_hash) \
73_(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
74_(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
Neale Ranns3f844d02017-02-18 00:03:54 -080075_(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del) \
76_(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050077_(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
78_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
79 sw_interface_ip6_set_link_local_address)
80
81extern void stats_dslock_with_hint (int hint, int tag);
82extern void stats_dsunlock (void);
83
84static void
85send_ip_neighbor_details (u8 is_ipv6,
86 u8 is_static,
87 u8 * mac_address,
88 u8 * ip_address,
89 unix_shared_memory_queue_t * q, u32 context)
90{
91 vl_api_ip_neighbor_details_t *mp;
92
93 mp = vl_msg_api_alloc (sizeof (*mp));
94 memset (mp, 0, sizeof (*mp));
95 mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS);
96 mp->context = context;
97 mp->is_ipv6 = is_ipv6;
98 mp->is_static = is_static;
99 memcpy (mp->mac_address, mac_address, 6);
100 memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4);
101
102 vl_msg_api_send_shmem (q, (u8 *) & mp);
103}
104
105static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500106vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
107{
108 unix_shared_memory_queue_t *q;
109
110 q = vl_api_client_index_to_input_queue (mp->client_index);
111 if (q == 0)
112 return;
113
114 u32 sw_if_index = ntohl (mp->sw_if_index);
115
116 if (mp->is_ipv6)
117 {
118 ip6_neighbor_t *n, *ns;
119
120 ns = ip6_neighbors_entries (sw_if_index);
121 /* *INDENT-OFF* */
122 vec_foreach (n, ns)
123 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500124 send_ip_neighbor_details
125 (mp->is_ipv6, ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0),
126 (u8 *) n->link_layer_address,
127 (u8 *) & (n->key.ip6_address.as_u8),
128 q, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500129 }
130 /* *INDENT-ON* */
131 vec_free (ns);
132 }
133 else
134 {
135 ethernet_arp_ip4_entry_t *n, *ns;
136
137 ns = ip4_neighbor_entries (sw_if_index);
138 /* *INDENT-OFF* */
139 vec_foreach (n, ns)
140 {
141 send_ip_neighbor_details (mp->is_ipv6,
142 ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0),
143 (u8*) n->ethernet_address,
144 (u8*) & (n->ip4_address.as_u8),
145 q, mp->context);
146 }
147 /* *INDENT-ON* */
148 vec_free (ns);
149 }
150}
151
152
153void
154copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg)
155{
156 int is_ip4;
157 vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
158
Neale Rannsda78f952017-05-24 09:15:43 -0700159 if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
Dave Barachb5e8a772016-12-06 12:04:42 -0500160 fp->afi = IP46_TYPE_IP4;
Neale Rannsda78f952017-05-24 09:15:43 -0700161 else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
Dave Barachb5e8a772016-12-06 12:04:42 -0500162 fp->afi = IP46_TYPE_IP6;
163 else
164 {
165 is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
166 if (is_ip4)
167 fp->afi = IP46_TYPE_IP4;
168 else
169 fp->afi = IP46_TYPE_IP6;
170 }
171 if (fp->afi == IP46_TYPE_IP4)
172 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
173 sizeof (api_rpath->rpath.frp_addr.ip4));
174 else
175 memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
176 sizeof (api_rpath->rpath.frp_addr.ip6));
177}
178
179static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500180send_ip_fib_details (vpe_api_main_t * am,
181 unix_shared_memory_queue_t * q,
182 u32 table_id, fib_prefix_t * pfx,
183 fib_route_path_encode_t * api_rpaths, u32 context)
184{
185 vl_api_ip_fib_details_t *mp;
186 fib_route_path_encode_t *api_rpath;
187 vl_api_fib_path_t *fp;
188 int path_count;
189
190 path_count = vec_len (api_rpaths);
191 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
192 if (!mp)
193 return;
194 memset (mp, 0, sizeof (*mp));
195 mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
196 mp->context = context;
197
198 mp->table_id = htonl (table_id);
199 mp->address_length = pfx->fp_len;
200 memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
201
202 mp->count = htonl (path_count);
203 fp = mp->path;
204 vec_foreach (api_rpath, api_rpaths)
205 {
206 memset (fp, 0, sizeof (*fp));
207 switch (api_rpath->dpo.dpoi_type)
208 {
209 case DPO_RECEIVE:
210 fp->is_local = true;
211 break;
212 case DPO_DROP:
213 fp->is_drop = true;
214 break;
215 case DPO_IP_NULL:
216 switch (api_rpath->dpo.dpoi_index)
217 {
218 case IP_NULL_ACTION_NONE:
219 fp->is_drop = true;
220 break;
221 case IP_NULL_ACTION_SEND_ICMP_UNREACH:
222 fp->is_unreach = true;
223 break;
224 case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
225 fp->is_prohibit = true;
226 break;
227 default:
228 break;
229 }
230 break;
231 default:
232 break;
233 }
Neale Rannsa0a908f2017-08-01 11:40:03 -0700234 fp->weight = api_rpath->rpath.frp_weight;
235 fp->preference = api_rpath->rpath.frp_preference;
Dave Barachb5e8a772016-12-06 12:04:42 -0500236 fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
237 copy_fib_next_hop (api_rpath, fp);
238 fp++;
239 }
240
241 vl_msg_api_send_shmem (q, (u8 *) & mp);
242}
243
Neale Rannsa3af3372017-03-28 03:49:52 -0700244typedef struct vl_api_ip_fib_dump_walk_ctx_t_
245{
246 fib_node_index_t *feis;
247} vl_api_ip_fib_dump_walk_ctx_t;
248
249static int
250vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
251{
252 vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
253
254 vec_add1 (ctx->feis, fei);
255
256 return (1);
257}
258
Dave Barachb5e8a772016-12-06 12:04:42 -0500259static void
260vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
261{
262 vpe_api_main_t *am = &vpe_api_main;
263 unix_shared_memory_queue_t *q;
264 ip4_main_t *im = &ip4_main;
265 fib_table_t *fib_table;
Neale Rannsa3af3372017-03-28 03:49:52 -0700266 fib_node_index_t *lfeip;
Dave Barachb5e8a772016-12-06 12:04:42 -0500267 fib_prefix_t pfx;
268 u32 fib_index;
269 fib_route_path_encode_t *api_rpaths;
Neale Rannsa3af3372017-03-28 03:49:52 -0700270 vl_api_ip_fib_dump_walk_ctx_t ctx = {
271 .feis = NULL,
272 };
Dave Barachb5e8a772016-12-06 12:04:42 -0500273
274 q = vl_api_client_index_to_input_queue (mp->client_index);
275 if (q == 0)
276 return;
277
278 /* *INDENT-OFF* */
279 pool_foreach (fib_table, im->fibs,
280 ({
Neale Rannsa3af3372017-03-28 03:49:52 -0700281 fib_table_walk(fib_table->ft_index,
282 FIB_PROTOCOL_IP4,
283 vl_api_ip_fib_dump_walk,
284 &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500285 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500286 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500287
Neale Rannsa3af3372017-03-28 03:49:52 -0700288 vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500289
Neale Rannsa3af3372017-03-28 03:49:52 -0700290 vec_foreach (lfeip, ctx.feis)
Dave Barachb5e8a772016-12-06 12:04:42 -0500291 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500292 fib_entry_get_prefix (*lfeip, &pfx);
293 fib_index = fib_entry_get_fib_index (*lfeip);
294 fib_table = fib_table_get (fib_index, pfx.fp_proto);
Dave Barachb5e8a772016-12-06 12:04:42 -0500295 api_rpaths = NULL;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500296 fib_entry_encode (*lfeip, &api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500297 send_ip_fib_details (am, q,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500298 fib_table->ft_table_id, &pfx, api_rpaths,
299 mp->context);
300 vec_free (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500301 }
302
Neale Rannsa3af3372017-03-28 03:49:52 -0700303 vec_free (ctx.feis);
Dave Barachb5e8a772016-12-06 12:04:42 -0500304}
305
306static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500307send_ip6_fib_details (vpe_api_main_t * am,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500308 unix_shared_memory_queue_t * q,
309 u32 table_id, fib_prefix_t * pfx,
310 fib_route_path_encode_t * api_rpaths, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500311{
312 vl_api_ip6_fib_details_t *mp;
313 fib_route_path_encode_t *api_rpath;
314 vl_api_fib_path_t *fp;
315 int path_count;
316
Dave Barachd7cb1b52016-12-09 09:52:16 -0500317 path_count = vec_len (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500318 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
319 if (!mp)
320 return;
321 memset (mp, 0, sizeof (*mp));
322 mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
323 mp->context = context;
324
325 mp->table_id = htonl (table_id);
326 mp->address_length = pfx->fp_len;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500327 memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
Dave Barachb5e8a772016-12-06 12:04:42 -0500328
329 mp->count = htonl (path_count);
330 fp = mp->path;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500331 vec_foreach (api_rpath, api_rpaths)
Dave Barachb5e8a772016-12-06 12:04:42 -0500332 {
333 memset (fp, 0, sizeof (*fp));
334 switch (api_rpath->dpo.dpoi_type)
335 {
336 case DPO_RECEIVE:
337 fp->is_local = true;
338 break;
339 case DPO_DROP:
340 fp->is_drop = true;
341 break;
342 case DPO_IP_NULL:
343 switch (api_rpath->dpo.dpoi_index)
344 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500345 case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_NONE:
Dave Barachb5e8a772016-12-06 12:04:42 -0500346 fp->is_drop = true;
347 break;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500348 case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_UNREACH:
Dave Barachb5e8a772016-12-06 12:04:42 -0500349 fp->is_unreach = true;
350 break;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500351 case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
Dave Barachb5e8a772016-12-06 12:04:42 -0500352 fp->is_prohibit = true;
353 break;
354 default:
355 break;
356 }
357 break;
358 default:
359 break;
360 }
Neale Rannsa0a908f2017-08-01 11:40:03 -0700361 fp->weight = api_rpath->rpath.frp_weight;
362 fp->preference = api_rpath->rpath.frp_preference;
363 fp->sw_if_index = api_rpath->rpath.frp_sw_if_index;
Dave Barachb5e8a772016-12-06 12:04:42 -0500364 copy_fib_next_hop (api_rpath, fp);
365 fp++;
366 }
367
368 vl_msg_api_send_shmem (q, (u8 *) & mp);
369}
370
Dave Barachd7cb1b52016-12-09 09:52:16 -0500371typedef struct apt_ip6_fib_show_ctx_t_
372{
373 u32 fib_index;
374 fib_node_index_t *entries;
Dave Barachb5e8a772016-12-06 12:04:42 -0500375} api_ip6_fib_show_ctx_t;
376
377static void
Dave Barachd7cb1b52016-12-09 09:52:16 -0500378api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500379{
380 api_ip6_fib_show_ctx_t *ctx = arg;
381
382 if ((kvp->key[2] >> 32) == ctx->fib_index)
383 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500384 vec_add1 (ctx->entries, kvp->value);
Dave Barachb5e8a772016-12-06 12:04:42 -0500385 }
386}
387
388static void
Dave Barachd7cb1b52016-12-09 09:52:16 -0500389api_ip6_fib_table_get_all (unix_shared_memory_queue_t * q,
390 vl_api_ip6_fib_dump_t * mp,
391 fib_table_t * fib_table)
Dave Barachb5e8a772016-12-06 12:04:42 -0500392{
393 vpe_api_main_t *am = &vpe_api_main;
394 ip6_main_t *im6 = &ip6_main;
Dave Barachb5e8a772016-12-06 12:04:42 -0500395 fib_node_index_t *fib_entry_index;
396 api_ip6_fib_show_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700397 .fib_index = fib_table->ft_index,
398 .entries = NULL,
Dave Barachb5e8a772016-12-06 12:04:42 -0500399 };
400 fib_route_path_encode_t *api_rpaths;
401 fib_prefix_t pfx;
402
Dave Barachd7cb1b52016-12-09 09:52:16 -0500403 BV (clib_bihash_foreach_key_value_pair)
404 ((BVT (clib_bihash) *) & im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].
405 ip6_hash, api_ip6_fib_table_put_entries, &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500406
Dave Barachd7cb1b52016-12-09 09:52:16 -0500407 vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500408
Dave Barachd7cb1b52016-12-09 09:52:16 -0500409 vec_foreach (fib_entry_index, ctx.entries)
410 {
411 fib_entry_get_prefix (*fib_entry_index, &pfx);
412 api_rpaths = NULL;
413 fib_entry_encode (*fib_entry_index, &api_rpaths);
414 send_ip6_fib_details (am, q,
415 fib_table->ft_table_id,
416 &pfx, api_rpaths, mp->context);
417 vec_free (api_rpaths);
418 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500419
Dave Barachd7cb1b52016-12-09 09:52:16 -0500420 vec_free (ctx.entries);
Dave Barachb5e8a772016-12-06 12:04:42 -0500421}
422
423static void
424vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
425{
426 unix_shared_memory_queue_t *q;
427 ip6_main_t *im6 = &ip6_main;
428 fib_table_t *fib_table;
429
430 q = vl_api_client_index_to_input_queue (mp->client_index);
431 if (q == 0)
432 return;
433
434 /* *INDENT-OFF* */
435 pool_foreach (fib_table, im6->fibs,
436 ({
437 api_ip6_fib_table_get_all(q, mp, fib_table);
438 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500439 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500440}
441
442static void
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800443send_ip_mfib_details (unix_shared_memory_queue_t * q,
444 u32 context, u32 table_id, fib_node_index_t mfei)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800445{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800446 fib_route_path_encode_t *api_rpath, *api_rpaths = NULL;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800447 vl_api_ip_mfib_details_t *mp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800448 mfib_entry_t *mfib_entry;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800449 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800450 mfib_prefix_t pfx;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800451 int path_count;
452
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800453 mfib_entry = mfib_entry_get (mfei);
454 mfib_entry_get_prefix (mfei, &pfx);
455 mfib_entry_encode (mfei, &api_rpaths);
456
Neale Ranns5a8123b2017-01-26 01:18:23 -0800457 path_count = vec_len (api_rpaths);
458 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
459 if (!mp)
460 return;
461 memset (mp, 0, sizeof (*mp));
462 mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
463 mp->context = context;
464
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800465 mp->rpf_id = mfib_entry->mfe_rpf_id;
466 mp->entry_flags = mfib_entry->mfe_flags;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800467 mp->table_id = htonl (table_id);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800468 mp->address_length = pfx.fp_len;
469 memcpy (mp->grp_address, &pfx.fp_grp_addr.ip4,
470 sizeof (pfx.fp_grp_addr.ip4));
471 memcpy (mp->src_address, &pfx.fp_src_addr.ip4,
472 sizeof (pfx.fp_src_addr.ip4));
Neale Ranns5a8123b2017-01-26 01:18:23 -0800473
474 mp->count = htonl (path_count);
475 fp = mp->path;
476 vec_foreach (api_rpath, api_rpaths)
477 {
478 memset (fp, 0, sizeof (*fp));
479
480 fp->weight = 0;
481 fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
482 copy_fib_next_hop (api_rpath, fp);
483 fp++;
484 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800485 vec_free (api_rpaths);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800486
487 vl_msg_api_send_shmem (q, (u8 *) & mp);
488}
489
490typedef struct vl_api_ip_mfib_dump_ctc_t_
491{
492 fib_node_index_t *entries;
493} vl_api_ip_mfib_dump_ctc_t;
494
495static int
496vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
497{
498 vl_api_ip_mfib_dump_ctc_t *ctx = arg;
499
500 vec_add1 (ctx->entries, fei);
501
502 return (0);
503}
504
505static void
506vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
507{
Neale Ranns5a8123b2017-01-26 01:18:23 -0800508 unix_shared_memory_queue_t *q;
509 ip4_main_t *im = &ip4_main;
510 mfib_table_t *mfib_table;
511 fib_node_index_t *mfeip;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800512 vl_api_ip_mfib_dump_ctc_t ctx = {
513 .entries = NULL,
514 };
515
516 q = vl_api_client_index_to_input_queue (mp->client_index);
517 if (q == 0)
518 return;
519
520
521 /* *INDENT-OFF* */
522 pool_foreach (mfib_table, im->mfibs,
523 ({
524 ip4_mfib_table_walk(&mfib_table->v4,
525 vl_api_ip_mfib_table_dump_walk,
526 &ctx);
527
528 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
529
530 vec_foreach (mfeip, ctx.entries)
531 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800532 send_ip_mfib_details (q, mp->context,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800533 mfib_table->mft_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800534 *mfeip);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800535 }
Neale Ranns5a8123b2017-01-26 01:18:23 -0800536 vec_reset_length (ctx.entries);
537
538 }));
539 /* *INDENT-ON* */
540
541 vec_free (ctx.entries);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800542}
543
544static void
Neale Ranns5a8123b2017-01-26 01:18:23 -0800545send_ip6_mfib_details (vpe_api_main_t * am,
546 unix_shared_memory_queue_t * q,
547 u32 table_id,
548 mfib_prefix_t * pfx,
549 fib_route_path_encode_t * api_rpaths, u32 context)
550{
551 vl_api_ip6_mfib_details_t *mp;
552 fib_route_path_encode_t *api_rpath;
553 vl_api_fib_path_t *fp;
554 int path_count;
555
556 path_count = vec_len (api_rpaths);
557 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
558 if (!mp)
559 return;
560 memset (mp, 0, sizeof (*mp));
561 mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
562 mp->context = context;
563
564 mp->table_id = htonl (table_id);
565 mp->address_length = pfx->fp_len;
566 memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6,
567 sizeof (pfx->fp_grp_addr.ip6));
568 memcpy (mp->src_address, &pfx->fp_src_addr.ip6,
569 sizeof (pfx->fp_src_addr.ip6));
570
571 mp->count = htonl (path_count);
572 fp = mp->path;
573 vec_foreach (api_rpath, api_rpaths)
574 {
575 memset (fp, 0, sizeof (*fp));
576
577 fp->weight = 0;
578 fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
579 copy_fib_next_hop (api_rpath, fp);
580 fp++;
581 }
582
583 vl_msg_api_send_shmem (q, (u8 *) & mp);
584}
585
586typedef struct vl_api_ip6_mfib_dump_ctc_t_
587{
588 fib_node_index_t *entries;
589} vl_api_ip6_mfib_dump_ctc_t;
590
591static int
592vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
593{
594 vl_api_ip6_mfib_dump_ctc_t *ctx = arg;
595
596 vec_add1 (ctx->entries, fei);
597
598 return (0);
599}
600
601static void
602vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
603{
604 vpe_api_main_t *am = &vpe_api_main;
605 unix_shared_memory_queue_t *q;
606 ip6_main_t *im = &ip6_main;
607 mfib_table_t *mfib_table;
608 fib_node_index_t *mfeip;
609 mfib_prefix_t pfx;
610 fib_route_path_encode_t *api_rpaths = NULL;
611 vl_api_ip6_mfib_dump_ctc_t ctx = {
612 .entries = NULL,
613 };
614
615 q = vl_api_client_index_to_input_queue (mp->client_index);
616 if (q == 0)
617 return;
618
619
620 /* *INDENT-OFF* */
621 pool_foreach (mfib_table, im->mfibs,
622 ({
623 ip6_mfib_table_walk(&mfib_table->v6,
624 vl_api_ip6_mfib_table_dump_walk,
625 &ctx);
626
627 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
628
629 vec_foreach(mfeip, ctx.entries)
630 {
631 mfib_entry_get_prefix (*mfeip, &pfx);
632 mfib_entry_encode (*mfeip, &api_rpaths);
633 send_ip6_mfib_details (am, q,
634 mfib_table->mft_table_id,
635 &pfx, api_rpaths,
636 mp->context);
637 }
638 vec_reset_length (api_rpaths);
639 vec_reset_length (ctx.entries);
640
641 }));
642 /* *INDENT-ON* */
643
644 vec_free (ctx.entries);
645 vec_free (api_rpaths);
646}
647
648static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500649vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
650 vlib_main_t * vm)
651{
652 vl_api_ip_neighbor_add_del_reply_t *rmp;
653 vnet_main_t *vnm = vnet_get_main ();
654 int rv = 0;
655
656 VALIDATE_SW_IF_INDEX (mp);
657
658 stats_dslock_with_hint (1 /* release hint */ , 7 /* tag */ );
659
660 /*
661 * there's no validation here of the ND/ARP entry being added.
662 * The expectation is that the FIB will ensure that nothing bad
663 * will come of adding bogus entries.
664 */
665 if (mp->is_ipv6)
666 {
667 if (mp->is_add)
668 rv = vnet_set_ip6_ethernet_neighbor
669 (vm, ntohl (mp->sw_if_index),
670 (ip6_address_t *) (mp->dst_address),
Neale Rannsb3b2de72017-03-08 05:17:22 -0800671 mp->mac_address, sizeof (mp->mac_address), mp->is_static,
672 mp->is_no_adj_fib);
Dave Barachb5e8a772016-12-06 12:04:42 -0500673 else
674 rv = vnet_unset_ip6_ethernet_neighbor
675 (vm, ntohl (mp->sw_if_index),
676 (ip6_address_t *) (mp->dst_address),
677 mp->mac_address, sizeof (mp->mac_address));
678 }
679 else
680 {
681 ethernet_arp_ip4_over_ethernet_address_t a;
682
683 clib_memcpy (&a.ethernet, mp->mac_address, 6);
684 clib_memcpy (&a.ip4, mp->dst_address, 4);
685
686 if (mp->is_add)
687 rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
Neale Rannsb3b2de72017-03-08 05:17:22 -0800688 &a, mp->is_static,
689 mp->is_no_adj_fib);
Dave Barachb5e8a772016-12-06 12:04:42 -0500690 else
691 rv =
692 vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a);
693 }
694
695 BAD_SW_IF_INDEX_LABEL;
696
697 stats_dsunlock ();
698 REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
699}
700
701int
702add_del_route_t_handler (u8 is_multipath,
703 u8 is_add,
704 u8 is_drop,
705 u8 is_unreach,
706 u8 is_prohibit,
707 u8 is_local,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800708 u8 is_multicast,
Dave Barachb5e8a772016-12-06 12:04:42 -0500709 u8 is_classify,
710 u32 classify_table_index,
711 u8 is_resolve_host,
712 u8 is_resolve_attached,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800713 u8 is_interface_rx,
714 u8 is_rpf_id,
Dave Barachb5e8a772016-12-06 12:04:42 -0500715 u32 fib_index,
716 const fib_prefix_t * prefix,
Neale Rannsda78f952017-05-24 09:15:43 -0700717 dpo_proto_t next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500718 const ip46_address_t * next_hop,
719 u32 next_hop_sw_if_index,
720 u8 next_hop_fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -0700721 u16 next_hop_weight,
722 u16 next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500723 mpls_label_t next_hop_via_label,
724 mpls_label_t * next_hop_out_label_stack)
725{
726 vnet_classify_main_t *cm = &vnet_classify_main;
727 fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
728 fib_route_path_t path = {
Neale Rannsda78f952017-05-24 09:15:43 -0700729 .frp_proto = next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500730 .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
731 .frp_sw_if_index = next_hop_sw_if_index,
732 .frp_fib_index = next_hop_fib_index,
733 .frp_weight = next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -0700734 .frp_preference = next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500735 .frp_label_stack = next_hop_out_label_stack,
736 };
737 fib_route_path_t *paths = NULL;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800738 fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
Dave Barachb5e8a772016-12-06 12:04:42 -0500739
740 if (MPLS_LABEL_INVALID != next_hop_via_label)
741 {
Neale Rannsda78f952017-05-24 09:15:43 -0700742 path.frp_proto = DPO_PROTO_MPLS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500743 path.frp_local_label = next_hop_via_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800744 path.frp_eos = MPLS_NON_EOS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500745 }
746 if (is_resolve_host)
747 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
748 if (is_resolve_attached)
749 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800750 if (is_interface_rx)
751 path_flags |= FIB_ROUTE_PATH_INTF_RX;
752 if (is_rpf_id)
753 path_flags |= FIB_ROUTE_PATH_RPF_ID;
754 if (is_multicast)
755 entry_flags |= FIB_ENTRY_FLAG_MULTICAST;
Dave Barachb5e8a772016-12-06 12:04:42 -0500756
757 path.frp_flags = path_flags;
758
759 if (is_multipath)
760 {
761 stats_dslock_with_hint (1 /* release hint */ , 10 /* tag */ );
762
763
764 vec_add1 (paths, path);
765
766 if (is_add)
767 fib_table_entry_path_add2 (fib_index,
768 prefix,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800769 FIB_SOURCE_API, entry_flags, paths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500770 else
771 fib_table_entry_path_remove2 (fib_index,
772 prefix, FIB_SOURCE_API, paths);
773
774 vec_free (paths);
775 stats_dsunlock ();
776 return 0;
777 }
778
779 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
780
781 if (is_drop || is_local || is_classify || is_unreach || is_prohibit)
782 {
783 /*
784 * special route types that link directly to the adj
785 */
786 if (is_add)
787 {
788 dpo_id_t dpo = DPO_INVALID;
789 dpo_proto_t dproto;
790
791 dproto = fib_proto_to_dpo (prefix->fp_proto);
792
793 if (is_drop)
794 ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
795 else if (is_local)
796 receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
797 else if (is_unreach)
798 ip_null_dpo_add_and_lock (dproto,
799 IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
800 else if (is_prohibit)
801 ip_null_dpo_add_and_lock (dproto,
802 IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
803 &dpo);
804 else if (is_classify)
805 {
806 if (pool_is_free_index (cm->tables,
807 ntohl (classify_table_index)))
808 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500809 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500810 return VNET_API_ERROR_NO_SUCH_TABLE;
811 }
812
813 dpo_set (&dpo, DPO_CLASSIFY, dproto,
814 classify_dpo_create (dproto,
815 ntohl (classify_table_index)));
816 }
817 else
818 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500819 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500820 return VNET_API_ERROR_NO_SUCH_TABLE;
821 }
822
823 fib_table_entry_special_dpo_update (fib_index,
824 prefix,
825 FIB_SOURCE_API,
826 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
827 dpo_reset (&dpo);
828 }
829 else
830 {
831 fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
832 }
833 }
834 else
835 {
836 if (is_add)
837 {
838 vec_add1 (paths, path);
839 fib_table_entry_update (fib_index,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800840 prefix, FIB_SOURCE_API, entry_flags, paths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500841 vec_free (paths);
842 }
843 else
844 {
845 fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
846 }
847 }
848
Dave Barachd7cb1b52016-12-09 09:52:16 -0500849 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500850 return (0);
851}
852
853int
854add_del_route_check (fib_protocol_t table_proto,
855 u32 table_id,
856 u32 next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700857 dpo_proto_t next_hop_table_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500858 u32 next_hop_table_id,
859 u8 create_missing_tables,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800860 u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500861{
862 vnet_main_t *vnm = vnet_get_main ();
863
864 *fib_index = fib_table_find (table_proto, ntohl (table_id));
865 if (~0 == *fib_index)
866 {
867 if (create_missing_tables)
868 {
869 *fib_index = fib_table_find_or_create_and_lock (table_proto,
870 ntohl (table_id));
871 }
872 else
873 {
874 /* No such VRF, and we weren't asked to create one */
875 return VNET_API_ERROR_NO_SUCH_FIB;
876 }
877 }
878
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800879 if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index))
Dave Barachb5e8a772016-12-06 12:04:42 -0500880 {
881 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
882 ntohl (next_hop_sw_if_index)))
883 {
884 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
885 }
886 }
887 else
888 {
Neale Rannsda78f952017-05-24 09:15:43 -0700889 fib_protocol_t fib_nh_proto;
890
891 if (next_hop_table_proto > DPO_PROTO_MPLS)
892 return (0);
893
894 fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto);
895
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800896 if (is_rpf_id)
Neale Rannsda78f952017-05-24 09:15:43 -0700897 *next_hop_fib_index = mfib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800898 ntohl (next_hop_table_id));
899 else
Neale Rannsda78f952017-05-24 09:15:43 -0700900 *next_hop_fib_index = fib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800901 ntohl (next_hop_table_id));
Dave Barachb5e8a772016-12-06 12:04:42 -0500902
903 if (~0 == *next_hop_fib_index)
904 {
905 if (create_missing_tables)
906 {
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800907 if (is_rpf_id)
908 *next_hop_fib_index =
Neale Rannsda78f952017-05-24 09:15:43 -0700909 mfib_table_find_or_create_and_lock (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800910 ntohl
911 (next_hop_table_id));
912 else
913 *next_hop_fib_index =
Neale Rannsda78f952017-05-24 09:15:43 -0700914 fib_table_find_or_create_and_lock (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800915 ntohl
916 (next_hop_table_id));
Dave Barachb5e8a772016-12-06 12:04:42 -0500917 }
918 else
919 {
920 /* No such VRF, and we weren't asked to create one */
921 return VNET_API_ERROR_NO_SUCH_FIB;
922 }
923 }
924 }
925
926 return (0);
927}
928
929static int
930ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
931{
932 u32 fib_index, next_hop_fib_index;
933 mpls_label_t *label_stack = NULL;
934 int rv, ii, n_labels;;
935
936 rv = add_del_route_check (FIB_PROTOCOL_IP4,
937 mp->table_id,
938 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700939 DPO_PROTO_IP4,
Dave Barachb5e8a772016-12-06 12:04:42 -0500940 mp->next_hop_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800941 mp->create_vrf_if_needed, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -0500942 &fib_index, &next_hop_fib_index);
943
944 if (0 != rv)
945 return (rv);
946
947 fib_prefix_t pfx = {
948 .fp_len = mp->dst_address_length,
949 .fp_proto = FIB_PROTOCOL_IP4,
950 };
951 clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
952
953 ip46_address_t nh;
954 memset (&nh, 0, sizeof (nh));
955 memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
956
957 n_labels = mp->next_hop_n_out_labels;
958 if (n_labels == 0)
959 ;
960 else if (1 == n_labels)
961 vec_add1 (label_stack, ntohl (mp->next_hop_out_label_stack[0]));
962 else
963 {
964 vec_validate (label_stack, n_labels - 1);
965 for (ii = 0; ii < n_labels; ii++)
966 label_stack[ii] = ntohl (mp->next_hop_out_label_stack[ii]);
967 }
968
969 return (add_del_route_t_handler (mp->is_multipath,
970 mp->is_add,
971 mp->is_drop,
972 mp->is_unreach,
973 mp->is_prohibit,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800974 mp->is_local, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -0500975 mp->is_classify,
976 mp->classify_table_index,
977 mp->is_resolve_host,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800978 mp->is_resolve_attached, 0, 0,
Neale Rannsda78f952017-05-24 09:15:43 -0700979 fib_index, &pfx, DPO_PROTO_IP4,
Dave Barachb5e8a772016-12-06 12:04:42 -0500980 &nh,
981 ntohl (mp->next_hop_sw_if_index),
982 next_hop_fib_index,
983 mp->next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -0700984 mp->next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500985 ntohl (mp->next_hop_via_label),
986 label_stack));
987}
988
989static int
990ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
991{
992 u32 fib_index, next_hop_fib_index;
993 mpls_label_t *label_stack = NULL;
994 int rv, ii, n_labels;;
995
996 rv = add_del_route_check (FIB_PROTOCOL_IP6,
997 mp->table_id,
998 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700999 DPO_PROTO_IP6,
Dave Barachb5e8a772016-12-06 12:04:42 -05001000 mp->next_hop_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001001 mp->create_vrf_if_needed, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001002 &fib_index, &next_hop_fib_index);
1003
1004 if (0 != rv)
1005 return (rv);
1006
1007 fib_prefix_t pfx = {
1008 .fp_len = mp->dst_address_length,
1009 .fp_proto = FIB_PROTOCOL_IP6,
1010 };
1011 clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
1012
1013 ip46_address_t nh;
1014 memset (&nh, 0, sizeof (nh));
1015 memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
1016
1017 n_labels = mp->next_hop_n_out_labels;
1018 if (n_labels == 0)
1019 ;
1020 else if (1 == n_labels)
1021 vec_add1 (label_stack, ntohl (mp->next_hop_out_label_stack[0]));
1022 else
1023 {
1024 vec_validate (label_stack, n_labels - 1);
1025 for (ii = 0; ii < n_labels; ii++)
1026 label_stack[ii] = ntohl (mp->next_hop_out_label_stack[ii]);
1027 }
1028
1029 return (add_del_route_t_handler (mp->is_multipath,
1030 mp->is_add,
1031 mp->is_drop,
1032 mp->is_unreach,
1033 mp->is_prohibit,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001034 mp->is_local, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001035 mp->is_classify,
1036 mp->classify_table_index,
1037 mp->is_resolve_host,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001038 mp->is_resolve_attached, 0, 0,
Neale Rannsda78f952017-05-24 09:15:43 -07001039 fib_index, &pfx, DPO_PROTO_IP6,
Dave Barachb5e8a772016-12-06 12:04:42 -05001040 &nh, ntohl (mp->next_hop_sw_if_index),
1041 next_hop_fib_index,
1042 mp->next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -07001043 mp->next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -05001044 ntohl (mp->next_hop_via_label),
1045 label_stack));
1046}
1047
1048void
1049vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1050{
1051 vl_api_ip_add_del_route_reply_t *rmp;
1052 int rv;
1053 vnet_main_t *vnm = vnet_get_main ();
1054
1055 vnm->api_errno = 0;
1056
1057 if (mp->is_ipv6)
1058 rv = ip6_add_del_route_t_handler (mp);
1059 else
1060 rv = ip4_add_del_route_t_handler (mp);
1061
1062 rv = (rv == 0) ? vnm->api_errno : rv;
1063
1064 REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
1065}
1066
Neale Ranns32e1c012016-11-22 17:07:28 +00001067static int
1068add_del_mroute_check (fib_protocol_t table_proto,
1069 u32 table_id,
1070 u32 next_hop_sw_if_index,
1071 u8 is_local, u8 create_missing_tables, u32 * fib_index)
1072{
1073 vnet_main_t *vnm = vnet_get_main ();
1074
1075 *fib_index = mfib_table_find (table_proto, ntohl (table_id));
1076 if (~0 == *fib_index)
1077 {
1078 if (create_missing_tables)
1079 {
1080 *fib_index = mfib_table_find_or_create_and_lock (table_proto,
1081 ntohl (table_id));
1082 }
1083 else
1084 {
1085 /* No such VRF, and we weren't asked to create one */
1086 return VNET_API_ERROR_NO_SUCH_FIB;
1087 }
1088 }
1089
1090 if (~0 != ntohl (next_hop_sw_if_index))
1091 {
1092 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1093 ntohl (next_hop_sw_if_index)))
1094 {
1095 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1096 }
1097 }
1098
1099 return (0);
1100}
1101
1102static int
1103mroute_add_del_handler (u8 is_add,
1104 u8 is_local,
1105 u32 fib_index,
1106 const mfib_prefix_t * prefix,
1107 u32 entry_flags,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001108 fib_rpf_id_t rpf_id,
Neale Ranns32e1c012016-11-22 17:07:28 +00001109 u32 next_hop_sw_if_index, u32 itf_flags)
1110{
1111 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
1112
1113 fib_route_path_t path = {
1114 .frp_sw_if_index = next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001115 .frp_proto = fib_proto_to_dpo (prefix->fp_proto),
Neale Ranns32e1c012016-11-22 17:07:28 +00001116 };
1117
1118 if (is_local)
1119 path.frp_flags |= FIB_ROUTE_PATH_LOCAL;
1120
1121
1122 if (!is_local && ~0 == next_hop_sw_if_index)
1123 {
1124 mfib_table_entry_update (fib_index, prefix,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001125 MFIB_SOURCE_API, rpf_id, entry_flags);
Neale Ranns32e1c012016-11-22 17:07:28 +00001126 }
1127 else
1128 {
1129 if (is_add)
1130 {
1131 mfib_table_entry_path_update (fib_index, prefix,
1132 MFIB_SOURCE_API, &path, itf_flags);
1133 }
1134 else
1135 {
1136 mfib_table_entry_path_remove (fib_index, prefix,
1137 MFIB_SOURCE_API, &path);
1138 }
1139 }
1140
1141 stats_dsunlock ();
1142 return (0);
1143}
1144
1145static int
1146api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1147{
1148 fib_protocol_t fproto;
1149 u32 fib_index;
1150 int rv;
1151
1152 fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
1153 rv = add_del_mroute_check (fproto,
1154 mp->table_id,
1155 mp->next_hop_sw_if_index,
1156 mp->is_local,
1157 mp->create_vrf_if_needed, &fib_index);
1158
1159 if (0 != rv)
1160 return (rv);
1161
1162 mfib_prefix_t pfx = {
1163 .fp_len = ntohs (mp->grp_address_length),
1164 .fp_proto = fproto,
1165 };
1166
1167 if (FIB_PROTOCOL_IP4 == fproto)
1168 {
1169 clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address,
1170 sizeof (pfx.fp_grp_addr.ip4));
1171 clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
1172 sizeof (pfx.fp_src_addr.ip4));
1173 }
1174 else
1175 {
1176 clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address,
1177 sizeof (pfx.fp_grp_addr.ip6));
1178 clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
1179 sizeof (pfx.fp_src_addr.ip6));
1180 }
1181
1182 return (mroute_add_del_handler (mp->is_add,
1183 mp->is_local,
1184 fib_index, &pfx,
1185 ntohl (mp->entry_flags),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001186 ntohl (mp->rpf_id),
Neale Ranns32e1c012016-11-22 17:07:28 +00001187 ntohl (mp->next_hop_sw_if_index),
1188 ntohl (mp->itf_flags)));
1189}
1190
1191void
1192vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1193{
1194 vl_api_ip_mroute_add_del_reply_t *rmp;
1195 int rv;
1196 vnet_main_t *vnm = vnet_get_main ();
1197
1198 vnm->api_errno = 0;
1199
1200 rv = api_mroute_add_del_t_handler (mp);
1201
1202 rv = (rv == 0) ? vnm->api_errno : rv;
1203
1204 REPLY_MACRO (VL_API_IP_MROUTE_ADD_DEL_REPLY);
1205}
1206
Dave Barachb5e8a772016-12-06 12:04:42 -05001207static void
1208send_ip_details (vpe_api_main_t * am,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001209 unix_shared_memory_queue_t * q, u32 sw_if_index,
1210 u8 is_ipv6, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001211{
1212 vl_api_ip_details_t *mp;
1213
1214 mp = vl_msg_api_alloc (sizeof (*mp));
1215 memset (mp, 0, sizeof (*mp));
1216 mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
1217
1218 mp->sw_if_index = ntohl (sw_if_index);
Jon Loeliger466f0d42017-02-09 12:17:50 -06001219 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001220 mp->context = context;
1221
1222 vl_msg_api_send_shmem (q, (u8 *) & mp);
1223}
1224
1225static void
1226send_ip_address_details (vpe_api_main_t * am,
1227 unix_shared_memory_queue_t * q,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001228 u8 * ip, u16 prefix_length,
1229 u32 sw_if_index, u8 is_ipv6, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001230{
1231 vl_api_ip_address_details_t *mp;
1232
1233 mp = vl_msg_api_alloc (sizeof (*mp));
1234 memset (mp, 0, sizeof (*mp));
1235 mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
1236
1237 if (is_ipv6)
1238 {
1239 clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
1240 }
1241 else
1242 {
1243 u32 *tp = (u32 *) mp->ip;
1244 *tp = *(u32 *) ip;
1245 }
1246 mp->prefix_length = prefix_length;
1247 mp->context = context;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001248 mp->sw_if_index = htonl (sw_if_index);
1249 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001250
1251 vl_msg_api_send_shmem (q, (u8 *) & mp);
1252}
1253
1254static void
1255vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
1256{
1257 vpe_api_main_t *am = &vpe_api_main;
1258 unix_shared_memory_queue_t *q;
1259 ip6_address_t *r6;
1260 ip4_address_t *r4;
1261 ip6_main_t *im6 = &ip6_main;
1262 ip4_main_t *im4 = &ip4_main;
1263 ip_lookup_main_t *lm6 = &im6->lookup_main;
1264 ip_lookup_main_t *lm4 = &im4->lookup_main;
1265 ip_interface_address_t *ia = 0;
1266 u32 sw_if_index = ~0;
1267 int rv __attribute__ ((unused)) = 0;
1268
1269 VALIDATE_SW_IF_INDEX (mp);
1270
1271 sw_if_index = ntohl (mp->sw_if_index);
1272
1273 q = vl_api_client_index_to_input_queue (mp->client_index);
1274 if (q == 0)
1275 return;
1276
Dave Barachb5e8a772016-12-06 12:04:42 -05001277 if (mp->is_ipv6)
1278 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001279 /* *INDENT-OFF* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001280 foreach_ip_interface_address (lm6, ia, sw_if_index,
1281 1 /* honor unnumbered */,
1282 ({
1283 r6 = ip_interface_address_get_address (lm6, ia);
1284 u16 prefix_length = ia->address_length;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001285 send_ip_address_details(am, q, (u8*)r6, prefix_length,
1286 sw_if_index, 1, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001287 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001288 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001289 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001290 else
1291 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001292 /* *INDENT-OFF* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001293 foreach_ip_interface_address (lm4, ia, sw_if_index,
1294 1 /* honor unnumbered */,
1295 ({
1296 r4 = ip_interface_address_get_address (lm4, ia);
1297 u16 prefix_length = ia->address_length;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001298 send_ip_address_details(am, q, (u8*)r4, prefix_length,
1299 sw_if_index, 0, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001300 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001301 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001302 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001303 BAD_SW_IF_INDEX_LABEL;
1304}
1305
1306static void
1307vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
1308{
1309 vpe_api_main_t *am = &vpe_api_main;
1310 vnet_main_t *vnm = vnet_get_main ();
1311 vlib_main_t *vm = vlib_get_main ();
1312 vnet_interface_main_t *im = &vnm->interface_main;
1313 unix_shared_memory_queue_t *q;
1314 vnet_sw_interface_t *si, *sorted_sis;
1315 u32 sw_if_index = ~0;
1316
1317 q = vl_api_client_index_to_input_queue (mp->client_index);
1318 if (q == 0)
1319 {
1320 return;
1321 }
1322
1323 /* Gather interfaces. */
1324 sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
1325 _vec_len (sorted_sis) = 0;
1326 /* *INDENT-OFF* */
1327 pool_foreach (si, im->sw_interfaces,
1328 ({
1329 vec_add1 (sorted_sis, si[0]);
1330 }));
1331 /* *INDENT-ON* */
1332
1333 vec_foreach (si, sorted_sis)
1334 {
1335 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1336 {
1337 if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
1338 {
1339 continue;
1340 }
1341 sw_if_index = si->sw_if_index;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001342 send_ip_details (am, q, sw_if_index, mp->is_ipv6, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001343 }
1344 }
1345}
1346
1347static void
1348set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1349{
1350 vl_api_set_ip_flow_hash_reply_t *rmp;
Neale Ranns227038a2017-04-21 01:07:59 -07001351 int rv;
1352 u32 table_id;
1353 flow_hash_config_t flow_hash_config = 0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001354
Neale Ranns227038a2017-04-21 01:07:59 -07001355 table_id = ntohl (mp->vrf_id);
1356
1357#define _(a,b) if (mp->a) flow_hash_config |= b;
1358 foreach_flow_hash_bit;
1359#undef _
1360
1361 rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
Dave Barachb5e8a772016-12-06 12:04:42 -05001362
1363 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1364}
1365
1366static void
1367set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1368{
1369 vl_api_set_ip_flow_hash_reply_t *rmp;
1370 int rv;
1371 u32 table_id;
1372 flow_hash_config_t flow_hash_config = 0;
1373
1374 table_id = ntohl (mp->vrf_id);
1375
1376#define _(a,b) if (mp->a) flow_hash_config |= b;
1377 foreach_flow_hash_bit;
1378#undef _
1379
1380 rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
1381
1382 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1383}
1384
1385
1386static void
1387vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t * mp)
1388{
1389 if (mp->is_ipv6 == 0)
1390 set_ip4_flow_hash (mp);
1391 else
1392 set_ip6_flow_hash (mp);
1393}
1394
1395static void
1396 vl_api_sw_interface_ip6nd_ra_config_t_handler
1397 (vl_api_sw_interface_ip6nd_ra_config_t * mp)
1398{
1399 vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
1400 vlib_main_t *vm = vlib_get_main ();
1401 int rv = 0;
1402 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
1403 default_router;
1404
1405 is_no = mp->is_no == 1;
1406 suppress = mp->suppress == 1;
1407 managed = mp->managed == 1;
1408 other = mp->other == 1;
1409 ll_option = mp->ll_option == 1;
1410 send_unicast = mp->send_unicast == 1;
1411 cease = mp->cease == 1;
1412 default_router = mp->default_router == 1;
1413
1414 VALIDATE_SW_IF_INDEX (mp);
1415
1416 rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
1417 suppress, managed, other,
1418 ll_option, send_unicast, cease,
1419 default_router, ntohl (mp->lifetime),
1420 ntohl (mp->initial_count),
1421 ntohl (mp->initial_interval),
1422 ntohl (mp->max_interval),
1423 ntohl (mp->min_interval), is_no);
1424
1425 BAD_SW_IF_INDEX_LABEL;
1426
1427 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
1428}
1429
1430static void
1431 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
1432 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
1433{
1434 vlib_main_t *vm = vlib_get_main ();
1435 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
1436 int rv = 0;
1437 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
1438
1439 VALIDATE_SW_IF_INDEX (mp);
1440
1441 is_no = mp->is_no == 1;
1442 use_default = mp->use_default == 1;
1443 no_advertise = mp->no_advertise == 1;
1444 off_link = mp->off_link == 1;
1445 no_autoconfig = mp->no_autoconfig == 1;
1446 no_onlink = mp->no_onlink == 1;
1447
1448 rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
1449 (ip6_address_t *) mp->address,
1450 mp->address_length, use_default,
1451 ntohl (mp->val_lifetime),
1452 ntohl (mp->pref_lifetime), no_advertise,
1453 off_link, no_autoconfig, no_onlink, is_no);
1454
1455 BAD_SW_IF_INDEX_LABEL;
1456 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
1457}
1458
1459static void
Neale Ranns3f844d02017-02-18 00:03:54 -08001460send_ip6nd_proxy_details (unix_shared_memory_queue_t * q,
1461 u32 context,
1462 const ip46_address_t * addr, u32 sw_if_index)
1463{
1464 vl_api_ip6nd_proxy_details_t *mp;
1465
1466 mp = vl_msg_api_alloc (sizeof (*mp));
1467 memset (mp, 0, sizeof (*mp));
1468 mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
1469 mp->context = context;
1470 mp->sw_if_index = htonl (sw_if_index);
1471 memcpy (mp->address, addr, 16);
1472
1473 vl_msg_api_send_shmem (q, (u8 *) & mp);
1474}
1475
Neale Ranns3f844d02017-02-18 00:03:54 -08001476typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
1477{
1478 u32 *indices;
1479} api_ip6nd_proxy_fib_table_walk_ctx_t;
1480
1481static int
1482api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
1483{
1484 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
1485
1486 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
1487 {
1488 vec_add1 (ctx->indices, fei);
1489 }
1490
1491 return (1);
1492}
1493
1494static void
1495vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
1496{
1497 ip6_main_t *im6 = &ip6_main;
1498 fib_table_t *fib_table;
1499 api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
1500 .indices = NULL,
1501 };
1502 fib_node_index_t *feip;
1503 fib_prefix_t pfx;
1504 unix_shared_memory_queue_t *q;
1505
1506 q = vl_api_client_index_to_input_queue (mp->client_index);
1507 if (q == 0)
1508 {
1509 return;
1510 }
1511
1512 /* *INDENT-OFF* */
1513 pool_foreach (fib_table, im6->fibs,
1514 ({
1515 fib_table_walk(fib_table->ft_index,
1516 FIB_PROTOCOL_IP6,
1517 api_ip6nd_proxy_fib_table_walk,
1518 &ctx);
1519 }));
1520 /* *INDENT-ON* */
1521
1522 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
1523
1524 vec_foreach (feip, ctx.indices)
1525 {
1526 fib_entry_get_prefix (*feip, &pfx);
1527
1528 send_ip6nd_proxy_details (q,
1529 mp->context,
1530 &pfx.fp_addr,
1531 fib_entry_get_resolving_interface (*feip));
1532 }
1533
1534 vec_free (ctx.indices);
1535}
1536
1537static void
1538vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
1539{
1540 vl_api_ip6nd_proxy_add_del_reply_t *rmp;
1541 int rv = 0;
1542
1543 VALIDATE_SW_IF_INDEX (mp);
1544
1545 rv = ip6_neighbor_proxy_add_del (ntohl (mp->sw_if_index),
1546 (ip6_address_t *) mp->address, mp->is_del);
1547
1548 BAD_SW_IF_INDEX_LABEL;
1549 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
1550}
1551
1552static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001553 vl_api_sw_interface_ip6_enable_disable_t_handler
1554 (vl_api_sw_interface_ip6_enable_disable_t * mp)
1555{
1556 vlib_main_t *vm = vlib_get_main ();
1557 vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
1558 vnet_main_t *vnm = vnet_get_main ();
1559 int rv = 0;
1560 clib_error_t *error;
1561
1562 vnm->api_errno = 0;
1563
1564 VALIDATE_SW_IF_INDEX (mp);
1565
1566 error =
1567 (mp->enable == 1) ? enable_ip6_interface (vm,
1568 ntohl (mp->sw_if_index)) :
1569 disable_ip6_interface (vm, ntohl (mp->sw_if_index));
1570
1571 if (error)
1572 {
1573 clib_error_report (error);
1574 rv = VNET_API_ERROR_UNSPECIFIED;
1575 }
1576 else
1577 {
1578 rv = vnm->api_errno;
1579 }
1580
1581 BAD_SW_IF_INDEX_LABEL;
1582
1583 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
1584}
1585
1586static void
1587 vl_api_sw_interface_ip6_set_link_local_address_t_handler
1588 (vl_api_sw_interface_ip6_set_link_local_address_t * mp)
1589{
1590 vlib_main_t *vm = vlib_get_main ();
1591 vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp;
1592 int rv = 0;
1593 clib_error_t *error;
1594 vnet_main_t *vnm = vnet_get_main ();
1595
1596 vnm->api_errno = 0;
1597
1598 VALIDATE_SW_IF_INDEX (mp);
1599
1600 error = set_ip6_link_local_address (vm,
1601 ntohl (mp->sw_if_index),
Neale Ranns75152282017-01-09 01:00:45 -08001602 (ip6_address_t *) mp->address);
Dave Barachb5e8a772016-12-06 12:04:42 -05001603 if (error)
1604 {
1605 clib_error_report (error);
1606 rv = VNET_API_ERROR_UNSPECIFIED;
1607 }
1608 else
1609 {
1610 rv = vnm->api_errno;
1611 }
1612
1613 BAD_SW_IF_INDEX_LABEL;
1614
1615 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
1616}
1617
Neale Ranns32e1c012016-11-22 17:07:28 +00001618void
1619vl_mfib_signal_send_one (unix_shared_memory_queue_t * q,
1620 u32 context, const mfib_signal_t * mfs)
1621{
1622 vl_api_mfib_signal_details_t *mp;
1623 mfib_prefix_t prefix;
1624 mfib_table_t *mfib;
1625 mfib_itf_t *mfi;
1626
1627 mp = vl_msg_api_alloc (sizeof (*mp));
1628
1629 memset (mp, 0, sizeof (*mp));
1630 mp->_vl_msg_id = ntohs (VL_API_MFIB_SIGNAL_DETAILS);
1631 mp->context = context;
1632
1633 mfi = mfib_itf_get (mfs->mfs_itf);
1634 mfib_entry_get_prefix (mfs->mfs_entry, &prefix);
1635 mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry),
1636 prefix.fp_proto);
1637 mp->table_id = ntohl (mfib->mft_table_id);
1638 mp->sw_if_index = ntohl (mfi->mfi_sw_if_index);
1639
1640 if (FIB_PROTOCOL_IP4 == prefix.fp_proto)
1641 {
1642 mp->grp_address_len = ntohs (prefix.fp_len);
1643
1644 memcpy (mp->grp_address, &prefix.fp_grp_addr.ip4, 4);
1645 if (prefix.fp_len > 32)
1646 {
1647 memcpy (mp->src_address, &prefix.fp_src_addr.ip4, 4);
1648 }
1649 }
1650 else
1651 {
1652 mp->grp_address_len = ntohs (prefix.fp_len);
1653
1654 ASSERT (0);
1655 }
1656
1657 if (0 != mfs->mfs_buffer_len)
1658 {
1659 mp->ip_packet_len = ntohs (mfs->mfs_buffer_len);
1660
1661 memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len);
1662 }
1663 else
1664 {
1665 mp->ip_packet_len = 0;
1666 }
1667
1668 vl_msg_api_send_shmem (q, (u8 *) & mp);
1669}
1670
1671static void
1672vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
1673{
1674 unix_shared_memory_queue_t *q;
1675
1676 q = vl_api_client_index_to_input_queue (mp->client_index);
1677 if (q == 0)
1678 {
1679 return;
1680 }
1681
1682 while (q->cursize < q->maxsize && mfib_signal_send_one (q, mp->context))
1683 ;
1684}
Dave Barachb5e8a772016-12-06 12:04:42 -05001685
1686#define vl_msg_name_crc_list
1687#include <vnet/ip/ip.api.h>
1688#undef vl_msg_name_crc_list
1689
1690static void
1691setup_message_id_table (api_main_t * am)
1692{
1693#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1694 foreach_vl_msg_name_crc_ip;
1695#undef _
1696}
1697
1698static clib_error_t *
1699ip_api_hookup (vlib_main_t * vm)
1700{
1701 api_main_t *am = &api_main;
1702
1703#define _(N,n) \
1704 vl_msg_api_set_handlers(VL_API_##N, #n, \
1705 vl_api_##n##_t_handler, \
1706 vl_noop_handler, \
1707 vl_api_##n##_t_endian, \
1708 vl_api_##n##_t_print, \
1709 sizeof(vl_api_##n##_t), 1);
1710 foreach_ip_api_msg;
1711#undef _
1712
1713 /*
1714 * Set up the (msg_name, crc, message-id) table
1715 */
1716 setup_message_id_table (am);
1717
1718 return 0;
1719}
1720
1721VLIB_API_INIT_FUNCTION (ip_api_hookup);
1722
1723/*
1724 * fd.io coding-style-patch-verification: ON
1725 *
1726 * Local Variables:
1727 * eval: (c-set-style "gnu")
1728 * End:
1729 */