blob: 4355d11e792ac0661c115ca2e37239dcfb460fbb [file] [log] [blame]
Dave Barachb5e8a772016-12-06 12:04:42 -05001/*
2 *------------------------------------------------------------------
3 * ip_api.c - vnet ip api
4 *
5 * Copyright (c) 2016 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vnet/vnet.h>
21#include <vlibmemory/api.h>
22
23#include <vnet/interface.h>
24#include <vnet/api_errno.h>
25#include <vnet/ethernet/ethernet.h>
26#include <vnet/ip/ip.h>
John Lo7f358b32018-04-28 01:19:24 -040027#include <vnet/ip/ip_neighbor.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050028#include <vnet/ip/ip6_neighbor.h>
29#include <vnet/fib/fib_table.h>
30#include <vnet/fib/fib_api.h>
31#include <vnet/dpo/drop_dpo.h>
32#include <vnet/dpo/receive_dpo.h>
33#include <vnet/dpo/lookup_dpo.h>
34#include <vnet/dpo/classify_dpo.h>
35#include <vnet/dpo/ip_null_dpo.h>
36#include <vnet/ethernet/arp_packet.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080037#include <vnet/mfib/ip6_mfib.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000038#include <vnet/mfib/ip4_mfib.h>
39#include <vnet/mfib/mfib_signal.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080040#include <vnet/mfib/mfib_entry.h>
Neale Rannsb8d44812017-11-10 06:53:54 -080041#include <vnet/ip/ip_source_and_port_range_check.h>
42#include <vnet/fib/ip4_fib.h>
43#include <vnet/fib/ip6_fib.h>
44#include <vnet/ip/ip6_hop_by_hop.h>
Klement Sekera75e7d132017-09-20 08:26:30 +020045#include <vnet/ip/ip4_reassembly.h>
46#include <vnet/ip/ip6_reassembly.h>
Neale Ranns0053de62018-05-22 08:40:52 -070047#include <vnet/ethernet/arp.h>
Matus Fabian75b9f452018-10-02 23:27:21 -070048#include <vnet/ip/ip_types_api.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) \
Matus Fabian75b9f452018-10-02 23:27:21 -0700106_(IP_CONTAINER_PROXY_DUMP, ip_container_proxy_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -0800107_(IOAM_ENABLE, ioam_enable) \
108_(IOAM_DISABLE, ioam_disable) \
109_(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \
110 ip_source_and_port_range_check_add_del) \
111_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
Klement Sekera75e7d132017-09-20 08:26:30 +0200112 ip_source_and_port_range_check_interface_add_del) \
113_(IP_REASSEMBLY_SET, ip_reassembly_set) \
Klement Sekera4c533132018-02-22 11:41:12 +0100114_(IP_REASSEMBLY_GET, ip_reassembly_get) \
115_(IP_REASSEMBLY_ENABLE_DISABLE, ip_reassembly_enable_disable)
Dave Barachb5e8a772016-12-06 12:04:42 -0500116
117extern void stats_dslock_with_hint (int hint, int tag);
118extern void stats_dsunlock (void);
119
120static void
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600121send_ip_neighbor_details (u32 sw_if_index,
122 u8 is_ipv6,
Dave Barachb5e8a772016-12-06 12:04:42 -0500123 u8 is_static,
124 u8 * mac_address,
Florin Coras6c4dae22018-01-09 06:39:23 -0800125 u8 * ip_address, vl_api_registration_t * reg,
126 u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500127{
128 vl_api_ip_neighbor_details_t *mp;
129
130 mp = vl_msg_api_alloc (sizeof (*mp));
131 memset (mp, 0, sizeof (*mp));
132 mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS);
133 mp->context = context;
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600134 mp->sw_if_index = htonl (sw_if_index);
Dave Barachb5e8a772016-12-06 12:04:42 -0500135 mp->is_ipv6 = is_ipv6;
136 mp->is_static = is_static;
137 memcpy (mp->mac_address, mac_address, 6);
138 memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4);
139
Florin Coras6c4dae22018-01-09 06:39:23 -0800140 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500141}
142
143static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500144vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
145{
Florin Coras6c4dae22018-01-09 06:39:23 -0800146 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500147
Florin Coras6c4dae22018-01-09 06:39:23 -0800148 reg = vl_api_client_index_to_registration (mp->client_index);
149 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500150 return;
151
152 u32 sw_if_index = ntohl (mp->sw_if_index);
153
154 if (mp->is_ipv6)
155 {
156 ip6_neighbor_t *n, *ns;
157
158 ns = ip6_neighbors_entries (sw_if_index);
159 /* *INDENT-OFF* */
160 vec_foreach (n, ns)
161 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500162 send_ip_neighbor_details
Brant Lin285434a2018-06-13 06:01:58 -0400163 (n->key.sw_if_index, mp->is_ipv6,
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600164 ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0),
Dave Barachd7cb1b52016-12-09 09:52:16 -0500165 (u8 *) n->link_layer_address,
166 (u8 *) & (n->key.ip6_address.as_u8),
Florin Coras6c4dae22018-01-09 06:39:23 -0800167 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500168 }
169 /* *INDENT-ON* */
170 vec_free (ns);
171 }
172 else
173 {
174 ethernet_arp_ip4_entry_t *n, *ns;
175
176 ns = ip4_neighbor_entries (sw_if_index);
177 /* *INDENT-OFF* */
178 vec_foreach (n, ns)
179 {
Brant Lin285434a2018-06-13 06:01:58 -0400180 send_ip_neighbor_details (n->sw_if_index, mp->is_ipv6,
Dave Barachb5e8a772016-12-06 12:04:42 -0500181 ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0),
182 (u8*) n->ethernet_address,
183 (u8*) & (n->ip4_address.as_u8),
Florin Coras6c4dae22018-01-09 06:39:23 -0800184 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500185 }
186 /* *INDENT-ON* */
187 vec_free (ns);
188 }
189}
190
Dave Barachb5e8a772016-12-06 12:04:42 -0500191static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500192send_ip_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800193 vl_api_registration_t * reg,
Neale Ranns2297af02017-09-12 09:45:04 -0700194 const fib_table_t * table,
195 const fib_prefix_t * pfx,
Dave Barachb5e8a772016-12-06 12:04:42 -0500196 fib_route_path_encode_t * api_rpaths, u32 context)
197{
198 vl_api_ip_fib_details_t *mp;
199 fib_route_path_encode_t *api_rpath;
200 vl_api_fib_path_t *fp;
201 int path_count;
202
203 path_count = vec_len (api_rpaths);
204 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
205 if (!mp)
206 return;
207 memset (mp, 0, sizeof (*mp));
208 mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
209 mp->context = context;
210
Neale Ranns2297af02017-09-12 09:45:04 -0700211 mp->table_id = htonl (table->ft_table_id);
212 memcpy (mp->table_name, table->ft_desc,
213 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Dave Barachb5e8a772016-12-06 12:04:42 -0500214 mp->address_length = pfx->fp_len;
215 memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
Neale Ranns008dbe12018-09-07 09:32:36 -0700216 mp->stats_index =
217 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500218
219 mp->count = htonl (path_count);
220 fp = mp->path;
221 vec_foreach (api_rpath, api_rpaths)
222 {
Neale Ranns81458422018-03-12 06:59:36 -0700223 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500224 fp++;
225 }
226
Florin Coras6c4dae22018-01-09 06:39:23 -0800227 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500228}
229
Neale Rannsa3af3372017-03-28 03:49:52 -0700230typedef struct vl_api_ip_fib_dump_walk_ctx_t_
231{
232 fib_node_index_t *feis;
233} vl_api_ip_fib_dump_walk_ctx_t;
234
Neale Ranns89541992017-04-06 04:41:02 -0700235static fib_table_walk_rc_t
Neale Rannsa3af3372017-03-28 03:49:52 -0700236vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
237{
238 vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
239
240 vec_add1 (ctx->feis, fei);
241
Neale Ranns89541992017-04-06 04:41:02 -0700242 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700243}
244
Dave Barachb5e8a772016-12-06 12:04:42 -0500245static void
246vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
247{
248 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800249 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500250 ip4_main_t *im = &ip4_main;
251 fib_table_t *fib_table;
Neale Rannsa3af3372017-03-28 03:49:52 -0700252 fib_node_index_t *lfeip;
Neale Rannsc5d43172018-07-30 08:04:40 -0700253 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500254 u32 fib_index;
255 fib_route_path_encode_t *api_rpaths;
Neale Rannsa3af3372017-03-28 03:49:52 -0700256 vl_api_ip_fib_dump_walk_ctx_t ctx = {
257 .feis = NULL,
258 };
Dave Barachb5e8a772016-12-06 12:04:42 -0500259
Florin Coras6c4dae22018-01-09 06:39:23 -0800260 reg = vl_api_client_index_to_registration (mp->client_index);
261 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500262 return;
263
264 /* *INDENT-OFF* */
265 pool_foreach (fib_table, im->fibs,
266 ({
Neale Rannsa3af3372017-03-28 03:49:52 -0700267 fib_table_walk(fib_table->ft_index,
268 FIB_PROTOCOL_IP4,
269 vl_api_ip_fib_dump_walk,
270 &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500271 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500272 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500273
Neale Rannsa3af3372017-03-28 03:49:52 -0700274 vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500275
Neale Rannsa3af3372017-03-28 03:49:52 -0700276 vec_foreach (lfeip, ctx.feis)
Dave Barachb5e8a772016-12-06 12:04:42 -0500277 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700278 pfx = fib_entry_get_prefix (*lfeip);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500279 fib_index = fib_entry_get_fib_index (*lfeip);
Neale Rannsc5d43172018-07-30 08:04:40 -0700280 fib_table = fib_table_get (fib_index, pfx->fp_proto);
Dave Barachb5e8a772016-12-06 12:04:42 -0500281 api_rpaths = NULL;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500282 fib_entry_encode (*lfeip, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700283 send_ip_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500284 vec_free (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500285 }
286
Neale Rannsa3af3372017-03-28 03:49:52 -0700287 vec_free (ctx.feis);
Dave Barachb5e8a772016-12-06 12:04:42 -0500288}
289
290static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500291send_ip6_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800292 vl_api_registration_t * reg,
Neale Rannsa161a6d2017-11-14 08:10:41 -0800293 const fib_table_t * table,
294 const fib_prefix_t * pfx,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500295 fib_route_path_encode_t * api_rpaths, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500296{
297 vl_api_ip6_fib_details_t *mp;
298 fib_route_path_encode_t *api_rpath;
299 vl_api_fib_path_t *fp;
300 int path_count;
301
Dave Barachd7cb1b52016-12-09 09:52:16 -0500302 path_count = vec_len (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500303 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
304 if (!mp)
305 return;
306 memset (mp, 0, sizeof (*mp));
307 mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
308 mp->context = context;
309
Neale Rannsa161a6d2017-11-14 08:10:41 -0800310 mp->table_id = htonl (table->ft_table_id);
Dave Barachb5e8a772016-12-06 12:04:42 -0500311 mp->address_length = pfx->fp_len;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500312 memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
Neale Rannsa161a6d2017-11-14 08:10:41 -0800313 memcpy (mp->table_name, table->ft_desc,
314 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Neale Ranns008dbe12018-09-07 09:32:36 -0700315 mp->stats_index =
316 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500317
318 mp->count = htonl (path_count);
319 fp = mp->path;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500320 vec_foreach (api_rpath, api_rpaths)
Dave Barachb5e8a772016-12-06 12:04:42 -0500321 {
Neale Ranns81458422018-03-12 06:59:36 -0700322 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500323 fp++;
324 }
325
Florin Coras6c4dae22018-01-09 06:39:23 -0800326 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500327}
328
Dave Barachd7cb1b52016-12-09 09:52:16 -0500329typedef struct apt_ip6_fib_show_ctx_t_
330{
331 u32 fib_index;
332 fib_node_index_t *entries;
Dave Barachb5e8a772016-12-06 12:04:42 -0500333} api_ip6_fib_show_ctx_t;
334
335static void
Dave Barachd7cb1b52016-12-09 09:52:16 -0500336api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500337{
338 api_ip6_fib_show_ctx_t *ctx = arg;
339
340 if ((kvp->key[2] >> 32) == ctx->fib_index)
341 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500342 vec_add1 (ctx->entries, kvp->value);
Dave Barachb5e8a772016-12-06 12:04:42 -0500343 }
344}
345
346static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800347api_ip6_fib_table_get_all (vl_api_registration_t * reg,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500348 vl_api_ip6_fib_dump_t * mp,
349 fib_table_t * fib_table)
Dave Barachb5e8a772016-12-06 12:04:42 -0500350{
351 vpe_api_main_t *am = &vpe_api_main;
352 ip6_main_t *im6 = &ip6_main;
Dave Barachb5e8a772016-12-06 12:04:42 -0500353 fib_node_index_t *fib_entry_index;
354 api_ip6_fib_show_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700355 .fib_index = fib_table->ft_index,
356 .entries = NULL,
Dave Barachb5e8a772016-12-06 12:04:42 -0500357 };
358 fib_route_path_encode_t *api_rpaths;
Neale Rannsc5d43172018-07-30 08:04:40 -0700359 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500360
Dave Barachd7cb1b52016-12-09 09:52:16 -0500361 BV (clib_bihash_foreach_key_value_pair)
362 ((BVT (clib_bihash) *) & im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].
363 ip6_hash, api_ip6_fib_table_put_entries, &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500364
Dave Barachd7cb1b52016-12-09 09:52:16 -0500365 vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500366
Dave Barachd7cb1b52016-12-09 09:52:16 -0500367 vec_foreach (fib_entry_index, ctx.entries)
368 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700369 pfx = fib_entry_get_prefix (*fib_entry_index);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500370 api_rpaths = NULL;
371 fib_entry_encode (*fib_entry_index, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700372 send_ip6_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500373 vec_free (api_rpaths);
374 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500375
Dave Barachd7cb1b52016-12-09 09:52:16 -0500376 vec_free (ctx.entries);
Dave Barachb5e8a772016-12-06 12:04:42 -0500377}
378
379static void
380vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
381{
Florin Coras6c4dae22018-01-09 06:39:23 -0800382 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500383 ip6_main_t *im6 = &ip6_main;
384 fib_table_t *fib_table;
385
Florin Coras6c4dae22018-01-09 06:39:23 -0800386 reg = vl_api_client_index_to_registration (mp->client_index);
387 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500388 return;
389
390 /* *INDENT-OFF* */
391 pool_foreach (fib_table, im6->fibs,
392 ({
Neale Ranns81458422018-03-12 06:59:36 -0700393 /* don't send link locals */
394 if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL)
395 continue;
396
Florin Coras6c4dae22018-01-09 06:39:23 -0800397 api_ip6_fib_table_get_all(reg, mp, fib_table);
Dave Barachb5e8a772016-12-06 12:04:42 -0500398 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500399 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500400}
401
402static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800403send_ip_mfib_details (vl_api_registration_t * reg,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800404 u32 context, u32 table_id, fib_node_index_t mfei)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800405{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800406 fib_route_path_encode_t *api_rpath, *api_rpaths = NULL;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800407 vl_api_ip_mfib_details_t *mp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800408 mfib_entry_t *mfib_entry;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800409 vl_api_fib_path_t *fp;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800410 mfib_prefix_t pfx;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800411 int path_count;
412
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800413 mfib_entry = mfib_entry_get (mfei);
414 mfib_entry_get_prefix (mfei, &pfx);
415 mfib_entry_encode (mfei, &api_rpaths);
416
Neale Ranns5a8123b2017-01-26 01:18:23 -0800417 path_count = vec_len (api_rpaths);
418 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
419 if (!mp)
420 return;
421 memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700422 mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800423 mp->context = context;
424
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800425 mp->rpf_id = mfib_entry->mfe_rpf_id;
426 mp->entry_flags = mfib_entry->mfe_flags;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800427 mp->table_id = htonl (table_id);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800428 mp->address_length = pfx.fp_len;
429 memcpy (mp->grp_address, &pfx.fp_grp_addr.ip4,
430 sizeof (pfx.fp_grp_addr.ip4));
431 memcpy (mp->src_address, &pfx.fp_src_addr.ip4,
432 sizeof (pfx.fp_src_addr.ip4));
Neale Ranns5a8123b2017-01-26 01:18:23 -0800433
434 mp->count = htonl (path_count);
435 fp = mp->path;
436 vec_foreach (api_rpath, api_rpaths)
437 {
Neale Ranns81458422018-03-12 06:59:36 -0700438 fib_api_path_encode (api_rpath, fp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800439 fp++;
440 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800441 vec_free (api_rpaths);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800442
Florin Coras6c4dae22018-01-09 06:39:23 -0800443 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800444}
445
446typedef struct vl_api_ip_mfib_dump_ctc_t_
447{
448 fib_node_index_t *entries;
449} vl_api_ip_mfib_dump_ctc_t;
450
451static int
452vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
453{
454 vl_api_ip_mfib_dump_ctc_t *ctx = arg;
455
456 vec_add1 (ctx->entries, fei);
457
458 return (0);
459}
460
461static void
462vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
463{
Florin Coras6c4dae22018-01-09 06:39:23 -0800464 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800465 ip4_main_t *im = &ip4_main;
466 mfib_table_t *mfib_table;
467 fib_node_index_t *mfeip;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800468 vl_api_ip_mfib_dump_ctc_t ctx = {
469 .entries = NULL,
470 };
471
Florin Coras6c4dae22018-01-09 06:39:23 -0800472 reg = vl_api_client_index_to_registration (mp->client_index);
473 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800474 return;
475
Neale Ranns5a8123b2017-01-26 01:18:23 -0800476 /* *INDENT-OFF* */
477 pool_foreach (mfib_table, im->mfibs,
478 ({
479 ip4_mfib_table_walk(&mfib_table->v4,
480 vl_api_ip_mfib_table_dump_walk,
481 &ctx);
482
483 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
484
485 vec_foreach (mfeip, ctx.entries)
486 {
Florin Coras6c4dae22018-01-09 06:39:23 -0800487 send_ip_mfib_details (reg, mp->context,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800488 mfib_table->mft_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800489 *mfeip);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800490 }
Neale Ranns5a8123b2017-01-26 01:18:23 -0800491 vec_reset_length (ctx.entries);
492
493 }));
494 /* *INDENT-ON* */
495
496 vec_free (ctx.entries);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800497}
498
499static void
Neale Ranns5a8123b2017-01-26 01:18:23 -0800500send_ip6_mfib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800501 vl_api_registration_t * reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800502 u32 table_id,
503 mfib_prefix_t * pfx,
504 fib_route_path_encode_t * api_rpaths, u32 context)
505{
506 vl_api_ip6_mfib_details_t *mp;
507 fib_route_path_encode_t *api_rpath;
508 vl_api_fib_path_t *fp;
509 int path_count;
510
511 path_count = vec_len (api_rpaths);
512 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
513 if (!mp)
514 return;
515 memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700516 mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800517 mp->context = context;
518
519 mp->table_id = htonl (table_id);
520 mp->address_length = pfx->fp_len;
521 memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6,
522 sizeof (pfx->fp_grp_addr.ip6));
523 memcpy (mp->src_address, &pfx->fp_src_addr.ip6,
524 sizeof (pfx->fp_src_addr.ip6));
525
526 mp->count = htonl (path_count);
527 fp = mp->path;
528 vec_foreach (api_rpath, api_rpaths)
529 {
Neale Ranns81458422018-03-12 06:59:36 -0700530 fib_api_path_encode (api_rpath, fp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800531 fp++;
532 }
533
Florin Coras6c4dae22018-01-09 06:39:23 -0800534 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800535}
536
537typedef struct vl_api_ip6_mfib_dump_ctc_t_
538{
539 fib_node_index_t *entries;
540} vl_api_ip6_mfib_dump_ctc_t;
541
542static int
543vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
544{
545 vl_api_ip6_mfib_dump_ctc_t *ctx = arg;
546
547 vec_add1 (ctx->entries, fei);
548
549 return (0);
550}
551
552static void
553vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
554{
555 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800556 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800557 ip6_main_t *im = &ip6_main;
558 mfib_table_t *mfib_table;
559 fib_node_index_t *mfeip;
560 mfib_prefix_t pfx;
561 fib_route_path_encode_t *api_rpaths = NULL;
562 vl_api_ip6_mfib_dump_ctc_t ctx = {
563 .entries = NULL,
564 };
565
Florin Coras6c4dae22018-01-09 06:39:23 -0800566 reg = vl_api_client_index_to_registration (mp->client_index);
567 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800568 return;
569
570
571 /* *INDENT-OFF* */
572 pool_foreach (mfib_table, im->mfibs,
573 ({
574 ip6_mfib_table_walk(&mfib_table->v6,
575 vl_api_ip6_mfib_table_dump_walk,
576 &ctx);
577
578 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
579
580 vec_foreach(mfeip, ctx.entries)
581 {
582 mfib_entry_get_prefix (*mfeip, &pfx);
583 mfib_entry_encode (*mfeip, &api_rpaths);
Florin Coras6c4dae22018-01-09 06:39:23 -0800584 send_ip6_mfib_details (am, reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800585 mfib_table->mft_table_id,
586 &pfx, api_rpaths,
587 mp->context);
588 }
589 vec_reset_length (api_rpaths);
590 vec_reset_length (ctx.entries);
591
592 }));
593 /* *INDENT-ON* */
594
595 vec_free (ctx.entries);
596 vec_free (api_rpaths);
597}
598
599static void
Neale Rannsd91c1db2017-07-31 02:30:50 -0700600vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp,
601 vlib_main_t * vm)
602{
603 vl_api_ip_punt_police_reply_t *rmp;
604 int rv = 0;
605
606 if (mp->is_ip6)
607 ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
608 else
609 ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
610
611 REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY);
612}
613
614static void
615vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp,
616 vlib_main_t * vm)
617{
618 vl_api_ip_punt_redirect_reply_t *rmp;
619 int rv = 0;
620
621 if (mp->is_add)
622 {
623 ip46_address_t nh;
624
625 memset (&nh, 0, sizeof (nh));
626
627 if (mp->is_ip6)
628 {
629 memcpy (&nh.ip6, mp->nh, sizeof (nh.ip6));
630
631 ip6_punt_redirect_add (ntohl (mp->rx_sw_if_index),
632 ntohl (mp->tx_sw_if_index), &nh);
633 }
634 else
635 {
636 memcpy (&nh.ip4, mp->nh, sizeof (nh.ip4));
637
638 ip4_punt_redirect_add (ntohl (mp->rx_sw_if_index),
639 ntohl (mp->tx_sw_if_index), &nh);
640 }
641 }
642 else
643 {
644 if (mp->is_ip6)
645 {
646 ip6_punt_redirect_del (ntohl (mp->rx_sw_if_index));
647 }
648 else
649 {
650 ip4_punt_redirect_del (ntohl (mp->rx_sw_if_index));
651 }
652 }
653
654 REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY);
655}
656
657static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500658vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
659 vlib_main_t * vm)
660{
Neale Ranns0bdd3192018-09-07 11:04:52 -0700661 ip46_address_t ip = ip46_address_initializer;
Dave Barachb5e8a772016-12-06 12:04:42 -0500662 vl_api_ip_neighbor_add_del_reply_t *rmp;
Neale Ranns0bdd3192018-09-07 11:04:52 -0700663 ip_neighbor_flags_t flags;
Neale Ranns14260392018-09-28 05:00:57 -0700664 u32 stats_index = ~0;
Dave Barachb5e8a772016-12-06 12:04:42 -0500665 int rv = 0;
666
667 VALIDATE_SW_IF_INDEX (mp);
668
669 stats_dslock_with_hint (1 /* release hint */ , 7 /* tag */ );
670
Neale Ranns0bdd3192018-09-07 11:04:52 -0700671 flags = IP_NEIGHBOR_FLAG_NODE;
672 if (mp->is_static)
673 flags |= IP_NEIGHBOR_FLAG_STATIC;
674 if (mp->is_no_adj_fib)
675 flags |= IP_NEIGHBOR_FLAG_NO_ADJ_FIB;
676
Dave Barachb5e8a772016-12-06 12:04:42 -0500677 if (mp->is_ipv6)
Neale Ranns0bdd3192018-09-07 11:04:52 -0700678 clib_memcpy (&ip.ip6, mp->dst_address, 16);
Dave Barachb5e8a772016-12-06 12:04:42 -0500679 else
Neale Ranns0bdd3192018-09-07 11:04:52 -0700680 clib_memcpy (&ip.ip4, mp->dst_address, 4);
Dave Barachb5e8a772016-12-06 12:04:42 -0500681
Neale Ranns0bdd3192018-09-07 11:04:52 -0700682 if (mp->is_add)
683 rv = ip_neighbor_add (&ip, mp->is_ipv6, mp->mac_address,
Neale Ranns14260392018-09-28 05:00:57 -0700684 ntohl (mp->sw_if_index), flags, &stats_index);
Neale Ranns0bdd3192018-09-07 11:04:52 -0700685 else
686 rv = ip_neighbor_del (&ip, mp->is_ipv6, ntohl (mp->sw_if_index));
Dave Barachb5e8a772016-12-06 12:04:42 -0500687
Dave Barachb5e8a772016-12-06 12:04:42 -0500688 stats_dsunlock ();
Neale Ranns8edad032017-10-09 05:26:13 -0700689
690 BAD_SW_IF_INDEX_LABEL;
Neale Ranns14260392018-09-28 05:00:57 -0700691
692 /* *INDENT-OFF* */
693 REPLY_MACRO2 (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY,
694 ({
695 rmp->stats_index = htonl (stats_index);
696 }));
697 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500698}
699
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700700void
Neale Ranns15002542017-09-10 04:39:11 -0700701ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
702{
703 u32 fib_index, mfib_index;
704
705 /*
706 * ignore action on the default table - this is always present
707 * and cannot be added nor deleted from the API
708 */
709 if (0 != table_id)
710 {
711 /*
712 * The API holds only one lock on the table.
713 * i.e. it can be added many times via the API but needs to be
714 * deleted only once.
715 * The FIB index for unicast and multicast is not necessarily the
716 * same, since internal VPP systesm (like LISP and SR) create
717 * their own unicast tables.
718 */
719 fib_index = fib_table_find (fproto, table_id);
720 mfib_index = mfib_table_find (fproto, table_id);
721
722 if (~0 != fib_index)
723 {
724 fib_table_unlock (fib_index, fproto,
725 (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
726 }
727 if (~0 != mfib_index)
728 {
729 mfib_table_unlock (mfib_index, fproto,
730 (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
731 }
732 }
733}
734
735void
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700736vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
737{
738 vl_api_ip_table_add_del_reply_t *rmp;
Neale Ranns15002542017-09-10 04:39:11 -0700739 fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
740 u32 table_id = ntohl (mp->table_id);
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700741 int rv = 0;
742
Neale Ranns15002542017-09-10 04:39:11 -0700743 if (mp->is_add)
744 {
Neale Ranns2297af02017-09-12 09:45:04 -0700745 ip_table_create (fproto, table_id, 1, mp->name);
Neale Ranns15002542017-09-10 04:39:11 -0700746 }
747 else
748 {
749 ip_table_delete (fproto, table_id, 1);
750 }
751
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700752 REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
753}
754
Dave Barachb5e8a772016-12-06 12:04:42 -0500755int
756add_del_route_t_handler (u8 is_multipath,
757 u8 is_add,
758 u8 is_drop,
759 u8 is_unreach,
760 u8 is_prohibit,
761 u8 is_local,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800762 u8 is_multicast,
Dave Barachb5e8a772016-12-06 12:04:42 -0500763 u8 is_classify,
764 u32 classify_table_index,
765 u8 is_resolve_host,
766 u8 is_resolve_attached,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800767 u8 is_interface_rx,
768 u8 is_rpf_id,
Neale Rannsf068c3e2018-01-03 04:18:48 -0800769 u8 is_dvr,
Neale Ranns054c03a2017-10-13 05:15:07 -0700770 u8 is_source_lookup,
Neale Ranns810086d2017-11-05 16:26:46 -0800771 u8 is_udp_encap,
Dave Barachb5e8a772016-12-06 12:04:42 -0500772 u32 fib_index,
773 const fib_prefix_t * prefix,
Neale Rannsda78f952017-05-24 09:15:43 -0700774 dpo_proto_t next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500775 const ip46_address_t * next_hop,
Neale Ranns810086d2017-11-05 16:26:46 -0800776 u32 next_hop_id,
Dave Barachb5e8a772016-12-06 12:04:42 -0500777 u32 next_hop_sw_if_index,
778 u8 next_hop_fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -0700779 u16 next_hop_weight,
780 u16 next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500781 mpls_label_t next_hop_via_label,
Neale Ranns31ed7442018-02-23 05:29:09 -0800782 fib_mpls_label_t * next_hop_out_label_stack)
Dave Barachb5e8a772016-12-06 12:04:42 -0500783{
784 vnet_classify_main_t *cm = &vnet_classify_main;
785 fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
786 fib_route_path_t path = {
Neale Rannsda78f952017-05-24 09:15:43 -0700787 .frp_proto = next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500788 .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
789 .frp_sw_if_index = next_hop_sw_if_index,
790 .frp_fib_index = next_hop_fib_index,
791 .frp_weight = next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -0700792 .frp_preference = next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500793 .frp_label_stack = next_hop_out_label_stack,
794 };
795 fib_route_path_t *paths = NULL;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800796 fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
Dave Barachb5e8a772016-12-06 12:04:42 -0500797
Neale Rannscaac3502017-09-18 18:04:10 -0700798 /*
799 * the special INVALID label meams we are not recursing via a
800 * label. Exp-null value is never a valid via-label so that
801 * also means it's not a via-label and means clients that set
802 * it to 0 by default get the expected behaviour
803 */
804 if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label))
Dave Barachb5e8a772016-12-06 12:04:42 -0500805 {
Neale Rannsda78f952017-05-24 09:15:43 -0700806 path.frp_proto = DPO_PROTO_MPLS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500807 path.frp_local_label = next_hop_via_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800808 path.frp_eos = MPLS_NON_EOS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500809 }
Neale Rannsf068c3e2018-01-03 04:18:48 -0800810 if (is_dvr)
811 path_flags |= FIB_ROUTE_PATH_DVR;
Dave Barachb5e8a772016-12-06 12:04:42 -0500812 if (is_resolve_host)
813 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
814 if (is_resolve_attached)
815 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800816 if (is_interface_rx)
817 path_flags |= FIB_ROUTE_PATH_INTF_RX;
818 if (is_rpf_id)
819 path_flags |= FIB_ROUTE_PATH_RPF_ID;
Neale Ranns054c03a2017-10-13 05:15:07 -0700820 if (is_source_lookup)
821 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800822 if (is_multicast)
823 entry_flags |= FIB_ENTRY_FLAG_MULTICAST;
Neale Ranns810086d2017-11-05 16:26:46 -0800824 if (is_udp_encap)
825 {
826 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
827 path.frp_udp_encap_id = next_hop_id;
828 }
Florin Coras79ae2d32017-12-16 08:31:06 -0800829 if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr)
830 && path.frp_fib_index != ~0)
831 {
832 path_flags |= FIB_ROUTE_PATH_DEAG;
833 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500834
835 path.frp_flags = path_flags;
836
Dave Barachb5e8a772016-12-06 12:04:42 -0500837 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
838
839 if (is_drop || is_local || is_classify || is_unreach || is_prohibit)
840 {
841 /*
842 * special route types that link directly to the adj
843 */
844 if (is_add)
845 {
846 dpo_id_t dpo = DPO_INVALID;
847 dpo_proto_t dproto;
848
849 dproto = fib_proto_to_dpo (prefix->fp_proto);
850
851 if (is_drop)
852 ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
853 else if (is_local)
854 receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
855 else if (is_unreach)
856 ip_null_dpo_add_and_lock (dproto,
857 IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
858 else if (is_prohibit)
859 ip_null_dpo_add_and_lock (dproto,
860 IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
861 &dpo);
862 else if (is_classify)
863 {
864 if (pool_is_free_index (cm->tables,
865 ntohl (classify_table_index)))
866 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500867 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500868 return VNET_API_ERROR_NO_SUCH_TABLE;
869 }
870
871 dpo_set (&dpo, DPO_CLASSIFY, dproto,
872 classify_dpo_create (dproto,
873 ntohl (classify_table_index)));
874 }
875 else
876 {
Dave Barachd7cb1b52016-12-09 09:52:16 -0500877 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500878 return VNET_API_ERROR_NO_SUCH_TABLE;
879 }
880
881 fib_table_entry_special_dpo_update (fib_index,
882 prefix,
883 FIB_SOURCE_API,
884 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
885 dpo_reset (&dpo);
886 }
887 else
888 {
889 fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
890 }
891 }
Neale Ranns3b93be52018-09-07 01:48:54 -0700892 else if (is_multipath)
893 {
894 vec_add1 (paths, path);
895
896 if (is_add)
897 fib_table_entry_path_add2 (fib_index,
898 prefix,
899 FIB_SOURCE_API, entry_flags, paths);
900 else
901 fib_table_entry_path_remove2 (fib_index,
902 prefix, FIB_SOURCE_API, paths);
903
904 vec_free (paths);
905 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500906 else
907 {
908 if (is_add)
909 {
910 vec_add1 (paths, path);
911 fib_table_entry_update (fib_index,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800912 prefix, FIB_SOURCE_API, entry_flags, paths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500913 vec_free (paths);
914 }
915 else
916 {
917 fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
918 }
919 }
920
Dave Barachd7cb1b52016-12-09 09:52:16 -0500921 stats_dsunlock ();
Dave Barachb5e8a772016-12-06 12:04:42 -0500922 return (0);
923}
924
925int
926add_del_route_check (fib_protocol_t table_proto,
927 u32 table_id,
928 u32 next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700929 dpo_proto_t next_hop_table_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500930 u32 next_hop_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800931 u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500932{
933 vnet_main_t *vnm = vnet_get_main ();
934
935 *fib_index = fib_table_find (table_proto, ntohl (table_id));
936 if (~0 == *fib_index)
937 {
Neale Rannsb93078d2018-01-25 07:48:12 -0800938 /* No such VRF, and we weren't asked to create one */
939 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -0500940 }
941
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800942 if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index))
Dave Barachb5e8a772016-12-06 12:04:42 -0500943 {
944 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
945 ntohl (next_hop_sw_if_index)))
946 {
947 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
948 }
949 }
950 else
951 {
Neale Rannsda78f952017-05-24 09:15:43 -0700952 fib_protocol_t fib_nh_proto;
953
954 if (next_hop_table_proto > DPO_PROTO_MPLS)
955 return (0);
956
957 fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto);
958
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800959 if (is_rpf_id)
Neale Rannsda78f952017-05-24 09:15:43 -0700960 *next_hop_fib_index = mfib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800961 ntohl (next_hop_table_id));
962 else
Neale Rannsda78f952017-05-24 09:15:43 -0700963 *next_hop_fib_index = fib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800964 ntohl (next_hop_table_id));
Dave Barachb5e8a772016-12-06 12:04:42 -0500965
966 if (~0 == *next_hop_fib_index)
967 {
Neale Rannsb93078d2018-01-25 07:48:12 -0800968 /* No such VRF, and we weren't asked to create one */
969 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -0500970 }
971 }
972
973 return (0);
974}
975
976static int
Neale Ranns008dbe12018-09-07 09:32:36 -0700977ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
978 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500979{
980 u32 fib_index, next_hop_fib_index;
Neale Ranns31ed7442018-02-23 05:29:09 -0800981 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -0500982 int rv, ii, n_labels;;
983
984 rv = add_del_route_check (FIB_PROTOCOL_IP4,
985 mp->table_id,
986 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700987 DPO_PROTO_IP4,
Dave Barachb5e8a772016-12-06 12:04:42 -0500988 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -0700989 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -0500990
991 if (0 != rv)
992 return (rv);
993
994 fib_prefix_t pfx = {
995 .fp_len = mp->dst_address_length,
996 .fp_proto = FIB_PROTOCOL_IP4,
997 };
998 clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
999
1000 ip46_address_t nh;
1001 memset (&nh, 0, sizeof (nh));
1002 memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
1003
1004 n_labels = mp->next_hop_n_out_labels;
1005 if (n_labels == 0)
1006 ;
Dave Barachb5e8a772016-12-06 12:04:42 -05001007 else
1008 {
1009 vec_validate (label_stack, n_labels - 1);
1010 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001011 {
1012 label_stack[ii].fml_value =
1013 ntohl (mp->next_hop_out_label_stack[ii].label);
1014 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1015 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1016 label_stack[ii].fml_mode =
1017 (mp->next_hop_out_label_stack[ii].is_uniform ?
1018 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1019 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001020 }
1021
Neale Ranns008dbe12018-09-07 09:32:36 -07001022 rv = add_del_route_t_handler (mp->is_multipath,
1023 mp->is_add,
1024 mp->is_drop,
1025 mp->is_unreach,
1026 mp->is_prohibit,
1027 mp->is_local, 0,
1028 mp->is_classify,
1029 mp->classify_table_index,
1030 mp->is_resolve_host,
1031 mp->is_resolve_attached, 0, 0,
1032 mp->is_dvr,
1033 mp->is_source_lookup,
1034 mp->is_udp_encap,
1035 fib_index, &pfx, DPO_PROTO_IP4,
1036 &nh,
1037 ntohl (mp->next_hop_id),
1038 ntohl (mp->next_hop_sw_if_index),
1039 next_hop_fib_index,
1040 mp->next_hop_weight,
1041 mp->next_hop_preference,
1042 ntohl (mp->next_hop_via_label), label_stack);
1043
1044 if (mp->is_add && 0 == rv)
1045 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1046
1047 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001048}
1049
Juraj Sloboda0012fcc2018-05-17 12:05:27 +02001050static int
Neale Ranns008dbe12018-09-07 09:32:36 -07001051ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
1052 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -05001053{
Neale Ranns31ed7442018-02-23 05:29:09 -08001054 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -05001055 u32 fib_index, next_hop_fib_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001056 int rv, ii, n_labels;;
1057
1058 rv = add_del_route_check (FIB_PROTOCOL_IP6,
1059 mp->table_id,
1060 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001061 DPO_PROTO_IP6,
Dave Barachb5e8a772016-12-06 12:04:42 -05001062 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001063 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001064
1065 if (0 != rv)
1066 return (rv);
1067
1068 fib_prefix_t pfx = {
1069 .fp_len = mp->dst_address_length,
1070 .fp_proto = FIB_PROTOCOL_IP6,
1071 };
1072 clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
1073
1074 ip46_address_t nh;
1075 memset (&nh, 0, sizeof (nh));
1076 memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
1077
1078 n_labels = mp->next_hop_n_out_labels;
1079 if (n_labels == 0)
1080 ;
Dave Barachb5e8a772016-12-06 12:04:42 -05001081 else
1082 {
1083 vec_validate (label_stack, n_labels - 1);
1084 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001085 {
1086 label_stack[ii].fml_value =
1087 ntohl (mp->next_hop_out_label_stack[ii].label);
1088 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1089 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1090 label_stack[ii].fml_mode =
1091 (mp->next_hop_out_label_stack[ii].is_uniform ?
1092 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1093 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001094 }
1095
Neale Ranns008dbe12018-09-07 09:32:36 -07001096 rv = add_del_route_t_handler (mp->is_multipath,
1097 mp->is_add,
1098 mp->is_drop,
1099 mp->is_unreach,
1100 mp->is_prohibit,
1101 mp->is_local, 0,
1102 mp->is_classify,
1103 mp->classify_table_index,
1104 mp->is_resolve_host,
1105 mp->is_resolve_attached, 0, 0,
1106 mp->is_dvr,
1107 mp->is_source_lookup,
1108 mp->is_udp_encap,
1109 fib_index, &pfx, DPO_PROTO_IP6,
1110 &nh, ntohl (mp->next_hop_id),
1111 ntohl (mp->next_hop_sw_if_index),
1112 next_hop_fib_index,
1113 mp->next_hop_weight,
1114 mp->next_hop_preference,
1115 ntohl (mp->next_hop_via_label), label_stack);
1116
1117 if (mp->is_add && 0 == rv)
1118 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1119
1120 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001121}
1122
1123void
1124vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1125{
1126 vl_api_ip_add_del_route_reply_t *rmp;
Neale Ranns008dbe12018-09-07 09:32:36 -07001127 u32 stats_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001128 int rv;
1129 vnet_main_t *vnm = vnet_get_main ();
1130
1131 vnm->api_errno = 0;
Neale Ranns008dbe12018-09-07 09:32:36 -07001132 stats_index = ~0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001133
1134 if (mp->is_ipv6)
Neale Ranns008dbe12018-09-07 09:32:36 -07001135 rv = ip6_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001136 else
Neale Ranns008dbe12018-09-07 09:32:36 -07001137 rv = ip4_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001138
1139 rv = (rv == 0) ? vnm->api_errno : rv;
1140
Neale Ranns008dbe12018-09-07 09:32:36 -07001141 /* *INDENT-OFF* */
1142 REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY,
1143 ({
1144 rmp->stats_index = htonl (stats_index);
1145 }))
1146 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001147}
1148
Neale Ranns15002542017-09-10 04:39:11 -07001149void
Neale Ranns2297af02017-09-12 09:45:04 -07001150ip_table_create (fib_protocol_t fproto,
1151 u32 table_id, u8 is_api, const u8 * name)
Neale Ranns15002542017-09-10 04:39:11 -07001152{
1153 u32 fib_index, mfib_index;
1154
1155 /*
1156 * ignore action on the default table - this is always present
1157 * and cannot be added nor deleted from the API
1158 */
1159 if (0 != table_id)
1160 {
1161 /*
1162 * The API holds only one lock on the table.
1163 * i.e. it can be added many times via the API but needs to be
1164 * deleted only once.
1165 * The FIB index for unicast and multicast is not necessarily the
1166 * same, since internal VPP systesm (like LISP and SR) create
1167 * their own unicast tables.
1168 */
1169 fib_index = fib_table_find (fproto, table_id);
1170 mfib_index = mfib_table_find (fproto, table_id);
1171
1172 if (~0 == fib_index)
1173 {
Neale Ranns2297af02017-09-12 09:45:04 -07001174 fib_table_find_or_create_and_lock_w_name (fproto, table_id,
1175 (is_api ?
1176 FIB_SOURCE_API :
1177 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001178 }
1179 if (~0 == mfib_index)
1180 {
Neale Ranns2297af02017-09-12 09:45:04 -07001181 mfib_table_find_or_create_and_lock_w_name (fproto, table_id,
1182 (is_api ?
1183 MFIB_SOURCE_API :
1184 MFIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001185 }
1186 }
1187}
1188
Neale Ranns32e1c012016-11-22 17:07:28 +00001189static int
1190add_del_mroute_check (fib_protocol_t table_proto,
1191 u32 table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001192 u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001193{
1194 vnet_main_t *vnm = vnet_get_main ();
1195
1196 *fib_index = mfib_table_find (table_proto, ntohl (table_id));
1197 if (~0 == *fib_index)
1198 {
Neale Ranns15002542017-09-10 04:39:11 -07001199 /* No such table */
1200 return VNET_API_ERROR_NO_SUCH_FIB;
Neale Ranns32e1c012016-11-22 17:07:28 +00001201 }
1202
1203 if (~0 != ntohl (next_hop_sw_if_index))
1204 {
1205 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1206 ntohl (next_hop_sw_if_index)))
1207 {
1208 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1209 }
1210 }
1211
1212 return (0);
1213}
1214
Neale Ranns28c142e2018-09-07 09:37:07 -07001215static fib_node_index_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001216mroute_add_del_handler (u8 is_add,
1217 u8 is_local,
1218 u32 fib_index,
1219 const mfib_prefix_t * prefix,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001220 dpo_proto_t nh_proto,
Neale Ranns32e1c012016-11-22 17:07:28 +00001221 u32 entry_flags,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001222 fib_rpf_id_t rpf_id,
Neale Rannse821ab12017-06-01 07:45:05 -07001223 u32 next_hop_sw_if_index,
1224 ip46_address_t * nh, u32 itf_flags, u32 bier_imp)
Neale Ranns32e1c012016-11-22 17:07:28 +00001225{
Neale Ranns28c142e2018-09-07 09:37:07 -07001226 fib_node_index_t mfib_entry_index = ~0;
1227
Neale Ranns32e1c012016-11-22 17:07:28 +00001228 stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
1229
1230 fib_route_path_t path = {
1231 .frp_sw_if_index = next_hop_sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001232 .frp_proto = nh_proto,
Neale Rannse821ab12017-06-01 07:45:05 -07001233 .frp_addr = *nh,
Neale Ranns32e1c012016-11-22 17:07:28 +00001234 };
1235
1236 if (is_local)
1237 path.frp_flags |= FIB_ROUTE_PATH_LOCAL;
1238
Neale Rannsd792d9c2017-10-21 10:53:20 -07001239 if (DPO_PROTO_BIER == nh_proto)
1240 {
1241 path.frp_bier_imp = bier_imp;
1242 path.frp_flags = FIB_ROUTE_PATH_BIER_IMP;
1243 }
1244 else if (!is_local && ~0 == next_hop_sw_if_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001245 {
Neale Ranns28c142e2018-09-07 09:37:07 -07001246 mfib_entry_index = mfib_table_entry_update (fib_index, prefix,
1247 MFIB_SOURCE_API,
1248 rpf_id, entry_flags);
Neale Rannsd792d9c2017-10-21 10:53:20 -07001249 goto done;
1250 }
1251
1252 if (is_add)
1253 {
Neale Ranns28c142e2018-09-07 09:37:07 -07001254 mfib_entry_index = mfib_table_entry_path_update (fib_index, prefix,
1255 MFIB_SOURCE_API,
1256 &path, itf_flags);
Neale Ranns32e1c012016-11-22 17:07:28 +00001257 }
1258 else
1259 {
Neale Rannsd792d9c2017-10-21 10:53:20 -07001260 mfib_table_entry_path_remove (fib_index, prefix,
1261 MFIB_SOURCE_API, &path);
Neale Ranns32e1c012016-11-22 17:07:28 +00001262 }
1263
Neale Rannsd792d9c2017-10-21 10:53:20 -07001264done:
Neale Ranns32e1c012016-11-22 17:07:28 +00001265 stats_dsunlock ();
Neale Ranns28c142e2018-09-07 09:37:07 -07001266 return (mfib_entry_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001267}
1268
1269static int
Neale Ranns28c142e2018-09-07 09:37:07 -07001270api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp,
1271 u32 * stats_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001272{
Neale Ranns28c142e2018-09-07 09:37:07 -07001273 fib_node_index_t mfib_entry_index;
Neale Ranns32e1c012016-11-22 17:07:28 +00001274 fib_protocol_t fproto;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001275 dpo_proto_t nh_proto;
Neale Rannse821ab12017-06-01 07:45:05 -07001276 ip46_address_t nh;
Neale Ranns32e1c012016-11-22 17:07:28 +00001277 u32 fib_index;
1278 int rv;
1279
Neale Rannsd792d9c2017-10-21 10:53:20 -07001280 nh_proto = mp->next_hop_afi;
Neale Ranns32e1c012016-11-22 17:07:28 +00001281 fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
1282 rv = add_del_mroute_check (fproto,
1283 mp->table_id,
1284 mp->next_hop_sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07001285 mp->is_local, &fib_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001286
1287 if (0 != rv)
1288 return (rv);
1289
1290 mfib_prefix_t pfx = {
1291 .fp_len = ntohs (mp->grp_address_length),
1292 .fp_proto = fproto,
1293 };
1294
1295 if (FIB_PROTOCOL_IP4 == fproto)
1296 {
1297 clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address,
1298 sizeof (pfx.fp_grp_addr.ip4));
1299 clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
1300 sizeof (pfx.fp_src_addr.ip4));
Neale Rannse821ab12017-06-01 07:45:05 -07001301 memset (&nh.ip6, 0, sizeof (nh.ip6));
1302 clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4));
Neale Ranns3e42ebe2018-10-04 08:36:56 -07001303 if (!ip46_address_is_zero (&pfx.fp_src_addr))
1304 pfx.fp_len = 64;
Neale Ranns32e1c012016-11-22 17:07:28 +00001305 }
1306 else
1307 {
1308 clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address,
1309 sizeof (pfx.fp_grp_addr.ip6));
1310 clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
1311 sizeof (pfx.fp_src_addr.ip6));
Neale Rannse821ab12017-06-01 07:45:05 -07001312 clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6));
Neale Ranns3e42ebe2018-10-04 08:36:56 -07001313 if (!ip46_address_is_zero (&pfx.fp_src_addr))
1314 pfx.fp_len = 256;
Neale Ranns32e1c012016-11-22 17:07:28 +00001315 }
1316
Neale Ranns28c142e2018-09-07 09:37:07 -07001317 mfib_entry_index = mroute_add_del_handler (mp->is_add,
1318 mp->is_local,
1319 fib_index, &pfx,
1320 nh_proto,
1321 ntohl (mp->entry_flags),
1322 ntohl (mp->rpf_id),
1323 ntohl (mp->next_hop_sw_if_index),
1324 &nh,
1325 ntohl (mp->itf_flags),
1326 ntohl (mp->bier_imp));
1327
1328 if (~0 != mfib_entry_index)
1329 *stats_index = mfib_entry_get_stats_index (mfib_entry_index);
1330
1331 return (rv);
Neale Ranns32e1c012016-11-22 17:07:28 +00001332}
1333
1334void
1335vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1336{
1337 vl_api_ip_mroute_add_del_reply_t *rmp;
Neale Ranns28c142e2018-09-07 09:37:07 -07001338 vnet_main_t *vnm;
1339 u32 stats_index;
Neale Ranns32e1c012016-11-22 17:07:28 +00001340 int rv;
Neale Ranns32e1c012016-11-22 17:07:28 +00001341
Neale Ranns28c142e2018-09-07 09:37:07 -07001342 vnm = vnet_get_main ();
Neale Ranns32e1c012016-11-22 17:07:28 +00001343 vnm->api_errno = 0;
Neale Ranns28c142e2018-09-07 09:37:07 -07001344 stats_index = ~0;
Neale Ranns32e1c012016-11-22 17:07:28 +00001345
Neale Ranns28c142e2018-09-07 09:37:07 -07001346 rv = api_mroute_add_del_t_handler (mp, &stats_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001347
Neale Ranns28c142e2018-09-07 09:37:07 -07001348 /* *INDENT-OFF* */
1349 REPLY_MACRO2 (VL_API_IP_MROUTE_ADD_DEL_REPLY,
1350 ({
1351 rmp->stats_index = htonl (stats_index);
1352 }));
1353 /* *INDENT-ON* */
Neale Ranns32e1c012016-11-22 17:07:28 +00001354}
1355
Dave Barachb5e8a772016-12-06 12:04:42 -05001356static void
1357send_ip_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001358 vl_api_registration_t * reg, u32 sw_if_index, u8 is_ipv6,
1359 u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001360{
1361 vl_api_ip_details_t *mp;
1362
1363 mp = vl_msg_api_alloc (sizeof (*mp));
1364 memset (mp, 0, sizeof (*mp));
1365 mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
1366
1367 mp->sw_if_index = ntohl (sw_if_index);
Jon Loeliger466f0d42017-02-09 12:17:50 -06001368 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001369 mp->context = context;
1370
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
1375send_ip_address_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001376 vl_api_registration_t * reg,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001377 u8 * ip, u16 prefix_length,
1378 u32 sw_if_index, u8 is_ipv6, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001379{
1380 vl_api_ip_address_details_t *mp;
1381
1382 mp = vl_msg_api_alloc (sizeof (*mp));
1383 memset (mp, 0, sizeof (*mp));
1384 mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
1385
1386 if (is_ipv6)
1387 {
1388 clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
1389 }
1390 else
1391 {
1392 u32 *tp = (u32 *) mp->ip;
1393 *tp = *(u32 *) ip;
1394 }
1395 mp->prefix_length = prefix_length;
1396 mp->context = context;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001397 mp->sw_if_index = htonl (sw_if_index);
1398 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001399
Florin Coras6c4dae22018-01-09 06:39:23 -08001400 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -05001401}
1402
1403static void
1404vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
1405{
1406 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001407 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001408 ip6_address_t *r6;
1409 ip4_address_t *r4;
1410 ip6_main_t *im6 = &ip6_main;
1411 ip4_main_t *im4 = &ip4_main;
1412 ip_lookup_main_t *lm6 = &im6->lookup_main;
1413 ip_lookup_main_t *lm4 = &im4->lookup_main;
1414 ip_interface_address_t *ia = 0;
1415 u32 sw_if_index = ~0;
1416 int rv __attribute__ ((unused)) = 0;
1417
1418 VALIDATE_SW_IF_INDEX (mp);
1419
1420 sw_if_index = ntohl (mp->sw_if_index);
1421
Florin Coras6c4dae22018-01-09 06:39:23 -08001422 reg = vl_api_client_index_to_registration (mp->client_index);
1423 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -05001424 return;
1425
Dave Barachb5e8a772016-12-06 12:04:42 -05001426 if (mp->is_ipv6)
1427 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001428 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001429 /* Do not send subnet details of the IP-interface for
1430 * unnumbered interfaces. otherwise listening clients
1431 * will be confused that the subnet is applied on more
1432 * than one interface */
1433 foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001434 ({
1435 r6 = ip_interface_address_get_address (lm6, ia);
1436 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001437 send_ip_address_details(am, reg, (u8*)r6, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001438 sw_if_index, 1, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001439 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001440 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001441 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001442 else
1443 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001444 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001445 foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001446 ({
1447 r4 = ip_interface_address_get_address (lm4, ia);
1448 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001449 send_ip_address_details(am, reg, (u8*)r4, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001450 sw_if_index, 0, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001451 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001452 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001453 }
Neale Ranns008dbe12018-09-07 09:32:36 -07001454
Dave Barachb5e8a772016-12-06 12:04:42 -05001455 BAD_SW_IF_INDEX_LABEL;
1456}
1457
1458static void
Neale Ranns9e2f9152018-05-18 02:27:10 -07001459send_ip_unnumbered_details (vpe_api_main_t * am,
1460 vl_api_registration_t * reg,
1461 u32 sw_if_index, u32 ip_sw_if_index, u32 context)
1462{
1463 vl_api_ip_unnumbered_details_t *mp;
1464
1465 mp = vl_msg_api_alloc (sizeof (*mp));
1466 memset (mp, 0, sizeof (*mp));
1467 mp->_vl_msg_id = ntohs (VL_API_IP_UNNUMBERED_DETAILS);
1468
1469 mp->context = context;
1470 mp->sw_if_index = htonl (sw_if_index);
1471 mp->ip_sw_if_index = htonl (ip_sw_if_index);
1472
1473 vl_api_send_msg (reg, (u8 *) mp);
1474}
1475
1476static void
1477vl_api_ip_unnumbered_dump_t_handler (vl_api_ip_unnumbered_dump_t * mp)
1478{
1479 vnet_main_t *vnm = vnet_get_main ();
1480 vnet_interface_main_t *im = &vnm->interface_main;
1481 int rv __attribute__ ((unused)) = 0;
1482 vpe_api_main_t *am = &vpe_api_main;
1483 vl_api_registration_t *reg;
1484 vnet_sw_interface_t *si;
1485 u32 sw_if_index;
1486
1487 sw_if_index = ntohl (mp->sw_if_index);
1488
1489 reg = vl_api_client_index_to_registration (mp->client_index);
1490 if (!reg)
1491 return;
1492
1493 if (~0 != sw_if_index)
1494 {
1495 VALIDATE_SW_IF_INDEX (mp);
1496
1497 si = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
1498
1499 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1500 {
1501 send_ip_unnumbered_details (am, reg,
1502 sw_if_index,
1503 si->unnumbered_sw_if_index,
1504 mp->context);
1505 }
1506 }
1507 else
1508 {
1509 /* *INDENT-OFF* */
1510 pool_foreach (si, im->sw_interfaces,
1511 ({
1512 if ((si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1513 {
1514 send_ip_unnumbered_details(am, reg,
1515 si->sw_if_index,
1516 si->unnumbered_sw_if_index,
1517 mp->context);
1518 }
1519 }));
1520 /* *INDENT-ON* */
1521 }
1522
1523 BAD_SW_IF_INDEX_LABEL;
1524}
1525
1526static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001527vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
1528{
1529 vpe_api_main_t *am = &vpe_api_main;
1530 vnet_main_t *vnm = vnet_get_main ();
1531 vlib_main_t *vm = vlib_get_main ();
1532 vnet_interface_main_t *im = &vnm->interface_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001533 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001534 vnet_sw_interface_t *si, *sorted_sis;
1535 u32 sw_if_index = ~0;
1536
Florin Coras6c4dae22018-01-09 06:39:23 -08001537 reg = vl_api_client_index_to_registration (mp->client_index);
1538 if (!reg)
1539 return;
Dave Barachb5e8a772016-12-06 12:04:42 -05001540
1541 /* Gather interfaces. */
1542 sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
1543 _vec_len (sorted_sis) = 0;
1544 /* *INDENT-OFF* */
1545 pool_foreach (si, im->sw_interfaces,
1546 ({
1547 vec_add1 (sorted_sis, si[0]);
1548 }));
1549 /* *INDENT-ON* */
1550
1551 vec_foreach (si, sorted_sis)
1552 {
1553 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1554 {
1555 if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
1556 {
1557 continue;
1558 }
1559 sw_if_index = si->sw_if_index;
Florin Coras6c4dae22018-01-09 06:39:23 -08001560 send_ip_details (am, reg, sw_if_index, mp->is_ipv6, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001561 }
1562 }
1563}
1564
1565static void
1566set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1567{
1568 vl_api_set_ip_flow_hash_reply_t *rmp;
Neale Ranns227038a2017-04-21 01:07:59 -07001569 int rv;
1570 u32 table_id;
1571 flow_hash_config_t flow_hash_config = 0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001572
Neale Ranns227038a2017-04-21 01:07:59 -07001573 table_id = ntohl (mp->vrf_id);
1574
1575#define _(a,b) if (mp->a) flow_hash_config |= b;
1576 foreach_flow_hash_bit;
1577#undef _
1578
1579 rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
Dave Barachb5e8a772016-12-06 12:04:42 -05001580
1581 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1582}
1583
1584static void
1585set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1586{
1587 vl_api_set_ip_flow_hash_reply_t *rmp;
1588 int rv;
1589 u32 table_id;
1590 flow_hash_config_t flow_hash_config = 0;
1591
1592 table_id = ntohl (mp->vrf_id);
1593
1594#define _(a,b) if (mp->a) flow_hash_config |= b;
1595 foreach_flow_hash_bit;
1596#undef _
1597
1598 rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
1599
1600 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1601}
1602
1603
1604static void
1605vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t * mp)
1606{
1607 if (mp->is_ipv6 == 0)
1608 set_ip4_flow_hash (mp);
1609 else
1610 set_ip6_flow_hash (mp);
1611}
1612
1613static void
1614 vl_api_sw_interface_ip6nd_ra_config_t_handler
1615 (vl_api_sw_interface_ip6nd_ra_config_t * mp)
1616{
1617 vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
1618 vlib_main_t *vm = vlib_get_main ();
1619 int rv = 0;
1620 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
1621 default_router;
1622
1623 is_no = mp->is_no == 1;
1624 suppress = mp->suppress == 1;
1625 managed = mp->managed == 1;
1626 other = mp->other == 1;
1627 ll_option = mp->ll_option == 1;
1628 send_unicast = mp->send_unicast == 1;
1629 cease = mp->cease == 1;
1630 default_router = mp->default_router == 1;
1631
1632 VALIDATE_SW_IF_INDEX (mp);
1633
1634 rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
1635 suppress, managed, other,
1636 ll_option, send_unicast, cease,
1637 default_router, ntohl (mp->lifetime),
1638 ntohl (mp->initial_count),
1639 ntohl (mp->initial_interval),
1640 ntohl (mp->max_interval),
1641 ntohl (mp->min_interval), is_no);
1642
1643 BAD_SW_IF_INDEX_LABEL;
1644
1645 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
1646}
1647
1648static void
1649 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
1650 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
1651{
1652 vlib_main_t *vm = vlib_get_main ();
1653 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
1654 int rv = 0;
1655 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
1656
1657 VALIDATE_SW_IF_INDEX (mp);
1658
1659 is_no = mp->is_no == 1;
1660 use_default = mp->use_default == 1;
1661 no_advertise = mp->no_advertise == 1;
1662 off_link = mp->off_link == 1;
1663 no_autoconfig = mp->no_autoconfig == 1;
1664 no_onlink = mp->no_onlink == 1;
1665
1666 rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
1667 (ip6_address_t *) mp->address,
1668 mp->address_length, use_default,
1669 ntohl (mp->val_lifetime),
1670 ntohl (mp->pref_lifetime), no_advertise,
1671 off_link, no_autoconfig, no_onlink, is_no);
1672
1673 BAD_SW_IF_INDEX_LABEL;
1674 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
1675}
1676
1677static void
Florin Coras6c4dae22018-01-09 06:39:23 -08001678send_ip6nd_proxy_details (vl_api_registration_t * reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001679 u32 context,
1680 const ip46_address_t * addr, u32 sw_if_index)
1681{
1682 vl_api_ip6nd_proxy_details_t *mp;
1683
1684 mp = vl_msg_api_alloc (sizeof (*mp));
1685 memset (mp, 0, sizeof (*mp));
1686 mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
1687 mp->context = context;
1688 mp->sw_if_index = htonl (sw_if_index);
1689 memcpy (mp->address, addr, 16);
1690
Florin Coras6c4dae22018-01-09 06:39:23 -08001691 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns3f844d02017-02-18 00:03:54 -08001692}
1693
Neale Ranns3f844d02017-02-18 00:03:54 -08001694typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
1695{
1696 u32 *indices;
1697} api_ip6nd_proxy_fib_table_walk_ctx_t;
1698
Neale Ranns89541992017-04-06 04:41:02 -07001699static fib_table_walk_rc_t
Neale Ranns3f844d02017-02-18 00:03:54 -08001700api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
1701{
1702 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
1703
1704 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
1705 {
1706 vec_add1 (ctx->indices, fei);
1707 }
1708
Neale Ranns89541992017-04-06 04:41:02 -07001709 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns3f844d02017-02-18 00:03:54 -08001710}
1711
1712static void
1713vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
1714{
1715 ip6_main_t *im6 = &ip6_main;
1716 fib_table_t *fib_table;
1717 api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
1718 .indices = NULL,
1719 };
1720 fib_node_index_t *feip;
Neale Rannsc5d43172018-07-30 08:04:40 -07001721 const fib_prefix_t *pfx;
Florin Coras6c4dae22018-01-09 06:39:23 -08001722 vl_api_registration_t *reg;
Neale Ranns3f844d02017-02-18 00:03:54 -08001723
Florin Coras6c4dae22018-01-09 06:39:23 -08001724 reg = vl_api_client_index_to_registration (mp->client_index);
1725 if (!reg)
1726 return;
Neale Ranns3f844d02017-02-18 00:03:54 -08001727
1728 /* *INDENT-OFF* */
1729 pool_foreach (fib_table, im6->fibs,
1730 ({
1731 fib_table_walk(fib_table->ft_index,
1732 FIB_PROTOCOL_IP6,
1733 api_ip6nd_proxy_fib_table_walk,
1734 &ctx);
1735 }));
1736 /* *INDENT-ON* */
1737
1738 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
1739
1740 vec_foreach (feip, ctx.indices)
1741 {
Neale Rannsc5d43172018-07-30 08:04:40 -07001742 pfx = fib_entry_get_prefix (*feip);
Neale Ranns3f844d02017-02-18 00:03:54 -08001743
Florin Coras6c4dae22018-01-09 06:39:23 -08001744 send_ip6nd_proxy_details (reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001745 mp->context,
Neale Rannsc5d43172018-07-30 08:04:40 -07001746 &pfx->fp_addr,
Neale Ranns3f844d02017-02-18 00:03:54 -08001747 fib_entry_get_resolving_interface (*feip));
1748 }
1749
1750 vec_free (ctx.indices);
1751}
1752
1753static void
1754vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
1755{
1756 vl_api_ip6nd_proxy_add_del_reply_t *rmp;
1757 int rv = 0;
1758
1759 VALIDATE_SW_IF_INDEX (mp);
1760
1761 rv = ip6_neighbor_proxy_add_del (ntohl (mp->sw_if_index),
1762 (ip6_address_t *) mp->address, mp->is_del);
1763
1764 BAD_SW_IF_INDEX_LABEL;
1765 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
1766}
1767
1768static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01001769 vl_api_ip6nd_send_router_solicitation_t_handler
1770 (vl_api_ip6nd_send_router_solicitation_t * mp)
1771{
1772 vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
1773 icmp6_send_router_solicitation_params_t params;
1774 vlib_main_t *vm = vlib_get_main ();
1775 int rv = 0;
1776
1777 VALIDATE_SW_IF_INDEX (mp);
1778
1779 BAD_SW_IF_INDEX_LABEL;
1780 REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
1781
1782 if (rv != 0)
1783 return;
1784
1785 params.irt = ntohl (mp->irt);
1786 params.mrt = ntohl (mp->mrt);
1787 params.mrc = ntohl (mp->mrc);
1788 params.mrd = ntohl (mp->mrd);
1789
1790 icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
1791 &params);
1792}
1793
1794static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001795 vl_api_sw_interface_ip6_enable_disable_t_handler
1796 (vl_api_sw_interface_ip6_enable_disable_t * mp)
1797{
1798 vlib_main_t *vm = vlib_get_main ();
1799 vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
1800 vnet_main_t *vnm = vnet_get_main ();
1801 int rv = 0;
1802 clib_error_t *error;
1803
1804 vnm->api_errno = 0;
1805
1806 VALIDATE_SW_IF_INDEX (mp);
1807
1808 error =
1809 (mp->enable == 1) ? enable_ip6_interface (vm,
1810 ntohl (mp->sw_if_index)) :
1811 disable_ip6_interface (vm, ntohl (mp->sw_if_index));
1812
1813 if (error)
1814 {
1815 clib_error_report (error);
1816 rv = VNET_API_ERROR_UNSPECIFIED;
1817 }
1818 else
1819 {
1820 rv = vnm->api_errno;
1821 }
1822
1823 BAD_SW_IF_INDEX_LABEL;
1824
1825 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
1826}
1827
1828static void
1829 vl_api_sw_interface_ip6_set_link_local_address_t_handler
1830 (vl_api_sw_interface_ip6_set_link_local_address_t * mp)
1831{
1832 vlib_main_t *vm = vlib_get_main ();
1833 vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp;
1834 int rv = 0;
1835 clib_error_t *error;
1836 vnet_main_t *vnm = vnet_get_main ();
1837
1838 vnm->api_errno = 0;
1839
1840 VALIDATE_SW_IF_INDEX (mp);
1841
1842 error = set_ip6_link_local_address (vm,
1843 ntohl (mp->sw_if_index),
Neale Ranns75152282017-01-09 01:00:45 -08001844 (ip6_address_t *) mp->address);
Dave Barachb5e8a772016-12-06 12:04:42 -05001845 if (error)
1846 {
1847 clib_error_report (error);
1848 rv = VNET_API_ERROR_UNSPECIFIED;
1849 }
1850 else
1851 {
1852 rv = vnm->api_errno;
1853 }
1854
1855 BAD_SW_IF_INDEX_LABEL;
1856
1857 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
1858}
1859
Neale Ranns32e1c012016-11-22 17:07:28 +00001860void
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001861vl_mfib_signal_send_one (vl_api_registration_t * reg,
Neale Ranns32e1c012016-11-22 17:07:28 +00001862 u32 context, const mfib_signal_t * mfs)
1863{
1864 vl_api_mfib_signal_details_t *mp;
1865 mfib_prefix_t prefix;
1866 mfib_table_t *mfib;
1867 mfib_itf_t *mfi;
1868
1869 mp = vl_msg_api_alloc (sizeof (*mp));
1870
1871 memset (mp, 0, sizeof (*mp));
1872 mp->_vl_msg_id = ntohs (VL_API_MFIB_SIGNAL_DETAILS);
1873 mp->context = context;
1874
1875 mfi = mfib_itf_get (mfs->mfs_itf);
1876 mfib_entry_get_prefix (mfs->mfs_entry, &prefix);
1877 mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry),
1878 prefix.fp_proto);
1879 mp->table_id = ntohl (mfib->mft_table_id);
1880 mp->sw_if_index = ntohl (mfi->mfi_sw_if_index);
1881
1882 if (FIB_PROTOCOL_IP4 == prefix.fp_proto)
1883 {
1884 mp->grp_address_len = ntohs (prefix.fp_len);
1885
1886 memcpy (mp->grp_address, &prefix.fp_grp_addr.ip4, 4);
1887 if (prefix.fp_len > 32)
1888 {
1889 memcpy (mp->src_address, &prefix.fp_src_addr.ip4, 4);
1890 }
1891 }
1892 else
1893 {
1894 mp->grp_address_len = ntohs (prefix.fp_len);
1895
1896 ASSERT (0);
1897 }
1898
1899 if (0 != mfs->mfs_buffer_len)
1900 {
1901 mp->ip_packet_len = ntohs (mfs->mfs_buffer_len);
1902
1903 memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len);
1904 }
1905 else
1906 {
1907 mp->ip_packet_len = 0;
1908 }
1909
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001910 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns32e1c012016-11-22 17:07:28 +00001911}
1912
1913static void
1914vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
1915{
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001916 vl_api_registration_t *reg;
Neale Ranns32e1c012016-11-22 17:07:28 +00001917
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001918 reg = vl_api_client_index_to_registration (mp->client_index);
1919 if (!reg)
1920 return;
Neale Ranns32e1c012016-11-22 17:07:28 +00001921
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001922 while (vl_api_can_send_msg (reg) && mfib_signal_send_one (reg, mp->context))
Neale Ranns32e1c012016-11-22 17:07:28 +00001923 ;
1924}
Dave Barachb5e8a772016-12-06 12:04:42 -05001925
Florin Coras595992c2017-11-06 17:17:08 -08001926static void
1927 vl_api_ip_container_proxy_add_del_t_handler
1928 (vl_api_ip_container_proxy_add_del_t * mp)
1929{
1930 vl_api_ip_container_proxy_add_del_reply_t *rmp;
1931 vnet_ip_container_proxy_args_t args;
1932 int rv = 0;
1933 clib_error_t *error;
1934
1935 memset (&args, 0, sizeof (args));
1936 ip_set (&args.prefix.fp_addr, mp->ip, mp->is_ip4);
1937 args.prefix.fp_len = mp->plen ? mp->plen : (mp->is_ip4 ? 32 : 128);
1938 args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1939 args.is_add = mp->is_add;
1940 if ((error = vnet_ip_container_proxy_add_del (&args)))
1941 {
1942 rv = clib_error_get_code (error);
1943 clib_error_report (error);
1944 }
1945
1946 REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY);
1947}
1948
Matus Fabian75b9f452018-10-02 23:27:21 -07001949typedef struct ip_container_proxy_walk_ctx_t_
1950{
1951 vl_api_registration_t *reg;
1952 u32 context;
1953} ip_container_proxy_walk_ctx_t;
1954
1955static int
1956ip_container_proxy_send_details (const fib_prefix_t * pfx, u32 sw_if_index,
1957 void *args)
1958{
1959 vl_api_ip_container_proxy_details_t *mp;
1960 ip_container_proxy_walk_ctx_t *ctx = args;
1961
1962 mp = vl_msg_api_alloc (sizeof (*mp));
1963 if (!mp)
1964 return 1;
1965
1966 memset (mp, 0, sizeof (*mp));
1967 mp->_vl_msg_id = ntohs (VL_API_IP_CONTAINER_PROXY_DETAILS);
1968 mp->context = ctx->context;
1969
1970 mp->sw_if_index = ntohl (sw_if_index);
1971 ip_prefix_encode (pfx, &mp->prefix);
1972
1973 vl_api_send_msg (ctx->reg, (u8 *) mp);
1974
1975 return 1;
1976}
1977
1978static void
1979vl_api_ip_container_proxy_dump_t_handler (vl_api_ip_container_proxy_dump_t *
1980 mp)
1981{
1982 vl_api_registration_t *reg;
1983
1984 reg = vl_api_client_index_to_registration (mp->client_index);
1985 if (!reg)
1986 return;
1987
1988 ip_container_proxy_walk_ctx_t ctx = {
1989 .context = mp->context,
1990 .reg = reg,
1991 };
1992
1993 ip_container_proxy_walk (ip_container_proxy_send_details, &ctx);
1994}
1995
Neale Rannsb8d44812017-11-10 06:53:54 -08001996static void
1997vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
1998{
1999 int rv = 0;
2000 vl_api_ioam_enable_reply_t *rmp;
2001 clib_error_t *error;
2002
2003 /* Ignoring the profile id as currently a single profile
2004 * is supported */
2005 error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
2006 mp->seqno, mp->analyse);
2007 if (error)
2008 {
2009 clib_error_report (error);
2010 rv = clib_error_get_code (error);
2011 }
2012
2013 REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
2014}
2015
2016static void
2017vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
2018{
2019 int rv = 0;
2020 vl_api_ioam_disable_reply_t *rmp;
2021 clib_error_t *error;
2022
2023 error = clear_ioam_rewrite_fn ();
2024 if (error)
2025 {
2026 clib_error_report (error);
2027 rv = clib_error_get_code (error);
2028 }
2029
2030 REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
2031}
2032
2033static void
2034 vl_api_ip_source_and_port_range_check_add_del_t_handler
2035 (vl_api_ip_source_and_port_range_check_add_del_t * mp)
2036{
2037 vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
2038 int rv = 0;
2039
2040 u8 is_ipv6 = mp->is_ipv6;
2041 u8 is_add = mp->is_add;
2042 u8 mask_length = mp->mask_length;
2043 ip4_address_t ip4_addr;
2044 ip6_address_t ip6_addr;
2045 u16 *low_ports = 0;
2046 u16 *high_ports = 0;
2047 u32 vrf_id;
2048 u16 tmp_low, tmp_high;
2049 u8 num_ranges;
2050 int i;
2051
2052 // Validate port range
2053 num_ranges = mp->number_of_ranges;
2054 if (num_ranges > 32)
2055 { // This is size of array in VPE.API
2056 rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
2057 goto reply;
2058 }
2059
2060 vec_reset_length (low_ports);
2061 vec_reset_length (high_ports);
2062
2063 for (i = 0; i < num_ranges; i++)
2064 {
2065 tmp_low = mp->low_ports[i];
2066 tmp_high = mp->high_ports[i];
2067 // If tmp_low <= tmp_high then only need to check tmp_low = 0
2068 // If tmp_low <= tmp_high then only need to check tmp_high > 65535
2069 if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
2070 {
2071 rv = VNET_API_ERROR_INVALID_VALUE;
2072 goto reply;
2073 }
2074 vec_add1 (low_ports, tmp_low);
2075 vec_add1 (high_ports, tmp_high + 1);
2076 }
2077
2078 // Validate mask_length
2079 if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
2080 {
2081 rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
2082 goto reply;
2083 }
2084
2085 vrf_id = ntohl (mp->vrf_id);
2086
2087 if (vrf_id < 1)
2088 {
2089 rv = VNET_API_ERROR_INVALID_VALUE;
2090 goto reply;
2091 }
2092
2093
2094 if (is_ipv6)
2095 {
2096 clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
2097 rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
2098 mask_length,
2099 vrf_id,
2100 low_ports,
2101 high_ports, is_add);
2102 }
2103 else
2104 {
2105 clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
2106 rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
2107 mask_length,
2108 vrf_id,
2109 low_ports,
2110 high_ports, is_add);
2111 }
2112
2113reply:
2114 vec_free (low_ports);
2115 vec_free (high_ports);
2116 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
2117}
2118
2119static void
2120 vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
2121 (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
2122{
2123 vlib_main_t *vm = vlib_get_main ();
2124 vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
2125 ip4_main_t *im = &ip4_main;
2126 int rv;
2127 u32 sw_if_index;
2128 u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2129 u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2130 uword *p = 0;
2131 int i;
2132
2133 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
2134 ntohl (mp->tcp_out_vrf_id);
2135 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
2136 ntohl (mp->udp_out_vrf_id);
2137 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
2138 ntohl (mp->tcp_in_vrf_id);
2139 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
2140 ntohl (mp->udp_in_vrf_id);
2141
2142
2143 for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
2144 {
2145 if (vrf_id[i] != 0 && vrf_id[i] != ~0)
2146 {
2147 p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
2148
2149 if (p == 0)
2150 {
2151 rv = VNET_API_ERROR_INVALID_VALUE;
2152 goto reply;
2153 }
2154
2155 fib_index[i] = p[0];
2156 }
2157 else
2158 fib_index[i] = ~0;
2159 }
2160 sw_if_index = ntohl (mp->sw_if_index);
2161
2162 VALIDATE_SW_IF_INDEX (mp);
2163
2164 rv =
2165 set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
2166 mp->is_add);
2167
2168 BAD_SW_IF_INDEX_LABEL;
2169reply:
2170
2171 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
2172}
2173
2174#define IP4_ARP_EVENT 3
2175#define IP6_ND_EVENT 4
2176
2177static int arp_change_delete_callback (u32 pool_index, u8 * notused);
2178static int nd_change_delete_callback (u32 pool_index, u8 * notused);
2179static vlib_node_registration_t ip_resolver_process_node;
2180
2181static void
2182handle_ip4_arp_event (u32 pool_index)
2183{
2184 vpe_api_main_t *vam = &vpe_api_main;
2185 vnet_main_t *vnm = vam->vnet_main;
2186 vlib_main_t *vm = vam->vlib_main;
2187 vl_api_ip4_arp_event_t *event;
2188 vl_api_ip4_arp_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002189 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002190
2191 /* Client can cancel, die, etc. */
2192 if (pool_is_free_index (vam->arp_events, pool_index))
2193 return;
2194
2195 event = pool_elt_at_index (vam->arp_events, pool_index);
2196
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002197 reg = vl_api_client_index_to_registration (event->client_index);
2198 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002199 {
2200 (void) vnet_add_del_ip4_arp_change_event
2201 (vnm, arp_change_delete_callback,
2202 event->pid, &event->address,
2203 ip_resolver_process_node.index, IP4_ARP_EVENT,
2204 ~0 /* pool index, notused */ , 0 /* is_add */ );
2205 return;
2206 }
2207
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002208 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002209 {
2210 mp = vl_msg_api_alloc (sizeof (*mp));
2211 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002212 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002213 }
2214 else
2215 {
2216 static f64 last_time;
2217 /*
2218 * Throttle syslog msgs.
2219 * It's pretty tempting to just revoke the registration...
2220 */
2221 if (vlib_time_now (vm) > last_time + 10.0)
2222 {
2223 clib_warning ("arp event for %U to pid %d: queue stuffed!",
2224 format_ip4_address, &event->address, event->pid);
2225 last_time = vlib_time_now (vm);
2226 }
2227 }
2228}
2229
Neale Rannsf12dad62018-06-04 18:41:24 -07002230static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002231handle_ip6_nd_event (u32 pool_index)
2232{
2233 vpe_api_main_t *vam = &vpe_api_main;
2234 vnet_main_t *vnm = vam->vnet_main;
2235 vlib_main_t *vm = vam->vlib_main;
2236 vl_api_ip6_nd_event_t *event;
2237 vl_api_ip6_nd_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002238 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002239
2240 /* Client can cancel, die, etc. */
2241 if (pool_is_free_index (vam->nd_events, pool_index))
2242 return;
2243
2244 event = pool_elt_at_index (vam->nd_events, pool_index);
2245
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002246 reg = vl_api_client_index_to_registration (event->client_index);
2247 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002248 {
2249 (void) vnet_add_del_ip6_nd_change_event
2250 (vnm, nd_change_delete_callback,
2251 event->pid, &event->address,
2252 ip_resolver_process_node.index, IP6_ND_EVENT,
2253 ~0 /* pool index, notused */ , 0 /* is_add */ );
2254 return;
2255 }
2256
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002257 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002258 {
2259 mp = vl_msg_api_alloc (sizeof (*mp));
2260 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002261 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002262 }
2263 else
2264 {
2265 static f64 last_time;
2266 /*
2267 * Throttle syslog msgs.
2268 * It's pretty tempting to just revoke the registration...
2269 */
2270 if (vlib_time_now (vm) > last_time + 10.0)
2271 {
2272 clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
2273 format_ip6_address, &event->address, event->pid);
2274 last_time = vlib_time_now (vm);
2275 }
2276 }
2277}
2278
2279static uword
2280resolver_process (vlib_main_t * vm,
2281 vlib_node_runtime_t * rt, vlib_frame_t * f)
2282{
2283 volatile f64 timeout = 100.0;
2284 volatile uword *event_data = 0;
2285
2286 while (1)
2287 {
2288 vlib_process_wait_for_event_or_clock (vm, timeout);
2289
2290 uword event_type =
2291 vlib_process_get_events (vm, (uword **) & event_data);
2292
2293 int i;
2294 switch (event_type)
2295 {
2296 case IP4_ARP_EVENT:
2297 for (i = 0; i < vec_len (event_data); i++)
2298 handle_ip4_arp_event (event_data[i]);
2299 break;
2300
2301 case IP6_ND_EVENT:
2302 for (i = 0; i < vec_len (event_data); i++)
2303 handle_ip6_nd_event (event_data[i]);
2304 break;
2305
2306 case ~0: /* timeout */
2307 break;
2308 }
2309
2310 vec_reset_length (event_data);
2311 }
2312 return 0; /* or not */
2313}
2314
2315/* *INDENT-OFF* */
2316VLIB_REGISTER_NODE (ip_resolver_process_node,static) = {
2317 .function = resolver_process,
2318 .type = VLIB_NODE_TYPE_PROCESS,
2319 .name = "ip-route-resolver-process",
2320};
2321/* *INDENT-ON* */
2322
2323static int
2324nd_change_data_callback (u32 pool_index, u8 * new_mac,
2325 u32 sw_if_index, ip6_address_t * address)
2326{
2327 vpe_api_main_t *am = &vpe_api_main;
2328 vl_api_ip6_nd_event_t *event;
2329
2330 if (pool_is_free_index (am->nd_events, pool_index))
2331 return 1;
2332
2333 event = pool_elt_at_index (am->nd_events, pool_index);
2334 if (eth_mac_equal (event->new_mac, new_mac) &&
2335 sw_if_index == ntohl (event->sw_if_index))
2336 {
2337 return 1;
2338 }
2339
2340 clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2341 event->sw_if_index = htonl (sw_if_index);
2342 return 0;
2343}
2344
2345static int
2346arp_change_delete_callback (u32 pool_index, u8 * notused)
2347{
2348 vpe_api_main_t *am = &vpe_api_main;
2349
2350 if (pool_is_free_index (am->arp_events, pool_index))
2351 return 1;
2352
2353 pool_put_index (am->arp_events, pool_index);
2354 return 0;
2355}
2356
2357static int
2358nd_change_delete_callback (u32 pool_index, u8 * notused)
2359{
2360 vpe_api_main_t *am = &vpe_api_main;
2361
2362 if (pool_is_free_index (am->nd_events, pool_index))
2363 return 1;
2364
2365 pool_put_index (am->nd_events, pool_index);
2366 return 0;
2367}
2368
2369static vlib_node_registration_t wc_arp_process_node;
2370
2371enum
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002372{ WC_ARP_REPORT, WC_ND_REPORT, RA_REPORT, REPORT_MAX };
Neale Rannsb8d44812017-11-10 06:53:54 -08002373
2374static uword
2375wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
2376{
2377 /* These cross the longjmp boundry (vlib_process_wait_for_event)
2378 * and need to be volatile - to prevent them from being optimized into
2379 * a register - which could change during suspension */
2380
2381 volatile wc_arp_report_t arp_prev = { 0 };
2382 volatile wc_nd_report_t nd_prev = { 0 };
2383 volatile f64 last_arp = vlib_time_now (vm);
2384 volatile f64 last_nd = vlib_time_now (vm);
2385
2386 while (1)
2387 {
2388 vlib_process_wait_for_event (vm);
2389 uword event_type = WC_ARP_REPORT;
2390 void *event_data = vlib_process_get_event_data (vm, &event_type);
2391
2392 f64 now = vlib_time_now (vm);
2393 int i;
2394 if (event_type == WC_ARP_REPORT)
2395 {
2396 wc_arp_report_t *arp_events = event_data;
2397 for (i = 0; i < vec_len (arp_events); i++)
2398 {
2399 /* discard dup event */
2400 if (arp_prev.ip4 == arp_events[i].ip4 &&
2401 eth_mac_equal ((u8 *) arp_prev.mac, arp_events[i].mac) &&
2402 arp_prev.sw_if_index == arp_events[i].sw_if_index &&
2403 (now - last_arp) < 10.0)
2404 {
2405 continue;
2406 }
2407 arp_prev = arp_events[i];
2408 last_arp = now;
2409 vpe_client_registration_t *reg;
2410 /* *INDENT-OFF* */
2411 pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations,
2412 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002413 vl_api_registration_t *vl_reg;
2414 vl_reg = vl_api_client_index_to_registration (reg->client_index);
Chris Luke30684ac2018-03-29 12:56:58 -07002415 ASSERT (vl_reg != NULL);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002416 if (reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002417 {
2418 vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event);
2419 memset (event, 0, sizeof *event);
2420 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2421 event->client_index = reg->client_index;
2422 event->pid = reg->client_pid;
2423 event->mac_ip = 1;
2424 event->address = arp_events[i].ip4;
2425 event->sw_if_index = htonl(arp_events[i].sw_if_index);
2426 memcpy(event->new_mac, arp_events[i].mac, sizeof event->new_mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002427 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002428 }
2429 }));
2430 /* *INDENT-ON* */
2431 }
2432 }
2433 else if (event_type == WC_ND_REPORT)
2434 {
2435 wc_nd_report_t *nd_events = event_data;
2436 for (i = 0; i < vec_len (nd_events); i++)
2437 {
2438 /* discard dup event */
2439 if (ip6_address_is_equal
2440 ((ip6_address_t *) & nd_prev.ip6, &nd_events[i].ip6)
2441 && eth_mac_equal ((u8 *) nd_prev.mac, nd_events[i].mac)
2442 && nd_prev.sw_if_index == nd_events[i].sw_if_index
2443 && (now - last_nd) < 10.0)
2444 {
2445 continue;
2446 }
2447 nd_prev = nd_events[i];
2448 last_nd = now;
2449 vpe_client_registration_t *reg;
2450 /* *INDENT-OFF* */
2451 pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations,
2452 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002453 vl_api_registration_t *vl_reg;
2454 vl_reg = vl_api_client_index_to_registration (reg->client_index);
2455 if (vl_reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002456 {
2457 vl_api_ip6_nd_event_t * event = vl_msg_api_alloc (sizeof *event);
2458 memset (event, 0, sizeof *event);
2459 event->_vl_msg_id = htons (VL_API_IP6_ND_EVENT);
2460 event->client_index = reg->client_index;
2461 event->pid = reg->client_pid;
2462 event->mac_ip = 1;
2463 memcpy(event->address, nd_events[i].ip6.as_u8, sizeof event->address);
2464 event->sw_if_index = htonl(nd_events[i].sw_if_index);
2465 memcpy(event->new_mac, nd_events[i].mac, sizeof event->new_mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002466 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002467 }
2468 }));
2469 /* *INDENT-ON* */
2470 }
2471 }
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002472 else if (event_type == RA_REPORT)
2473 {
2474 ra_report_t *ra_events = event_data;
2475 for (i = 0; i < vec_len (ra_events); i++)
2476 {
Juraj Sloboda52574522018-05-03 10:03:50 +02002477 ip6_neighbor_public_main_t *npm = &ip6_neighbor_public_main;
2478 call_ip6_neighbor_callbacks (&ra_events[i],
2479 npm->ra_report_functions);
2480
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002481 vpe_client_registration_t *reg;
2482 /* *INDENT-OFF* */
2483 pool_foreach(reg, vpe_api_main.ip6_ra_events_registrations,
2484 ({
2485 vl_api_registration_t *vl_reg;
2486 vl_reg =
2487 vl_api_client_index_to_registration (reg->client_index);
2488 if (vl_reg && vl_api_can_send_msg (vl_reg))
2489 {
2490 u32 event_size =
2491 sizeof (vl_api_ip6_ra_event_t) +
2492 vec_len (ra_events[i].prefixes) *
2493 sizeof (vl_api_ip6_ra_prefix_info_t);
2494 vl_api_ip6_ra_event_t *event =
2495 vl_msg_api_alloc (event_size);
2496 memset (event, 0, event_size);
2497 event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT);
2498 event->client_index = reg->client_index;
2499 event->pid = reg->client_pid;
2500
2501 event->sw_if_index = clib_host_to_net_u32 (ra_events[i].sw_if_index);
2502
2503 memcpy (event->router_address, ra_events[i].router_address, 16);
2504
2505 event->current_hop_limit = ra_events[i].current_hop_limit;
2506 event->flags = ra_events[i].flags;
2507 event->router_lifetime_in_sec =
2508 clib_host_to_net_u16 (ra_events
2509 [i].router_lifetime_in_sec);
2510 event->neighbor_reachable_time_in_msec =
2511 clib_host_to_net_u32 (ra_events
2512 [i].neighbor_reachable_time_in_msec);
2513 event->time_in_msec_between_retransmitted_neighbor_solicitations
2514 =
2515 clib_host_to_net_u32 (ra_events
2516 [i].time_in_msec_between_retransmitted_neighbor_solicitations);
2517
2518 event->n_prefixes =
2519 clib_host_to_net_u32 (vec_len (ra_events[i].prefixes));
2520 vl_api_ip6_ra_prefix_info_t *prefix =
2521 (typeof (prefix)) event->prefixes;
2522 u32 j;
2523 for (j = 0; j < vec_len (ra_events[i].prefixes); j++)
2524 {
2525 ra_report_prefix_info_t *info =
2526 &ra_events[i].prefixes[j];
2527 memcpy (prefix->dst_address, info->dst_address.as_u8,
2528 16);
2529 prefix->dst_address_length = info->dst_address_length;
2530 prefix->flags = info->flags;
2531 prefix->valid_time =
2532 clib_host_to_net_u32 (info->valid_time);
2533 prefix->preferred_time =
2534 clib_host_to_net_u32 (info->preferred_time);
2535 prefix++;
2536 }
2537
2538 vl_api_send_msg (vl_reg, (u8 *) event);
2539 }
2540 }));
Juraj Slobodad7f58cc2018-07-27 11:23:14 +02002541 /* *INDENT-ON* */
2542 vec_free (ra_events[i].prefixes);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002543 }
2544 }
Neale Rannsb8d44812017-11-10 06:53:54 -08002545 vlib_process_put_event_data (vm, event_data);
2546 }
2547
2548 return 0;
2549}
2550
2551/* *INDENT-OFF* */
2552VLIB_REGISTER_NODE (wc_arp_process_node,static) = {
2553 .function = wc_arp_process,
2554 .type = VLIB_NODE_TYPE_PROCESS,
2555 .name = "wildcard-ip4-arp-publisher-process",
2556};
2557/* *INDENT-ON* */
2558
2559static int
2560arp_change_data_callback (u32 pool_index, u8 * new_mac,
2561 u32 sw_if_index, u32 address)
2562{
2563 vpe_api_main_t *am = &vpe_api_main;
2564 vl_api_ip4_arp_event_t *event;
2565
2566 if (pool_is_free_index (am->arp_events, pool_index))
2567 return 1;
2568
2569 event = pool_elt_at_index (am->arp_events, pool_index);
2570 if (eth_mac_equal (event->new_mac, new_mac) &&
2571 sw_if_index == ntohl (event->sw_if_index))
2572 {
2573 return 1;
2574 }
2575
2576 clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2577 event->sw_if_index = htonl (sw_if_index);
2578 return 0;
2579}
2580
2581static void
2582vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
2583{
2584 vpe_api_main_t *am = &vpe_api_main;
2585 vnet_main_t *vnm = vnet_get_main ();
2586 vl_api_want_ip4_arp_events_reply_t *rmp;
2587 int rv = 0;
2588
2589 if (mp->address == 0)
2590 {
2591 uword *p =
2592 hash_get (am->wc_ip4_arp_events_registration_hash, mp->client_index);
2593 vpe_client_registration_t *rp;
2594 if (p)
2595 {
2596 if (mp->enable_disable)
2597 {
2598 clib_warning ("pid %d: already enabled...", mp->pid);
2599 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2600 goto reply;
2601 }
2602 else
2603 {
2604 rp =
2605 pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2606 pool_put (am->wc_ip4_arp_events_registrations, rp);
2607 hash_unset (am->wc_ip4_arp_events_registration_hash,
2608 mp->client_index);
2609 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002610 wc_arp_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002611 goto reply;
2612 }
2613 }
2614 if (mp->enable_disable == 0)
2615 {
2616 clib_warning ("pid %d: already disabled...", mp->pid);
2617 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2618 goto reply;
2619 }
2620 pool_get (am->wc_ip4_arp_events_registrations, rp);
2621 rp->client_index = mp->client_index;
2622 rp->client_pid = mp->pid;
2623 hash_set (am->wc_ip4_arp_events_registration_hash, rp->client_index,
2624 rp - am->wc_ip4_arp_events_registrations);
2625 wc_arp_set_publisher_node (wc_arp_process_node.index, WC_ARP_REPORT);
2626 goto reply;
2627 }
2628
2629 if (mp->enable_disable)
2630 {
2631 vl_api_ip4_arp_event_t *event;
2632 pool_get (am->arp_events, event);
2633 rv = vnet_add_del_ip4_arp_change_event
2634 (vnm, arp_change_data_callback,
2635 mp->pid, &mp->address /* addr, in net byte order */ ,
2636 ip_resolver_process_node.index,
2637 IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
2638
2639 if (rv)
2640 {
2641 pool_put (am->arp_events, event);
2642 goto reply;
2643 }
2644 memset (event, 0, sizeof (*event));
2645
2646 /* Python API expects events to have no context */
2647 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2648 event->client_index = mp->client_index;
2649 event->address = mp->address;
2650 event->pid = mp->pid;
2651 if (mp->address == 0)
2652 event->mac_ip = 1;
2653 }
2654 else
2655 {
2656 rv = vnet_add_del_ip4_arp_change_event
2657 (vnm, arp_change_delete_callback,
2658 mp->pid, &mp->address /* addr, in net byte order */ ,
2659 ip_resolver_process_node.index,
2660 IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2661 }
2662reply:
2663 REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
2664}
2665
Neale Rannsf12dad62018-06-04 18:41:24 -07002666static clib_error_t *
2667want_ip4_arp_events_reaper (u32 client_index)
2668{
2669 vpe_client_registration_t *rp;
2670 vl_api_ip4_arp_event_t *event;
2671 u32 *to_delete, *event_id;
2672 vpe_api_main_t *am;
2673 vnet_main_t *vnm;
2674 uword *p;
2675
2676 am = &vpe_api_main;
2677 vnm = vnet_get_main ();
2678 to_delete = NULL;
2679
2680 /* clear out all of its pending resolutions */
2681 /* *INDENT-OFF* */
2682 pool_foreach(event, am->arp_events,
2683 ({
2684 if (event->client_index == client_index)
2685 {
2686 vec_add1(to_delete, event - am->arp_events);
2687 }
2688 }));
2689 /* *INDENT-ON* */
2690
2691 vec_foreach (event_id, to_delete)
2692 {
2693 event = pool_elt_at_index (am->arp_events, *event_id);
2694 vnet_add_del_ip4_arp_change_event
2695 (vnm, arp_change_delete_callback,
2696 event->pid, &event->address,
2697 ip_resolver_process_node.index, IP4_ARP_EVENT,
2698 ~0 /* pool index, notused */ , 0 /* is_add */ );
2699 }
2700 vec_free (to_delete);
2701
2702 /* remove from the registration hash */
2703 p = hash_get (am->wc_ip4_arp_events_registration_hash, client_index);
2704
2705 if (p)
2706 {
2707 rp = pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2708 pool_put (am->wc_ip4_arp_events_registrations, rp);
2709 hash_unset (am->wc_ip4_arp_events_registration_hash, client_index);
2710 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
2711 wc_arp_set_publisher_node (~0, REPORT_MAX);
2712 }
2713 return (NULL);
2714}
2715
2716VL_MSG_API_REAPER_FUNCTION (want_ip4_arp_events_reaper);
2717
Neale Rannsb8d44812017-11-10 06:53:54 -08002718static void
2719vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
2720{
2721 vpe_api_main_t *am = &vpe_api_main;
2722 vnet_main_t *vnm = vnet_get_main ();
2723 vl_api_want_ip6_nd_events_reply_t *rmp;
2724 int rv = 0;
2725
2726 if (ip6_address_is_zero ((ip6_address_t *) mp->address))
2727 {
2728 uword *p =
2729 hash_get (am->wc_ip6_nd_events_registration_hash, mp->client_index);
2730 vpe_client_registration_t *rp;
2731 if (p)
2732 {
2733 if (mp->enable_disable)
2734 {
2735 clib_warning ("pid %d: already enabled...", mp->pid);
2736 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2737 goto reply;
2738 }
2739 else
2740 {
2741 rp =
2742 pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2743 pool_put (am->wc_ip6_nd_events_registrations, rp);
2744 hash_unset (am->wc_ip6_nd_events_registration_hash,
2745 mp->client_index);
2746 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002747 wc_nd_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002748 goto reply;
2749 }
2750 }
2751 if (mp->enable_disable == 0)
2752 {
2753 clib_warning ("pid %d: already disabled...", mp->pid);
2754 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2755 goto reply;
2756 }
2757 pool_get (am->wc_ip6_nd_events_registrations, rp);
2758 rp->client_index = mp->client_index;
2759 rp->client_pid = mp->pid;
2760 hash_set (am->wc_ip6_nd_events_registration_hash, rp->client_index,
2761 rp - am->wc_ip6_nd_events_registrations);
2762 wc_nd_set_publisher_node (wc_arp_process_node.index, WC_ND_REPORT);
2763 goto reply;
2764 }
2765
2766 if (mp->enable_disable)
2767 {
2768 vl_api_ip6_nd_event_t *event;
2769 pool_get (am->nd_events, event);
2770
2771 rv = vnet_add_del_ip6_nd_change_event
2772 (vnm, nd_change_data_callback,
2773 mp->pid, mp->address /* addr, in net byte order */ ,
2774 ip_resolver_process_node.index,
2775 IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
2776
2777 if (rv)
2778 {
2779 pool_put (am->nd_events, event);
2780 goto reply;
2781 }
2782 memset (event, 0, sizeof (*event));
2783
2784 event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
2785 event->client_index = mp->client_index;
2786 clib_memcpy (event->address, mp->address, sizeof event->address);
2787 event->pid = mp->pid;
2788 }
2789 else
2790 {
2791 rv = vnet_add_del_ip6_nd_change_event
2792 (vnm, nd_change_delete_callback,
2793 mp->pid, mp->address /* addr, in net byte order */ ,
2794 ip_resolver_process_node.index,
2795 IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2796 }
2797reply:
2798 REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
2799}
2800
Neale Rannsf12dad62018-06-04 18:41:24 -07002801static clib_error_t *
2802want_ip6_nd_events_reaper (u32 client_index)
2803{
2804
2805 vpe_client_registration_t *rp;
2806 vl_api_ip6_nd_event_t *event;
2807 u32 *to_delete, *event_id;
2808 vpe_api_main_t *am;
2809 vnet_main_t *vnm;
2810 uword *p;
2811
2812 am = &vpe_api_main;
2813 vnm = vnet_get_main ();
2814 to_delete = NULL;
2815
2816 /* clear out all of its pending resolutions */
2817 /* *INDENT-OFF* */
2818 pool_foreach(event, am->nd_events,
2819 ({
2820 if (event->client_index == client_index)
2821 {
2822 vec_add1(to_delete, event - am->nd_events);
2823 }
2824 }));
2825 /* *INDENT-ON* */
2826
2827 vec_foreach (event_id, to_delete)
2828 {
2829 event = pool_elt_at_index (am->nd_events, *event_id);
2830 vnet_add_del_ip6_nd_change_event
2831 (vnm, nd_change_delete_callback,
2832 event->pid, &event->address,
2833 ip_resolver_process_node.index, IP6_ND_EVENT,
2834 ~0 /* pool index, notused */ , 0 /* is_add */ );
2835 }
2836 vec_free (to_delete);
2837
2838 /* remove from the registration hash */
2839 p = hash_get (am->wc_ip6_nd_events_registration_hash, client_index);
2840
2841 if (p)
2842 {
2843 rp = pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2844 pool_put (am->wc_ip6_nd_events_registrations, rp);
2845 hash_unset (am->wc_ip6_nd_events_registration_hash, client_index);
2846 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
2847 wc_nd_set_publisher_node (~0, REPORT_MAX);
2848 }
2849 return (NULL);
2850}
2851
2852VL_MSG_API_REAPER_FUNCTION (want_ip6_nd_events_reaper);
2853
Neale Rannsb8d44812017-11-10 06:53:54 -08002854static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002855vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
2856{
2857 vpe_api_main_t *am = &vpe_api_main;
2858 vl_api_want_ip6_ra_events_reply_t *rmp;
2859 int rv = 0;
2860
2861 uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
2862 vpe_client_registration_t *rp;
2863 if (p)
2864 {
2865 if (mp->enable_disable)
2866 {
2867 clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
2868 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2869 goto reply;
2870 }
2871 else
2872 {
2873 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2874 pool_put (am->ip6_ra_events_registrations, rp);
2875 hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002876 goto reply;
2877 }
2878 }
2879 if (mp->enable_disable == 0)
2880 {
2881 clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
2882 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2883 goto reply;
2884 }
2885 pool_get (am->ip6_ra_events_registrations, rp);
2886 rp->client_index = mp->client_index;
2887 rp->client_pid = ntohl (mp->pid);
2888 hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
2889 rp - am->ip6_ra_events_registrations);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002890
2891reply:
2892 REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
2893}
2894
Neale Rannsf12dad62018-06-04 18:41:24 -07002895static clib_error_t *
2896want_ip6_ra_events_reaper (u32 client_index)
2897{
2898 vpe_api_main_t *am = &vpe_api_main;
2899 vpe_client_registration_t *rp;
2900 uword *p;
2901
2902 p = hash_get (am->ip6_ra_events_registration_hash, client_index);
2903
2904 if (p)
2905 {
2906 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2907 pool_put (am->ip6_ra_events_registrations, rp);
2908 hash_unset (am->ip6_ra_events_registration_hash, client_index);
2909 }
2910 return (NULL);
2911}
2912
2913VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
2914
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002915static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002916vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
2917{
2918 vl_api_proxy_arp_add_del_reply_t *rmp;
2919 u32 fib_index;
2920 int rv;
2921 ip4_main_t *im = &ip4_main;
Neale Rannsb8d44812017-11-10 06:53:54 -08002922 uword *p;
2923
Ole Troan3288ed72017-12-06 17:00:05 +01002924 stats_dslock_with_hint (1 /* release hint */ , 6 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08002925
Neale Ranns0053de62018-05-22 08:40:52 -07002926 p = hash_get (im->fib_index_by_table_id, ntohl (mp->proxy.vrf_id));
Neale Rannsb8d44812017-11-10 06:53:54 -08002927
2928 if (!p)
2929 {
2930 rv = VNET_API_ERROR_NO_SUCH_FIB;
2931 goto out;
2932 }
2933
2934 fib_index = p[0];
2935
Neale Ranns0053de62018-05-22 08:40:52 -07002936 rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->proxy.low_address,
2937 (ip4_address_t *) mp->proxy.hi_address,
Neale Rannsb8d44812017-11-10 06:53:54 -08002938 fib_index, mp->is_add == 0);
2939
2940out:
Ole Troan3288ed72017-12-06 17:00:05 +01002941 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08002942 REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
2943}
2944
Neale Ranns0053de62018-05-22 08:40:52 -07002945typedef struct proxy_arp_walk_ctx_t_
2946{
2947 vl_api_registration_t *reg;
2948 u32 context;
2949} proxy_arp_walk_ctx_t;
2950
2951static walk_rc_t
2952send_proxy_arp_details (const ip4_address_t * lo_addr,
2953 const ip4_address_t * hi_addr,
2954 u32 fib_index, void *data)
2955{
2956 vl_api_proxy_arp_details_t *mp;
2957 proxy_arp_walk_ctx_t *ctx;
2958
2959 ctx = data;
2960
2961 mp = vl_msg_api_alloc (sizeof (*mp));
2962 memset (mp, 0, sizeof (*mp));
2963 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_DETAILS);
2964 mp->context = ctx->context;
2965 mp->proxy.vrf_id = htonl (fib_index);
2966 clib_memcpy (mp->proxy.low_address, lo_addr,
2967 sizeof (mp->proxy.low_address));
2968 clib_memcpy (mp->proxy.hi_address, hi_addr, sizeof (mp->proxy.hi_address));
2969
2970 vl_api_send_msg (ctx->reg, (u8 *) mp);
2971
2972 return (WALK_CONTINUE);
2973}
2974
2975static void
2976vl_api_proxy_arp_dump_t_handler (vl_api_proxy_arp_dump_t * mp)
2977{
2978 vl_api_registration_t *reg;
2979
2980 reg = vl_api_client_index_to_registration (mp->client_index);
2981 if (!reg)
2982 return;
2983
2984 proxy_arp_walk_ctx_t wctx = {
2985 .reg = reg,
2986 .context = mp->context,
2987 };
2988
2989 proxy_arp_walk (send_proxy_arp_details, &wctx);
2990}
2991
2992static walk_rc_t
2993send_proxy_arp_intfc_details (vnet_main_t * vnm,
2994 vnet_sw_interface_t * si, void *data)
2995{
2996 vl_api_proxy_arp_intfc_details_t *mp;
2997 proxy_arp_walk_ctx_t *ctx;
2998
2999 if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
3000 return (WALK_CONTINUE);
3001
3002 ctx = data;
3003
3004 mp = vl_msg_api_alloc (sizeof (*mp));
3005 memset (mp, 0, sizeof (*mp));
3006 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_INTFC_DETAILS);
3007 mp->context = ctx->context;
3008 mp->sw_if_index = htonl (si->sw_if_index);
3009
3010 vl_api_send_msg (ctx->reg, (u8 *) mp);
3011
3012 return (WALK_CONTINUE);
3013}
3014
3015static void
3016vl_api_proxy_arp_intfc_dump_t_handler (vl_api_proxy_arp_intfc_dump_t * mp)
3017{
3018 vl_api_registration_t *reg;
3019
3020 reg = vl_api_client_index_to_registration (mp->client_index);
3021 if (!reg)
3022 return;
3023
3024 proxy_arp_walk_ctx_t wctx = {
3025 .reg = reg,
3026 .context = mp->context,
3027 };
3028
3029 vnet_sw_interface_walk (vnet_get_main (),
3030 send_proxy_arp_intfc_details, &wctx);
3031}
3032
Neale Rannsb8d44812017-11-10 06:53:54 -08003033static void
3034 vl_api_proxy_arp_intfc_enable_disable_t_handler
3035 (vl_api_proxy_arp_intfc_enable_disable_t * mp)
3036{
3037 int rv = 0;
3038 vnet_main_t *vnm = vnet_get_main ();
3039 vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
3040
3041 VALIDATE_SW_IF_INDEX (mp);
3042
3043 vnet_sw_interface_t *si =
3044 vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
3045
3046 ASSERT (si);
3047
3048 if (mp->enable_disable)
3049 si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
3050 else
3051 si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
3052
3053 BAD_SW_IF_INDEX_LABEL;
3054
3055 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
3056}
3057
John Loc7b43042018-04-13 16:46:22 -04003058static void
3059vl_api_ip_probe_neighbor_t_handler (vl_api_ip_probe_neighbor_t * mp)
3060{
3061 int rv = 0;
3062 vlib_main_t *vm = vlib_get_main ();
3063 vl_api_ip_probe_neighbor_reply_t *rmp;
3064 clib_error_t *error;
3065
3066 VALIDATE_SW_IF_INDEX (mp);
3067
3068 u32 sw_if_index = ntohl (mp->sw_if_index);
3069
3070 if (mp->is_ipv6)
3071 error = ip6_probe_neighbor (vm, (ip6_address_t *) mp->dst_address,
John Lo86376342018-06-11 20:14:49 -04003072 sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04003073 else
3074 error = ip4_probe_neighbor (vm, (ip4_address_t *) mp->dst_address,
John Lo86376342018-06-11 20:14:49 -04003075 sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04003076
3077 if (error)
3078 {
3079 clib_error_report (error);
3080 rv = clib_error_get_code (error);
3081 }
3082
3083 BAD_SW_IF_INDEX_LABEL;
3084
3085 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
3086}
3087
John Lo7f358b32018-04-28 01:19:24 -04003088static void
3089 vl_api_ip_scan_neighbor_enable_disable_t_handler
3090 (vl_api_ip_scan_neighbor_enable_disable_t * mp)
3091{
3092 int rv = 0;
3093 vl_api_ip_scan_neighbor_enable_disable_reply_t *rmp;
3094 ip_neighbor_scan_arg_t arg;
3095
3096 arg.mode = mp->mode;
3097 arg.scan_interval = mp->scan_interval;
3098 arg.max_proc_time = mp->max_proc_time;
3099 arg.max_update = mp->max_update;
3100 arg.scan_int_delay = mp->scan_int_delay;
3101 arg.stale_threshold = mp->stale_threshold;
3102 ip_neighbor_scan_enable_disable (&arg);
3103
3104 REPLY_MACRO (VL_API_IP_SCAN_NEIGHBOR_ENABLE_DISABLE_REPLY);
3105}
3106
Neale Rannsb8d44812017-11-10 06:53:54 -08003107static int
3108ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3109{
3110 vnet_main_t *vnm = vnet_get_main ();
3111 vnet_interface_main_t *im = &vnm->interface_main;
3112 ip4_main_t *im4 = &ip4_main;
3113 static u32 *sw_if_indices_to_shut;
Neale Rannsb8d44812017-11-10 06:53:54 -08003114 fib_table_t *fib_table;
3115 ip4_fib_t *fib;
3116 u32 sw_if_index;
3117 int i;
3118 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3119 u32 target_fib_id = ntohl (mp->vrf_id);
3120
Ole Troan3288ed72017-12-06 17:00:05 +01003121 stats_dslock_with_hint (1 /* release hint */ , 8 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08003122
3123 /* *INDENT-OFF* */
3124 pool_foreach (fib_table, im4->fibs,
3125 ({
3126 vnet_sw_interface_t * si;
3127
3128 fib = pool_elt_at_index (im4->v4_fibs, fib_table->ft_index);
3129
3130 if (fib->table_id != target_fib_id)
3131 continue;
3132
3133 /* remove any mpls encap/decap labels */
3134 mpls_fib_reset_labels (fib->table_id);
3135
3136 /* remove any proxy arps in this fib */
3137 vnet_proxy_arp_fib_reset (fib->table_id);
3138
3139 /* Set the flow hash for this fib to the default */
3140 vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3141
3142 vec_reset_length (sw_if_indices_to_shut);
3143
3144 /* Shut down interfaces in this FIB / clean out intfc routes */
3145 pool_foreach (si, im->sw_interfaces,
3146 ({
3147 u32 sw_if_index = si->sw_if_index;
3148
3149 if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
3150 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
3151 fib->index))
3152 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3153 }));
3154
3155 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3156 sw_if_index = sw_if_indices_to_shut[i];
3157
3158 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3159 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3160 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3161 }
3162
3163 fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
3164
3165 rv = 0;
3166 break;
3167 })); /* pool_foreach (fib) */
3168 /* *INDENT-ON* */
3169
Ole Troan3288ed72017-12-06 17:00:05 +01003170 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08003171 return rv;
3172}
3173
3174static int
3175ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3176{
3177 vnet_main_t *vnm = vnet_get_main ();
3178 vnet_interface_main_t *im = &vnm->interface_main;
3179 ip6_main_t *im6 = &ip6_main;
Neale Rannsb8d44812017-11-10 06:53:54 -08003180 static u32 *sw_if_indices_to_shut;
3181 fib_table_t *fib_table;
3182 ip6_fib_t *fib;
3183 u32 sw_if_index;
3184 int i;
3185 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3186 u32 target_fib_id = ntohl (mp->vrf_id);
3187
Ole Troan3288ed72017-12-06 17:00:05 +01003188 stats_dslock_with_hint (1 /* release hint */ , 9 /* tag */ );
Neale Rannsb8d44812017-11-10 06:53:54 -08003189
3190 /* *INDENT-OFF* */
3191 pool_foreach (fib_table, im6->fibs,
3192 ({
3193 vnet_sw_interface_t * si;
3194
3195 fib = pool_elt_at_index (im6->v6_fibs, fib_table->ft_index);
3196
3197 if (fib->table_id != target_fib_id)
3198 continue;
3199
3200 vec_reset_length (sw_if_indices_to_shut);
3201
3202 /* Set the flow hash for this fib to the default */
3203 vnet_set_ip6_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3204
3205 /* Shut down interfaces in this FIB / clean out intfc routes */
3206 pool_foreach (si, im->sw_interfaces,
3207 ({
3208 if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
3209 fib->index)
3210 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3211 }));
3212
3213 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3214 sw_if_index = sw_if_indices_to_shut[i];
3215
3216 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3217 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3218 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3219 }
3220
3221 fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
3222
3223 rv = 0;
3224 break;
3225 })); /* pool_foreach (fib) */
3226 /* *INDENT-ON* */
3227
Ole Troan3288ed72017-12-06 17:00:05 +01003228 stats_dsunlock ();
Neale Rannsb8d44812017-11-10 06:53:54 -08003229 return rv;
3230}
3231
3232static void
3233vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3234{
3235 int rv;
3236 vl_api_reset_fib_reply_t *rmp;
3237
3238 if (mp->is_ipv6)
3239 rv = ip6_reset_fib_t_handler (mp);
3240 else
3241 rv = ip4_reset_fib_t_handler (mp);
3242
3243 REPLY_MACRO (VL_API_RESET_FIB_REPLY);
3244}
3245
3246static void
3247vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
3248{
3249 int rv;
3250 vl_api_set_arp_neighbor_limit_reply_t *rmp;
3251 vnet_main_t *vnm = vnet_get_main ();
3252 clib_error_t *error;
3253
3254 vnm->api_errno = 0;
3255
3256 if (mp->is_ipv6)
3257 error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
3258 else
3259 error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
3260
3261 if (error)
3262 {
3263 clib_error_report (error);
3264 rv = VNET_API_ERROR_UNSPECIFIED;
3265 }
3266 else
3267 {
3268 rv = vnm->api_errno;
3269 }
3270
3271 REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3272}
3273
Klement Sekera75e7d132017-09-20 08:26:30 +02003274void
3275vl_api_ip_reassembly_set_t_handler (vl_api_ip_reassembly_set_t * mp)
3276{
3277 vl_api_ip_reassembly_set_reply_t *rmp;
3278 int rv = 0;
3279 if (mp->is_ip6)
3280 {
3281 rv = ip6_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3282 clib_net_to_host_u32 (mp->max_reassemblies),
3283 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3284 }
3285 else
3286 {
3287 rv = ip4_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3288 clib_net_to_host_u32 (mp->max_reassemblies),
3289 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3290 }
3291
3292 REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
3293}
3294
3295void
3296vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
3297{
3298 unix_shared_memory_queue_t *q;
3299
3300 q = vl_api_client_index_to_input_queue (mp->client_index);
3301
3302 if (q == 0)
3303 return;
3304
3305 vl_api_ip_reassembly_get_reply_t *rmp = vl_msg_api_alloc (sizeof (*rmp));
3306 memset (rmp, 0, sizeof (*rmp));
3307 rmp->_vl_msg_id = ntohs (VL_API_IP_REASSEMBLY_GET_REPLY);
3308 rmp->context = mp->context;
3309 rmp->retval = 0;
3310 if (mp->is_ip6)
3311 {
3312 rmp->is_ip6 = 1;
3313 ip6_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
3314 &rmp->expire_walk_interval_ms);
3315 }
3316 else
3317 {
3318 rmp->is_ip6 = 0;
3319 ip4_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
3320 &rmp->expire_walk_interval_ms);
3321 }
3322 rmp->timeout_ms = clib_host_to_net_u32 (rmp->timeout_ms);
3323 rmp->max_reassemblies = clib_host_to_net_u32 (rmp->max_reassemblies);
3324 rmp->expire_walk_interval_ms =
3325 clib_host_to_net_u32 (rmp->expire_walk_interval_ms);
3326 vl_msg_api_send_shmem (q, (u8 *) & rmp);
3327}
3328
Klement Sekera4c533132018-02-22 11:41:12 +01003329void
3330 vl_api_ip_reassembly_enable_disable_t_handler
3331 (vl_api_ip_reassembly_enable_disable_t * mp)
3332{
3333 vl_api_ip_reassembly_enable_disable_reply_t *rmp;
3334 int rv = 0;
3335 rv = ip4_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3336 mp->enable_ip4);
3337 if (0 == rv)
3338 {
3339 rv = ip6_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3340 mp->enable_ip6);
3341 }
3342
3343 REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
3344}
3345
Dave Barachb5e8a772016-12-06 12:04:42 -05003346#define vl_msg_name_crc_list
3347#include <vnet/ip/ip.api.h>
3348#undef vl_msg_name_crc_list
3349
3350static void
3351setup_message_id_table (api_main_t * am)
3352{
3353#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
3354 foreach_vl_msg_name_crc_ip;
3355#undef _
3356}
3357
3358static clib_error_t *
3359ip_api_hookup (vlib_main_t * vm)
3360{
3361 api_main_t *am = &api_main;
3362
3363#define _(N,n) \
3364 vl_msg_api_set_handlers(VL_API_##N, #n, \
3365 vl_api_##n##_t_handler, \
3366 vl_noop_handler, \
3367 vl_api_##n##_t_endian, \
3368 vl_api_##n##_t_print, \
3369 sizeof(vl_api_##n##_t), 1);
3370 foreach_ip_api_msg;
3371#undef _
3372
3373 /*
3374 * Set up the (msg_name, crc, message-id) table
3375 */
3376 setup_message_id_table (am);
3377
Juraj Sloboda52574522018-05-03 10:03:50 +02003378 ra_set_publisher_node (wc_arp_process_node.index, RA_REPORT);
3379
Dave Barachb5e8a772016-12-06 12:04:42 -05003380 return 0;
3381}
3382
3383VLIB_API_INIT_FUNCTION (ip_api_hookup);
3384
3385/*
3386 * fd.io coding-style-patch-verification: ON
3387 *
3388 * Local Variables:
3389 * eval: (c-set-style "gnu")
3390 * End:
3391 */