blob: bed5889b24a43ac201ae9d0c18d5f88f86477322 [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
Neale Rannsb8d44812017-11-10 06:53:54 -080023#include <vpp/stats/stats.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050024#include <vnet/interface.h>
25#include <vnet/api_errno.h>
26#include <vnet/ethernet/ethernet.h>
27#include <vnet/ip/ip.h>
John Lo7f358b32018-04-28 01:19:24 -040028#include <vnet/ip/ip_neighbor.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050029#include <vnet/ip/ip6_neighbor.h>
30#include <vnet/fib/fib_table.h>
31#include <vnet/fib/fib_api.h>
32#include <vnet/dpo/drop_dpo.h>
33#include <vnet/dpo/receive_dpo.h>
34#include <vnet/dpo/lookup_dpo.h>
35#include <vnet/dpo/classify_dpo.h>
36#include <vnet/dpo/ip_null_dpo.h>
37#include <vnet/ethernet/arp_packet.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080038#include <vnet/mfib/ip6_mfib.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000039#include <vnet/mfib/ip4_mfib.h>
40#include <vnet/mfib/mfib_signal.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080041#include <vnet/mfib/mfib_entry.h>
Neale Rannsb8d44812017-11-10 06:53:54 -080042#include <vnet/ip/ip_source_and_port_range_check.h>
43#include <vnet/fib/ip4_fib.h>
44#include <vnet/fib/ip6_fib.h>
45#include <vnet/ip/ip6_hop_by_hop.h>
Klement Sekera75e7d132017-09-20 08:26:30 +020046#include <vnet/ip/ip4_reassembly.h>
47#include <vnet/ip/ip6_reassembly.h>
Neale Ranns0053de62018-05-22 08:40:52 -070048#include <vnet/ethernet/arp.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050049
50#include <vnet/vnet_msg_enum.h>
51
52#define vl_typedefs /* define message structures */
53#include <vnet/vnet_all_api_h.h>
54#undef vl_typedefs
55
56#define vl_endianfun /* define message structures */
57#include <vnet/vnet_all_api_h.h>
58#undef vl_endianfun
59
60/* instantiate all the print functions we know about */
61#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
62#define vl_printfun
63#include <vnet/vnet_all_api_h.h>
64#undef vl_printfun
65
66#include <vlibapi/api_helper_macros.h>
67
Neale Ranns5a8123b2017-01-26 01:18:23 -080068
Dave Barachb5e8a772016-12-06 12:04:42 -050069#define foreach_ip_api_msg \
70_(IP_FIB_DUMP, ip_fib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050071_(IP6_FIB_DUMP, ip6_fib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080072_(IP_MFIB_DUMP, ip_mfib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080073_(IP6_MFIB_DUMP, ip6_mfib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050074_(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \
Neale Ranns32e1c012016-11-22 17:07:28 +000075_(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080076_(MFIB_SIGNAL_DUMP, mfib_signal_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050077_(IP_ADDRESS_DUMP, ip_address_dump) \
Neale Ranns9e2f9152018-05-18 02:27:10 -070078_(IP_UNNUMBERED_DUMP, ip_unnumbered_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050079_(IP_DUMP, ip_dump) \
80_(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
Neale Rannsb8d44812017-11-10 06:53:54 -080081_(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \
John Loc7b43042018-04-13 16:46:22 -040082_(IP_PROBE_NEIGHBOR, ip_probe_neighbor) \
John Lo7f358b32018-04-28 01:19:24 -040083_(IP_SCAN_NEIGHBOR_ENABLE_DISABLE, ip_scan_neighbor_enable_disable) \
Neale Rannsb8d44812017-11-10 06:53:54 -080084_(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \
85_(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \
Juraj Sloboda4b9669d2018-01-15 10:39:21 +010086_(WANT_IP6_RA_EVENTS, want_ip6_ra_events) \
Neale Rannsb8d44812017-11-10 06:53:54 -080087_(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \
Neale Ranns0053de62018-05-22 08:40:52 -070088_(PROXY_ARP_DUMP, proxy_arp_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -080089_(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \
Neale Ranns0053de62018-05-22 08:40:52 -070090 _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -080091_(RESET_FIB, reset_fib) \
Dave Barachb5e8a772016-12-06 12:04:42 -050092_(IP_ADD_DEL_ROUTE, ip_add_del_route) \
Neale Ranns28ab9cc2017-08-14 07:18:42 -070093_(IP_TABLE_ADD_DEL, ip_table_add_del) \
Neale Rannsd91c1db2017-07-31 02:30:50 -070094_(IP_PUNT_POLICE, ip_punt_police) \
95_(IP_PUNT_REDIRECT, ip_punt_redirect) \
Dave Barachb5e8a772016-12-06 12:04:42 -050096_(SET_IP_FLOW_HASH,set_ip_flow_hash) \
97_(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
98_(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
Neale Ranns3f844d02017-02-18 00:03:54 -080099_(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del) \
100_(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \
Juraj Sloboda4b9669d2018-01-15 10:39:21 +0100101_(IP6ND_SEND_ROUTER_SOLICITATION, ip6nd_send_router_solicitation) \
Dave Barachb5e8a772016-12-06 12:04:42 -0500102_(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
103_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
Florin Coras595992c2017-11-06 17:17:08 -0800104 sw_interface_ip6_set_link_local_address) \
Neale Rannsb8d44812017-11-10 06:53:54 -0800105_(IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del) \
106_(IOAM_ENABLE, ioam_enable) \
107_(IOAM_DISABLE, ioam_disable) \
108_(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \
109 ip_source_and_port_range_check_add_del) \
110_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
Klement Sekera75e7d132017-09-20 08:26:30 +0200111 ip_source_and_port_range_check_interface_add_del) \
112_(IP_REASSEMBLY_SET, ip_reassembly_set) \
Klement Sekera4c533132018-02-22 11:41:12 +0100113_(IP_REASSEMBLY_GET, ip_reassembly_get) \
114_(IP_REASSEMBLY_ENABLE_DISABLE, ip_reassembly_enable_disable)
Dave Barachb5e8a772016-12-06 12:04:42 -0500115
116extern void stats_dslock_with_hint (int hint, int tag);
117extern void stats_dsunlock (void);
118
119static void
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600120send_ip_neighbor_details (u32 sw_if_index,
121 u8 is_ipv6,
Dave Barachb5e8a772016-12-06 12:04:42 -0500122 u8 is_static,
123 u8 * mac_address,
Florin Coras6c4dae22018-01-09 06:39:23 -0800124 u8 * ip_address, vl_api_registration_t * reg,
125 u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500126{
127 vl_api_ip_neighbor_details_t *mp;
128
129 mp = vl_msg_api_alloc (sizeof (*mp));
130 memset (mp, 0, sizeof (*mp));
131 mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS);
132 mp->context = context;
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600133 mp->sw_if_index = htonl (sw_if_index);
Dave Barachb5e8a772016-12-06 12:04:42 -0500134 mp->is_ipv6 = is_ipv6;
135 mp->is_static = is_static;
136 memcpy (mp->mac_address, mac_address, 6);
137 memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4);
138
Florin Coras6c4dae22018-01-09 06:39:23 -0800139 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500140}
141
142static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500143vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
144{
Florin Coras6c4dae22018-01-09 06:39:23 -0800145 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500146
Florin Coras6c4dae22018-01-09 06:39:23 -0800147 reg = vl_api_client_index_to_registration (mp->client_index);
148 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500149 return;
150
151 u32 sw_if_index = ntohl (mp->sw_if_index);
152
153 if (mp->is_ipv6)
154 {
155 ip6_neighbor_t *n, *ns;
156
157 ns = ip6_neighbors_entries (sw_if_index);
158 /* *INDENT-OFF* */
159 vec_foreach (n, ns)
160 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500161 send_ip_neighbor_details
Brant Lin285434a2018-06-13 06:01:58 -0400162 (n->key.sw_if_index, mp->is_ipv6,
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600163 ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0),
Dave Barachd7cb1b52016-12-09 09:52:16 -0500164 (u8 *) n->link_layer_address,
165 (u8 *) & (n->key.ip6_address.as_u8),
Florin Coras6c4dae22018-01-09 06:39:23 -0800166 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500167 }
168 /* *INDENT-ON* */
169 vec_free (ns);
170 }
171 else
172 {
173 ethernet_arp_ip4_entry_t *n, *ns;
174
175 ns = ip4_neighbor_entries (sw_if_index);
176 /* *INDENT-OFF* */
177 vec_foreach (n, ns)
178 {
Brant Lin285434a2018-06-13 06:01:58 -0400179 send_ip_neighbor_details (n->sw_if_index, mp->is_ipv6,
Dave Barachb5e8a772016-12-06 12:04:42 -0500180 ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0),
181 (u8*) n->ethernet_address,
182 (u8*) & (n->ip4_address.as_u8),
Florin Coras6c4dae22018-01-09 06:39:23 -0800183 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500184 }
185 /* *INDENT-ON* */
186 vec_free (ns);
187 }
188}
189
Dave Barachb5e8a772016-12-06 12:04:42 -0500190static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500191send_ip_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800192 vl_api_registration_t * reg,
Neale Ranns2297af02017-09-12 09:45:04 -0700193 const fib_table_t * table,
194 const fib_prefix_t * pfx,
Dave Barachb5e8a772016-12-06 12:04:42 -0500195 fib_route_path_encode_t * api_rpaths, u32 context)
196{
197 vl_api_ip_fib_details_t *mp;
198 fib_route_path_encode_t *api_rpath;
199 vl_api_fib_path_t *fp;
200 int path_count;
201
202 path_count = vec_len (api_rpaths);
203 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
204 if (!mp)
205 return;
206 memset (mp, 0, sizeof (*mp));
207 mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
208 mp->context = context;
209
Neale Ranns2297af02017-09-12 09:45:04 -0700210 mp->table_id = htonl (table->ft_table_id);
211 memcpy (mp->table_name, table->ft_desc,
212 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Dave Barachb5e8a772016-12-06 12:04:42 -0500213 mp->address_length = pfx->fp_len;
214 memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
Neale Ranns008dbe12018-09-07 09:32:36 -0700215 mp->stats_index =
216 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500217
218 mp->count = htonl (path_count);
219 fp = mp->path;
220 vec_foreach (api_rpath, api_rpaths)
221 {
Neale Ranns81458422018-03-12 06:59:36 -0700222 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500223 fp++;
224 }
225
Florin Coras6c4dae22018-01-09 06:39:23 -0800226 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500227}
228
Neale Rannsa3af3372017-03-28 03:49:52 -0700229typedef struct vl_api_ip_fib_dump_walk_ctx_t_
230{
231 fib_node_index_t *feis;
232} vl_api_ip_fib_dump_walk_ctx_t;
233
Neale Ranns89541992017-04-06 04:41:02 -0700234static fib_table_walk_rc_t
Neale Rannsa3af3372017-03-28 03:49:52 -0700235vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
236{
237 vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
238
239 vec_add1 (ctx->feis, fei);
240
Neale Ranns89541992017-04-06 04:41:02 -0700241 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700242}
243
Dave Barachb5e8a772016-12-06 12:04:42 -0500244static void
245vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
246{
247 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800248 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500249 ip4_main_t *im = &ip4_main;
250 fib_table_t *fib_table;
Neale Rannsa3af3372017-03-28 03:49:52 -0700251 fib_node_index_t *lfeip;
Neale Rannsc5d43172018-07-30 08:04:40 -0700252 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500253 u32 fib_index;
254 fib_route_path_encode_t *api_rpaths;
Neale Rannsa3af3372017-03-28 03:49:52 -0700255 vl_api_ip_fib_dump_walk_ctx_t ctx = {
256 .feis = NULL,
257 };
Dave Barachb5e8a772016-12-06 12:04:42 -0500258
Florin Coras6c4dae22018-01-09 06:39:23 -0800259 reg = vl_api_client_index_to_registration (mp->client_index);
260 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500261 return;
262
263 /* *INDENT-OFF* */
264 pool_foreach (fib_table, im->fibs,
265 ({
Neale Rannsa3af3372017-03-28 03:49:52 -0700266 fib_table_walk(fib_table->ft_index,
267 FIB_PROTOCOL_IP4,
268 vl_api_ip_fib_dump_walk,
269 &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500270 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500271 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500272
Neale Rannsa3af3372017-03-28 03:49:52 -0700273 vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500274
Neale Rannsa3af3372017-03-28 03:49:52 -0700275 vec_foreach (lfeip, ctx.feis)
Dave Barachb5e8a772016-12-06 12:04:42 -0500276 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700277 pfx = fib_entry_get_prefix (*lfeip);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500278 fib_index = fib_entry_get_fib_index (*lfeip);
Neale Rannsc5d43172018-07-30 08:04:40 -0700279 fib_table = fib_table_get (fib_index, pfx->fp_proto);
Dave Barachb5e8a772016-12-06 12:04:42 -0500280 api_rpaths = NULL;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500281 fib_entry_encode (*lfeip, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700282 send_ip_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500283 vec_free (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500284 }
285
Neale Rannsa3af3372017-03-28 03:49:52 -0700286 vec_free (ctx.feis);
Dave Barachb5e8a772016-12-06 12:04:42 -0500287}
288
289static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500290send_ip6_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800291 vl_api_registration_t * reg,
Neale Rannsa161a6d2017-11-14 08:10:41 -0800292 const fib_table_t * table,
293 const fib_prefix_t * pfx,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500294 fib_route_path_encode_t * api_rpaths, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500295{
296 vl_api_ip6_fib_details_t *mp;
297 fib_route_path_encode_t *api_rpath;
298 vl_api_fib_path_t *fp;
299 int path_count;
300
Dave Barachd7cb1b52016-12-09 09:52:16 -0500301 path_count = vec_len (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500302 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
303 if (!mp)
304 return;
305 memset (mp, 0, sizeof (*mp));
306 mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
307 mp->context = context;
308
Neale Rannsa161a6d2017-11-14 08:10:41 -0800309 mp->table_id = htonl (table->ft_table_id);
Dave Barachb5e8a772016-12-06 12:04:42 -0500310 mp->address_length = pfx->fp_len;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500311 memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
Neale Rannsa161a6d2017-11-14 08:10:41 -0800312 memcpy (mp->table_name, table->ft_desc,
313 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Neale Ranns008dbe12018-09-07 09:32:36 -0700314 mp->stats_index =
315 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500316
317 mp->count = htonl (path_count);
318 fp = mp->path;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500319 vec_foreach (api_rpath, api_rpaths)
Dave Barachb5e8a772016-12-06 12:04:42 -0500320 {
Neale Ranns81458422018-03-12 06:59:36 -0700321 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500322 fp++;
323 }
324
Florin Coras6c4dae22018-01-09 06:39:23 -0800325 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500326}
327
Dave Barachd7cb1b52016-12-09 09:52:16 -0500328typedef struct apt_ip6_fib_show_ctx_t_
329{
330 u32 fib_index;
331 fib_node_index_t *entries;
Dave Barachb5e8a772016-12-06 12:04:42 -0500332} api_ip6_fib_show_ctx_t;
333
334static void
Dave Barachd7cb1b52016-12-09 09:52:16 -0500335api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500336{
337 api_ip6_fib_show_ctx_t *ctx = arg;
338
339 if ((kvp->key[2] >> 32) == ctx->fib_index)
340 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500341 vec_add1 (ctx->entries, kvp->value);
Dave Barachb5e8a772016-12-06 12:04:42 -0500342 }
343}
344
345static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800346api_ip6_fib_table_get_all (vl_api_registration_t * reg,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500347 vl_api_ip6_fib_dump_t * mp,
348 fib_table_t * fib_table)
Dave Barachb5e8a772016-12-06 12:04:42 -0500349{
350 vpe_api_main_t *am = &vpe_api_main;
351 ip6_main_t *im6 = &ip6_main;
Dave Barachb5e8a772016-12-06 12:04:42 -0500352 fib_node_index_t *fib_entry_index;
353 api_ip6_fib_show_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700354 .fib_index = fib_table->ft_index,
355 .entries = NULL,
Dave Barachb5e8a772016-12-06 12:04:42 -0500356 };
357 fib_route_path_encode_t *api_rpaths;
Neale Rannsc5d43172018-07-30 08:04:40 -0700358 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500359
Dave Barachd7cb1b52016-12-09 09:52:16 -0500360 BV (clib_bihash_foreach_key_value_pair)
361 ((BVT (clib_bihash) *) & im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].
362 ip6_hash, api_ip6_fib_table_put_entries, &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500363
Dave Barachd7cb1b52016-12-09 09:52:16 -0500364 vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500365
Dave Barachd7cb1b52016-12-09 09:52:16 -0500366 vec_foreach (fib_entry_index, ctx.entries)
367 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700368 pfx = fib_entry_get_prefix (*fib_entry_index);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500369 api_rpaths = NULL;
370 fib_entry_encode (*fib_entry_index, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700371 send_ip6_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500372 vec_free (api_rpaths);
373 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500374
Dave Barachd7cb1b52016-12-09 09:52:16 -0500375 vec_free (ctx.entries);
Dave Barachb5e8a772016-12-06 12:04:42 -0500376}
377
378static void
379vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
380{
Florin Coras6c4dae22018-01-09 06:39:23 -0800381 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500382 ip6_main_t *im6 = &ip6_main;
383 fib_table_t *fib_table;
384
Florin Coras6c4dae22018-01-09 06:39:23 -0800385 reg = vl_api_client_index_to_registration (mp->client_index);
386 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500387 return;
388
389 /* *INDENT-OFF* */
390 pool_foreach (fib_table, im6->fibs,
391 ({
Neale Ranns81458422018-03-12 06:59:36 -0700392 /* don't send link locals */
393 if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL)
394 continue;
395
Florin Coras6c4dae22018-01-09 06:39:23 -0800396 api_ip6_fib_table_get_all(reg, mp, fib_table);
Dave Barachb5e8a772016-12-06 12:04:42 -0500397 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500398 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500399}
400
401static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800402send_ip_mfib_details (vl_api_registration_t * reg,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800403 u32 context, u32 table_id, fib_node_index_t mfei)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800404{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800405 fib_route_path_encode_t *api_rpath, *api_rpaths = NULL;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800406 vl_api_ip_mfib_details_t *mp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800407 mfib_entry_t *mfib_entry;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800408 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800409 mfib_prefix_t pfx;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800410 int path_count;
411
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800412 mfib_entry = mfib_entry_get (mfei);
413 mfib_entry_get_prefix (mfei, &pfx);
414 mfib_entry_encode (mfei, &api_rpaths);
415
Neale Ranns5a8123b2017-01-26 01:18:23 -0800416 path_count = vec_len (api_rpaths);
417 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
418 if (!mp)
419 return;
420 memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700421 mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800422 mp->context = context;
423
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800424 mp->rpf_id = mfib_entry->mfe_rpf_id;
425 mp->entry_flags = mfib_entry->mfe_flags;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800426 mp->table_id = htonl (table_id);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800427 mp->address_length = pfx.fp_len;
428 memcpy (mp->grp_address, &pfx.fp_grp_addr.ip4,
429 sizeof (pfx.fp_grp_addr.ip4));
430 memcpy (mp->src_address, &pfx.fp_src_addr.ip4,
431 sizeof (pfx.fp_src_addr.ip4));
Neale Ranns5a8123b2017-01-26 01:18:23 -0800432
433 mp->count = htonl (path_count);
434 fp = mp->path;
435 vec_foreach (api_rpath, api_rpaths)
436 {
Neale Ranns81458422018-03-12 06:59:36 -0700437 fib_api_path_encode (api_rpath, fp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800438 fp++;
439 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800440 vec_free (api_rpaths);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800441
Florin Coras6c4dae22018-01-09 06:39:23 -0800442 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800443}
444
445typedef struct vl_api_ip_mfib_dump_ctc_t_
446{
447 fib_node_index_t *entries;
448} vl_api_ip_mfib_dump_ctc_t;
449
450static int
451vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
452{
453 vl_api_ip_mfib_dump_ctc_t *ctx = arg;
454
455 vec_add1 (ctx->entries, fei);
456
457 return (0);
458}
459
460static void
461vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
462{
Florin Coras6c4dae22018-01-09 06:39:23 -0800463 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800464 ip4_main_t *im = &ip4_main;
465 mfib_table_t *mfib_table;
466 fib_node_index_t *mfeip;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800467 vl_api_ip_mfib_dump_ctc_t ctx = {
468 .entries = NULL,
469 };
470
Florin Coras6c4dae22018-01-09 06:39:23 -0800471 reg = vl_api_client_index_to_registration (mp->client_index);
472 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800473 return;
474
Neale Ranns5a8123b2017-01-26 01:18:23 -0800475 /* *INDENT-OFF* */
476 pool_foreach (mfib_table, im->mfibs,
477 ({
478 ip4_mfib_table_walk(&mfib_table->v4,
479 vl_api_ip_mfib_table_dump_walk,
480 &ctx);
481
482 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
483
484 vec_foreach (mfeip, ctx.entries)
485 {
Florin Coras6c4dae22018-01-09 06:39:23 -0800486 send_ip_mfib_details (reg, mp->context,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800487 mfib_table->mft_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800488 *mfeip);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800489 }
Neale Ranns5a8123b2017-01-26 01:18:23 -0800490 vec_reset_length (ctx.entries);
491
492 }));
493 /* *INDENT-ON* */
494
495 vec_free (ctx.entries);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800496}
497
498static void
Neale Ranns5a8123b2017-01-26 01:18:23 -0800499send_ip6_mfib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800500 vl_api_registration_t * reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800501 u32 table_id,
502 mfib_prefix_t * pfx,
503 fib_route_path_encode_t * api_rpaths, u32 context)
504{
505 vl_api_ip6_mfib_details_t *mp;
506 fib_route_path_encode_t *api_rpath;
507 vl_api_fib_path_t *fp;
508 int path_count;
509
510 path_count = vec_len (api_rpaths);
511 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
512 if (!mp)
513 return;
514 memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700515 mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800516 mp->context = context;
517
518 mp->table_id = htonl (table_id);
519 mp->address_length = pfx->fp_len;
520 memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6,
521 sizeof (pfx->fp_grp_addr.ip6));
522 memcpy (mp->src_address, &pfx->fp_src_addr.ip6,
523 sizeof (pfx->fp_src_addr.ip6));
524
525 mp->count = htonl (path_count);
526 fp = mp->path;
527 vec_foreach (api_rpath, api_rpaths)
528 {
Neale Ranns81458422018-03-12 06:59:36 -0700529 fib_api_path_encode (api_rpath, fp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800530 fp++;
531 }
532
Florin Coras6c4dae22018-01-09 06:39:23 -0800533 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800534}
535
536typedef struct vl_api_ip6_mfib_dump_ctc_t_
537{
538 fib_node_index_t *entries;
539} vl_api_ip6_mfib_dump_ctc_t;
540
541static int
542vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
543{
544 vl_api_ip6_mfib_dump_ctc_t *ctx = arg;
545
546 vec_add1 (ctx->entries, fei);
547
548 return (0);
549}
550
551static void
552vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
553{
554 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800555 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800556 ip6_main_t *im = &ip6_main;
557 mfib_table_t *mfib_table;
558 fib_node_index_t *mfeip;
559 mfib_prefix_t pfx;
560 fib_route_path_encode_t *api_rpaths = NULL;
561 vl_api_ip6_mfib_dump_ctc_t ctx = {
562 .entries = NULL,
563 };
564
Florin Coras6c4dae22018-01-09 06:39:23 -0800565 reg = vl_api_client_index_to_registration (mp->client_index);
566 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800567 return;
568
569
570 /* *INDENT-OFF* */
571 pool_foreach (mfib_table, im->mfibs,
572 ({
573 ip6_mfib_table_walk(&mfib_table->v6,
574 vl_api_ip6_mfib_table_dump_walk,
575 &ctx);
576
577 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
578
579 vec_foreach(mfeip, ctx.entries)
580 {
581 mfib_entry_get_prefix (*mfeip, &pfx);
582 mfib_entry_encode (*mfeip, &api_rpaths);
Florin Coras6c4dae22018-01-09 06:39:23 -0800583 send_ip6_mfib_details (am, reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800584 mfib_table->mft_table_id,
585 &pfx, api_rpaths,
586 mp->context);
587 }
588 vec_reset_length (api_rpaths);
589 vec_reset_length (ctx.entries);
590
591 }));
592 /* *INDENT-ON* */
593
594 vec_free (ctx.entries);
595 vec_free (api_rpaths);
596}
597
598static void
Neale Rannsd91c1db2017-07-31 02:30:50 -0700599vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp,
600 vlib_main_t * vm)
601{
602 vl_api_ip_punt_police_reply_t *rmp;
603 int rv = 0;
604
605 if (mp->is_ip6)
606 ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
607 else
608 ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
609
610 REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY);
611}
612
613static void
614vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp,
615 vlib_main_t * vm)
616{
617 vl_api_ip_punt_redirect_reply_t *rmp;
618 int rv = 0;
619
620 if (mp->is_add)
621 {
622 ip46_address_t nh;
623
624 memset (&nh, 0, sizeof (nh));
625
626 if (mp->is_ip6)
627 {
628 memcpy (&nh.ip6, mp->nh, sizeof (nh.ip6));
629
630 ip6_punt_redirect_add (ntohl (mp->rx_sw_if_index),
631 ntohl (mp->tx_sw_if_index), &nh);
632 }
633 else
634 {
635 memcpy (&nh.ip4, mp->nh, sizeof (nh.ip4));
636
637 ip4_punt_redirect_add (ntohl (mp->rx_sw_if_index),
638 ntohl (mp->tx_sw_if_index), &nh);
639 }
640 }
641 else
642 {
643 if (mp->is_ip6)
644 {
645 ip6_punt_redirect_del (ntohl (mp->rx_sw_if_index));
646 }
647 else
648 {
649 ip4_punt_redirect_del (ntohl (mp->rx_sw_if_index));
650 }
651 }
652
653 REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY);
654}
655
656static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500657vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
658 vlib_main_t * vm)
659{
Neale Ranns0bdd3192018-09-07 11:04:52 -0700660 ip46_address_t ip = ip46_address_initializer;
Dave Barachb5e8a772016-12-06 12:04:42 -0500661 vl_api_ip_neighbor_add_del_reply_t *rmp;
Neale Ranns0bdd3192018-09-07 11:04:52 -0700662 ip_neighbor_flags_t flags;
Dave Barachb5e8a772016-12-06 12:04:42 -0500663 int rv = 0;
664
665 VALIDATE_SW_IF_INDEX (mp);
666
667 stats_dslock_with_hint (1 /* release hint */ , 7 /* tag */ );
668
Neale Ranns0bdd3192018-09-07 11:04:52 -0700669 flags = IP_NEIGHBOR_FLAG_NODE;
670 if (mp->is_static)
671 flags |= IP_NEIGHBOR_FLAG_STATIC;
672 if (mp->is_no_adj_fib)
673 flags |= IP_NEIGHBOR_FLAG_NO_ADJ_FIB;
674
Dave Barachb5e8a772016-12-06 12:04:42 -0500675 if (mp->is_ipv6)
Neale Ranns0bdd3192018-09-07 11:04:52 -0700676 clib_memcpy (&ip.ip6, mp->dst_address, 16);
Dave Barachb5e8a772016-12-06 12:04:42 -0500677 else
Neale Ranns0bdd3192018-09-07 11:04:52 -0700678 clib_memcpy (&ip.ip4, mp->dst_address, 4);
Dave Barachb5e8a772016-12-06 12:04:42 -0500679
Neale Ranns0bdd3192018-09-07 11:04:52 -0700680 if (mp->is_add)
681 rv = ip_neighbor_add (&ip, mp->is_ipv6, mp->mac_address,
682 ntohl (mp->sw_if_index), flags);
683 else
684 rv = ip_neighbor_del (&ip, mp->is_ipv6, ntohl (mp->sw_if_index));
Dave Barachb5e8a772016-12-06 12:04:42 -0500685
Dave Barachb5e8a772016-12-06 12:04:42 -0500686 stats_dsunlock ();
Neale Ranns8edad032017-10-09 05:26:13 -0700687
688 BAD_SW_IF_INDEX_LABEL;
Dave Barachb5e8a772016-12-06 12:04:42 -0500689 REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
690}
691
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700692void
Neale Ranns15002542017-09-10 04:39:11 -0700693ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
694{
695 u32 fib_index, mfib_index;
696
697 /*
698 * ignore action on the default table - this is always present
699 * and cannot be added nor deleted from the API
700 */
701 if (0 != table_id)
702 {
703 /*
704 * The API holds only one lock on the table.
705 * i.e. it can be added many times via the API but needs to be
706 * deleted only once.
707 * The FIB index for unicast and multicast is not necessarily the
708 * same, since internal VPP systesm (like LISP and SR) create
709 * their own unicast tables.
710 */
711 fib_index = fib_table_find (fproto, table_id);
712 mfib_index = mfib_table_find (fproto, table_id);
713
714 if (~0 != fib_index)
715 {
716 fib_table_unlock (fib_index, fproto,
717 (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
718 }
719 if (~0 != mfib_index)
720 {
721 mfib_table_unlock (mfib_index, fproto,
722 (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
723 }
724 }
725}
726
727void
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700728vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
729{
730 vl_api_ip_table_add_del_reply_t *rmp;
Neale Ranns15002542017-09-10 04:39:11 -0700731 fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
732 u32 table_id = ntohl (mp->table_id);
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700733 int rv = 0;
734
Neale Ranns15002542017-09-10 04:39:11 -0700735 if (mp->is_add)
736 {
Neale Ranns2297af02017-09-12 09:45:04 -0700737 ip_table_create (fproto, table_id, 1, mp->name);
Neale Ranns15002542017-09-10 04:39:11 -0700738 }
739 else
740 {
741 ip_table_delete (fproto, table_id, 1);
742 }
743
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700744 REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
745}
746
Dave Barachb5e8a772016-12-06 12:04:42 -0500747int
748add_del_route_t_handler (u8 is_multipath,
749 u8 is_add,
750 u8 is_drop,
751 u8 is_unreach,
752 u8 is_prohibit,
753 u8 is_local,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800754 u8 is_multicast,
Dave Barachb5e8a772016-12-06 12:04:42 -0500755 u8 is_classify,
756 u32 classify_table_index,
757 u8 is_resolve_host,
758 u8 is_resolve_attached,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800759 u8 is_interface_rx,
760 u8 is_rpf_id,
Neale Rannsf068c3e2018-01-03 04:18:48 -0800761 u8 is_dvr,
Neale Ranns054c03a2017-10-13 05:15:07 -0700762 u8 is_source_lookup,
Neale Ranns810086d2017-11-05 16:26:46 -0800763 u8 is_udp_encap,
Dave Barachb5e8a772016-12-06 12:04:42 -0500764 u32 fib_index,
765 const fib_prefix_t * prefix,
Neale Rannsda78f952017-05-24 09:15:43 -0700766 dpo_proto_t next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500767 const ip46_address_t * next_hop,
Neale Ranns810086d2017-11-05 16:26:46 -0800768 u32 next_hop_id,
Dave Barachb5e8a772016-12-06 12:04:42 -0500769 u32 next_hop_sw_if_index,
770 u8 next_hop_fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -0700771 u16 next_hop_weight,
772 u16 next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500773 mpls_label_t next_hop_via_label,
Neale Ranns31ed7442018-02-23 05:29:09 -0800774 fib_mpls_label_t * next_hop_out_label_stack)
Dave Barachb5e8a772016-12-06 12:04:42 -0500775{
776 vnet_classify_main_t *cm = &vnet_classify_main;
777 fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
778 fib_route_path_t path = {
Neale Rannsda78f952017-05-24 09:15:43 -0700779 .frp_proto = next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500780 .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
781 .frp_sw_if_index = next_hop_sw_if_index,
782 .frp_fib_index = next_hop_fib_index,
783 .frp_weight = next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -0700784 .frp_preference = next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500785 .frp_label_stack = next_hop_out_label_stack,
786 };
787 fib_route_path_t *paths = NULL;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800788 fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
Dave Barachb5e8a772016-12-06 12:04:42 -0500789
Neale Rannscaac3502017-09-18 18:04:10 -0700790 /*
791 * the special INVALID label meams we are not recursing via a
792 * label. Exp-null value is never a valid via-label so that
793 * also means it's not a via-label and means clients that set
794 * it to 0 by default get the expected behaviour
795 */
796 if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label))
Dave Barachb5e8a772016-12-06 12:04:42 -0500797 {
Neale Rannsda78f952017-05-24 09:15:43 -0700798 path.frp_proto = DPO_PROTO_MPLS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500799 path.frp_local_label = next_hop_via_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800800 path.frp_eos = MPLS_NON_EOS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500801 }
Neale Rannsf068c3e2018-01-03 04:18:48 -0800802 if (is_dvr)
803 path_flags |= FIB_ROUTE_PATH_DVR;
Dave Barachb5e8a772016-12-06 12:04:42 -0500804 if (is_resolve_host)
805 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
806 if (is_resolve_attached)
807 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800808 if (is_interface_rx)
809 path_flags |= FIB_ROUTE_PATH_INTF_RX;
810 if (is_rpf_id)
811 path_flags |= FIB_ROUTE_PATH_RPF_ID;
Neale Ranns054c03a2017-10-13 05:15:07 -0700812 if (is_source_lookup)
813 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800814 if (is_multicast)
815 entry_flags |= FIB_ENTRY_FLAG_MULTICAST;
Neale Ranns810086d2017-11-05 16:26:46 -0800816 if (is_udp_encap)
817 {
818 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
819 path.frp_udp_encap_id = next_hop_id;
820 }
Florin Coras79ae2d32017-12-16 08:31:06 -0800821 if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr)
822 && path.frp_fib_index != ~0)
823 {
824 path_flags |= FIB_ROUTE_PATH_DEAG;
825 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500826
827 path.frp_flags = path_flags;
828
Dave Barachb5e8a772016-12-06 12:04:42 -0500829 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
830
831 if (is_drop || is_local || is_classify || is_unreach || is_prohibit)
832 {
833 /*
834 * special route types that link directly to the adj
835 */
836 if (is_add)
837 {
838 dpo_id_t dpo = DPO_INVALID;
839 dpo_proto_t dproto;
840
841 dproto = fib_proto_to_dpo (prefix->fp_proto);
842
843 if (is_drop)
844 ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
845 else if (is_local)
846 receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
847 else if (is_unreach)
848 ip_null_dpo_add_and_lock (dproto,
849 IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
850 else if (is_prohibit)
851 ip_null_dpo_add_and_lock (dproto,
852 IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
853 &dpo);
854 else if (is_classify)
855 {
856 if (pool_is_free_index (cm->tables,
857 ntohl (classify_table_index)))
858 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500859 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500860 return VNET_API_ERROR_NO_SUCH_TABLE;
861 }
862
863 dpo_set (&dpo, DPO_CLASSIFY, dproto,
864 classify_dpo_create (dproto,
865 ntohl (classify_table_index)));
866 }
867 else
868 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500869 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500870 return VNET_API_ERROR_NO_SUCH_TABLE;
871 }
872
873 fib_table_entry_special_dpo_update (fib_index,
874 prefix,
875 FIB_SOURCE_API,
876 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
877 dpo_reset (&dpo);
878 }
879 else
880 {
881 fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
882 }
883 }
Neale Ranns3b93be52018-09-07 01:48:54 -0700884 else if (is_multipath)
885 {
886 vec_add1 (paths, path);
887
888 if (is_add)
889 fib_table_entry_path_add2 (fib_index,
890 prefix,
891 FIB_SOURCE_API, entry_flags, paths);
892 else
893 fib_table_entry_path_remove2 (fib_index,
894 prefix, FIB_SOURCE_API, paths);
895
896 vec_free (paths);
897 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500898 else
899 {
900 if (is_add)
901 {
902 vec_add1 (paths, path);
903 fib_table_entry_update (fib_index,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800904 prefix, FIB_SOURCE_API, entry_flags, paths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500905 vec_free (paths);
906 }
907 else
908 {
909 fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
910 }
911 }
912
Dave Barachd7cb1b52016-12-09 09:52:16 -0500913 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500914 return (0);
915}
916
917int
918add_del_route_check (fib_protocol_t table_proto,
919 u32 table_id,
920 u32 next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700921 dpo_proto_t next_hop_table_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500922 u32 next_hop_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800923 u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500924{
925 vnet_main_t *vnm = vnet_get_main ();
926
927 *fib_index = fib_table_find (table_proto, ntohl (table_id));
928 if (~0 == *fib_index)
929 {
Neale Rannsb93078d2018-01-25 07:48:12 -0800930 /* No such VRF, and we weren't asked to create one */
931 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -0500932 }
933
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800934 if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index))
Dave Barachb5e8a772016-12-06 12:04:42 -0500935 {
936 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
937 ntohl (next_hop_sw_if_index)))
938 {
939 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
940 }
941 }
942 else
943 {
Neale Rannsda78f952017-05-24 09:15:43 -0700944 fib_protocol_t fib_nh_proto;
945
946 if (next_hop_table_proto > DPO_PROTO_MPLS)
947 return (0);
948
949 fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto);
950
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800951 if (is_rpf_id)
Neale Rannsda78f952017-05-24 09:15:43 -0700952 *next_hop_fib_index = mfib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800953 ntohl (next_hop_table_id));
954 else
Neale Rannsda78f952017-05-24 09:15:43 -0700955 *next_hop_fib_index = fib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800956 ntohl (next_hop_table_id));
Dave Barachb5e8a772016-12-06 12:04:42 -0500957
958 if (~0 == *next_hop_fib_index)
959 {
Neale Rannsb93078d2018-01-25 07:48:12 -0800960 /* No such VRF, and we weren't asked to create one */
961 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -0500962 }
963 }
964
965 return (0);
966}
967
968static int
Neale Ranns008dbe12018-09-07 09:32:36 -0700969ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
970 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500971{
972 u32 fib_index, next_hop_fib_index;
Neale Ranns31ed7442018-02-23 05:29:09 -0800973 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -0500974 int rv, ii, n_labels;;
975
976 rv = add_del_route_check (FIB_PROTOCOL_IP4,
977 mp->table_id,
978 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700979 DPO_PROTO_IP4,
Dave Barachb5e8a772016-12-06 12:04:42 -0500980 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -0700981 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -0500982
983 if (0 != rv)
984 return (rv);
985
986 fib_prefix_t pfx = {
987 .fp_len = mp->dst_address_length,
988 .fp_proto = FIB_PROTOCOL_IP4,
989 };
990 clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
991
992 ip46_address_t nh;
993 memset (&nh, 0, sizeof (nh));
994 memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
995
996 n_labels = mp->next_hop_n_out_labels;
997 if (n_labels == 0)
998 ;
Dave Barachb5e8a772016-12-06 12:04:42 -0500999 else
1000 {
1001 vec_validate (label_stack, n_labels - 1);
1002 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001003 {
1004 label_stack[ii].fml_value =
1005 ntohl (mp->next_hop_out_label_stack[ii].label);
1006 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1007 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1008 label_stack[ii].fml_mode =
1009 (mp->next_hop_out_label_stack[ii].is_uniform ?
1010 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1011 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001012 }
1013
Neale Ranns008dbe12018-09-07 09:32:36 -07001014 rv = add_del_route_t_handler (mp->is_multipath,
1015 mp->is_add,
1016 mp->is_drop,
1017 mp->is_unreach,
1018 mp->is_prohibit,
1019 mp->is_local, 0,
1020 mp->is_classify,
1021 mp->classify_table_index,
1022 mp->is_resolve_host,
1023 mp->is_resolve_attached, 0, 0,
1024 mp->is_dvr,
1025 mp->is_source_lookup,
1026 mp->is_udp_encap,
1027 fib_index, &pfx, DPO_PROTO_IP4,
1028 &nh,
1029 ntohl (mp->next_hop_id),
1030 ntohl (mp->next_hop_sw_if_index),
1031 next_hop_fib_index,
1032 mp->next_hop_weight,
1033 mp->next_hop_preference,
1034 ntohl (mp->next_hop_via_label), label_stack);
1035
1036 if (mp->is_add && 0 == rv)
1037 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1038
1039 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001040}
1041
Juraj Sloboda0012fcc2018-05-17 12:05:27 +02001042static int
Neale Ranns008dbe12018-09-07 09:32:36 -07001043ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
1044 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -05001045{
Neale Ranns31ed7442018-02-23 05:29:09 -08001046 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -05001047 u32 fib_index, next_hop_fib_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001048 int rv, ii, n_labels;;
1049
1050 rv = add_del_route_check (FIB_PROTOCOL_IP6,
1051 mp->table_id,
1052 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001053 DPO_PROTO_IP6,
Dave Barachb5e8a772016-12-06 12:04:42 -05001054 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001055 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001056
1057 if (0 != rv)
1058 return (rv);
1059
1060 fib_prefix_t pfx = {
1061 .fp_len = mp->dst_address_length,
1062 .fp_proto = FIB_PROTOCOL_IP6,
1063 };
1064 clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
1065
1066 ip46_address_t nh;
1067 memset (&nh, 0, sizeof (nh));
1068 memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
1069
1070 n_labels = mp->next_hop_n_out_labels;
1071 if (n_labels == 0)
1072 ;
Dave Barachb5e8a772016-12-06 12:04:42 -05001073 else
1074 {
1075 vec_validate (label_stack, n_labels - 1);
1076 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001077 {
1078 label_stack[ii].fml_value =
1079 ntohl (mp->next_hop_out_label_stack[ii].label);
1080 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1081 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1082 label_stack[ii].fml_mode =
1083 (mp->next_hop_out_label_stack[ii].is_uniform ?
1084 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1085 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001086 }
1087
Neale Ranns008dbe12018-09-07 09:32:36 -07001088 rv = add_del_route_t_handler (mp->is_multipath,
1089 mp->is_add,
1090 mp->is_drop,
1091 mp->is_unreach,
1092 mp->is_prohibit,
1093 mp->is_local, 0,
1094 mp->is_classify,
1095 mp->classify_table_index,
1096 mp->is_resolve_host,
1097 mp->is_resolve_attached, 0, 0,
1098 mp->is_dvr,
1099 mp->is_source_lookup,
1100 mp->is_udp_encap,
1101 fib_index, &pfx, DPO_PROTO_IP6,
1102 &nh, ntohl (mp->next_hop_id),
1103 ntohl (mp->next_hop_sw_if_index),
1104 next_hop_fib_index,
1105 mp->next_hop_weight,
1106 mp->next_hop_preference,
1107 ntohl (mp->next_hop_via_label), label_stack);
1108
1109 if (mp->is_add && 0 == rv)
1110 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1111
1112 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001113}
1114
1115void
1116vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1117{
1118 vl_api_ip_add_del_route_reply_t *rmp;
Neale Ranns008dbe12018-09-07 09:32:36 -07001119 u32 stats_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001120 int rv;
1121 vnet_main_t *vnm = vnet_get_main ();
1122
1123 vnm->api_errno = 0;
Neale Ranns008dbe12018-09-07 09:32:36 -07001124 stats_index = ~0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001125
1126 if (mp->is_ipv6)
Neale Ranns008dbe12018-09-07 09:32:36 -07001127 rv = ip6_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001128 else
Neale Ranns008dbe12018-09-07 09:32:36 -07001129 rv = ip4_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001130
1131 rv = (rv == 0) ? vnm->api_errno : rv;
1132
Neale Ranns008dbe12018-09-07 09:32:36 -07001133 /* *INDENT-OFF* */
1134 REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY,
1135 ({
1136 rmp->stats_index = htonl (stats_index);
1137 }))
1138 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001139}
1140
Neale Ranns15002542017-09-10 04:39:11 -07001141void
Neale Ranns2297af02017-09-12 09:45:04 -07001142ip_table_create (fib_protocol_t fproto,
1143 u32 table_id, u8 is_api, const u8 * name)
Neale Ranns15002542017-09-10 04:39:11 -07001144{
1145 u32 fib_index, mfib_index;
1146
1147 /*
1148 * ignore action on the default table - this is always present
1149 * and cannot be added nor deleted from the API
1150 */
1151 if (0 != table_id)
1152 {
1153 /*
1154 * The API holds only one lock on the table.
1155 * i.e. it can be added many times via the API but needs to be
1156 * deleted only once.
1157 * The FIB index for unicast and multicast is not necessarily the
1158 * same, since internal VPP systesm (like LISP and SR) create
1159 * their own unicast tables.
1160 */
1161 fib_index = fib_table_find (fproto, table_id);
1162 mfib_index = mfib_table_find (fproto, table_id);
1163
1164 if (~0 == fib_index)
1165 {
Neale Ranns2297af02017-09-12 09:45:04 -07001166 fib_table_find_or_create_and_lock_w_name (fproto, table_id,
1167 (is_api ?
1168 FIB_SOURCE_API :
1169 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001170 }
1171 if (~0 == mfib_index)
1172 {
Neale Ranns2297af02017-09-12 09:45:04 -07001173 mfib_table_find_or_create_and_lock_w_name (fproto, table_id,
1174 (is_api ?
1175 MFIB_SOURCE_API :
1176 MFIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001177 }
1178 }
1179}
1180
Neale Ranns32e1c012016-11-22 17:07:28 +00001181static int
1182add_del_mroute_check (fib_protocol_t table_proto,
1183 u32 table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001184 u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001185{
1186 vnet_main_t *vnm = vnet_get_main ();
1187
1188 *fib_index = mfib_table_find (table_proto, ntohl (table_id));
1189 if (~0 == *fib_index)
1190 {
Neale Ranns15002542017-09-10 04:39:11 -07001191 /* No such table */
1192 return VNET_API_ERROR_NO_SUCH_FIB;
Neale Ranns32e1c012016-11-22 17:07:28 +00001193 }
1194
1195 if (~0 != ntohl (next_hop_sw_if_index))
1196 {
1197 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1198 ntohl (next_hop_sw_if_index)))
1199 {
1200 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1201 }
1202 }
1203
1204 return (0);
1205}
1206
1207static int
1208mroute_add_del_handler (u8 is_add,
1209 u8 is_local,
1210 u32 fib_index,
1211 const mfib_prefix_t * prefix,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001212 dpo_proto_t nh_proto,
Neale Ranns32e1c012016-11-22 17:07:28 +00001213 u32 entry_flags,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001214 fib_rpf_id_t rpf_id,
Neale Rannse821ab12017-06-01 07:45:05 -07001215 u32 next_hop_sw_if_index,
1216 ip46_address_t * nh, u32 itf_flags, u32 bier_imp)
Neale Ranns32e1c012016-11-22 17:07:28 +00001217{
1218 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
1219
1220 fib_route_path_t path = {
1221 .frp_sw_if_index = next_hop_sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001222 .frp_proto = nh_proto,
Neale Rannse821ab12017-06-01 07:45:05 -07001223 .frp_addr = *nh,
Neale Ranns32e1c012016-11-22 17:07:28 +00001224 };
1225
1226 if (is_local)
1227 path.frp_flags |= FIB_ROUTE_PATH_LOCAL;
1228
Neale Rannsd792d9c2017-10-21 10:53:20 -07001229 if (DPO_PROTO_BIER == nh_proto)
1230 {
1231 path.frp_bier_imp = bier_imp;
1232 path.frp_flags = FIB_ROUTE_PATH_BIER_IMP;
1233 }
1234 else if (!is_local && ~0 == next_hop_sw_if_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001235 {
1236 mfib_table_entry_update (fib_index, prefix,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001237 MFIB_SOURCE_API, rpf_id, entry_flags);
Neale Rannsd792d9c2017-10-21 10:53:20 -07001238 goto done;
1239 }
1240
1241 if (is_add)
1242 {
1243 mfib_table_entry_path_update (fib_index, prefix,
1244 MFIB_SOURCE_API, &path, itf_flags);
Neale Ranns32e1c012016-11-22 17:07:28 +00001245 }
1246 else
1247 {
Neale Rannsd792d9c2017-10-21 10:53:20 -07001248 mfib_table_entry_path_remove (fib_index, prefix,
1249 MFIB_SOURCE_API, &path);
Neale Ranns32e1c012016-11-22 17:07:28 +00001250 }
1251
Neale Rannsd792d9c2017-10-21 10:53:20 -07001252done:
Neale Ranns32e1c012016-11-22 17:07:28 +00001253 stats_dsunlock ();
1254 return (0);
1255}
1256
1257static int
1258api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1259{
1260 fib_protocol_t fproto;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001261 dpo_proto_t nh_proto;
Neale Rannse821ab12017-06-01 07:45:05 -07001262 ip46_address_t nh;
Neale Ranns32e1c012016-11-22 17:07:28 +00001263 u32 fib_index;
1264 int rv;
1265
Neale Rannsd792d9c2017-10-21 10:53:20 -07001266 nh_proto = mp->next_hop_afi;
Neale Ranns32e1c012016-11-22 17:07:28 +00001267 fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
1268 rv = add_del_mroute_check (fproto,
1269 mp->table_id,
1270 mp->next_hop_sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07001271 mp->is_local, &fib_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001272
1273 if (0 != rv)
1274 return (rv);
1275
1276 mfib_prefix_t pfx = {
1277 .fp_len = ntohs (mp->grp_address_length),
1278 .fp_proto = fproto,
1279 };
1280
1281 if (FIB_PROTOCOL_IP4 == fproto)
1282 {
1283 clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address,
1284 sizeof (pfx.fp_grp_addr.ip4));
1285 clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
1286 sizeof (pfx.fp_src_addr.ip4));
Neale Rannse821ab12017-06-01 07:45:05 -07001287 memset (&nh.ip6, 0, sizeof (nh.ip6));
1288 clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4));
Neale Ranns32e1c012016-11-22 17:07:28 +00001289 }
1290 else
1291 {
1292 clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address,
1293 sizeof (pfx.fp_grp_addr.ip6));
1294 clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
1295 sizeof (pfx.fp_src_addr.ip6));
Neale Rannse821ab12017-06-01 07:45:05 -07001296 clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6));
Neale Ranns32e1c012016-11-22 17:07:28 +00001297 }
1298
1299 return (mroute_add_del_handler (mp->is_add,
1300 mp->is_local,
1301 fib_index, &pfx,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001302 nh_proto,
Neale Ranns32e1c012016-11-22 17:07:28 +00001303 ntohl (mp->entry_flags),
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001304 ntohl (mp->rpf_id),
Neale Ranns32e1c012016-11-22 17:07:28 +00001305 ntohl (mp->next_hop_sw_if_index),
Neale Rannse821ab12017-06-01 07:45:05 -07001306 &nh,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001307 ntohl (mp->itf_flags),
1308 ntohl (mp->bier_imp)));
Neale Ranns32e1c012016-11-22 17:07:28 +00001309}
1310
1311void
1312vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1313{
1314 vl_api_ip_mroute_add_del_reply_t *rmp;
1315 int rv;
1316 vnet_main_t *vnm = vnet_get_main ();
1317
1318 vnm->api_errno = 0;
1319
1320 rv = api_mroute_add_del_t_handler (mp);
1321
1322 rv = (rv == 0) ? vnm->api_errno : rv;
1323
1324 REPLY_MACRO (VL_API_IP_MROUTE_ADD_DEL_REPLY);
1325}
1326
Dave Barachb5e8a772016-12-06 12:04:42 -05001327static void
1328send_ip_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001329 vl_api_registration_t * reg, u32 sw_if_index, u8 is_ipv6,
1330 u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001331{
1332 vl_api_ip_details_t *mp;
1333
1334 mp = vl_msg_api_alloc (sizeof (*mp));
1335 memset (mp, 0, sizeof (*mp));
1336 mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
1337
1338 mp->sw_if_index = ntohl (sw_if_index);
Jon Loeliger466f0d42017-02-09 12:17:50 -06001339 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001340 mp->context = context;
1341
Florin Coras6c4dae22018-01-09 06:39:23 -08001342 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -05001343}
1344
1345static void
1346send_ip_address_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001347 vl_api_registration_t * reg,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001348 u8 * ip, u16 prefix_length,
1349 u32 sw_if_index, u8 is_ipv6, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001350{
1351 vl_api_ip_address_details_t *mp;
1352
1353 mp = vl_msg_api_alloc (sizeof (*mp));
1354 memset (mp, 0, sizeof (*mp));
1355 mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
1356
1357 if (is_ipv6)
1358 {
1359 clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
1360 }
1361 else
1362 {
1363 u32 *tp = (u32 *) mp->ip;
1364 *tp = *(u32 *) ip;
1365 }
1366 mp->prefix_length = prefix_length;
1367 mp->context = context;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001368 mp->sw_if_index = htonl (sw_if_index);
1369 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001370
Florin Coras6c4dae22018-01-09 06:39:23 -08001371 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -05001372}
1373
1374static void
1375vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
1376{
1377 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001378 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001379 ip6_address_t *r6;
1380 ip4_address_t *r4;
1381 ip6_main_t *im6 = &ip6_main;
1382 ip4_main_t *im4 = &ip4_main;
1383 ip_lookup_main_t *lm6 = &im6->lookup_main;
1384 ip_lookup_main_t *lm4 = &im4->lookup_main;
1385 ip_interface_address_t *ia = 0;
1386 u32 sw_if_index = ~0;
1387 int rv __attribute__ ((unused)) = 0;
1388
1389 VALIDATE_SW_IF_INDEX (mp);
1390
1391 sw_if_index = ntohl (mp->sw_if_index);
1392
Florin Coras6c4dae22018-01-09 06:39:23 -08001393 reg = vl_api_client_index_to_registration (mp->client_index);
1394 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -05001395 return;
1396
Dave Barachb5e8a772016-12-06 12:04:42 -05001397 if (mp->is_ipv6)
1398 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001399 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001400 /* Do not send subnet details of the IP-interface for
1401 * unnumbered interfaces. otherwise listening clients
1402 * will be confused that the subnet is applied on more
1403 * than one interface */
1404 foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001405 ({
1406 r6 = ip_interface_address_get_address (lm6, ia);
1407 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001408 send_ip_address_details(am, reg, (u8*)r6, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001409 sw_if_index, 1, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001410 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001411 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001412 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001413 else
1414 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001415 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001416 foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001417 ({
1418 r4 = ip_interface_address_get_address (lm4, ia);
1419 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001420 send_ip_address_details(am, reg, (u8*)r4, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001421 sw_if_index, 0, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001422 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001423 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001424 }
Neale Ranns008dbe12018-09-07 09:32:36 -07001425
Dave Barachb5e8a772016-12-06 12:04:42 -05001426 BAD_SW_IF_INDEX_LABEL;
1427}
1428
1429static void
Neale Ranns9e2f9152018-05-18 02:27:10 -07001430send_ip_unnumbered_details (vpe_api_main_t * am,
1431 vl_api_registration_t * reg,
1432 u32 sw_if_index, u32 ip_sw_if_index, u32 context)
1433{
1434 vl_api_ip_unnumbered_details_t *mp;
1435
1436 mp = vl_msg_api_alloc (sizeof (*mp));
1437 memset (mp, 0, sizeof (*mp));
1438 mp->_vl_msg_id = ntohs (VL_API_IP_UNNUMBERED_DETAILS);
1439
1440 mp->context = context;
1441 mp->sw_if_index = htonl (sw_if_index);
1442 mp->ip_sw_if_index = htonl (ip_sw_if_index);
1443
1444 vl_api_send_msg (reg, (u8 *) mp);
1445}
1446
1447static void
1448vl_api_ip_unnumbered_dump_t_handler (vl_api_ip_unnumbered_dump_t * mp)
1449{
1450 vnet_main_t *vnm = vnet_get_main ();
1451 vnet_interface_main_t *im = &vnm->interface_main;
1452 int rv __attribute__ ((unused)) = 0;
1453 vpe_api_main_t *am = &vpe_api_main;
1454 vl_api_registration_t *reg;
1455 vnet_sw_interface_t *si;
1456 u32 sw_if_index;
1457
1458 sw_if_index = ntohl (mp->sw_if_index);
1459
1460 reg = vl_api_client_index_to_registration (mp->client_index);
1461 if (!reg)
1462 return;
1463
1464 if (~0 != sw_if_index)
1465 {
1466 VALIDATE_SW_IF_INDEX (mp);
1467
1468 si = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
1469
1470 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1471 {
1472 send_ip_unnumbered_details (am, reg,
1473 sw_if_index,
1474 si->unnumbered_sw_if_index,
1475 mp->context);
1476 }
1477 }
1478 else
1479 {
1480 /* *INDENT-OFF* */
1481 pool_foreach (si, im->sw_interfaces,
1482 ({
1483 if ((si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1484 {
1485 send_ip_unnumbered_details(am, reg,
1486 si->sw_if_index,
1487 si->unnumbered_sw_if_index,
1488 mp->context);
1489 }
1490 }));
1491 /* *INDENT-ON* */
1492 }
1493
1494 BAD_SW_IF_INDEX_LABEL;
1495}
1496
1497static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001498vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
1499{
1500 vpe_api_main_t *am = &vpe_api_main;
1501 vnet_main_t *vnm = vnet_get_main ();
1502 vlib_main_t *vm = vlib_get_main ();
1503 vnet_interface_main_t *im = &vnm->interface_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001504 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001505 vnet_sw_interface_t *si, *sorted_sis;
1506 u32 sw_if_index = ~0;
1507
Florin Coras6c4dae22018-01-09 06:39:23 -08001508 reg = vl_api_client_index_to_registration (mp->client_index);
1509 if (!reg)
1510 return;
Dave Barachb5e8a772016-12-06 12:04:42 -05001511
1512 /* Gather interfaces. */
1513 sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
1514 _vec_len (sorted_sis) = 0;
1515 /* *INDENT-OFF* */
1516 pool_foreach (si, im->sw_interfaces,
1517 ({
1518 vec_add1 (sorted_sis, si[0]);
1519 }));
1520 /* *INDENT-ON* */
1521
1522 vec_foreach (si, sorted_sis)
1523 {
1524 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1525 {
1526 if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
1527 {
1528 continue;
1529 }
1530 sw_if_index = si->sw_if_index;
Florin Coras6c4dae22018-01-09 06:39:23 -08001531 send_ip_details (am, reg, sw_if_index, mp->is_ipv6, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001532 }
1533 }
1534}
1535
1536static void
1537set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1538{
1539 vl_api_set_ip_flow_hash_reply_t *rmp;
Neale Ranns227038a2017-04-21 01:07:59 -07001540 int rv;
1541 u32 table_id;
1542 flow_hash_config_t flow_hash_config = 0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001543
Neale Ranns227038a2017-04-21 01:07:59 -07001544 table_id = ntohl (mp->vrf_id);
1545
1546#define _(a,b) if (mp->a) flow_hash_config |= b;
1547 foreach_flow_hash_bit;
1548#undef _
1549
1550 rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
Dave Barachb5e8a772016-12-06 12:04:42 -05001551
1552 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1553}
1554
1555static void
1556set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1557{
1558 vl_api_set_ip_flow_hash_reply_t *rmp;
1559 int rv;
1560 u32 table_id;
1561 flow_hash_config_t flow_hash_config = 0;
1562
1563 table_id = ntohl (mp->vrf_id);
1564
1565#define _(a,b) if (mp->a) flow_hash_config |= b;
1566 foreach_flow_hash_bit;
1567#undef _
1568
1569 rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
1570
1571 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1572}
1573
1574
1575static void
1576vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t * mp)
1577{
1578 if (mp->is_ipv6 == 0)
1579 set_ip4_flow_hash (mp);
1580 else
1581 set_ip6_flow_hash (mp);
1582}
1583
1584static void
1585 vl_api_sw_interface_ip6nd_ra_config_t_handler
1586 (vl_api_sw_interface_ip6nd_ra_config_t * mp)
1587{
1588 vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
1589 vlib_main_t *vm = vlib_get_main ();
1590 int rv = 0;
1591 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
1592 default_router;
1593
1594 is_no = mp->is_no == 1;
1595 suppress = mp->suppress == 1;
1596 managed = mp->managed == 1;
1597 other = mp->other == 1;
1598 ll_option = mp->ll_option == 1;
1599 send_unicast = mp->send_unicast == 1;
1600 cease = mp->cease == 1;
1601 default_router = mp->default_router == 1;
1602
1603 VALIDATE_SW_IF_INDEX (mp);
1604
1605 rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
1606 suppress, managed, other,
1607 ll_option, send_unicast, cease,
1608 default_router, ntohl (mp->lifetime),
1609 ntohl (mp->initial_count),
1610 ntohl (mp->initial_interval),
1611 ntohl (mp->max_interval),
1612 ntohl (mp->min_interval), is_no);
1613
1614 BAD_SW_IF_INDEX_LABEL;
1615
1616 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
1617}
1618
1619static void
1620 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
1621 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
1622{
1623 vlib_main_t *vm = vlib_get_main ();
1624 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
1625 int rv = 0;
1626 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
1627
1628 VALIDATE_SW_IF_INDEX (mp);
1629
1630 is_no = mp->is_no == 1;
1631 use_default = mp->use_default == 1;
1632 no_advertise = mp->no_advertise == 1;
1633 off_link = mp->off_link == 1;
1634 no_autoconfig = mp->no_autoconfig == 1;
1635 no_onlink = mp->no_onlink == 1;
1636
1637 rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
1638 (ip6_address_t *) mp->address,
1639 mp->address_length, use_default,
1640 ntohl (mp->val_lifetime),
1641 ntohl (mp->pref_lifetime), no_advertise,
1642 off_link, no_autoconfig, no_onlink, is_no);
1643
1644 BAD_SW_IF_INDEX_LABEL;
1645 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
1646}
1647
1648static void
Florin Coras6c4dae22018-01-09 06:39:23 -08001649send_ip6nd_proxy_details (vl_api_registration_t * reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001650 u32 context,
1651 const ip46_address_t * addr, u32 sw_if_index)
1652{
1653 vl_api_ip6nd_proxy_details_t *mp;
1654
1655 mp = vl_msg_api_alloc (sizeof (*mp));
1656 memset (mp, 0, sizeof (*mp));
1657 mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
1658 mp->context = context;
1659 mp->sw_if_index = htonl (sw_if_index);
1660 memcpy (mp->address, addr, 16);
1661
Florin Coras6c4dae22018-01-09 06:39:23 -08001662 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns3f844d02017-02-18 00:03:54 -08001663}
1664
Neale Ranns3f844d02017-02-18 00:03:54 -08001665typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
1666{
1667 u32 *indices;
1668} api_ip6nd_proxy_fib_table_walk_ctx_t;
1669
Neale Ranns89541992017-04-06 04:41:02 -07001670static fib_table_walk_rc_t
Neale Ranns3f844d02017-02-18 00:03:54 -08001671api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
1672{
1673 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
1674
1675 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
1676 {
1677 vec_add1 (ctx->indices, fei);
1678 }
1679
Neale Ranns89541992017-04-06 04:41:02 -07001680 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns3f844d02017-02-18 00:03:54 -08001681}
1682
1683static void
1684vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
1685{
1686 ip6_main_t *im6 = &ip6_main;
1687 fib_table_t *fib_table;
1688 api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
1689 .indices = NULL,
1690 };
1691 fib_node_index_t *feip;
Neale Rannsc5d43172018-07-30 08:04:40 -07001692 const fib_prefix_t *pfx;
Florin Coras6c4dae22018-01-09 06:39:23 -08001693 vl_api_registration_t *reg;
Neale Ranns3f844d02017-02-18 00:03:54 -08001694
Florin Coras6c4dae22018-01-09 06:39:23 -08001695 reg = vl_api_client_index_to_registration (mp->client_index);
1696 if (!reg)
1697 return;
Neale Ranns3f844d02017-02-18 00:03:54 -08001698
1699 /* *INDENT-OFF* */
1700 pool_foreach (fib_table, im6->fibs,
1701 ({
1702 fib_table_walk(fib_table->ft_index,
1703 FIB_PROTOCOL_IP6,
1704 api_ip6nd_proxy_fib_table_walk,
1705 &ctx);
1706 }));
1707 /* *INDENT-ON* */
1708
1709 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
1710
1711 vec_foreach (feip, ctx.indices)
1712 {
Neale Rannsc5d43172018-07-30 08:04:40 -07001713 pfx = fib_entry_get_prefix (*feip);
Neale Ranns3f844d02017-02-18 00:03:54 -08001714
Florin Coras6c4dae22018-01-09 06:39:23 -08001715 send_ip6nd_proxy_details (reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001716 mp->context,
Neale Rannsc5d43172018-07-30 08:04:40 -07001717 &pfx->fp_addr,
Neale Ranns3f844d02017-02-18 00:03:54 -08001718 fib_entry_get_resolving_interface (*feip));
1719 }
1720
1721 vec_free (ctx.indices);
1722}
1723
1724static void
1725vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
1726{
1727 vl_api_ip6nd_proxy_add_del_reply_t *rmp;
1728 int rv = 0;
1729
1730 VALIDATE_SW_IF_INDEX (mp);
1731
1732 rv = ip6_neighbor_proxy_add_del (ntohl (mp->sw_if_index),
1733 (ip6_address_t *) mp->address, mp->is_del);
1734
1735 BAD_SW_IF_INDEX_LABEL;
1736 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
1737}
1738
1739static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01001740 vl_api_ip6nd_send_router_solicitation_t_handler
1741 (vl_api_ip6nd_send_router_solicitation_t * mp)
1742{
1743 vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
1744 icmp6_send_router_solicitation_params_t params;
1745 vlib_main_t *vm = vlib_get_main ();
1746 int rv = 0;
1747
1748 VALIDATE_SW_IF_INDEX (mp);
1749
1750 BAD_SW_IF_INDEX_LABEL;
1751 REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
1752
1753 if (rv != 0)
1754 return;
1755
1756 params.irt = ntohl (mp->irt);
1757 params.mrt = ntohl (mp->mrt);
1758 params.mrc = ntohl (mp->mrc);
1759 params.mrd = ntohl (mp->mrd);
1760
1761 icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
1762 &params);
1763}
1764
1765static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001766 vl_api_sw_interface_ip6_enable_disable_t_handler
1767 (vl_api_sw_interface_ip6_enable_disable_t * mp)
1768{
1769 vlib_main_t *vm = vlib_get_main ();
1770 vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
1771 vnet_main_t *vnm = vnet_get_main ();
1772 int rv = 0;
1773 clib_error_t *error;
1774
1775 vnm->api_errno = 0;
1776
1777 VALIDATE_SW_IF_INDEX (mp);
1778
1779 error =
1780 (mp->enable == 1) ? enable_ip6_interface (vm,
1781 ntohl (mp->sw_if_index)) :
1782 disable_ip6_interface (vm, ntohl (mp->sw_if_index));
1783
1784 if (error)
1785 {
1786 clib_error_report (error);
1787 rv = VNET_API_ERROR_UNSPECIFIED;
1788 }
1789 else
1790 {
1791 rv = vnm->api_errno;
1792 }
1793
1794 BAD_SW_IF_INDEX_LABEL;
1795
1796 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
1797}
1798
1799static void
1800 vl_api_sw_interface_ip6_set_link_local_address_t_handler
1801 (vl_api_sw_interface_ip6_set_link_local_address_t * mp)
1802{
1803 vlib_main_t *vm = vlib_get_main ();
1804 vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp;
1805 int rv = 0;
1806 clib_error_t *error;
1807 vnet_main_t *vnm = vnet_get_main ();
1808
1809 vnm->api_errno = 0;
1810
1811 VALIDATE_SW_IF_INDEX (mp);
1812
1813 error = set_ip6_link_local_address (vm,
1814 ntohl (mp->sw_if_index),
Neale Ranns75152282017-01-09 01:00:45 -08001815 (ip6_address_t *) mp->address);
Dave Barachb5e8a772016-12-06 12:04:42 -05001816 if (error)
1817 {
1818 clib_error_report (error);
1819 rv = VNET_API_ERROR_UNSPECIFIED;
1820 }
1821 else
1822 {
1823 rv = vnm->api_errno;
1824 }
1825
1826 BAD_SW_IF_INDEX_LABEL;
1827
1828 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
1829}
1830
Neale Ranns32e1c012016-11-22 17:07:28 +00001831void
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001832vl_mfib_signal_send_one (vl_api_registration_t * reg,
Neale Ranns32e1c012016-11-22 17:07:28 +00001833 u32 context, const mfib_signal_t * mfs)
1834{
1835 vl_api_mfib_signal_details_t *mp;
1836 mfib_prefix_t prefix;
1837 mfib_table_t *mfib;
1838 mfib_itf_t *mfi;
1839
1840 mp = vl_msg_api_alloc (sizeof (*mp));
1841
1842 memset (mp, 0, sizeof (*mp));
1843 mp->_vl_msg_id = ntohs (VL_API_MFIB_SIGNAL_DETAILS);
1844 mp->context = context;
1845
1846 mfi = mfib_itf_get (mfs->mfs_itf);
1847 mfib_entry_get_prefix (mfs->mfs_entry, &prefix);
1848 mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry),
1849 prefix.fp_proto);
1850 mp->table_id = ntohl (mfib->mft_table_id);
1851 mp->sw_if_index = ntohl (mfi->mfi_sw_if_index);
1852
1853 if (FIB_PROTOCOL_IP4 == prefix.fp_proto)
1854 {
1855 mp->grp_address_len = ntohs (prefix.fp_len);
1856
1857 memcpy (mp->grp_address, &prefix.fp_grp_addr.ip4, 4);
1858 if (prefix.fp_len > 32)
1859 {
1860 memcpy (mp->src_address, &prefix.fp_src_addr.ip4, 4);
1861 }
1862 }
1863 else
1864 {
1865 mp->grp_address_len = ntohs (prefix.fp_len);
1866
1867 ASSERT (0);
1868 }
1869
1870 if (0 != mfs->mfs_buffer_len)
1871 {
1872 mp->ip_packet_len = ntohs (mfs->mfs_buffer_len);
1873
1874 memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len);
1875 }
1876 else
1877 {
1878 mp->ip_packet_len = 0;
1879 }
1880
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001881 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns32e1c012016-11-22 17:07:28 +00001882}
1883
1884static void
1885vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
1886{
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001887 vl_api_registration_t *reg;
Neale Ranns32e1c012016-11-22 17:07:28 +00001888
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001889 reg = vl_api_client_index_to_registration (mp->client_index);
1890 if (!reg)
1891 return;
Neale Ranns32e1c012016-11-22 17:07:28 +00001892
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001893 while (vl_api_can_send_msg (reg) && mfib_signal_send_one (reg, mp->context))
Neale Ranns32e1c012016-11-22 17:07:28 +00001894 ;
1895}
Dave Barachb5e8a772016-12-06 12:04:42 -05001896
Florin Coras595992c2017-11-06 17:17:08 -08001897static void
1898 vl_api_ip_container_proxy_add_del_t_handler
1899 (vl_api_ip_container_proxy_add_del_t * mp)
1900{
1901 vl_api_ip_container_proxy_add_del_reply_t *rmp;
1902 vnet_ip_container_proxy_args_t args;
1903 int rv = 0;
1904 clib_error_t *error;
1905
1906 memset (&args, 0, sizeof (args));
1907 ip_set (&args.prefix.fp_addr, mp->ip, mp->is_ip4);
1908 args.prefix.fp_len = mp->plen ? mp->plen : (mp->is_ip4 ? 32 : 128);
1909 args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1910 args.is_add = mp->is_add;
1911 if ((error = vnet_ip_container_proxy_add_del (&args)))
1912 {
1913 rv = clib_error_get_code (error);
1914 clib_error_report (error);
1915 }
1916
1917 REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY);
1918}
1919
Neale Rannsb8d44812017-11-10 06:53:54 -08001920static void
1921vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
1922{
1923 int rv = 0;
1924 vl_api_ioam_enable_reply_t *rmp;
1925 clib_error_t *error;
1926
1927 /* Ignoring the profile id as currently a single profile
1928 * is supported */
1929 error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
1930 mp->seqno, mp->analyse);
1931 if (error)
1932 {
1933 clib_error_report (error);
1934 rv = clib_error_get_code (error);
1935 }
1936
1937 REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
1938}
1939
1940static void
1941vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
1942{
1943 int rv = 0;
1944 vl_api_ioam_disable_reply_t *rmp;
1945 clib_error_t *error;
1946
1947 error = clear_ioam_rewrite_fn ();
1948 if (error)
1949 {
1950 clib_error_report (error);
1951 rv = clib_error_get_code (error);
1952 }
1953
1954 REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
1955}
1956
1957static void
1958 vl_api_ip_source_and_port_range_check_add_del_t_handler
1959 (vl_api_ip_source_and_port_range_check_add_del_t * mp)
1960{
1961 vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
1962 int rv = 0;
1963
1964 u8 is_ipv6 = mp->is_ipv6;
1965 u8 is_add = mp->is_add;
1966 u8 mask_length = mp->mask_length;
1967 ip4_address_t ip4_addr;
1968 ip6_address_t ip6_addr;
1969 u16 *low_ports = 0;
1970 u16 *high_ports = 0;
1971 u32 vrf_id;
1972 u16 tmp_low, tmp_high;
1973 u8 num_ranges;
1974 int i;
1975
1976 // Validate port range
1977 num_ranges = mp->number_of_ranges;
1978 if (num_ranges > 32)
1979 { // This is size of array in VPE.API
1980 rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
1981 goto reply;
1982 }
1983
1984 vec_reset_length (low_ports);
1985 vec_reset_length (high_ports);
1986
1987 for (i = 0; i < num_ranges; i++)
1988 {
1989 tmp_low = mp->low_ports[i];
1990 tmp_high = mp->high_ports[i];
1991 // If tmp_low <= tmp_high then only need to check tmp_low = 0
1992 // If tmp_low <= tmp_high then only need to check tmp_high > 65535
1993 if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
1994 {
1995 rv = VNET_API_ERROR_INVALID_VALUE;
1996 goto reply;
1997 }
1998 vec_add1 (low_ports, tmp_low);
1999 vec_add1 (high_ports, tmp_high + 1);
2000 }
2001
2002 // Validate mask_length
2003 if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
2004 {
2005 rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
2006 goto reply;
2007 }
2008
2009 vrf_id = ntohl (mp->vrf_id);
2010
2011 if (vrf_id < 1)
2012 {
2013 rv = VNET_API_ERROR_INVALID_VALUE;
2014 goto reply;
2015 }
2016
2017
2018 if (is_ipv6)
2019 {
2020 clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
2021 rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
2022 mask_length,
2023 vrf_id,
2024 low_ports,
2025 high_ports, is_add);
2026 }
2027 else
2028 {
2029 clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
2030 rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
2031 mask_length,
2032 vrf_id,
2033 low_ports,
2034 high_ports, is_add);
2035 }
2036
2037reply:
2038 vec_free (low_ports);
2039 vec_free (high_ports);
2040 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
2041}
2042
2043static void
2044 vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
2045 (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
2046{
2047 vlib_main_t *vm = vlib_get_main ();
2048 vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
2049 ip4_main_t *im = &ip4_main;
2050 int rv;
2051 u32 sw_if_index;
2052 u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2053 u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2054 uword *p = 0;
2055 int i;
2056
2057 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
2058 ntohl (mp->tcp_out_vrf_id);
2059 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
2060 ntohl (mp->udp_out_vrf_id);
2061 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
2062 ntohl (mp->tcp_in_vrf_id);
2063 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
2064 ntohl (mp->udp_in_vrf_id);
2065
2066
2067 for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
2068 {
2069 if (vrf_id[i] != 0 && vrf_id[i] != ~0)
2070 {
2071 p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
2072
2073 if (p == 0)
2074 {
2075 rv = VNET_API_ERROR_INVALID_VALUE;
2076 goto reply;
2077 }
2078
2079 fib_index[i] = p[0];
2080 }
2081 else
2082 fib_index[i] = ~0;
2083 }
2084 sw_if_index = ntohl (mp->sw_if_index);
2085
2086 VALIDATE_SW_IF_INDEX (mp);
2087
2088 rv =
2089 set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
2090 mp->is_add);
2091
2092 BAD_SW_IF_INDEX_LABEL;
2093reply:
2094
2095 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
2096}
2097
2098#define IP4_ARP_EVENT 3
2099#define IP6_ND_EVENT 4
2100
2101static int arp_change_delete_callback (u32 pool_index, u8 * notused);
2102static int nd_change_delete_callback (u32 pool_index, u8 * notused);
2103static vlib_node_registration_t ip_resolver_process_node;
2104
2105static void
2106handle_ip4_arp_event (u32 pool_index)
2107{
2108 vpe_api_main_t *vam = &vpe_api_main;
2109 vnet_main_t *vnm = vam->vnet_main;
2110 vlib_main_t *vm = vam->vlib_main;
2111 vl_api_ip4_arp_event_t *event;
2112 vl_api_ip4_arp_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002113 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002114
2115 /* Client can cancel, die, etc. */
2116 if (pool_is_free_index (vam->arp_events, pool_index))
2117 return;
2118
2119 event = pool_elt_at_index (vam->arp_events, pool_index);
2120
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002121 reg = vl_api_client_index_to_registration (event->client_index);
2122 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002123 {
2124 (void) vnet_add_del_ip4_arp_change_event
2125 (vnm, arp_change_delete_callback,
2126 event->pid, &event->address,
2127 ip_resolver_process_node.index, IP4_ARP_EVENT,
2128 ~0 /* pool index, notused */ , 0 /* is_add */ );
2129 return;
2130 }
2131
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002132 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002133 {
2134 mp = vl_msg_api_alloc (sizeof (*mp));
2135 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002136 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002137 }
2138 else
2139 {
2140 static f64 last_time;
2141 /*
2142 * Throttle syslog msgs.
2143 * It's pretty tempting to just revoke the registration...
2144 */
2145 if (vlib_time_now (vm) > last_time + 10.0)
2146 {
2147 clib_warning ("arp event for %U to pid %d: queue stuffed!",
2148 format_ip4_address, &event->address, event->pid);
2149 last_time = vlib_time_now (vm);
2150 }
2151 }
2152}
2153
Neale Rannsf12dad62018-06-04 18:41:24 -07002154static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002155handle_ip6_nd_event (u32 pool_index)
2156{
2157 vpe_api_main_t *vam = &vpe_api_main;
2158 vnet_main_t *vnm = vam->vnet_main;
2159 vlib_main_t *vm = vam->vlib_main;
2160 vl_api_ip6_nd_event_t *event;
2161 vl_api_ip6_nd_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002162 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002163
2164 /* Client can cancel, die, etc. */
2165 if (pool_is_free_index (vam->nd_events, pool_index))
2166 return;
2167
2168 event = pool_elt_at_index (vam->nd_events, pool_index);
2169
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002170 reg = vl_api_client_index_to_registration (event->client_index);
2171 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002172 {
2173 (void) vnet_add_del_ip6_nd_change_event
2174 (vnm, nd_change_delete_callback,
2175 event->pid, &event->address,
2176 ip_resolver_process_node.index, IP6_ND_EVENT,
2177 ~0 /* pool index, notused */ , 0 /* is_add */ );
2178 return;
2179 }
2180
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002181 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002182 {
2183 mp = vl_msg_api_alloc (sizeof (*mp));
2184 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002185 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002186 }
2187 else
2188 {
2189 static f64 last_time;
2190 /*
2191 * Throttle syslog msgs.
2192 * It's pretty tempting to just revoke the registration...
2193 */
2194 if (vlib_time_now (vm) > last_time + 10.0)
2195 {
2196 clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
2197 format_ip6_address, &event->address, event->pid);
2198 last_time = vlib_time_now (vm);
2199 }
2200 }
2201}
2202
2203static uword
2204resolver_process (vlib_main_t * vm,
2205 vlib_node_runtime_t * rt, vlib_frame_t * f)
2206{
2207 volatile f64 timeout = 100.0;
2208 volatile uword *event_data = 0;
2209
2210 while (1)
2211 {
2212 vlib_process_wait_for_event_or_clock (vm, timeout);
2213
2214 uword event_type =
2215 vlib_process_get_events (vm, (uword **) & event_data);
2216
2217 int i;
2218 switch (event_type)
2219 {
2220 case IP4_ARP_EVENT:
2221 for (i = 0; i < vec_len (event_data); i++)
2222 handle_ip4_arp_event (event_data[i]);
2223 break;
2224
2225 case IP6_ND_EVENT:
2226 for (i = 0; i < vec_len (event_data); i++)
2227 handle_ip6_nd_event (event_data[i]);
2228 break;
2229
2230 case ~0: /* timeout */
2231 break;
2232 }
2233
2234 vec_reset_length (event_data);
2235 }
2236 return 0; /* or not */
2237}
2238
2239/* *INDENT-OFF* */
2240VLIB_REGISTER_NODE (ip_resolver_process_node,static) = {
2241 .function = resolver_process,
2242 .type = VLIB_NODE_TYPE_PROCESS,
2243 .name = "ip-route-resolver-process",
2244};
2245/* *INDENT-ON* */
2246
2247static int
2248nd_change_data_callback (u32 pool_index, u8 * new_mac,
2249 u32 sw_if_index, ip6_address_t * address)
2250{
2251 vpe_api_main_t *am = &vpe_api_main;
2252 vl_api_ip6_nd_event_t *event;
2253
2254 if (pool_is_free_index (am->nd_events, pool_index))
2255 return 1;
2256
2257 event = pool_elt_at_index (am->nd_events, pool_index);
2258 if (eth_mac_equal (event->new_mac, new_mac) &&
2259 sw_if_index == ntohl (event->sw_if_index))
2260 {
2261 return 1;
2262 }
2263
2264 clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2265 event->sw_if_index = htonl (sw_if_index);
2266 return 0;
2267}
2268
2269static int
2270arp_change_delete_callback (u32 pool_index, u8 * notused)
2271{
2272 vpe_api_main_t *am = &vpe_api_main;
2273
2274 if (pool_is_free_index (am->arp_events, pool_index))
2275 return 1;
2276
2277 pool_put_index (am->arp_events, pool_index);
2278 return 0;
2279}
2280
2281static int
2282nd_change_delete_callback (u32 pool_index, u8 * notused)
2283{
2284 vpe_api_main_t *am = &vpe_api_main;
2285
2286 if (pool_is_free_index (am->nd_events, pool_index))
2287 return 1;
2288
2289 pool_put_index (am->nd_events, pool_index);
2290 return 0;
2291}
2292
2293static vlib_node_registration_t wc_arp_process_node;
2294
2295enum
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002296{ WC_ARP_REPORT, WC_ND_REPORT, RA_REPORT, REPORT_MAX };
Neale Rannsb8d44812017-11-10 06:53:54 -08002297
2298static uword
2299wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
2300{
2301 /* These cross the longjmp boundry (vlib_process_wait_for_event)
2302 * and need to be volatile - to prevent them from being optimized into
2303 * a register - which could change during suspension */
2304
2305 volatile wc_arp_report_t arp_prev = { 0 };
2306 volatile wc_nd_report_t nd_prev = { 0 };
2307 volatile f64 last_arp = vlib_time_now (vm);
2308 volatile f64 last_nd = vlib_time_now (vm);
2309
2310 while (1)
2311 {
2312 vlib_process_wait_for_event (vm);
2313 uword event_type = WC_ARP_REPORT;
2314 void *event_data = vlib_process_get_event_data (vm, &event_type);
2315
2316 f64 now = vlib_time_now (vm);
2317 int i;
2318 if (event_type == WC_ARP_REPORT)
2319 {
2320 wc_arp_report_t *arp_events = event_data;
2321 for (i = 0; i < vec_len (arp_events); i++)
2322 {
2323 /* discard dup event */
2324 if (arp_prev.ip4 == arp_events[i].ip4 &&
2325 eth_mac_equal ((u8 *) arp_prev.mac, arp_events[i].mac) &&
2326 arp_prev.sw_if_index == arp_events[i].sw_if_index &&
2327 (now - last_arp) < 10.0)
2328 {
2329 continue;
2330 }
2331 arp_prev = arp_events[i];
2332 last_arp = now;
2333 vpe_client_registration_t *reg;
2334 /* *INDENT-OFF* */
2335 pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations,
2336 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002337 vl_api_registration_t *vl_reg;
2338 vl_reg = vl_api_client_index_to_registration (reg->client_index);
Chris Luke30684ac2018-03-29 12:56:58 -07002339 ASSERT (vl_reg != NULL);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002340 if (reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002341 {
2342 vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event);
2343 memset (event, 0, sizeof *event);
2344 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2345 event->client_index = reg->client_index;
2346 event->pid = reg->client_pid;
2347 event->mac_ip = 1;
2348 event->address = arp_events[i].ip4;
2349 event->sw_if_index = htonl(arp_events[i].sw_if_index);
2350 memcpy(event->new_mac, arp_events[i].mac, sizeof event->new_mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002351 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002352 }
2353 }));
2354 /* *INDENT-ON* */
2355 }
2356 }
2357 else if (event_type == WC_ND_REPORT)
2358 {
2359 wc_nd_report_t *nd_events = event_data;
2360 for (i = 0; i < vec_len (nd_events); i++)
2361 {
2362 /* discard dup event */
2363 if (ip6_address_is_equal
2364 ((ip6_address_t *) & nd_prev.ip6, &nd_events[i].ip6)
2365 && eth_mac_equal ((u8 *) nd_prev.mac, nd_events[i].mac)
2366 && nd_prev.sw_if_index == nd_events[i].sw_if_index
2367 && (now - last_nd) < 10.0)
2368 {
2369 continue;
2370 }
2371 nd_prev = nd_events[i];
2372 last_nd = now;
2373 vpe_client_registration_t *reg;
2374 /* *INDENT-OFF* */
2375 pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations,
2376 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002377 vl_api_registration_t *vl_reg;
2378 vl_reg = vl_api_client_index_to_registration (reg->client_index);
2379 if (vl_reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002380 {
2381 vl_api_ip6_nd_event_t * event = vl_msg_api_alloc (sizeof *event);
2382 memset (event, 0, sizeof *event);
2383 event->_vl_msg_id = htons (VL_API_IP6_ND_EVENT);
2384 event->client_index = reg->client_index;
2385 event->pid = reg->client_pid;
2386 event->mac_ip = 1;
2387 memcpy(event->address, nd_events[i].ip6.as_u8, sizeof event->address);
2388 event->sw_if_index = htonl(nd_events[i].sw_if_index);
2389 memcpy(event->new_mac, nd_events[i].mac, sizeof event->new_mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002390 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002391 }
2392 }));
2393 /* *INDENT-ON* */
2394 }
2395 }
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002396 else if (event_type == RA_REPORT)
2397 {
2398 ra_report_t *ra_events = event_data;
2399 for (i = 0; i < vec_len (ra_events); i++)
2400 {
Juraj Sloboda52574522018-05-03 10:03:50 +02002401 ip6_neighbor_public_main_t *npm = &ip6_neighbor_public_main;
2402 call_ip6_neighbor_callbacks (&ra_events[i],
2403 npm->ra_report_functions);
2404
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002405 vpe_client_registration_t *reg;
2406 /* *INDENT-OFF* */
2407 pool_foreach(reg, vpe_api_main.ip6_ra_events_registrations,
2408 ({
2409 vl_api_registration_t *vl_reg;
2410 vl_reg =
2411 vl_api_client_index_to_registration (reg->client_index);
2412 if (vl_reg && vl_api_can_send_msg (vl_reg))
2413 {
2414 u32 event_size =
2415 sizeof (vl_api_ip6_ra_event_t) +
2416 vec_len (ra_events[i].prefixes) *
2417 sizeof (vl_api_ip6_ra_prefix_info_t);
2418 vl_api_ip6_ra_event_t *event =
2419 vl_msg_api_alloc (event_size);
2420 memset (event, 0, event_size);
2421 event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT);
2422 event->client_index = reg->client_index;
2423 event->pid = reg->client_pid;
2424
2425 event->sw_if_index = clib_host_to_net_u32 (ra_events[i].sw_if_index);
2426
2427 memcpy (event->router_address, ra_events[i].router_address, 16);
2428
2429 event->current_hop_limit = ra_events[i].current_hop_limit;
2430 event->flags = ra_events[i].flags;
2431 event->router_lifetime_in_sec =
2432 clib_host_to_net_u16 (ra_events
2433 [i].router_lifetime_in_sec);
2434 event->neighbor_reachable_time_in_msec =
2435 clib_host_to_net_u32 (ra_events
2436 [i].neighbor_reachable_time_in_msec);
2437 event->time_in_msec_between_retransmitted_neighbor_solicitations
2438 =
2439 clib_host_to_net_u32 (ra_events
2440 [i].time_in_msec_between_retransmitted_neighbor_solicitations);
2441
2442 event->n_prefixes =
2443 clib_host_to_net_u32 (vec_len (ra_events[i].prefixes));
2444 vl_api_ip6_ra_prefix_info_t *prefix =
2445 (typeof (prefix)) event->prefixes;
2446 u32 j;
2447 for (j = 0; j < vec_len (ra_events[i].prefixes); j++)
2448 {
2449 ra_report_prefix_info_t *info =
2450 &ra_events[i].prefixes[j];
2451 memcpy (prefix->dst_address, info->dst_address.as_u8,
2452 16);
2453 prefix->dst_address_length = info->dst_address_length;
2454 prefix->flags = info->flags;
2455 prefix->valid_time =
2456 clib_host_to_net_u32 (info->valid_time);
2457 prefix->preferred_time =
2458 clib_host_to_net_u32 (info->preferred_time);
2459 prefix++;
2460 }
2461
2462 vl_api_send_msg (vl_reg, (u8 *) event);
2463 }
2464 }));
Juraj Slobodad7f58cc2018-07-27 11:23:14 +02002465 /* *INDENT-ON* */
2466 vec_free (ra_events[i].prefixes);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002467 }
2468 }
Neale Rannsb8d44812017-11-10 06:53:54 -08002469 vlib_process_put_event_data (vm, event_data);
2470 }
2471
2472 return 0;
2473}
2474
2475/* *INDENT-OFF* */
2476VLIB_REGISTER_NODE (wc_arp_process_node,static) = {
2477 .function = wc_arp_process,
2478 .type = VLIB_NODE_TYPE_PROCESS,
2479 .name = "wildcard-ip4-arp-publisher-process",
2480};
2481/* *INDENT-ON* */
2482
2483static int
2484arp_change_data_callback (u32 pool_index, u8 * new_mac,
2485 u32 sw_if_index, u32 address)
2486{
2487 vpe_api_main_t *am = &vpe_api_main;
2488 vl_api_ip4_arp_event_t *event;
2489
2490 if (pool_is_free_index (am->arp_events, pool_index))
2491 return 1;
2492
2493 event = pool_elt_at_index (am->arp_events, pool_index);
2494 if (eth_mac_equal (event->new_mac, new_mac) &&
2495 sw_if_index == ntohl (event->sw_if_index))
2496 {
2497 return 1;
2498 }
2499
2500 clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2501 event->sw_if_index = htonl (sw_if_index);
2502 return 0;
2503}
2504
2505static void
2506vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
2507{
2508 vpe_api_main_t *am = &vpe_api_main;
2509 vnet_main_t *vnm = vnet_get_main ();
2510 vl_api_want_ip4_arp_events_reply_t *rmp;
2511 int rv = 0;
2512
2513 if (mp->address == 0)
2514 {
2515 uword *p =
2516 hash_get (am->wc_ip4_arp_events_registration_hash, mp->client_index);
2517 vpe_client_registration_t *rp;
2518 if (p)
2519 {
2520 if (mp->enable_disable)
2521 {
2522 clib_warning ("pid %d: already enabled...", mp->pid);
2523 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2524 goto reply;
2525 }
2526 else
2527 {
2528 rp =
2529 pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2530 pool_put (am->wc_ip4_arp_events_registrations, rp);
2531 hash_unset (am->wc_ip4_arp_events_registration_hash,
2532 mp->client_index);
2533 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002534 wc_arp_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002535 goto reply;
2536 }
2537 }
2538 if (mp->enable_disable == 0)
2539 {
2540 clib_warning ("pid %d: already disabled...", mp->pid);
2541 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2542 goto reply;
2543 }
2544 pool_get (am->wc_ip4_arp_events_registrations, rp);
2545 rp->client_index = mp->client_index;
2546 rp->client_pid = mp->pid;
2547 hash_set (am->wc_ip4_arp_events_registration_hash, rp->client_index,
2548 rp - am->wc_ip4_arp_events_registrations);
2549 wc_arp_set_publisher_node (wc_arp_process_node.index, WC_ARP_REPORT);
2550 goto reply;
2551 }
2552
2553 if (mp->enable_disable)
2554 {
2555 vl_api_ip4_arp_event_t *event;
2556 pool_get (am->arp_events, event);
2557 rv = vnet_add_del_ip4_arp_change_event
2558 (vnm, arp_change_data_callback,
2559 mp->pid, &mp->address /* addr, in net byte order */ ,
2560 ip_resolver_process_node.index,
2561 IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
2562
2563 if (rv)
2564 {
2565 pool_put (am->arp_events, event);
2566 goto reply;
2567 }
2568 memset (event, 0, sizeof (*event));
2569
2570 /* Python API expects events to have no context */
2571 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2572 event->client_index = mp->client_index;
2573 event->address = mp->address;
2574 event->pid = mp->pid;
2575 if (mp->address == 0)
2576 event->mac_ip = 1;
2577 }
2578 else
2579 {
2580 rv = vnet_add_del_ip4_arp_change_event
2581 (vnm, arp_change_delete_callback,
2582 mp->pid, &mp->address /* addr, in net byte order */ ,
2583 ip_resolver_process_node.index,
2584 IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2585 }
2586reply:
2587 REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
2588}
2589
Neale Rannsf12dad62018-06-04 18:41:24 -07002590static clib_error_t *
2591want_ip4_arp_events_reaper (u32 client_index)
2592{
2593 vpe_client_registration_t *rp;
2594 vl_api_ip4_arp_event_t *event;
2595 u32 *to_delete, *event_id;
2596 vpe_api_main_t *am;
2597 vnet_main_t *vnm;
2598 uword *p;
2599
2600 am = &vpe_api_main;
2601 vnm = vnet_get_main ();
2602 to_delete = NULL;
2603
2604 /* clear out all of its pending resolutions */
2605 /* *INDENT-OFF* */
2606 pool_foreach(event, am->arp_events,
2607 ({
2608 if (event->client_index == client_index)
2609 {
2610 vec_add1(to_delete, event - am->arp_events);
2611 }
2612 }));
2613 /* *INDENT-ON* */
2614
2615 vec_foreach (event_id, to_delete)
2616 {
2617 event = pool_elt_at_index (am->arp_events, *event_id);
2618 vnet_add_del_ip4_arp_change_event
2619 (vnm, arp_change_delete_callback,
2620 event->pid, &event->address,
2621 ip_resolver_process_node.index, IP4_ARP_EVENT,
2622 ~0 /* pool index, notused */ , 0 /* is_add */ );
2623 }
2624 vec_free (to_delete);
2625
2626 /* remove from the registration hash */
2627 p = hash_get (am->wc_ip4_arp_events_registration_hash, client_index);
2628
2629 if (p)
2630 {
2631 rp = pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2632 pool_put (am->wc_ip4_arp_events_registrations, rp);
2633 hash_unset (am->wc_ip4_arp_events_registration_hash, client_index);
2634 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
2635 wc_arp_set_publisher_node (~0, REPORT_MAX);
2636 }
2637 return (NULL);
2638}
2639
2640VL_MSG_API_REAPER_FUNCTION (want_ip4_arp_events_reaper);
2641
Neale Rannsb8d44812017-11-10 06:53:54 -08002642static void
2643vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
2644{
2645 vpe_api_main_t *am = &vpe_api_main;
2646 vnet_main_t *vnm = vnet_get_main ();
2647 vl_api_want_ip6_nd_events_reply_t *rmp;
2648 int rv = 0;
2649
2650 if (ip6_address_is_zero ((ip6_address_t *) mp->address))
2651 {
2652 uword *p =
2653 hash_get (am->wc_ip6_nd_events_registration_hash, mp->client_index);
2654 vpe_client_registration_t *rp;
2655 if (p)
2656 {
2657 if (mp->enable_disable)
2658 {
2659 clib_warning ("pid %d: already enabled...", mp->pid);
2660 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2661 goto reply;
2662 }
2663 else
2664 {
2665 rp =
2666 pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2667 pool_put (am->wc_ip6_nd_events_registrations, rp);
2668 hash_unset (am->wc_ip6_nd_events_registration_hash,
2669 mp->client_index);
2670 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002671 wc_nd_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002672 goto reply;
2673 }
2674 }
2675 if (mp->enable_disable == 0)
2676 {
2677 clib_warning ("pid %d: already disabled...", mp->pid);
2678 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2679 goto reply;
2680 }
2681 pool_get (am->wc_ip6_nd_events_registrations, rp);
2682 rp->client_index = mp->client_index;
2683 rp->client_pid = mp->pid;
2684 hash_set (am->wc_ip6_nd_events_registration_hash, rp->client_index,
2685 rp - am->wc_ip6_nd_events_registrations);
2686 wc_nd_set_publisher_node (wc_arp_process_node.index, WC_ND_REPORT);
2687 goto reply;
2688 }
2689
2690 if (mp->enable_disable)
2691 {
2692 vl_api_ip6_nd_event_t *event;
2693 pool_get (am->nd_events, event);
2694
2695 rv = vnet_add_del_ip6_nd_change_event
2696 (vnm, nd_change_data_callback,
2697 mp->pid, mp->address /* addr, in net byte order */ ,
2698 ip_resolver_process_node.index,
2699 IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
2700
2701 if (rv)
2702 {
2703 pool_put (am->nd_events, event);
2704 goto reply;
2705 }
2706 memset (event, 0, sizeof (*event));
2707
2708 event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
2709 event->client_index = mp->client_index;
2710 clib_memcpy (event->address, mp->address, sizeof event->address);
2711 event->pid = mp->pid;
2712 }
2713 else
2714 {
2715 rv = vnet_add_del_ip6_nd_change_event
2716 (vnm, nd_change_delete_callback,
2717 mp->pid, mp->address /* addr, in net byte order */ ,
2718 ip_resolver_process_node.index,
2719 IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2720 }
2721reply:
2722 REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
2723}
2724
Neale Rannsf12dad62018-06-04 18:41:24 -07002725static clib_error_t *
2726want_ip6_nd_events_reaper (u32 client_index)
2727{
2728
2729 vpe_client_registration_t *rp;
2730 vl_api_ip6_nd_event_t *event;
2731 u32 *to_delete, *event_id;
2732 vpe_api_main_t *am;
2733 vnet_main_t *vnm;
2734 uword *p;
2735
2736 am = &vpe_api_main;
2737 vnm = vnet_get_main ();
2738 to_delete = NULL;
2739
2740 /* clear out all of its pending resolutions */
2741 /* *INDENT-OFF* */
2742 pool_foreach(event, am->nd_events,
2743 ({
2744 if (event->client_index == client_index)
2745 {
2746 vec_add1(to_delete, event - am->nd_events);
2747 }
2748 }));
2749 /* *INDENT-ON* */
2750
2751 vec_foreach (event_id, to_delete)
2752 {
2753 event = pool_elt_at_index (am->nd_events, *event_id);
2754 vnet_add_del_ip6_nd_change_event
2755 (vnm, nd_change_delete_callback,
2756 event->pid, &event->address,
2757 ip_resolver_process_node.index, IP6_ND_EVENT,
2758 ~0 /* pool index, notused */ , 0 /* is_add */ );
2759 }
2760 vec_free (to_delete);
2761
2762 /* remove from the registration hash */
2763 p = hash_get (am->wc_ip6_nd_events_registration_hash, client_index);
2764
2765 if (p)
2766 {
2767 rp = pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2768 pool_put (am->wc_ip6_nd_events_registrations, rp);
2769 hash_unset (am->wc_ip6_nd_events_registration_hash, client_index);
2770 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
2771 wc_nd_set_publisher_node (~0, REPORT_MAX);
2772 }
2773 return (NULL);
2774}
2775
2776VL_MSG_API_REAPER_FUNCTION (want_ip6_nd_events_reaper);
2777
Neale Rannsb8d44812017-11-10 06:53:54 -08002778static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002779vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
2780{
2781 vpe_api_main_t *am = &vpe_api_main;
2782 vl_api_want_ip6_ra_events_reply_t *rmp;
2783 int rv = 0;
2784
2785 uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
2786 vpe_client_registration_t *rp;
2787 if (p)
2788 {
2789 if (mp->enable_disable)
2790 {
2791 clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
2792 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2793 goto reply;
2794 }
2795 else
2796 {
2797 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2798 pool_put (am->ip6_ra_events_registrations, rp);
2799 hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002800 goto reply;
2801 }
2802 }
2803 if (mp->enable_disable == 0)
2804 {
2805 clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
2806 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2807 goto reply;
2808 }
2809 pool_get (am->ip6_ra_events_registrations, rp);
2810 rp->client_index = mp->client_index;
2811 rp->client_pid = ntohl (mp->pid);
2812 hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
2813 rp - am->ip6_ra_events_registrations);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002814
2815reply:
2816 REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
2817}
2818
Neale Rannsf12dad62018-06-04 18:41:24 -07002819static clib_error_t *
2820want_ip6_ra_events_reaper (u32 client_index)
2821{
2822 vpe_api_main_t *am = &vpe_api_main;
2823 vpe_client_registration_t *rp;
2824 uword *p;
2825
2826 p = hash_get (am->ip6_ra_events_registration_hash, client_index);
2827
2828 if (p)
2829 {
2830 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2831 pool_put (am->ip6_ra_events_registrations, rp);
2832 hash_unset (am->ip6_ra_events_registration_hash, client_index);
2833 }
2834 return (NULL);
2835}
2836
2837VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
2838
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002839static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002840vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
2841{
2842 vl_api_proxy_arp_add_del_reply_t *rmp;
2843 u32 fib_index;
2844 int rv;
2845 ip4_main_t *im = &ip4_main;
Neale Rannsb8d44812017-11-10 06:53:54 -08002846 uword *p;
2847
Ole Troan3288ed72017-12-06 17:00:05 +01002848 stats_dslock_with_hint (1 /* release hint */ , 6 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08002849
Neale Ranns0053de62018-05-22 08:40:52 -07002850 p = hash_get (im->fib_index_by_table_id, ntohl (mp->proxy.vrf_id));
Neale Rannsb8d44812017-11-10 06:53:54 -08002851
2852 if (!p)
2853 {
2854 rv = VNET_API_ERROR_NO_SUCH_FIB;
2855 goto out;
2856 }
2857
2858 fib_index = p[0];
2859
Neale Ranns0053de62018-05-22 08:40:52 -07002860 rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->proxy.low_address,
2861 (ip4_address_t *) mp->proxy.hi_address,
Neale Rannsb8d44812017-11-10 06:53:54 -08002862 fib_index, mp->is_add == 0);
2863
2864out:
Ole Troan3288ed72017-12-06 17:00:05 +01002865 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08002866 REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
2867}
2868
Neale Ranns0053de62018-05-22 08:40:52 -07002869typedef struct proxy_arp_walk_ctx_t_
2870{
2871 vl_api_registration_t *reg;
2872 u32 context;
2873} proxy_arp_walk_ctx_t;
2874
2875static walk_rc_t
2876send_proxy_arp_details (const ip4_address_t * lo_addr,
2877 const ip4_address_t * hi_addr,
2878 u32 fib_index, void *data)
2879{
2880 vl_api_proxy_arp_details_t *mp;
2881 proxy_arp_walk_ctx_t *ctx;
2882
2883 ctx = data;
2884
2885 mp = vl_msg_api_alloc (sizeof (*mp));
2886 memset (mp, 0, sizeof (*mp));
2887 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_DETAILS);
2888 mp->context = ctx->context;
2889 mp->proxy.vrf_id = htonl (fib_index);
2890 clib_memcpy (mp->proxy.low_address, lo_addr,
2891 sizeof (mp->proxy.low_address));
2892 clib_memcpy (mp->proxy.hi_address, hi_addr, sizeof (mp->proxy.hi_address));
2893
2894 vl_api_send_msg (ctx->reg, (u8 *) mp);
2895
2896 return (WALK_CONTINUE);
2897}
2898
2899static void
2900vl_api_proxy_arp_dump_t_handler (vl_api_proxy_arp_dump_t * mp)
2901{
2902 vl_api_registration_t *reg;
2903
2904 reg = vl_api_client_index_to_registration (mp->client_index);
2905 if (!reg)
2906 return;
2907
2908 proxy_arp_walk_ctx_t wctx = {
2909 .reg = reg,
2910 .context = mp->context,
2911 };
2912
2913 proxy_arp_walk (send_proxy_arp_details, &wctx);
2914}
2915
2916static walk_rc_t
2917send_proxy_arp_intfc_details (vnet_main_t * vnm,
2918 vnet_sw_interface_t * si, void *data)
2919{
2920 vl_api_proxy_arp_intfc_details_t *mp;
2921 proxy_arp_walk_ctx_t *ctx;
2922
2923 if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
2924 return (WALK_CONTINUE);
2925
2926 ctx = data;
2927
2928 mp = vl_msg_api_alloc (sizeof (*mp));
2929 memset (mp, 0, sizeof (*mp));
2930 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_INTFC_DETAILS);
2931 mp->context = ctx->context;
2932 mp->sw_if_index = htonl (si->sw_if_index);
2933
2934 vl_api_send_msg (ctx->reg, (u8 *) mp);
2935
2936 return (WALK_CONTINUE);
2937}
2938
2939static void
2940vl_api_proxy_arp_intfc_dump_t_handler (vl_api_proxy_arp_intfc_dump_t * mp)
2941{
2942 vl_api_registration_t *reg;
2943
2944 reg = vl_api_client_index_to_registration (mp->client_index);
2945 if (!reg)
2946 return;
2947
2948 proxy_arp_walk_ctx_t wctx = {
2949 .reg = reg,
2950 .context = mp->context,
2951 };
2952
2953 vnet_sw_interface_walk (vnet_get_main (),
2954 send_proxy_arp_intfc_details, &wctx);
2955}
2956
Neale Rannsb8d44812017-11-10 06:53:54 -08002957static void
2958 vl_api_proxy_arp_intfc_enable_disable_t_handler
2959 (vl_api_proxy_arp_intfc_enable_disable_t * mp)
2960{
2961 int rv = 0;
2962 vnet_main_t *vnm = vnet_get_main ();
2963 vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
2964
2965 VALIDATE_SW_IF_INDEX (mp);
2966
2967 vnet_sw_interface_t *si =
2968 vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
2969
2970 ASSERT (si);
2971
2972 if (mp->enable_disable)
2973 si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2974 else
2975 si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2976
2977 BAD_SW_IF_INDEX_LABEL;
2978
2979 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2980}
2981
John Loc7b43042018-04-13 16:46:22 -04002982static void
2983vl_api_ip_probe_neighbor_t_handler (vl_api_ip_probe_neighbor_t * mp)
2984{
2985 int rv = 0;
2986 vlib_main_t *vm = vlib_get_main ();
2987 vl_api_ip_probe_neighbor_reply_t *rmp;
2988 clib_error_t *error;
2989
2990 VALIDATE_SW_IF_INDEX (mp);
2991
2992 u32 sw_if_index = ntohl (mp->sw_if_index);
2993
2994 if (mp->is_ipv6)
2995 error = ip6_probe_neighbor (vm, (ip6_address_t *) mp->dst_address,
John Lo86376342018-06-11 20:14:49 -04002996 sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04002997 else
2998 error = ip4_probe_neighbor (vm, (ip4_address_t *) mp->dst_address,
John Lo86376342018-06-11 20:14:49 -04002999 sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04003000
3001 if (error)
3002 {
3003 clib_error_report (error);
3004 rv = clib_error_get_code (error);
3005 }
3006
3007 BAD_SW_IF_INDEX_LABEL;
3008
3009 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
3010}
3011
John Lo7f358b32018-04-28 01:19:24 -04003012static void
3013 vl_api_ip_scan_neighbor_enable_disable_t_handler
3014 (vl_api_ip_scan_neighbor_enable_disable_t * mp)
3015{
3016 int rv = 0;
3017 vl_api_ip_scan_neighbor_enable_disable_reply_t *rmp;
3018 ip_neighbor_scan_arg_t arg;
3019
3020 arg.mode = mp->mode;
3021 arg.scan_interval = mp->scan_interval;
3022 arg.max_proc_time = mp->max_proc_time;
3023 arg.max_update = mp->max_update;
3024 arg.scan_int_delay = mp->scan_int_delay;
3025 arg.stale_threshold = mp->stale_threshold;
3026 ip_neighbor_scan_enable_disable (&arg);
3027
3028 REPLY_MACRO (VL_API_IP_SCAN_NEIGHBOR_ENABLE_DISABLE_REPLY);
3029}
3030
Neale Rannsb8d44812017-11-10 06:53:54 -08003031static int
3032ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3033{
3034 vnet_main_t *vnm = vnet_get_main ();
3035 vnet_interface_main_t *im = &vnm->interface_main;
3036 ip4_main_t *im4 = &ip4_main;
3037 static u32 *sw_if_indices_to_shut;
Neale Rannsb8d44812017-11-10 06:53:54 -08003038 fib_table_t *fib_table;
3039 ip4_fib_t *fib;
3040 u32 sw_if_index;
3041 int i;
3042 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3043 u32 target_fib_id = ntohl (mp->vrf_id);
3044
Ole Troan3288ed72017-12-06 17:00:05 +01003045 stats_dslock_with_hint (1 /* release hint */ , 8 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08003046
3047 /* *INDENT-OFF* */
3048 pool_foreach (fib_table, im4->fibs,
3049 ({
3050 vnet_sw_interface_t * si;
3051
3052 fib = pool_elt_at_index (im4->v4_fibs, fib_table->ft_index);
3053
3054 if (fib->table_id != target_fib_id)
3055 continue;
3056
3057 /* remove any mpls encap/decap labels */
3058 mpls_fib_reset_labels (fib->table_id);
3059
3060 /* remove any proxy arps in this fib */
3061 vnet_proxy_arp_fib_reset (fib->table_id);
3062
3063 /* Set the flow hash for this fib to the default */
3064 vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3065
3066 vec_reset_length (sw_if_indices_to_shut);
3067
3068 /* Shut down interfaces in this FIB / clean out intfc routes */
3069 pool_foreach (si, im->sw_interfaces,
3070 ({
3071 u32 sw_if_index = si->sw_if_index;
3072
3073 if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
3074 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
3075 fib->index))
3076 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3077 }));
3078
3079 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3080 sw_if_index = sw_if_indices_to_shut[i];
3081
3082 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3083 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3084 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3085 }
3086
3087 fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
3088
3089 rv = 0;
3090 break;
3091 })); /* pool_foreach (fib) */
3092 /* *INDENT-ON* */
3093
Ole Troan3288ed72017-12-06 17:00:05 +01003094 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08003095 return rv;
3096}
3097
3098static int
3099ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3100{
3101 vnet_main_t *vnm = vnet_get_main ();
3102 vnet_interface_main_t *im = &vnm->interface_main;
3103 ip6_main_t *im6 = &ip6_main;
Neale Rannsb8d44812017-11-10 06:53:54 -08003104 static u32 *sw_if_indices_to_shut;
3105 fib_table_t *fib_table;
3106 ip6_fib_t *fib;
3107 u32 sw_if_index;
3108 int i;
3109 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3110 u32 target_fib_id = ntohl (mp->vrf_id);
3111
Ole Troan3288ed72017-12-06 17:00:05 +01003112 stats_dslock_with_hint (1 /* release hint */ , 9 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08003113
3114 /* *INDENT-OFF* */
3115 pool_foreach (fib_table, im6->fibs,
3116 ({
3117 vnet_sw_interface_t * si;
3118
3119 fib = pool_elt_at_index (im6->v6_fibs, fib_table->ft_index);
3120
3121 if (fib->table_id != target_fib_id)
3122 continue;
3123
3124 vec_reset_length (sw_if_indices_to_shut);
3125
3126 /* Set the flow hash for this fib to the default */
3127 vnet_set_ip6_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3128
3129 /* Shut down interfaces in this FIB / clean out intfc routes */
3130 pool_foreach (si, im->sw_interfaces,
3131 ({
3132 if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
3133 fib->index)
3134 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3135 }));
3136
3137 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3138 sw_if_index = sw_if_indices_to_shut[i];
3139
3140 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3141 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3142 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3143 }
3144
3145 fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
3146
3147 rv = 0;
3148 break;
3149 })); /* pool_foreach (fib) */
3150 /* *INDENT-ON* */
3151
Ole Troan3288ed72017-12-06 17:00:05 +01003152 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08003153 return rv;
3154}
3155
3156static void
3157vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3158{
3159 int rv;
3160 vl_api_reset_fib_reply_t *rmp;
3161
3162 if (mp->is_ipv6)
3163 rv = ip6_reset_fib_t_handler (mp);
3164 else
3165 rv = ip4_reset_fib_t_handler (mp);
3166
3167 REPLY_MACRO (VL_API_RESET_FIB_REPLY);
3168}
3169
3170static void
3171vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
3172{
3173 int rv;
3174 vl_api_set_arp_neighbor_limit_reply_t *rmp;
3175 vnet_main_t *vnm = vnet_get_main ();
3176 clib_error_t *error;
3177
3178 vnm->api_errno = 0;
3179
3180 if (mp->is_ipv6)
3181 error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
3182 else
3183 error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
3184
3185 if (error)
3186 {
3187 clib_error_report (error);
3188 rv = VNET_API_ERROR_UNSPECIFIED;
3189 }
3190 else
3191 {
3192 rv = vnm->api_errno;
3193 }
3194
3195 REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3196}
3197
Klement Sekera75e7d132017-09-20 08:26:30 +02003198void
3199vl_api_ip_reassembly_set_t_handler (vl_api_ip_reassembly_set_t * mp)
3200{
3201 vl_api_ip_reassembly_set_reply_t *rmp;
3202 int rv = 0;
3203 if (mp->is_ip6)
3204 {
3205 rv = ip6_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3206 clib_net_to_host_u32 (mp->max_reassemblies),
3207 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3208 }
3209 else
3210 {
3211 rv = ip4_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3212 clib_net_to_host_u32 (mp->max_reassemblies),
3213 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3214 }
3215
3216 REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
3217}
3218
3219void
3220vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
3221{
3222 unix_shared_memory_queue_t *q;
3223
3224 q = vl_api_client_index_to_input_queue (mp->client_index);
3225
3226 if (q == 0)
3227 return;
3228
3229 vl_api_ip_reassembly_get_reply_t *rmp = vl_msg_api_alloc (sizeof (*rmp));
3230 memset (rmp, 0, sizeof (*rmp));
3231 rmp->_vl_msg_id = ntohs (VL_API_IP_REASSEMBLY_GET_REPLY);
3232 rmp->context = mp->context;
3233 rmp->retval = 0;
3234 if (mp->is_ip6)
3235 {
3236 rmp->is_ip6 = 1;
3237 ip6_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
3238 &rmp->expire_walk_interval_ms);
3239 }
3240 else
3241 {
3242 rmp->is_ip6 = 0;
3243 ip4_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
3244 &rmp->expire_walk_interval_ms);
3245 }
3246 rmp->timeout_ms = clib_host_to_net_u32 (rmp->timeout_ms);
3247 rmp->max_reassemblies = clib_host_to_net_u32 (rmp->max_reassemblies);
3248 rmp->expire_walk_interval_ms =
3249 clib_host_to_net_u32 (rmp->expire_walk_interval_ms);
3250 vl_msg_api_send_shmem (q, (u8 *) & rmp);
3251}
3252
Klement Sekera4c533132018-02-22 11:41:12 +01003253void
3254 vl_api_ip_reassembly_enable_disable_t_handler
3255 (vl_api_ip_reassembly_enable_disable_t * mp)
3256{
3257 vl_api_ip_reassembly_enable_disable_reply_t *rmp;
3258 int rv = 0;
3259 rv = ip4_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3260 mp->enable_ip4);
3261 if (0 == rv)
3262 {
3263 rv = ip6_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3264 mp->enable_ip6);
3265 }
3266
3267 REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
3268}
3269
Dave Barachb5e8a772016-12-06 12:04:42 -05003270#define vl_msg_name_crc_list
3271#include <vnet/ip/ip.api.h>
3272#undef vl_msg_name_crc_list
3273
3274static void
3275setup_message_id_table (api_main_t * am)
3276{
3277#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
3278 foreach_vl_msg_name_crc_ip;
3279#undef _
3280}
3281
3282static clib_error_t *
3283ip_api_hookup (vlib_main_t * vm)
3284{
3285 api_main_t *am = &api_main;
3286
3287#define _(N,n) \
3288 vl_msg_api_set_handlers(VL_API_##N, #n, \
3289 vl_api_##n##_t_handler, \
3290 vl_noop_handler, \
3291 vl_api_##n##_t_endian, \
3292 vl_api_##n##_t_print, \
3293 sizeof(vl_api_##n##_t), 1);
3294 foreach_ip_api_msg;
3295#undef _
3296
3297 /*
3298 * Set up the (msg_name, crc, message-id) table
3299 */
3300 setup_message_id_table (am);
3301
Juraj Sloboda52574522018-05-03 10:03:50 +02003302 ra_set_publisher_node (wc_arp_process_node.index, RA_REPORT);
3303
Dave Barachb5e8a772016-12-06 12:04:42 -05003304 return 0;
3305}
3306
3307VLIB_API_INIT_FUNCTION (ip_api_hookup);
3308
3309/*
3310 * fd.io coding-style-patch-verification: ON
3311 *
3312 * Local Variables:
3313 * eval: (c-set-style "gnu")
3314 * End:
3315 */