blob: 06caf111b91101e993f8187fbbe488af3d4871e4 [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>
Neale Ranns37029302018-08-10 05:30:06 -070026#include <vnet/ethernet/ethernet_types_api.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050027#include <vnet/ip/ip.h>
John Lo7f358b32018-04-28 01:19:24 -040028#include <vnet/ip/ip_neighbor.h>
Neale Ranns37029302018-08-10 05:30:06 -070029#include <vnet/ip/ip_types_api.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050030#include <vnet/ip/ip6_neighbor.h>
Pavel Kotucek609e1212018-11-27 09:59:44 +010031#include <vnet/ip/ip_punt_drop.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050032#include <vnet/fib/fib_table.h>
33#include <vnet/fib/fib_api.h>
34#include <vnet/dpo/drop_dpo.h>
35#include <vnet/dpo/receive_dpo.h>
36#include <vnet/dpo/lookup_dpo.h>
37#include <vnet/dpo/classify_dpo.h>
38#include <vnet/dpo/ip_null_dpo.h>
39#include <vnet/ethernet/arp_packet.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080040#include <vnet/mfib/ip6_mfib.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000041#include <vnet/mfib/ip4_mfib.h>
42#include <vnet/mfib/mfib_signal.h>
Neale Ranns5a8123b2017-01-26 01:18:23 -080043#include <vnet/mfib/mfib_entry.h>
Neale Rannsb8d44812017-11-10 06:53:54 -080044#include <vnet/ip/ip_source_and_port_range_check.h>
45#include <vnet/fib/ip4_fib.h>
46#include <vnet/fib/ip6_fib.h>
47#include <vnet/ip/ip6_hop_by_hop.h>
Klement Sekera75e7d132017-09-20 08:26:30 +020048#include <vnet/ip/ip4_reassembly.h>
49#include <vnet/ip/ip6_reassembly.h>
Neale Ranns0053de62018-05-22 08:40:52 -070050#include <vnet/ethernet/arp.h>
Matus Fabian75b9f452018-10-02 23:27:21 -070051#include <vnet/ip/ip_types_api.h>
Dave Barachb5e8a772016-12-06 12:04:42 -050052
53#include <vnet/vnet_msg_enum.h>
54
55#define vl_typedefs /* define message structures */
56#include <vnet/vnet_all_api_h.h>
57#undef vl_typedefs
58
59#define vl_endianfun /* define message structures */
60#include <vnet/vnet_all_api_h.h>
61#undef vl_endianfun
62
63/* instantiate all the print functions we know about */
64#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
65#define vl_printfun
66#include <vnet/vnet_all_api_h.h>
67#undef vl_printfun
68
69#include <vlibapi/api_helper_macros.h>
70
Neale Ranns5a8123b2017-01-26 01:18:23 -080071
Dave Barachb5e8a772016-12-06 12:04:42 -050072#define foreach_ip_api_msg \
73_(IP_FIB_DUMP, ip_fib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050074_(IP6_FIB_DUMP, ip6_fib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080075_(IP_MFIB_DUMP, ip_mfib_dump) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080076_(IP6_MFIB_DUMP, ip6_mfib_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050077_(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \
Neale Ranns32e1c012016-11-22 17:07:28 +000078_(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \
Neale Ranns5a8123b2017-01-26 01:18:23 -080079_(MFIB_SIGNAL_DUMP, mfib_signal_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050080_(IP_ADDRESS_DUMP, ip_address_dump) \
Neale Ranns9e2f9152018-05-18 02:27:10 -070081_(IP_UNNUMBERED_DUMP, ip_unnumbered_dump) \
Dave Barachb5e8a772016-12-06 12:04:42 -050082_(IP_DUMP, ip_dump) \
83_(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
Neale Rannsb8d44812017-11-10 06:53:54 -080084_(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \
John Loc7b43042018-04-13 16:46:22 -040085_(IP_PROBE_NEIGHBOR, ip_probe_neighbor) \
John Lo7f358b32018-04-28 01:19:24 -040086_(IP_SCAN_NEIGHBOR_ENABLE_DISABLE, ip_scan_neighbor_enable_disable) \
Neale Rannsb8d44812017-11-10 06:53:54 -080087_(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \
88_(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \
Juraj Sloboda4b9669d2018-01-15 10:39:21 +010089_(WANT_IP6_RA_EVENTS, want_ip6_ra_events) \
Neale Rannsb8d44812017-11-10 06:53:54 -080090_(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \
Neale Ranns0053de62018-05-22 08:40:52 -070091_(PROXY_ARP_DUMP, proxy_arp_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -080092_(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \
Neale Ranns0053de62018-05-22 08:40:52 -070093 _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -080094_(RESET_FIB, reset_fib) \
Dave Barachb5e8a772016-12-06 12:04:42 -050095_(IP_ADD_DEL_ROUTE, ip_add_del_route) \
Neale Ranns28ab9cc2017-08-14 07:18:42 -070096_(IP_TABLE_ADD_DEL, ip_table_add_del) \
Neale Rannsd91c1db2017-07-31 02:30:50 -070097_(IP_PUNT_POLICE, ip_punt_police) \
98_(IP_PUNT_REDIRECT, ip_punt_redirect) \
Dave Barachb5e8a772016-12-06 12:04:42 -050099_(SET_IP_FLOW_HASH,set_ip_flow_hash) \
100_(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
101_(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
Neale Ranns3f844d02017-02-18 00:03:54 -0800102_(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del) \
103_(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \
Juraj Sloboda4b9669d2018-01-15 10:39:21 +0100104_(IP6ND_SEND_ROUTER_SOLICITATION, ip6nd_send_router_solicitation) \
Dave Barachb5e8a772016-12-06 12:04:42 -0500105_(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
Neale Rannsb8d44812017-11-10 06:53:54 -0800106_(IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del) \
Matus Fabian75b9f452018-10-02 23:27:21 -0700107_(IP_CONTAINER_PROXY_DUMP, ip_container_proxy_dump) \
Neale Rannsb8d44812017-11-10 06:53:54 -0800108_(IOAM_ENABLE, ioam_enable) \
109_(IOAM_DISABLE, ioam_disable) \
110_(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \
111 ip_source_and_port_range_check_add_del) \
112_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
Klement Sekera75e7d132017-09-20 08:26:30 +0200113 ip_source_and_port_range_check_interface_add_del) \
Chore3460b012018-11-28 10:53:11 +0330114_(IP_SOURCE_CHECK_INTERFACE_ADD_DEL, \
115 ip_source_check_interface_add_del) \
Klement Sekera75e7d132017-09-20 08:26:30 +0200116_(IP_REASSEMBLY_SET, ip_reassembly_set) \
Klement Sekera4c533132018-02-22 11:41:12 +0100117_(IP_REASSEMBLY_GET, ip_reassembly_get) \
Pavel Kotucek609e1212018-11-27 09:59:44 +0100118_(IP_REASSEMBLY_ENABLE_DISABLE, ip_reassembly_enable_disable) \
119_(IP_PUNT_REDIRECT_DUMP, ip_punt_redirect_dump)
120
Dave Barachb5e8a772016-12-06 12:04:42 -0500121
Neale Ranns37029302018-08-10 05:30:06 -0700122static vl_api_ip_neighbor_flags_t
123ip_neighbor_flags_encode (ip_neighbor_flags_t f)
124{
125 vl_api_ip_neighbor_flags_t v = IP_API_NEIGHBOR_FLAG_NONE;
126
127 if (f & IP_NEIGHBOR_FLAG_STATIC)
128 v |= IP_API_NEIGHBOR_FLAG_STATIC;
129 if (f & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY)
130 v |= IP_API_NEIGHBOR_FLAG_NO_FIB_ENTRY;
131
132 return (clib_host_to_net_u32 (v));
133}
134
Dave Barachb5e8a772016-12-06 12:04:42 -0500135static void
Jon Loeligeraf8dfbf2017-11-08 13:07:39 -0600136send_ip_neighbor_details (u32 sw_if_index,
Neale Ranns37029302018-08-10 05:30:06 -0700137 const ip46_address_t * ip_address,
138 const mac_address_t * mac,
139 ip_neighbor_flags_t flags,
140 vl_api_registration_t * reg, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500141{
142 vl_api_ip_neighbor_details_t *mp;
143
144 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400145 clib_memset (mp, 0, sizeof (*mp));
Dave Barachb5e8a772016-12-06 12:04:42 -0500146 mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS);
147 mp->context = context;
Neale Ranns37029302018-08-10 05:30:06 -0700148 mp->neighbor.sw_if_index = htonl (sw_if_index);
149 mp->neighbor.flags = ip_neighbor_flags_encode (flags);
150
151 ip_address_encode (ip_address, IP46_TYPE_ANY, &mp->neighbor.ip_address);
152 mac_address_encode (mac, mp->neighbor.mac_address);
Dave Barachb5e8a772016-12-06 12:04:42 -0500153
Florin Coras6c4dae22018-01-09 06:39:23 -0800154 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500155}
156
157static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500158vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
159{
Florin Coras6c4dae22018-01-09 06:39:23 -0800160 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500161
Florin Coras6c4dae22018-01-09 06:39:23 -0800162 reg = vl_api_client_index_to_registration (mp->client_index);
163 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500164 return;
165
166 u32 sw_if_index = ntohl (mp->sw_if_index);
167
168 if (mp->is_ipv6)
169 {
170 ip6_neighbor_t *n, *ns;
171
172 ns = ip6_neighbors_entries (sw_if_index);
173 /* *INDENT-OFF* */
174 vec_foreach (n, ns)
175 {
Neale Ranns37029302018-08-10 05:30:06 -0700176 ip46_address_t nh = {
177 .ip6 = {
178 .as_u64[0] = n->key.ip6_address.as_u64[0],
179 .as_u64[1] = n->key.ip6_address.as_u64[1],
180 },
181 };
182 send_ip_neighbor_details (n->key.sw_if_index, &nh,
183 &n->mac, n->flags,
184 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500185 }
186 /* *INDENT-ON* */
187 vec_free (ns);
188 }
189 else
190 {
191 ethernet_arp_ip4_entry_t *n, *ns;
192
193 ns = ip4_neighbor_entries (sw_if_index);
194 /* *INDENT-OFF* */
195 vec_foreach (n, ns)
196 {
Neale Ranns37029302018-08-10 05:30:06 -0700197 ip46_address_t nh = {
198 .ip4 = {
199 .as_u32 = n->ip4_address.as_u32,
200 },
201 };
202
203 send_ip_neighbor_details (n->sw_if_index, &nh,
204 &n->mac, n->flags,
205 reg, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -0500206 }
207 /* *INDENT-ON* */
208 vec_free (ns);
209 }
210}
211
Dave Barachb5e8a772016-12-06 12:04:42 -0500212static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500213send_ip_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800214 vl_api_registration_t * reg,
Neale Ranns2297af02017-09-12 09:45:04 -0700215 const fib_table_t * table,
216 const fib_prefix_t * pfx,
Dave Barachb5e8a772016-12-06 12:04:42 -0500217 fib_route_path_encode_t * api_rpaths, u32 context)
218{
219 vl_api_ip_fib_details_t *mp;
220 fib_route_path_encode_t *api_rpath;
221 vl_api_fib_path_t *fp;
222 int path_count;
223
224 path_count = vec_len (api_rpaths);
225 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
226 if (!mp)
227 return;
Dave Barachb7b92992018-10-17 10:38:51 -0400228 clib_memset (mp, 0, sizeof (*mp));
Dave Barachb5e8a772016-12-06 12:04:42 -0500229 mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
230 mp->context = context;
231
Neale Ranns2297af02017-09-12 09:45:04 -0700232 mp->table_id = htonl (table->ft_table_id);
233 memcpy (mp->table_name, table->ft_desc,
234 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Dave Barachb5e8a772016-12-06 12:04:42 -0500235 mp->address_length = pfx->fp_len;
236 memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
Neale Ranns008dbe12018-09-07 09:32:36 -0700237 mp->stats_index =
238 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500239
240 mp->count = htonl (path_count);
241 fp = mp->path;
242 vec_foreach (api_rpath, api_rpaths)
243 {
Neale Ranns81458422018-03-12 06:59:36 -0700244 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500245 fp++;
246 }
247
Florin Coras6c4dae22018-01-09 06:39:23 -0800248 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500249}
250
Neale Rannsa3af3372017-03-28 03:49:52 -0700251typedef struct vl_api_ip_fib_dump_walk_ctx_t_
252{
253 fib_node_index_t *feis;
254} vl_api_ip_fib_dump_walk_ctx_t;
255
Neale Ranns89541992017-04-06 04:41:02 -0700256static fib_table_walk_rc_t
Neale Rannsa3af3372017-03-28 03:49:52 -0700257vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
258{
259 vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
260
261 vec_add1 (ctx->feis, fei);
262
Neale Ranns89541992017-04-06 04:41:02 -0700263 return (FIB_TABLE_WALK_CONTINUE);
Neale Rannsa3af3372017-03-28 03:49:52 -0700264}
265
Dave Barachb5e8a772016-12-06 12:04:42 -0500266static void
267vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
268{
269 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800270 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500271 ip4_main_t *im = &ip4_main;
272 fib_table_t *fib_table;
Neale Rannsa3af3372017-03-28 03:49:52 -0700273 fib_node_index_t *lfeip;
Neale Rannsc5d43172018-07-30 08:04:40 -0700274 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500275 u32 fib_index;
276 fib_route_path_encode_t *api_rpaths;
Neale Rannsa3af3372017-03-28 03:49:52 -0700277 vl_api_ip_fib_dump_walk_ctx_t ctx = {
278 .feis = NULL,
279 };
Dave Barachb5e8a772016-12-06 12:04:42 -0500280
Florin Coras6c4dae22018-01-09 06:39:23 -0800281 reg = vl_api_client_index_to_registration (mp->client_index);
282 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500283 return;
284
285 /* *INDENT-OFF* */
286 pool_foreach (fib_table, im->fibs,
287 ({
Neale Rannsa3af3372017-03-28 03:49:52 -0700288 fib_table_walk(fib_table->ft_index,
289 FIB_PROTOCOL_IP4,
290 vl_api_ip_fib_dump_walk,
291 &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500292 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500293 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500294
Neale Rannsa3af3372017-03-28 03:49:52 -0700295 vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500296
Neale Rannsa3af3372017-03-28 03:49:52 -0700297 vec_foreach (lfeip, ctx.feis)
Dave Barachb5e8a772016-12-06 12:04:42 -0500298 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700299 pfx = fib_entry_get_prefix (*lfeip);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500300 fib_index = fib_entry_get_fib_index (*lfeip);
Neale Rannsc5d43172018-07-30 08:04:40 -0700301 fib_table = fib_table_get (fib_index, pfx->fp_proto);
Dave Barachb5e8a772016-12-06 12:04:42 -0500302 api_rpaths = NULL;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500303 fib_entry_encode (*lfeip, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700304 send_ip_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500305 vec_free (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500306 }
307
Neale Rannsa3af3372017-03-28 03:49:52 -0700308 vec_free (ctx.feis);
Dave Barachb5e8a772016-12-06 12:04:42 -0500309}
310
311static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500312send_ip6_fib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800313 vl_api_registration_t * reg,
Neale Rannsa161a6d2017-11-14 08:10:41 -0800314 const fib_table_t * table,
315 const fib_prefix_t * pfx,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500316 fib_route_path_encode_t * api_rpaths, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -0500317{
318 vl_api_ip6_fib_details_t *mp;
319 fib_route_path_encode_t *api_rpath;
320 vl_api_fib_path_t *fp;
321 int path_count;
322
Dave Barachd7cb1b52016-12-09 09:52:16 -0500323 path_count = vec_len (api_rpaths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500324 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
325 if (!mp)
326 return;
Dave Barachb7b92992018-10-17 10:38:51 -0400327 clib_memset (mp, 0, sizeof (*mp));
Dave Barachb5e8a772016-12-06 12:04:42 -0500328 mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
329 mp->context = context;
330
Neale Rannsa161a6d2017-11-14 08:10:41 -0800331 mp->table_id = htonl (table->ft_table_id);
Dave Barachb5e8a772016-12-06 12:04:42 -0500332 mp->address_length = pfx->fp_len;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500333 memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
Neale Rannsa161a6d2017-11-14 08:10:41 -0800334 memcpy (mp->table_name, table->ft_desc,
335 clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
Neale Ranns008dbe12018-09-07 09:32:36 -0700336 mp->stats_index =
337 htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
Dave Barachb5e8a772016-12-06 12:04:42 -0500338
339 mp->count = htonl (path_count);
340 fp = mp->path;
Dave Barachd7cb1b52016-12-09 09:52:16 -0500341 vec_foreach (api_rpath, api_rpaths)
Dave Barachb5e8a772016-12-06 12:04:42 -0500342 {
Neale Ranns81458422018-03-12 06:59:36 -0700343 fib_api_path_encode (api_rpath, fp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500344 fp++;
345 }
346
Florin Coras6c4dae22018-01-09 06:39:23 -0800347 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -0500348}
349
Dave Barachd7cb1b52016-12-09 09:52:16 -0500350typedef struct apt_ip6_fib_show_ctx_t_
351{
Dave Barachd7cb1b52016-12-09 09:52:16 -0500352 fib_node_index_t *entries;
Dave Barachb5e8a772016-12-06 12:04:42 -0500353} api_ip6_fib_show_ctx_t;
354
Neale Ranns5c1f5592019-01-25 00:51:09 -0800355static fib_table_walk_rc_t
356api_ip6_fib_table_put_entries (fib_node_index_t fei, void *arg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500357{
358 api_ip6_fib_show_ctx_t *ctx = arg;
359
Neale Ranns5c1f5592019-01-25 00:51:09 -0800360 vec_add1 (ctx->entries, fei);
361
362 return (FIB_TABLE_WALK_CONTINUE);
Dave Barachb5e8a772016-12-06 12:04:42 -0500363}
364
365static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800366api_ip6_fib_table_get_all (vl_api_registration_t * reg,
Dave Barachd7cb1b52016-12-09 09:52:16 -0500367 vl_api_ip6_fib_dump_t * mp,
368 fib_table_t * fib_table)
Dave Barachb5e8a772016-12-06 12:04:42 -0500369{
370 vpe_api_main_t *am = &vpe_api_main;
Dave Barachb5e8a772016-12-06 12:04:42 -0500371 fib_node_index_t *fib_entry_index;
372 api_ip6_fib_show_ctx_t ctx = {
Neale Rannsa3af3372017-03-28 03:49:52 -0700373 .entries = NULL,
Dave Barachb5e8a772016-12-06 12:04:42 -0500374 };
375 fib_route_path_encode_t *api_rpaths;
Neale Rannsc5d43172018-07-30 08:04:40 -0700376 const fib_prefix_t *pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -0500377
Neale Ranns5c1f5592019-01-25 00:51:09 -0800378 ip6_fib_table_walk (fib_table->ft_index,
379 api_ip6_fib_table_put_entries, &ctx);
Dave Barachb5e8a772016-12-06 12:04:42 -0500380
Dave Barachd7cb1b52016-12-09 09:52:16 -0500381 vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort);
Dave Barachb5e8a772016-12-06 12:04:42 -0500382
Dave Barachd7cb1b52016-12-09 09:52:16 -0500383 vec_foreach (fib_entry_index, ctx.entries)
384 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700385 pfx = fib_entry_get_prefix (*fib_entry_index);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500386 api_rpaths = NULL;
387 fib_entry_encode (*fib_entry_index, &api_rpaths);
Neale Rannsc5d43172018-07-30 08:04:40 -0700388 send_ip6_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context);
Dave Barachd7cb1b52016-12-09 09:52:16 -0500389 vec_free (api_rpaths);
390 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500391
Dave Barachd7cb1b52016-12-09 09:52:16 -0500392 vec_free (ctx.entries);
Dave Barachb5e8a772016-12-06 12:04:42 -0500393}
394
395static void
396vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
397{
Florin Coras6c4dae22018-01-09 06:39:23 -0800398 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -0500399 ip6_main_t *im6 = &ip6_main;
400 fib_table_t *fib_table;
401
Florin Coras6c4dae22018-01-09 06:39:23 -0800402 reg = vl_api_client_index_to_registration (mp->client_index);
403 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -0500404 return;
405
406 /* *INDENT-OFF* */
407 pool_foreach (fib_table, im6->fibs,
408 ({
Neale Ranns81458422018-03-12 06:59:36 -0700409 /* don't send link locals */
410 if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL)
411 continue;
412
Florin Coras6c4dae22018-01-09 06:39:23 -0800413 api_ip6_fib_table_get_all(reg, mp, fib_table);
Dave Barachb5e8a772016-12-06 12:04:42 -0500414 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -0500415 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500416}
417
418static void
Florin Coras6c4dae22018-01-09 06:39:23 -0800419send_ip_mfib_details (vl_api_registration_t * reg,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800420 u32 context, u32 table_id, fib_node_index_t mfei)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800421{
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800422 fib_route_path_encode_t *api_rpath, *api_rpaths = NULL;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800423 vl_api_ip_mfib_details_t *mp;
Neale Ranns9e829a82018-12-17 05:50:32 -0800424 const mfib_prefix_t *pfx;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800425 mfib_entry_t *mfib_entry;
Neale Ranns7c03ed42018-12-27 03:21:28 -0800426 vl_api_mfib_path_t *fp;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800427 int path_count;
428
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800429 mfib_entry = mfib_entry_get (mfei);
Neale Ranns9e829a82018-12-17 05:50:32 -0800430 pfx = mfib_entry_get_prefix (mfei);
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800431 mfib_entry_encode (mfei, &api_rpaths);
432
Neale Ranns5a8123b2017-01-26 01:18:23 -0800433 path_count = vec_len (api_rpaths);
434 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
435 if (!mp)
436 return;
Dave Barachb7b92992018-10-17 10:38:51 -0400437 clib_memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700438 mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800439 mp->context = context;
440
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800441 mp->rpf_id = mfib_entry->mfe_rpf_id;
442 mp->entry_flags = mfib_entry->mfe_flags;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800443 mp->table_id = htonl (table_id);
Neale Ranns9e829a82018-12-17 05:50:32 -0800444 mp->address_length = pfx->fp_len;
445 memcpy (mp->grp_address, &pfx->fp_grp_addr.ip4,
446 sizeof (pfx->fp_grp_addr.ip4));
447 memcpy (mp->src_address, &pfx->fp_src_addr.ip4,
448 sizeof (pfx->fp_src_addr.ip4));
Neale Ranns5a8123b2017-01-26 01:18:23 -0800449
450 mp->count = htonl (path_count);
451 fp = mp->path;
452 vec_foreach (api_rpath, api_rpaths)
453 {
Neale Ranns7c03ed42018-12-27 03:21:28 -0800454 fib_api_path_encode (api_rpath, &fp->path);
455 fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800456 fp++;
457 }
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800458 vec_free (api_rpaths);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800459
Florin Coras6c4dae22018-01-09 06:39:23 -0800460 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800461}
462
463typedef struct vl_api_ip_mfib_dump_ctc_t_
464{
465 fib_node_index_t *entries;
466} vl_api_ip_mfib_dump_ctc_t;
467
468static int
469vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
470{
471 vl_api_ip_mfib_dump_ctc_t *ctx = arg;
472
473 vec_add1 (ctx->entries, fei);
474
475 return (0);
476}
477
478static void
479vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
480{
Florin Coras6c4dae22018-01-09 06:39:23 -0800481 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800482 ip4_main_t *im = &ip4_main;
483 mfib_table_t *mfib_table;
484 fib_node_index_t *mfeip;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800485 vl_api_ip_mfib_dump_ctc_t ctx = {
486 .entries = NULL,
487 };
488
Florin Coras6c4dae22018-01-09 06:39:23 -0800489 reg = vl_api_client_index_to_registration (mp->client_index);
490 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800491 return;
492
Neale Ranns5a8123b2017-01-26 01:18:23 -0800493 /* *INDENT-OFF* */
494 pool_foreach (mfib_table, im->mfibs,
495 ({
496 ip4_mfib_table_walk(&mfib_table->v4,
497 vl_api_ip_mfib_table_dump_walk,
498 &ctx);
499
500 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
501
502 vec_foreach (mfeip, ctx.entries)
503 {
Florin Coras6c4dae22018-01-09 06:39:23 -0800504 send_ip_mfib_details (reg, mp->context,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800505 mfib_table->mft_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800506 *mfeip);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800507 }
Neale Ranns5a8123b2017-01-26 01:18:23 -0800508 vec_reset_length (ctx.entries);
509
510 }));
511 /* *INDENT-ON* */
512
513 vec_free (ctx.entries);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800514}
515
516static void
Neale Ranns5a8123b2017-01-26 01:18:23 -0800517send_ip6_mfib_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800518 vl_api_registration_t * reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800519 u32 table_id,
Neale Ranns9e829a82018-12-17 05:50:32 -0800520 const mfib_prefix_t * pfx,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800521 fib_route_path_encode_t * api_rpaths, u32 context)
522{
523 vl_api_ip6_mfib_details_t *mp;
524 fib_route_path_encode_t *api_rpath;
Neale Ranns7c03ed42018-12-27 03:21:28 -0800525 vl_api_mfib_path_t *fp;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800526 int path_count;
527
528 path_count = vec_len (api_rpaths);
529 mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
530 if (!mp)
531 return;
Dave Barachb7b92992018-10-17 10:38:51 -0400532 clib_memset (mp, 0, sizeof (*mp));
Neale Rannsd792d9c2017-10-21 10:53:20 -0700533 mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800534 mp->context = context;
535
536 mp->table_id = htonl (table_id);
537 mp->address_length = pfx->fp_len;
538 memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6,
539 sizeof (pfx->fp_grp_addr.ip6));
540 memcpy (mp->src_address, &pfx->fp_src_addr.ip6,
541 sizeof (pfx->fp_src_addr.ip6));
542
543 mp->count = htonl (path_count);
544 fp = mp->path;
545 vec_foreach (api_rpath, api_rpaths)
546 {
Neale Ranns7c03ed42018-12-27 03:21:28 -0800547 fib_api_path_encode (api_rpath, &fp->path);
548 fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800549 fp++;
550 }
551
Florin Coras6c4dae22018-01-09 06:39:23 -0800552 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800553}
554
555typedef struct vl_api_ip6_mfib_dump_ctc_t_
556{
557 fib_node_index_t *entries;
558} vl_api_ip6_mfib_dump_ctc_t;
559
560static int
561vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
562{
563 vl_api_ip6_mfib_dump_ctc_t *ctx = arg;
564
565 vec_add1 (ctx->entries, fei);
566
567 return (0);
568}
569
570static void
571vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
572{
573 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800574 vl_api_registration_t *reg;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800575 ip6_main_t *im = &ip6_main;
576 mfib_table_t *mfib_table;
Neale Ranns9e829a82018-12-17 05:50:32 -0800577 const mfib_prefix_t *pfx;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800578 fib_node_index_t *mfeip;
Neale Ranns5a8123b2017-01-26 01:18:23 -0800579 fib_route_path_encode_t *api_rpaths = NULL;
580 vl_api_ip6_mfib_dump_ctc_t ctx = {
581 .entries = NULL,
582 };
583
Florin Coras6c4dae22018-01-09 06:39:23 -0800584 reg = vl_api_client_index_to_registration (mp->client_index);
585 if (!reg)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800586 return;
587
588
589 /* *INDENT-OFF* */
590 pool_foreach (mfib_table, im->mfibs,
591 ({
592 ip6_mfib_table_walk(&mfib_table->v6,
593 vl_api_ip6_mfib_table_dump_walk,
594 &ctx);
595
596 vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort);
597
598 vec_foreach(mfeip, ctx.entries)
599 {
Neale Ranns9e829a82018-12-17 05:50:32 -0800600 pfx = mfib_entry_get_prefix (*mfeip);
Neale Ranns5a8123b2017-01-26 01:18:23 -0800601 mfib_entry_encode (*mfeip, &api_rpaths);
Florin Coras6c4dae22018-01-09 06:39:23 -0800602 send_ip6_mfib_details (am, reg,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800603 mfib_table->mft_table_id,
Neale Ranns9e829a82018-12-17 05:50:32 -0800604 pfx, api_rpaths,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800605 mp->context);
606 }
607 vec_reset_length (api_rpaths);
608 vec_reset_length (ctx.entries);
609
610 }));
611 /* *INDENT-ON* */
612
613 vec_free (ctx.entries);
614 vec_free (api_rpaths);
615}
616
617static void
Neale Rannsd91c1db2017-07-31 02:30:50 -0700618vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp,
619 vlib_main_t * vm)
620{
621 vl_api_ip_punt_police_reply_t *rmp;
622 int rv = 0;
623
624 if (mp->is_ip6)
625 ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
626 else
627 ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
628
629 REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY);
630}
631
632static void
633vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp,
634 vlib_main_t * vm)
635{
636 vl_api_ip_punt_redirect_reply_t *rmp;
637 int rv = 0;
Pavel Kotucek609e1212018-11-27 09:59:44 +0100638 ip46_type_t ipv;
639 ip46_address_t nh;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700640
Pavel Kotucek609e1212018-11-27 09:59:44 +0100641 if (!vnet_sw_if_index_is_api_valid (ntohl (mp->punt.tx_sw_if_index)))
642 goto bad_sw_if_index;
643
644 ipv = ip_address_decode (&mp->punt.nh, &nh);
Neale Rannsd91c1db2017-07-31 02:30:50 -0700645 if (mp->is_add)
646 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100647 if (ipv == IP46_TYPE_IP6)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700648 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100649 ip6_punt_redirect_add (ntohl (mp->punt.rx_sw_if_index),
650 ntohl (mp->punt.tx_sw_if_index), &nh);
Neale Rannsd91c1db2017-07-31 02:30:50 -0700651 }
Pavel Kotucek609e1212018-11-27 09:59:44 +0100652 else if (ipv == IP46_TYPE_IP4)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700653 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100654 ip4_punt_redirect_add (ntohl (mp->punt.rx_sw_if_index),
655 ntohl (mp->punt.tx_sw_if_index), &nh);
Neale Rannsd91c1db2017-07-31 02:30:50 -0700656 }
657 }
658 else
659 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100660 if (ipv == IP46_TYPE_IP6)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700661 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100662 ip6_punt_redirect_del (ntohl (mp->punt.rx_sw_if_index));
Neale Rannsd91c1db2017-07-31 02:30:50 -0700663 }
Pavel Kotucek609e1212018-11-27 09:59:44 +0100664 else if (ipv == IP46_TYPE_IP4)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700665 {
Pavel Kotucek609e1212018-11-27 09:59:44 +0100666 ip4_punt_redirect_del (ntohl (mp->punt.rx_sw_if_index));
Neale Rannsd91c1db2017-07-31 02:30:50 -0700667 }
668 }
669
Pavel Kotucek609e1212018-11-27 09:59:44 +0100670 BAD_SW_IF_INDEX_LABEL;
671
Neale Rannsd91c1db2017-07-31 02:30:50 -0700672 REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY);
673}
674
Neale Ranns37029302018-08-10 05:30:06 -0700675static ip_neighbor_flags_t
676ip_neighbor_flags_decode (vl_api_ip_neighbor_flags_t v)
677{
678 ip_neighbor_flags_t f = IP_NEIGHBOR_FLAG_NONE;
679
680 v = clib_net_to_host_u32 (v);
681
682 if (v & IP_API_NEIGHBOR_FLAG_STATIC)
683 f |= IP_NEIGHBOR_FLAG_STATIC;
684 if (v & IP_API_NEIGHBOR_FLAG_NO_FIB_ENTRY)
685 f |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
686
687 return (f);
688}
689
Neale Rannsd91c1db2017-07-31 02:30:50 -0700690static void
Dave Barachb5e8a772016-12-06 12:04:42 -0500691vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
692 vlib_main_t * vm)
693{
694 vl_api_ip_neighbor_add_del_reply_t *rmp;
Neale Ranns0bdd3192018-09-07 11:04:52 -0700695 ip_neighbor_flags_t flags;
Neale Ranns14260392018-09-28 05:00:57 -0700696 u32 stats_index = ~0;
Neale Ranns37029302018-08-10 05:30:06 -0700697 ip46_address_t ip;
698 mac_address_t mac;
699 ip46_type_t type;
Dave Barachb5e8a772016-12-06 12:04:42 -0500700 int rv = 0;
701
Neale Ranns37029302018-08-10 05:30:06 -0700702 VALIDATE_SW_IF_INDEX ((&mp->neighbor));
Dave Barachb5e8a772016-12-06 12:04:42 -0500703
Neale Ranns37029302018-08-10 05:30:06 -0700704 flags = ip_neighbor_flags_decode (mp->neighbor.flags);
705 type = ip_address_decode (&mp->neighbor.ip_address, &ip);
706 mac_address_decode (mp->neighbor.mac_address, &mac);
Neale Ranns0bdd3192018-09-07 11:04:52 -0700707
Neale Ranns37029302018-08-10 05:30:06 -0700708 /*
709 * there's no validation here of the ND/ARP entry being added.
710 * The expectation is that the FIB will ensure that nothing bad
711 * will come of adding bogus entries.
712 */
Neale Ranns0bdd3192018-09-07 11:04:52 -0700713 if (mp->is_add)
Neale Ranns37029302018-08-10 05:30:06 -0700714 rv = ip_neighbor_add (&ip, type, &mac,
715 ntohl (mp->neighbor.sw_if_index),
716 flags, &stats_index);
Neale Ranns0bdd3192018-09-07 11:04:52 -0700717 else
Neale Ranns37029302018-08-10 05:30:06 -0700718 rv = ip_neighbor_del (&ip, type, ntohl (mp->neighbor.sw_if_index));
Dave Barachb5e8a772016-12-06 12:04:42 -0500719
Neale Ranns8edad032017-10-09 05:26:13 -0700720 BAD_SW_IF_INDEX_LABEL;
Neale Ranns14260392018-09-28 05:00:57 -0700721
722 /* *INDENT-OFF* */
723 REPLY_MACRO2 (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY,
724 ({
725 rmp->stats_index = htonl (stats_index);
726 }));
727 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -0500728}
729
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700730void
Neale Ranns15002542017-09-10 04:39:11 -0700731ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
732{
733 u32 fib_index, mfib_index;
734
735 /*
736 * ignore action on the default table - this is always present
737 * and cannot be added nor deleted from the API
738 */
739 if (0 != table_id)
740 {
741 /*
742 * The API holds only one lock on the table.
743 * i.e. it can be added many times via the API but needs to be
744 * deleted only once.
745 * The FIB index for unicast and multicast is not necessarily the
746 * same, since internal VPP systesm (like LISP and SR) create
747 * their own unicast tables.
748 */
749 fib_index = fib_table_find (fproto, table_id);
750 mfib_index = mfib_table_find (fproto, table_id);
751
752 if (~0 != fib_index)
753 {
754 fib_table_unlock (fib_index, fproto,
755 (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
756 }
757 if (~0 != mfib_index)
758 {
759 mfib_table_unlock (mfib_index, fproto,
760 (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
761 }
762 }
763}
764
765void
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700766vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
767{
768 vl_api_ip_table_add_del_reply_t *rmp;
Neale Ranns15002542017-09-10 04:39:11 -0700769 fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
770 u32 table_id = ntohl (mp->table_id);
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700771 int rv = 0;
772
Neale Ranns15002542017-09-10 04:39:11 -0700773 if (mp->is_add)
774 {
Neale Ranns2297af02017-09-12 09:45:04 -0700775 ip_table_create (fproto, table_id, 1, mp->name);
Neale Ranns15002542017-09-10 04:39:11 -0700776 }
777 else
778 {
779 ip_table_delete (fproto, table_id, 1);
780 }
781
Neale Ranns28ab9cc2017-08-14 07:18:42 -0700782 REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
783}
784
Dave Barachb5e8a772016-12-06 12:04:42 -0500785int
786add_del_route_t_handler (u8 is_multipath,
787 u8 is_add,
788 u8 is_drop,
789 u8 is_unreach,
790 u8 is_prohibit,
791 u8 is_local,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800792 u8 is_multicast,
Dave Barachb5e8a772016-12-06 12:04:42 -0500793 u8 is_classify,
794 u32 classify_table_index,
795 u8 is_resolve_host,
796 u8 is_resolve_attached,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800797 u8 is_interface_rx,
798 u8 is_rpf_id,
Neale Rannsf068c3e2018-01-03 04:18:48 -0800799 u8 is_dvr,
Neale Ranns054c03a2017-10-13 05:15:07 -0700800 u8 is_source_lookup,
Neale Ranns810086d2017-11-05 16:26:46 -0800801 u8 is_udp_encap,
Dave Barachb5e8a772016-12-06 12:04:42 -0500802 u32 fib_index,
803 const fib_prefix_t * prefix,
Neale Rannsda78f952017-05-24 09:15:43 -0700804 dpo_proto_t next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500805 const ip46_address_t * next_hop,
Neale Ranns810086d2017-11-05 16:26:46 -0800806 u32 next_hop_id,
Dave Barachb5e8a772016-12-06 12:04:42 -0500807 u32 next_hop_sw_if_index,
808 u8 next_hop_fib_index,
Neale Ranns57b58602017-07-15 07:37:25 -0700809 u16 next_hop_weight,
810 u16 next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500811 mpls_label_t next_hop_via_label,
Neale Ranns31ed7442018-02-23 05:29:09 -0800812 fib_mpls_label_t * next_hop_out_label_stack)
Dave Barachb5e8a772016-12-06 12:04:42 -0500813{
814 vnet_classify_main_t *cm = &vnet_classify_main;
815 fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
816 fib_route_path_t path = {
Neale Rannsda78f952017-05-24 09:15:43 -0700817 .frp_proto = next_hop_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500818 .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
819 .frp_sw_if_index = next_hop_sw_if_index,
820 .frp_fib_index = next_hop_fib_index,
821 .frp_weight = next_hop_weight,
Neale Ranns57b58602017-07-15 07:37:25 -0700822 .frp_preference = next_hop_preference,
Dave Barachb5e8a772016-12-06 12:04:42 -0500823 .frp_label_stack = next_hop_out_label_stack,
824 };
825 fib_route_path_t *paths = NULL;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800826 fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
Dave Barachb5e8a772016-12-06 12:04:42 -0500827
Neale Rannscaac3502017-09-18 18:04:10 -0700828 /*
Jim Thompsonf324dec2019-04-08 03:22:21 -0500829 * the special INVALID label means we are not recursing via a
Neale Rannscaac3502017-09-18 18:04:10 -0700830 * label. Exp-null value is never a valid via-label so that
831 * also means it's not a via-label and means clients that set
832 * it to 0 by default get the expected behaviour
833 */
834 if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label))
Dave Barachb5e8a772016-12-06 12:04:42 -0500835 {
Neale Rannsda78f952017-05-24 09:15:43 -0700836 path.frp_proto = DPO_PROTO_MPLS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500837 path.frp_local_label = next_hop_via_label;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800838 path.frp_eos = MPLS_NON_EOS;
Dave Barachb5e8a772016-12-06 12:04:42 -0500839 }
Neale Ranns775f73c2018-12-20 03:01:49 -0800840 if (is_local)
Neale Ranns7425f922019-01-23 00:36:16 -0800841 {
842 path_flags |= FIB_ROUTE_PATH_LOCAL;
843 if (~0 != next_hop_sw_if_index)
844 {
845 entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL);
846 }
847 }
Neale Rannsf068c3e2018-01-03 04:18:48 -0800848 if (is_dvr)
849 path_flags |= FIB_ROUTE_PATH_DVR;
Dave Barachb5e8a772016-12-06 12:04:42 -0500850 if (is_resolve_host)
851 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
852 if (is_resolve_attached)
853 path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800854 if (is_interface_rx)
855 path_flags |= FIB_ROUTE_PATH_INTF_RX;
856 if (is_rpf_id)
857 path_flags |= FIB_ROUTE_PATH_RPF_ID;
Neale Ranns054c03a2017-10-13 05:15:07 -0700858 if (is_source_lookup)
859 path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800860 if (is_multicast)
861 entry_flags |= FIB_ENTRY_FLAG_MULTICAST;
Neale Ranns810086d2017-11-05 16:26:46 -0800862 if (is_udp_encap)
863 {
864 path_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
865 path.frp_udp_encap_id = next_hop_id;
866 }
Florin Coras79ae2d32017-12-16 08:31:06 -0800867 if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr)
868 && path.frp_fib_index != ~0)
869 {
870 path_flags |= FIB_ROUTE_PATH_DEAG;
871 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500872
873 path.frp_flags = path_flags;
874
Neale Ranns7425f922019-01-23 00:36:16 -0800875 if (is_drop || (is_local && (~0 == next_hop_sw_if_index)) ||
876 is_classify || is_unreach || is_prohibit)
Dave Barachb5e8a772016-12-06 12:04:42 -0500877 {
878 /*
879 * special route types that link directly to the adj
880 */
881 if (is_add)
882 {
883 dpo_id_t dpo = DPO_INVALID;
884 dpo_proto_t dproto;
885
886 dproto = fib_proto_to_dpo (prefix->fp_proto);
887
888 if (is_drop)
889 ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
890 else if (is_local)
891 receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
892 else if (is_unreach)
893 ip_null_dpo_add_and_lock (dproto,
894 IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
895 else if (is_prohibit)
896 ip_null_dpo_add_and_lock (dproto,
897 IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
898 &dpo);
899 else if (is_classify)
900 {
901 if (pool_is_free_index (cm->tables,
902 ntohl (classify_table_index)))
903 {
Dave Barachb5e8a772016-12-06 12:04:42 -0500904 return VNET_API_ERROR_NO_SUCH_TABLE;
905 }
906
907 dpo_set (&dpo, DPO_CLASSIFY, dproto,
908 classify_dpo_create (dproto,
909 ntohl (classify_table_index)));
910 }
911 else
912 {
Dave Barachb5e8a772016-12-06 12:04:42 -0500913 return VNET_API_ERROR_NO_SUCH_TABLE;
914 }
915
916 fib_table_entry_special_dpo_update (fib_index,
917 prefix,
918 FIB_SOURCE_API,
919 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
920 dpo_reset (&dpo);
921 }
922 else
923 {
924 fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
925 }
926 }
Neale Ranns3b93be52018-09-07 01:48:54 -0700927 else if (is_multipath)
928 {
929 vec_add1 (paths, path);
930
931 if (is_add)
932 fib_table_entry_path_add2 (fib_index,
933 prefix,
934 FIB_SOURCE_API, entry_flags, paths);
935 else
936 fib_table_entry_path_remove2 (fib_index,
937 prefix, FIB_SOURCE_API, paths);
938
939 vec_free (paths);
940 }
Dave Barachb5e8a772016-12-06 12:04:42 -0500941 else
942 {
943 if (is_add)
944 {
945 vec_add1 (paths, path);
946 fib_table_entry_update (fib_index,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800947 prefix, FIB_SOURCE_API, entry_flags, paths);
Dave Barachb5e8a772016-12-06 12:04:42 -0500948 vec_free (paths);
949 }
950 else
951 {
952 fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
953 }
954 }
955
Dave Barachb5e8a772016-12-06 12:04:42 -0500956 return (0);
957}
958
959int
960add_del_route_check (fib_protocol_t table_proto,
961 u32 table_id,
962 u32 next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -0700963 dpo_proto_t next_hop_table_proto,
Dave Barachb5e8a772016-12-06 12:04:42 -0500964 u32 next_hop_table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800965 u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
Dave Barachb5e8a772016-12-06 12:04:42 -0500966{
967 vnet_main_t *vnm = vnet_get_main ();
968
969 *fib_index = fib_table_find (table_proto, ntohl (table_id));
970 if (~0 == *fib_index)
971 {
Neale Rannsb93078d2018-01-25 07:48:12 -0800972 /* No such VRF, and we weren't asked to create one */
973 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -0500974 }
975
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800976 if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index))
Dave Barachb5e8a772016-12-06 12:04:42 -0500977 {
978 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
979 ntohl (next_hop_sw_if_index)))
980 {
981 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
982 }
983 }
984 else
985 {
Neale Rannsda78f952017-05-24 09:15:43 -0700986 fib_protocol_t fib_nh_proto;
987
988 if (next_hop_table_proto > DPO_PROTO_MPLS)
989 return (0);
990
991 fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto);
992
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800993 if (is_rpf_id)
Neale Rannsda78f952017-05-24 09:15:43 -0700994 *next_hop_fib_index = mfib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800995 ntohl (next_hop_table_id));
996 else
Neale Rannsda78f952017-05-24 09:15:43 -0700997 *next_hop_fib_index = fib_table_find (fib_nh_proto,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800998 ntohl (next_hop_table_id));
Dave Barachb5e8a772016-12-06 12:04:42 -0500999
1000 if (~0 == *next_hop_fib_index)
1001 {
Neale Rannsb93078d2018-01-25 07:48:12 -08001002 /* No such VRF, and we weren't asked to create one */
1003 return VNET_API_ERROR_NO_SUCH_FIB;
Dave Barachb5e8a772016-12-06 12:04:42 -05001004 }
1005 }
1006
1007 return (0);
1008}
1009
1010static int
Neale Ranns008dbe12018-09-07 09:32:36 -07001011ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
1012 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -05001013{
1014 u32 fib_index, next_hop_fib_index;
Neale Ranns31ed7442018-02-23 05:29:09 -08001015 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -05001016 int rv, ii, n_labels;;
1017
1018 rv = add_del_route_check (FIB_PROTOCOL_IP4,
1019 mp->table_id,
1020 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001021 DPO_PROTO_IP4,
Dave Barachb5e8a772016-12-06 12:04:42 -05001022 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001023 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001024
1025 if (0 != rv)
1026 return (rv);
1027
1028 fib_prefix_t pfx = {
1029 .fp_len = mp->dst_address_length,
1030 .fp_proto = FIB_PROTOCOL_IP4,
1031 };
1032 clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
1033
1034 ip46_address_t nh;
Dave Barachb7b92992018-10-17 10:38:51 -04001035 clib_memset (&nh, 0, sizeof (nh));
Dave Barachb5e8a772016-12-06 12:04:42 -05001036 memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
1037
1038 n_labels = mp->next_hop_n_out_labels;
1039 if (n_labels == 0)
1040 ;
Dave Barachb5e8a772016-12-06 12:04:42 -05001041 else
1042 {
1043 vec_validate (label_stack, n_labels - 1);
1044 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001045 {
1046 label_stack[ii].fml_value =
1047 ntohl (mp->next_hop_out_label_stack[ii].label);
1048 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1049 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1050 label_stack[ii].fml_mode =
1051 (mp->next_hop_out_label_stack[ii].is_uniform ?
1052 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1053 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001054 }
1055
Neale Ranns008dbe12018-09-07 09:32:36 -07001056 rv = add_del_route_t_handler (mp->is_multipath,
1057 mp->is_add,
1058 mp->is_drop,
1059 mp->is_unreach,
1060 mp->is_prohibit,
1061 mp->is_local, 0,
1062 mp->is_classify,
1063 mp->classify_table_index,
1064 mp->is_resolve_host,
1065 mp->is_resolve_attached, 0, 0,
1066 mp->is_dvr,
1067 mp->is_source_lookup,
1068 mp->is_udp_encap,
1069 fib_index, &pfx, DPO_PROTO_IP4,
1070 &nh,
1071 ntohl (mp->next_hop_id),
1072 ntohl (mp->next_hop_sw_if_index),
1073 next_hop_fib_index,
1074 mp->next_hop_weight,
1075 mp->next_hop_preference,
1076 ntohl (mp->next_hop_via_label), label_stack);
1077
1078 if (mp->is_add && 0 == rv)
1079 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1080
1081 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001082}
1083
Juraj Sloboda0012fcc2018-05-17 12:05:27 +02001084static int
Neale Ranns008dbe12018-09-07 09:32:36 -07001085ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
1086 u32 * stats_index)
Dave Barachb5e8a772016-12-06 12:04:42 -05001087{
Neale Ranns31ed7442018-02-23 05:29:09 -08001088 fib_mpls_label_t *label_stack = NULL;
Dave Barachb5e8a772016-12-06 12:04:42 -05001089 u32 fib_index, next_hop_fib_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001090 int rv, ii, n_labels;;
1091
1092 rv = add_del_route_check (FIB_PROTOCOL_IP6,
1093 mp->table_id,
1094 mp->next_hop_sw_if_index,
Neale Rannsda78f952017-05-24 09:15:43 -07001095 DPO_PROTO_IP6,
Dave Barachb5e8a772016-12-06 12:04:42 -05001096 mp->next_hop_table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001097 0, &fib_index, &next_hop_fib_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001098
1099 if (0 != rv)
1100 return (rv);
1101
1102 fib_prefix_t pfx = {
1103 .fp_len = mp->dst_address_length,
1104 .fp_proto = FIB_PROTOCOL_IP6,
1105 };
1106 clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
1107
1108 ip46_address_t nh;
Dave Barachb7b92992018-10-17 10:38:51 -04001109 clib_memset (&nh, 0, sizeof (nh));
Dave Barachb5e8a772016-12-06 12:04:42 -05001110 memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
1111
1112 n_labels = mp->next_hop_n_out_labels;
1113 if (n_labels == 0)
1114 ;
Dave Barachb5e8a772016-12-06 12:04:42 -05001115 else
1116 {
1117 vec_validate (label_stack, n_labels - 1);
1118 for (ii = 0; ii < n_labels; ii++)
Neale Ranns31ed7442018-02-23 05:29:09 -08001119 {
1120 label_stack[ii].fml_value =
1121 ntohl (mp->next_hop_out_label_stack[ii].label);
1122 label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl;
1123 label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp;
1124 label_stack[ii].fml_mode =
1125 (mp->next_hop_out_label_stack[ii].is_uniform ?
1126 FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE);
1127 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001128 }
1129
Neale Ranns008dbe12018-09-07 09:32:36 -07001130 rv = add_del_route_t_handler (mp->is_multipath,
1131 mp->is_add,
1132 mp->is_drop,
1133 mp->is_unreach,
1134 mp->is_prohibit,
1135 mp->is_local, 0,
1136 mp->is_classify,
1137 mp->classify_table_index,
1138 mp->is_resolve_host,
1139 mp->is_resolve_attached, 0, 0,
1140 mp->is_dvr,
1141 mp->is_source_lookup,
1142 mp->is_udp_encap,
1143 fib_index, &pfx, DPO_PROTO_IP6,
1144 &nh, ntohl (mp->next_hop_id),
1145 ntohl (mp->next_hop_sw_if_index),
1146 next_hop_fib_index,
1147 mp->next_hop_weight,
1148 mp->next_hop_preference,
1149 ntohl (mp->next_hop_via_label), label_stack);
1150
1151 if (mp->is_add && 0 == rv)
1152 *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
1153
1154 return (rv);
Dave Barachb5e8a772016-12-06 12:04:42 -05001155}
1156
1157void
1158vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1159{
1160 vl_api_ip_add_del_route_reply_t *rmp;
Neale Ranns008dbe12018-09-07 09:32:36 -07001161 u32 stats_index;
Dave Barachb5e8a772016-12-06 12:04:42 -05001162 int rv;
1163 vnet_main_t *vnm = vnet_get_main ();
1164
1165 vnm->api_errno = 0;
Neale Ranns008dbe12018-09-07 09:32:36 -07001166 stats_index = ~0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001167
1168 if (mp->is_ipv6)
Neale Ranns008dbe12018-09-07 09:32:36 -07001169 rv = ip6_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001170 else
Neale Ranns008dbe12018-09-07 09:32:36 -07001171 rv = ip4_add_del_route_t_handler (mp, &stats_index);
Dave Barachb5e8a772016-12-06 12:04:42 -05001172
1173 rv = (rv == 0) ? vnm->api_errno : rv;
1174
Neale Ranns008dbe12018-09-07 09:32:36 -07001175 /* *INDENT-OFF* */
1176 REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY,
1177 ({
1178 rmp->stats_index = htonl (stats_index);
1179 }))
1180 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001181}
1182
Neale Ranns15002542017-09-10 04:39:11 -07001183void
Neale Ranns2297af02017-09-12 09:45:04 -07001184ip_table_create (fib_protocol_t fproto,
1185 u32 table_id, u8 is_api, const u8 * name)
Neale Ranns15002542017-09-10 04:39:11 -07001186{
1187 u32 fib_index, mfib_index;
1188
1189 /*
1190 * ignore action on the default table - this is always present
1191 * and cannot be added nor deleted from the API
1192 */
1193 if (0 != table_id)
1194 {
1195 /*
1196 * The API holds only one lock on the table.
1197 * i.e. it can be added many times via the API but needs to be
1198 * deleted only once.
1199 * The FIB index for unicast and multicast is not necessarily the
1200 * same, since internal VPP systesm (like LISP and SR) create
1201 * their own unicast tables.
1202 */
1203 fib_index = fib_table_find (fproto, table_id);
1204 mfib_index = mfib_table_find (fproto, table_id);
1205
1206 if (~0 == fib_index)
1207 {
Neale Ranns2297af02017-09-12 09:45:04 -07001208 fib_table_find_or_create_and_lock_w_name (fproto, table_id,
1209 (is_api ?
1210 FIB_SOURCE_API :
1211 FIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001212 }
1213 if (~0 == mfib_index)
1214 {
Neale Ranns2297af02017-09-12 09:45:04 -07001215 mfib_table_find_or_create_and_lock_w_name (fproto, table_id,
1216 (is_api ?
1217 MFIB_SOURCE_API :
1218 MFIB_SOURCE_CLI), name);
Neale Ranns15002542017-09-10 04:39:11 -07001219 }
1220 }
1221}
1222
Neale Ranns32e1c012016-11-22 17:07:28 +00001223static int
1224add_del_mroute_check (fib_protocol_t table_proto,
1225 u32 table_id,
Neale Ranns15002542017-09-10 04:39:11 -07001226 u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001227{
1228 vnet_main_t *vnm = vnet_get_main ();
1229
1230 *fib_index = mfib_table_find (table_proto, ntohl (table_id));
1231 if (~0 == *fib_index)
1232 {
Neale Ranns15002542017-09-10 04:39:11 -07001233 /* No such table */
1234 return VNET_API_ERROR_NO_SUCH_FIB;
Neale Ranns32e1c012016-11-22 17:07:28 +00001235 }
1236
1237 if (~0 != ntohl (next_hop_sw_if_index))
1238 {
1239 if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1240 ntohl (next_hop_sw_if_index)))
1241 {
1242 return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1243 }
1244 }
1245
1246 return (0);
1247}
1248
Neale Ranns28c142e2018-09-07 09:37:07 -07001249static fib_node_index_t
Neale Ranns32e1c012016-11-22 17:07:28 +00001250mroute_add_del_handler (u8 is_add,
1251 u8 is_local,
1252 u32 fib_index,
1253 const mfib_prefix_t * prefix,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001254 dpo_proto_t nh_proto,
Neale Ranns32e1c012016-11-22 17:07:28 +00001255 u32 entry_flags,
Neale Ranns0f26c5a2017-03-01 15:12:11 -08001256 fib_rpf_id_t rpf_id,
Neale Rannse821ab12017-06-01 07:45:05 -07001257 u32 next_hop_sw_if_index,
1258 ip46_address_t * nh, u32 itf_flags, u32 bier_imp)
Neale Ranns32e1c012016-11-22 17:07:28 +00001259{
Neale Ranns28c142e2018-09-07 09:37:07 -07001260 fib_node_index_t mfib_entry_index = ~0;
1261
Neale Ranns32e1c012016-11-22 17:07:28 +00001262 fib_route_path_t path = {
1263 .frp_sw_if_index = next_hop_sw_if_index,
Neale Rannsd792d9c2017-10-21 10:53:20 -07001264 .frp_proto = nh_proto,
Neale Rannse821ab12017-06-01 07:45:05 -07001265 .frp_addr = *nh,
Neale Ranns32e1c012016-11-22 17:07:28 +00001266 };
1267
1268 if (is_local)
1269 path.frp_flags |= FIB_ROUTE_PATH_LOCAL;
1270
Neale Rannsd792d9c2017-10-21 10:53:20 -07001271 if (DPO_PROTO_BIER == nh_proto)
1272 {
1273 path.frp_bier_imp = bier_imp;
1274 path.frp_flags = FIB_ROUTE_PATH_BIER_IMP;
1275 }
1276 else if (!is_local && ~0 == next_hop_sw_if_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001277 {
Neale Ranns28c142e2018-09-07 09:37:07 -07001278 mfib_entry_index = mfib_table_entry_update (fib_index, prefix,
1279 MFIB_SOURCE_API,
1280 rpf_id, entry_flags);
Neale Rannsd792d9c2017-10-21 10:53:20 -07001281 goto done;
1282 }
1283
1284 if (is_add)
1285 {
Neale Ranns28c142e2018-09-07 09:37:07 -07001286 mfib_entry_index = mfib_table_entry_path_update (fib_index, prefix,
1287 MFIB_SOURCE_API,
1288 &path, itf_flags);
Neale Ranns32e1c012016-11-22 17:07:28 +00001289 }
1290 else
1291 {
Neale Rannsd792d9c2017-10-21 10:53:20 -07001292 mfib_table_entry_path_remove (fib_index, prefix,
1293 MFIB_SOURCE_API, &path);
Neale Ranns32e1c012016-11-22 17:07:28 +00001294 }
1295
Neale Rannsd792d9c2017-10-21 10:53:20 -07001296done:
Neale Ranns28c142e2018-09-07 09:37:07 -07001297 return (mfib_entry_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001298}
1299
1300static int
Neale Ranns28c142e2018-09-07 09:37:07 -07001301api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp,
1302 u32 * stats_index)
Neale Ranns32e1c012016-11-22 17:07:28 +00001303{
Neale Ranns28c142e2018-09-07 09:37:07 -07001304 fib_node_index_t mfib_entry_index;
Neale Ranns32e1c012016-11-22 17:07:28 +00001305 fib_protocol_t fproto;
Neale Rannsd792d9c2017-10-21 10:53:20 -07001306 dpo_proto_t nh_proto;
Neale Rannse821ab12017-06-01 07:45:05 -07001307 ip46_address_t nh;
Neale Ranns32e1c012016-11-22 17:07:28 +00001308 u32 fib_index;
1309 int rv;
1310
Neale Rannsd792d9c2017-10-21 10:53:20 -07001311 nh_proto = mp->next_hop_afi;
Neale Ranns32e1c012016-11-22 17:07:28 +00001312 fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
1313 rv = add_del_mroute_check (fproto,
1314 mp->table_id,
1315 mp->next_hop_sw_if_index,
Neale Ranns15002542017-09-10 04:39:11 -07001316 mp->is_local, &fib_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001317
1318 if (0 != rv)
1319 return (rv);
1320
1321 mfib_prefix_t pfx = {
1322 .fp_len = ntohs (mp->grp_address_length),
1323 .fp_proto = fproto,
1324 };
1325
1326 if (FIB_PROTOCOL_IP4 == fproto)
1327 {
1328 clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address,
1329 sizeof (pfx.fp_grp_addr.ip4));
1330 clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
1331 sizeof (pfx.fp_src_addr.ip4));
Dave Barachb7b92992018-10-17 10:38:51 -04001332 clib_memset (&nh.ip6, 0, sizeof (nh.ip6));
Neale Rannse821ab12017-06-01 07:45:05 -07001333 clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4));
Neale Ranns3e42ebe2018-10-04 08:36:56 -07001334 if (!ip46_address_is_zero (&pfx.fp_src_addr))
1335 pfx.fp_len = 64;
Neale Ranns32e1c012016-11-22 17:07:28 +00001336 }
1337 else
1338 {
1339 clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address,
1340 sizeof (pfx.fp_grp_addr.ip6));
1341 clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
1342 sizeof (pfx.fp_src_addr.ip6));
Neale Rannse821ab12017-06-01 07:45:05 -07001343 clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6));
Neale Ranns3e42ebe2018-10-04 08:36:56 -07001344 if (!ip46_address_is_zero (&pfx.fp_src_addr))
1345 pfx.fp_len = 256;
Neale Ranns32e1c012016-11-22 17:07:28 +00001346 }
1347
Neale Ranns28c142e2018-09-07 09:37:07 -07001348 mfib_entry_index = mroute_add_del_handler (mp->is_add,
1349 mp->is_local,
1350 fib_index, &pfx,
1351 nh_proto,
1352 ntohl (mp->entry_flags),
1353 ntohl (mp->rpf_id),
1354 ntohl (mp->next_hop_sw_if_index),
1355 &nh,
1356 ntohl (mp->itf_flags),
1357 ntohl (mp->bier_imp));
1358
1359 if (~0 != mfib_entry_index)
1360 *stats_index = mfib_entry_get_stats_index (mfib_entry_index);
1361
1362 return (rv);
Neale Ranns32e1c012016-11-22 17:07:28 +00001363}
1364
1365void
1366vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
1367{
1368 vl_api_ip_mroute_add_del_reply_t *rmp;
Neale Ranns28c142e2018-09-07 09:37:07 -07001369 vnet_main_t *vnm;
1370 u32 stats_index;
Neale Ranns32e1c012016-11-22 17:07:28 +00001371 int rv;
Neale Ranns32e1c012016-11-22 17:07:28 +00001372
Neale Ranns28c142e2018-09-07 09:37:07 -07001373 vnm = vnet_get_main ();
Neale Ranns32e1c012016-11-22 17:07:28 +00001374 vnm->api_errno = 0;
Neale Ranns28c142e2018-09-07 09:37:07 -07001375 stats_index = ~0;
Neale Ranns32e1c012016-11-22 17:07:28 +00001376
Neale Ranns28c142e2018-09-07 09:37:07 -07001377 rv = api_mroute_add_del_t_handler (mp, &stats_index);
Neale Ranns32e1c012016-11-22 17:07:28 +00001378
Neale Ranns28c142e2018-09-07 09:37:07 -07001379 /* *INDENT-OFF* */
1380 REPLY_MACRO2 (VL_API_IP_MROUTE_ADD_DEL_REPLY,
1381 ({
1382 rmp->stats_index = htonl (stats_index);
1383 }));
1384 /* *INDENT-ON* */
Neale Ranns32e1c012016-11-22 17:07:28 +00001385}
1386
Dave Barachb5e8a772016-12-06 12:04:42 -05001387static void
1388send_ip_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001389 vl_api_registration_t * reg, u32 sw_if_index, u8 is_ipv6,
1390 u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001391{
1392 vl_api_ip_details_t *mp;
1393
1394 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04001395 clib_memset (mp, 0, sizeof (*mp));
Dave Barachb5e8a772016-12-06 12:04:42 -05001396 mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
1397
1398 mp->sw_if_index = ntohl (sw_if_index);
Jon Loeliger466f0d42017-02-09 12:17:50 -06001399 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001400 mp->context = context;
1401
Florin Coras6c4dae22018-01-09 06:39:23 -08001402 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -05001403}
1404
1405static void
1406send_ip_address_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -08001407 vl_api_registration_t * reg,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001408 u8 * ip, u16 prefix_length,
1409 u32 sw_if_index, u8 is_ipv6, u32 context)
Dave Barachb5e8a772016-12-06 12:04:42 -05001410{
1411 vl_api_ip_address_details_t *mp;
1412
1413 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04001414 clib_memset (mp, 0, sizeof (*mp));
Dave Barachb5e8a772016-12-06 12:04:42 -05001415 mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
1416
1417 if (is_ipv6)
1418 {
1419 clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
1420 }
1421 else
1422 {
1423 u32 *tp = (u32 *) mp->ip;
1424 *tp = *(u32 *) ip;
1425 }
1426 mp->prefix_length = prefix_length;
1427 mp->context = context;
Jon Loeliger466f0d42017-02-09 12:17:50 -06001428 mp->sw_if_index = htonl (sw_if_index);
1429 mp->is_ipv6 = is_ipv6;
Dave Barachb5e8a772016-12-06 12:04:42 -05001430
Florin Coras6c4dae22018-01-09 06:39:23 -08001431 vl_api_send_msg (reg, (u8 *) mp);
Dave Barachb5e8a772016-12-06 12:04:42 -05001432}
1433
1434static void
1435vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
1436{
1437 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001438 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001439 ip6_address_t *r6;
1440 ip4_address_t *r4;
1441 ip6_main_t *im6 = &ip6_main;
1442 ip4_main_t *im4 = &ip4_main;
1443 ip_lookup_main_t *lm6 = &im6->lookup_main;
1444 ip_lookup_main_t *lm4 = &im4->lookup_main;
1445 ip_interface_address_t *ia = 0;
1446 u32 sw_if_index = ~0;
1447 int rv __attribute__ ((unused)) = 0;
1448
1449 VALIDATE_SW_IF_INDEX (mp);
1450
1451 sw_if_index = ntohl (mp->sw_if_index);
1452
Florin Coras6c4dae22018-01-09 06:39:23 -08001453 reg = vl_api_client_index_to_registration (mp->client_index);
1454 if (!reg)
Dave Barachb5e8a772016-12-06 12:04:42 -05001455 return;
1456
Dave Barachb5e8a772016-12-06 12:04:42 -05001457 if (mp->is_ipv6)
1458 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001459 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001460 /* Do not send subnet details of the IP-interface for
1461 * unnumbered interfaces. otherwise listening clients
1462 * will be confused that the subnet is applied on more
1463 * than one interface */
1464 foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001465 ({
1466 r6 = ip_interface_address_get_address (lm6, ia);
1467 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001468 send_ip_address_details(am, reg, (u8*)r6, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001469 sw_if_index, 1, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001470 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001471 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001472 }
Dave Barachb5e8a772016-12-06 12:04:42 -05001473 else
1474 {
Dave Barachd7cb1b52016-12-09 09:52:16 -05001475 /* *INDENT-OFF* */
Neale Ranns4f2db7d2018-05-17 09:38:13 -07001476 foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
Dave Barachb5e8a772016-12-06 12:04:42 -05001477 ({
1478 r4 = ip_interface_address_get_address (lm4, ia);
1479 u16 prefix_length = ia->address_length;
Florin Coras6c4dae22018-01-09 06:39:23 -08001480 send_ip_address_details(am, reg, (u8*)r4, prefix_length,
Jon Loeliger466f0d42017-02-09 12:17:50 -06001481 sw_if_index, 0, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001482 }));
Dave Barachd7cb1b52016-12-09 09:52:16 -05001483 /* *INDENT-ON* */
Dave Barachb5e8a772016-12-06 12:04:42 -05001484 }
Neale Ranns008dbe12018-09-07 09:32:36 -07001485
Dave Barachb5e8a772016-12-06 12:04:42 -05001486 BAD_SW_IF_INDEX_LABEL;
1487}
1488
1489static void
Neale Ranns9e2f9152018-05-18 02:27:10 -07001490send_ip_unnumbered_details (vpe_api_main_t * am,
1491 vl_api_registration_t * reg,
1492 u32 sw_if_index, u32 ip_sw_if_index, u32 context)
1493{
1494 vl_api_ip_unnumbered_details_t *mp;
1495
1496 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04001497 clib_memset (mp, 0, sizeof (*mp));
Neale Ranns9e2f9152018-05-18 02:27:10 -07001498 mp->_vl_msg_id = ntohs (VL_API_IP_UNNUMBERED_DETAILS);
1499
1500 mp->context = context;
1501 mp->sw_if_index = htonl (sw_if_index);
1502 mp->ip_sw_if_index = htonl (ip_sw_if_index);
1503
1504 vl_api_send_msg (reg, (u8 *) mp);
1505}
1506
1507static void
1508vl_api_ip_unnumbered_dump_t_handler (vl_api_ip_unnumbered_dump_t * mp)
1509{
1510 vnet_main_t *vnm = vnet_get_main ();
1511 vnet_interface_main_t *im = &vnm->interface_main;
1512 int rv __attribute__ ((unused)) = 0;
1513 vpe_api_main_t *am = &vpe_api_main;
1514 vl_api_registration_t *reg;
1515 vnet_sw_interface_t *si;
1516 u32 sw_if_index;
1517
1518 sw_if_index = ntohl (mp->sw_if_index);
1519
1520 reg = vl_api_client_index_to_registration (mp->client_index);
1521 if (!reg)
1522 return;
1523
1524 if (~0 != sw_if_index)
1525 {
1526 VALIDATE_SW_IF_INDEX (mp);
1527
1528 si = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
1529
1530 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1531 {
1532 send_ip_unnumbered_details (am, reg,
1533 sw_if_index,
1534 si->unnumbered_sw_if_index,
1535 mp->context);
1536 }
1537 }
1538 else
1539 {
1540 /* *INDENT-OFF* */
1541 pool_foreach (si, im->sw_interfaces,
1542 ({
1543 if ((si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1544 {
1545 send_ip_unnumbered_details(am, reg,
1546 si->sw_if_index,
1547 si->unnumbered_sw_if_index,
1548 mp->context);
1549 }
1550 }));
1551 /* *INDENT-ON* */
1552 }
1553
1554 BAD_SW_IF_INDEX_LABEL;
1555}
1556
1557static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001558vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
1559{
1560 vpe_api_main_t *am = &vpe_api_main;
1561 vnet_main_t *vnm = vnet_get_main ();
1562 vlib_main_t *vm = vlib_get_main ();
1563 vnet_interface_main_t *im = &vnm->interface_main;
Florin Coras6c4dae22018-01-09 06:39:23 -08001564 vl_api_registration_t *reg;
Dave Barachb5e8a772016-12-06 12:04:42 -05001565 vnet_sw_interface_t *si, *sorted_sis;
1566 u32 sw_if_index = ~0;
1567
Florin Coras6c4dae22018-01-09 06:39:23 -08001568 reg = vl_api_client_index_to_registration (mp->client_index);
1569 if (!reg)
1570 return;
Dave Barachb5e8a772016-12-06 12:04:42 -05001571
1572 /* Gather interfaces. */
1573 sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
1574 _vec_len (sorted_sis) = 0;
1575 /* *INDENT-OFF* */
1576 pool_foreach (si, im->sw_interfaces,
1577 ({
1578 vec_add1 (sorted_sis, si[0]);
1579 }));
1580 /* *INDENT-ON* */
1581
1582 vec_foreach (si, sorted_sis)
1583 {
1584 if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1585 {
1586 if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
1587 {
1588 continue;
1589 }
1590 sw_if_index = si->sw_if_index;
Florin Coras6c4dae22018-01-09 06:39:23 -08001591 send_ip_details (am, reg, sw_if_index, mp->is_ipv6, mp->context);
Dave Barachb5e8a772016-12-06 12:04:42 -05001592 }
1593 }
1594}
1595
1596static void
1597set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1598{
1599 vl_api_set_ip_flow_hash_reply_t *rmp;
Neale Ranns227038a2017-04-21 01:07:59 -07001600 int rv;
1601 u32 table_id;
1602 flow_hash_config_t flow_hash_config = 0;
Dave Barachb5e8a772016-12-06 12:04:42 -05001603
Neale Ranns227038a2017-04-21 01:07:59 -07001604 table_id = ntohl (mp->vrf_id);
1605
1606#define _(a,b) if (mp->a) flow_hash_config |= b;
1607 foreach_flow_hash_bit;
1608#undef _
1609
1610 rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config);
Dave Barachb5e8a772016-12-06 12:04:42 -05001611
1612 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1613}
1614
1615static void
1616set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp)
1617{
1618 vl_api_set_ip_flow_hash_reply_t *rmp;
1619 int rv;
1620 u32 table_id;
1621 flow_hash_config_t flow_hash_config = 0;
1622
1623 table_id = ntohl (mp->vrf_id);
1624
1625#define _(a,b) if (mp->a) flow_hash_config |= b;
1626 foreach_flow_hash_bit;
1627#undef _
1628
1629 rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
1630
1631 REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
1632}
1633
1634
1635static void
1636vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t * mp)
1637{
1638 if (mp->is_ipv6 == 0)
1639 set_ip4_flow_hash (mp);
1640 else
1641 set_ip6_flow_hash (mp);
1642}
1643
1644static void
1645 vl_api_sw_interface_ip6nd_ra_config_t_handler
1646 (vl_api_sw_interface_ip6nd_ra_config_t * mp)
1647{
1648 vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
1649 vlib_main_t *vm = vlib_get_main ();
1650 int rv = 0;
1651 u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
1652 default_router;
1653
1654 is_no = mp->is_no == 1;
1655 suppress = mp->suppress == 1;
1656 managed = mp->managed == 1;
1657 other = mp->other == 1;
1658 ll_option = mp->ll_option == 1;
1659 send_unicast = mp->send_unicast == 1;
1660 cease = mp->cease == 1;
1661 default_router = mp->default_router == 1;
1662
1663 VALIDATE_SW_IF_INDEX (mp);
1664
1665 rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
1666 suppress, managed, other,
1667 ll_option, send_unicast, cease,
1668 default_router, ntohl (mp->lifetime),
1669 ntohl (mp->initial_count),
1670 ntohl (mp->initial_interval),
1671 ntohl (mp->max_interval),
1672 ntohl (mp->min_interval), is_no);
1673
1674 BAD_SW_IF_INDEX_LABEL;
1675
1676 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
1677}
1678
1679static void
1680 vl_api_sw_interface_ip6nd_ra_prefix_t_handler
1681 (vl_api_sw_interface_ip6nd_ra_prefix_t * mp)
1682{
1683 vlib_main_t *vm = vlib_get_main ();
1684 vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
Neale Ranns37029302018-08-10 05:30:06 -07001685 fib_prefix_t pfx;
Dave Barachb5e8a772016-12-06 12:04:42 -05001686 int rv = 0;
1687 u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
1688
1689 VALIDATE_SW_IF_INDEX (mp);
1690
Neale Ranns37029302018-08-10 05:30:06 -07001691 ip_prefix_decode (&mp->prefix, &pfx);
Dave Barachb5e8a772016-12-06 12:04:42 -05001692 is_no = mp->is_no == 1;
1693 use_default = mp->use_default == 1;
1694 no_advertise = mp->no_advertise == 1;
1695 off_link = mp->off_link == 1;
1696 no_autoconfig = mp->no_autoconfig == 1;
1697 no_onlink = mp->no_onlink == 1;
1698
1699 rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
Neale Ranns37029302018-08-10 05:30:06 -07001700 &pfx.fp_addr.ip6,
1701 pfx.fp_len, use_default,
Dave Barachb5e8a772016-12-06 12:04:42 -05001702 ntohl (mp->val_lifetime),
1703 ntohl (mp->pref_lifetime), no_advertise,
1704 off_link, no_autoconfig, no_onlink, is_no);
1705
1706 BAD_SW_IF_INDEX_LABEL;
1707 REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
1708}
1709
1710static void
Florin Coras6c4dae22018-01-09 06:39:23 -08001711send_ip6nd_proxy_details (vl_api_registration_t * reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001712 u32 context,
1713 const ip46_address_t * addr, u32 sw_if_index)
1714{
1715 vl_api_ip6nd_proxy_details_t *mp;
1716
1717 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04001718 clib_memset (mp, 0, sizeof (*mp));
Neale Ranns3f844d02017-02-18 00:03:54 -08001719 mp->_vl_msg_id = ntohs (VL_API_IP6ND_PROXY_DETAILS);
1720 mp->context = context;
1721 mp->sw_if_index = htonl (sw_if_index);
Neale Ranns37029302018-08-10 05:30:06 -07001722
1723 ip6_address_encode (&addr->ip6, mp->ip);
Neale Ranns3f844d02017-02-18 00:03:54 -08001724
Florin Coras6c4dae22018-01-09 06:39:23 -08001725 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns3f844d02017-02-18 00:03:54 -08001726}
1727
Neale Ranns3f844d02017-02-18 00:03:54 -08001728typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
1729{
1730 u32 *indices;
1731} api_ip6nd_proxy_fib_table_walk_ctx_t;
1732
Neale Ranns89541992017-04-06 04:41:02 -07001733static fib_table_walk_rc_t
Neale Ranns3f844d02017-02-18 00:03:54 -08001734api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
1735{
1736 api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
1737
1738 if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY))
1739 {
1740 vec_add1 (ctx->indices, fei);
1741 }
1742
Neale Ranns89541992017-04-06 04:41:02 -07001743 return (FIB_TABLE_WALK_CONTINUE);
Neale Ranns3f844d02017-02-18 00:03:54 -08001744}
1745
1746static void
1747vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
1748{
1749 ip6_main_t *im6 = &ip6_main;
1750 fib_table_t *fib_table;
1751 api_ip6nd_proxy_fib_table_walk_ctx_t ctx = {
1752 .indices = NULL,
1753 };
1754 fib_node_index_t *feip;
Neale Rannsc5d43172018-07-30 08:04:40 -07001755 const fib_prefix_t *pfx;
Florin Coras6c4dae22018-01-09 06:39:23 -08001756 vl_api_registration_t *reg;
Neale Ranns3f844d02017-02-18 00:03:54 -08001757
Florin Coras6c4dae22018-01-09 06:39:23 -08001758 reg = vl_api_client_index_to_registration (mp->client_index);
1759 if (!reg)
1760 return;
Neale Ranns3f844d02017-02-18 00:03:54 -08001761
1762 /* *INDENT-OFF* */
1763 pool_foreach (fib_table, im6->fibs,
1764 ({
1765 fib_table_walk(fib_table->ft_index,
1766 FIB_PROTOCOL_IP6,
1767 api_ip6nd_proxy_fib_table_walk,
1768 &ctx);
1769 }));
1770 /* *INDENT-ON* */
1771
1772 vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort);
1773
1774 vec_foreach (feip, ctx.indices)
1775 {
Neale Rannsc5d43172018-07-30 08:04:40 -07001776 pfx = fib_entry_get_prefix (*feip);
Neale Ranns3f844d02017-02-18 00:03:54 -08001777
Florin Coras6c4dae22018-01-09 06:39:23 -08001778 send_ip6nd_proxy_details (reg,
Neale Ranns3f844d02017-02-18 00:03:54 -08001779 mp->context,
Neale Rannsc5d43172018-07-30 08:04:40 -07001780 &pfx->fp_addr,
Neale Ranns3f844d02017-02-18 00:03:54 -08001781 fib_entry_get_resolving_interface (*feip));
1782 }
1783
1784 vec_free (ctx.indices);
1785}
1786
1787static void
1788vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
1789{
1790 vl_api_ip6nd_proxy_add_del_reply_t *rmp;
Neale Ranns37029302018-08-10 05:30:06 -07001791 ip6_address_t ip6;
Neale Ranns3f844d02017-02-18 00:03:54 -08001792 int rv = 0;
1793
1794 VALIDATE_SW_IF_INDEX (mp);
1795
Neale Ranns37029302018-08-10 05:30:06 -07001796 ip6_address_decode (mp->ip, &ip6);
1797 rv = ip6_neighbor_proxy_add_del (ntohl (mp->sw_if_index), &ip6, mp->is_del);
Neale Ranns3f844d02017-02-18 00:03:54 -08001798
1799 BAD_SW_IF_INDEX_LABEL;
1800 REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
1801}
1802
1803static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01001804 vl_api_ip6nd_send_router_solicitation_t_handler
1805 (vl_api_ip6nd_send_router_solicitation_t * mp)
1806{
1807 vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
1808 icmp6_send_router_solicitation_params_t params;
1809 vlib_main_t *vm = vlib_get_main ();
1810 int rv = 0;
1811
1812 VALIDATE_SW_IF_INDEX (mp);
1813
1814 BAD_SW_IF_INDEX_LABEL;
1815 REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
1816
1817 if (rv != 0)
1818 return;
1819
1820 params.irt = ntohl (mp->irt);
1821 params.mrt = ntohl (mp->mrt);
1822 params.mrc = ntohl (mp->mrc);
1823 params.mrd = ntohl (mp->mrd);
1824
1825 icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
1826 &params);
1827}
1828
1829static void
Dave Barachb5e8a772016-12-06 12:04:42 -05001830 vl_api_sw_interface_ip6_enable_disable_t_handler
1831 (vl_api_sw_interface_ip6_enable_disable_t * mp)
1832{
1833 vlib_main_t *vm = vlib_get_main ();
1834 vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
1835 vnet_main_t *vnm = vnet_get_main ();
1836 int rv = 0;
1837 clib_error_t *error;
1838
1839 vnm->api_errno = 0;
1840
1841 VALIDATE_SW_IF_INDEX (mp);
1842
1843 error =
1844 (mp->enable == 1) ? enable_ip6_interface (vm,
1845 ntohl (mp->sw_if_index)) :
1846 disable_ip6_interface (vm, ntohl (mp->sw_if_index));
1847
1848 if (error)
1849 {
1850 clib_error_report (error);
1851 rv = VNET_API_ERROR_UNSPECIFIED;
1852 }
1853 else
1854 {
1855 rv = vnm->api_errno;
1856 }
1857
1858 BAD_SW_IF_INDEX_LABEL;
1859
1860 REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
1861}
1862
Neale Ranns32e1c012016-11-22 17:07:28 +00001863void
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001864vl_mfib_signal_send_one (vl_api_registration_t * reg,
Neale Ranns32e1c012016-11-22 17:07:28 +00001865 u32 context, const mfib_signal_t * mfs)
1866{
1867 vl_api_mfib_signal_details_t *mp;
Neale Ranns9e829a82018-12-17 05:50:32 -08001868 const mfib_prefix_t *prefix;
Neale Ranns32e1c012016-11-22 17:07:28 +00001869 mfib_table_t *mfib;
1870 mfib_itf_t *mfi;
1871
1872 mp = vl_msg_api_alloc (sizeof (*mp));
1873
Dave Barachb7b92992018-10-17 10:38:51 -04001874 clib_memset (mp, 0, sizeof (*mp));
Neale Ranns32e1c012016-11-22 17:07:28 +00001875 mp->_vl_msg_id = ntohs (VL_API_MFIB_SIGNAL_DETAILS);
1876 mp->context = context;
1877
1878 mfi = mfib_itf_get (mfs->mfs_itf);
Neale Ranns9e829a82018-12-17 05:50:32 -08001879 prefix = mfib_entry_get_prefix (mfs->mfs_entry);
Neale Ranns32e1c012016-11-22 17:07:28 +00001880 mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry),
Neale Ranns9e829a82018-12-17 05:50:32 -08001881 prefix->fp_proto);
Neale Ranns32e1c012016-11-22 17:07:28 +00001882 mp->table_id = ntohl (mfib->mft_table_id);
1883 mp->sw_if_index = ntohl (mfi->mfi_sw_if_index);
1884
Neale Ranns9e829a82018-12-17 05:50:32 -08001885 if (FIB_PROTOCOL_IP4 == prefix->fp_proto)
Neale Ranns32e1c012016-11-22 17:07:28 +00001886 {
Neale Ranns9e829a82018-12-17 05:50:32 -08001887 mp->grp_address_len = ntohs (prefix->fp_len);
Neale Ranns32e1c012016-11-22 17:07:28 +00001888
Neale Ranns9e829a82018-12-17 05:50:32 -08001889 memcpy (mp->grp_address, &prefix->fp_grp_addr.ip4, 4);
1890 if (prefix->fp_len > 32)
Neale Ranns32e1c012016-11-22 17:07:28 +00001891 {
Neale Ranns9e829a82018-12-17 05:50:32 -08001892 memcpy (mp->src_address, &prefix->fp_src_addr.ip4, 4);
Neale Ranns32e1c012016-11-22 17:07:28 +00001893 }
1894 }
1895 else
1896 {
Neale Ranns9e829a82018-12-17 05:50:32 -08001897 mp->grp_address_len = ntohs (prefix->fp_len);
Neale Ranns32e1c012016-11-22 17:07:28 +00001898
1899 ASSERT (0);
1900 }
1901
1902 if (0 != mfs->mfs_buffer_len)
1903 {
1904 mp->ip_packet_len = ntohs (mfs->mfs_buffer_len);
1905
1906 memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len);
1907 }
1908 else
1909 {
1910 mp->ip_packet_len = 0;
1911 }
1912
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001913 vl_api_send_msg (reg, (u8 *) mp);
Neale Ranns32e1c012016-11-22 17:07:28 +00001914}
1915
1916static void
1917vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
1918{
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001919 vl_api_registration_t *reg;
Neale Ranns32e1c012016-11-22 17:07:28 +00001920
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001921 reg = vl_api_client_index_to_registration (mp->client_index);
1922 if (!reg)
1923 return;
Neale Ranns32e1c012016-11-22 17:07:28 +00001924
Florin Corasaf0ff5a2018-01-10 08:17:03 -08001925 while (vl_api_can_send_msg (reg) && mfib_signal_send_one (reg, mp->context))
Neale Ranns32e1c012016-11-22 17:07:28 +00001926 ;
1927}
Dave Barachb5e8a772016-12-06 12:04:42 -05001928
Florin Coras595992c2017-11-06 17:17:08 -08001929static void
1930 vl_api_ip_container_proxy_add_del_t_handler
1931 (vl_api_ip_container_proxy_add_del_t * mp)
1932{
1933 vl_api_ip_container_proxy_add_del_reply_t *rmp;
1934 vnet_ip_container_proxy_args_t args;
1935 int rv = 0;
1936 clib_error_t *error;
1937
Dave Barachb7b92992018-10-17 10:38:51 -04001938 clib_memset (&args, 0, sizeof (args));
Neale Ranns37029302018-08-10 05:30:06 -07001939
1940 ip_prefix_decode (&mp->pfx, &args.prefix);
1941
Florin Coras595992c2017-11-06 17:17:08 -08001942 args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
1943 args.is_add = mp->is_add;
1944 if ((error = vnet_ip_container_proxy_add_del (&args)))
1945 {
1946 rv = clib_error_get_code (error);
1947 clib_error_report (error);
1948 }
1949
1950 REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY);
1951}
1952
Matus Fabian75b9f452018-10-02 23:27:21 -07001953typedef struct ip_container_proxy_walk_ctx_t_
1954{
1955 vl_api_registration_t *reg;
1956 u32 context;
1957} ip_container_proxy_walk_ctx_t;
1958
1959static int
1960ip_container_proxy_send_details (const fib_prefix_t * pfx, u32 sw_if_index,
1961 void *args)
1962{
1963 vl_api_ip_container_proxy_details_t *mp;
1964 ip_container_proxy_walk_ctx_t *ctx = args;
1965
1966 mp = vl_msg_api_alloc (sizeof (*mp));
1967 if (!mp)
1968 return 1;
1969
Dave Barachb7b92992018-10-17 10:38:51 -04001970 clib_memset (mp, 0, sizeof (*mp));
Matus Fabian75b9f452018-10-02 23:27:21 -07001971 mp->_vl_msg_id = ntohs (VL_API_IP_CONTAINER_PROXY_DETAILS);
1972 mp->context = ctx->context;
1973
1974 mp->sw_if_index = ntohl (sw_if_index);
1975 ip_prefix_encode (pfx, &mp->prefix);
1976
1977 vl_api_send_msg (ctx->reg, (u8 *) mp);
1978
1979 return 1;
1980}
1981
1982static void
1983vl_api_ip_container_proxy_dump_t_handler (vl_api_ip_container_proxy_dump_t *
1984 mp)
1985{
1986 vl_api_registration_t *reg;
1987
1988 reg = vl_api_client_index_to_registration (mp->client_index);
1989 if (!reg)
1990 return;
1991
1992 ip_container_proxy_walk_ctx_t ctx = {
1993 .context = mp->context,
1994 .reg = reg,
1995 };
1996
1997 ip_container_proxy_walk (ip_container_proxy_send_details, &ctx);
1998}
1999
Neale Rannsb8d44812017-11-10 06:53:54 -08002000static void
2001vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
2002{
2003 int rv = 0;
2004 vl_api_ioam_enable_reply_t *rmp;
2005 clib_error_t *error;
2006
2007 /* Ignoring the profile id as currently a single profile
2008 * is supported */
2009 error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
2010 mp->seqno, mp->analyse);
2011 if (error)
2012 {
2013 clib_error_report (error);
2014 rv = clib_error_get_code (error);
2015 }
2016
2017 REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
2018}
2019
2020static void
2021vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
2022{
2023 int rv = 0;
2024 vl_api_ioam_disable_reply_t *rmp;
2025 clib_error_t *error;
2026
2027 error = clear_ioam_rewrite_fn ();
2028 if (error)
2029 {
2030 clib_error_report (error);
2031 rv = clib_error_get_code (error);
2032 }
2033
2034 REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
2035}
2036
2037static void
2038 vl_api_ip_source_and_port_range_check_add_del_t_handler
2039 (vl_api_ip_source_and_port_range_check_add_del_t * mp)
2040{
2041 vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
2042 int rv = 0;
2043
Neale Rannsb8d44812017-11-10 06:53:54 -08002044 u8 is_add = mp->is_add;
Neale Ranns37029302018-08-10 05:30:06 -07002045 fib_prefix_t pfx;
Neale Rannsb8d44812017-11-10 06:53:54 -08002046 u16 *low_ports = 0;
2047 u16 *high_ports = 0;
2048 u32 vrf_id;
2049 u16 tmp_low, tmp_high;
2050 u8 num_ranges;
2051 int i;
2052
Neale Ranns37029302018-08-10 05:30:06 -07002053 ip_prefix_decode (&mp->prefix, &pfx);
2054
Neale Rannsb8d44812017-11-10 06:53:54 -08002055 // Validate port range
2056 num_ranges = mp->number_of_ranges;
2057 if (num_ranges > 32)
2058 { // This is size of array in VPE.API
2059 rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
2060 goto reply;
2061 }
2062
2063 vec_reset_length (low_ports);
2064 vec_reset_length (high_ports);
2065
2066 for (i = 0; i < num_ranges; i++)
2067 {
2068 tmp_low = mp->low_ports[i];
2069 tmp_high = mp->high_ports[i];
2070 // If tmp_low <= tmp_high then only need to check tmp_low = 0
2071 // If tmp_low <= tmp_high then only need to check tmp_high > 65535
2072 if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
2073 {
2074 rv = VNET_API_ERROR_INVALID_VALUE;
2075 goto reply;
2076 }
2077 vec_add1 (low_ports, tmp_low);
2078 vec_add1 (high_ports, tmp_high + 1);
2079 }
2080
Neale Rannsb8d44812017-11-10 06:53:54 -08002081 vrf_id = ntohl (mp->vrf_id);
2082
2083 if (vrf_id < 1)
2084 {
2085 rv = VNET_API_ERROR_INVALID_VALUE;
2086 goto reply;
2087 }
2088
2089
Neale Ranns37029302018-08-10 05:30:06 -07002090 if (FIB_PROTOCOL_IP6 == pfx.fp_proto)
Neale Rannsb8d44812017-11-10 06:53:54 -08002091 {
Neale Ranns37029302018-08-10 05:30:06 -07002092 rv = ip6_source_and_port_range_check_add_del (&pfx.fp_addr.ip6,
2093 pfx.fp_len,
Neale Rannsb8d44812017-11-10 06:53:54 -08002094 vrf_id,
2095 low_ports,
2096 high_ports, is_add);
2097 }
2098 else
2099 {
Neale Ranns37029302018-08-10 05:30:06 -07002100 rv = ip4_source_and_port_range_check_add_del (&pfx.fp_addr.ip4,
2101 pfx.fp_len,
Neale Rannsb8d44812017-11-10 06:53:54 -08002102 vrf_id,
2103 low_ports,
2104 high_ports, is_add);
2105 }
2106
2107reply:
2108 vec_free (low_ports);
2109 vec_free (high_ports);
2110 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
2111}
2112
2113static void
2114 vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
2115 (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
2116{
2117 vlib_main_t *vm = vlib_get_main ();
2118 vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
2119 ip4_main_t *im = &ip4_main;
2120 int rv;
2121 u32 sw_if_index;
2122 u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2123 u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
2124 uword *p = 0;
2125 int i;
2126
2127 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
2128 ntohl (mp->tcp_out_vrf_id);
2129 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
2130 ntohl (mp->udp_out_vrf_id);
2131 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
2132 ntohl (mp->tcp_in_vrf_id);
2133 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
2134 ntohl (mp->udp_in_vrf_id);
2135
2136
2137 for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
2138 {
2139 if (vrf_id[i] != 0 && vrf_id[i] != ~0)
2140 {
2141 p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
2142
2143 if (p == 0)
2144 {
2145 rv = VNET_API_ERROR_INVALID_VALUE;
2146 goto reply;
2147 }
2148
2149 fib_index[i] = p[0];
2150 }
2151 else
2152 fib_index[i] = ~0;
2153 }
2154 sw_if_index = ntohl (mp->sw_if_index);
2155
2156 VALIDATE_SW_IF_INDEX (mp);
2157
2158 rv =
2159 set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
2160 mp->is_add);
2161
2162 BAD_SW_IF_INDEX_LABEL;
2163reply:
2164
2165 REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
2166}
2167
Chore3460b012018-11-28 10:53:11 +03302168typedef union
2169{
2170 u32 fib_index;
2171} ip4_source_check_config_t;
2172
2173static void
2174 vl_api_ip_source_check_interface_add_del_t_handler
2175 (vl_api_ip_source_check_interface_add_del_t * mp)
2176{
2177 vl_api_ip_source_check_interface_add_del_reply_t *rmp;
2178 int rv;
2179 u32 sw_if_index = ntohl (mp->sw_if_index);
2180 u8 is_add = mp->is_add;
2181 char *feature_name =
2182 mp->loose ? "ip4-source-check-via-any" : "ip4-source-check-via-rx";
2183
2184 ip4_source_check_config_t config;
2185
2186 VALIDATE_SW_IF_INDEX (mp);
2187
2188 config.fib_index =
2189 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index);
2190 rv =
2191 vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
2192 is_add, &config, sizeof (config));
2193 BAD_SW_IF_INDEX_LABEL;
2194
2195 REPLY_MACRO (VL_API_IP_SOURCE_CHECK_INTERFACE_ADD_DEL_REPLY);
2196}
2197
Neale Rannsb8d44812017-11-10 06:53:54 -08002198#define IP4_ARP_EVENT 3
2199#define IP6_ND_EVENT 4
2200
Neale Rannsb8d44812017-11-10 06:53:54 -08002201static vlib_node_registration_t ip_resolver_process_node;
2202
Neale Ranns37029302018-08-10 05:30:06 -07002203static int
2204arp_change_delete_callback (u32 pool_index,
2205 const mac_address_t * mac,
2206 u32 sw_if_index, const ip4_address_t * address)
2207{
2208 vpe_api_main_t *am = &vpe_api_main;
2209
2210 if (pool_is_free_index (am->arp_events, pool_index))
2211 return 1;
2212
2213 pool_put_index (am->arp_events, pool_index);
2214 return 0;
2215}
2216
Neale Rannsb8d44812017-11-10 06:53:54 -08002217static void
2218handle_ip4_arp_event (u32 pool_index)
2219{
2220 vpe_api_main_t *vam = &vpe_api_main;
2221 vnet_main_t *vnm = vam->vnet_main;
2222 vlib_main_t *vm = vam->vlib_main;
2223 vl_api_ip4_arp_event_t *event;
2224 vl_api_ip4_arp_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002225 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002226
2227 /* Client can cancel, die, etc. */
2228 if (pool_is_free_index (vam->arp_events, pool_index))
2229 return;
2230
2231 event = pool_elt_at_index (vam->arp_events, pool_index);
2232
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002233 reg = vl_api_client_index_to_registration (event->client_index);
2234 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002235 {
2236 (void) vnet_add_del_ip4_arp_change_event
2237 (vnm, arp_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002238 event->pid, event->ip,
Neale Rannsb8d44812017-11-10 06:53:54 -08002239 ip_resolver_process_node.index, IP4_ARP_EVENT,
2240 ~0 /* pool index, notused */ , 0 /* is_add */ );
2241 return;
2242 }
2243
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002244 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002245 {
2246 mp = vl_msg_api_alloc (sizeof (*mp));
2247 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002248 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002249 }
2250 else
2251 {
2252 static f64 last_time;
2253 /*
2254 * Throttle syslog msgs.
2255 * It's pretty tempting to just revoke the registration...
2256 */
2257 if (vlib_time_now (vm) > last_time + 10.0)
2258 {
2259 clib_warning ("arp event for %U to pid %d: queue stuffed!",
Neale Ranns37029302018-08-10 05:30:06 -07002260 format_ip4_address, event->ip, event->pid);
Neale Rannsb8d44812017-11-10 06:53:54 -08002261 last_time = vlib_time_now (vm);
2262 }
2263 }
2264}
2265
Neale Ranns37029302018-08-10 05:30:06 -07002266static int
2267nd_change_delete_callback (u32 pool_index,
2268 const mac_address_t * mac,
2269 u32 sw_if_index, const ip6_address_t * addr)
2270{
2271 vpe_api_main_t *am = &vpe_api_main;
2272
2273 if (pool_is_free_index (am->nd_events, pool_index))
2274 return 1;
2275
2276 pool_put_index (am->nd_events, pool_index);
2277 return 0;
2278}
2279
Neale Rannsf12dad62018-06-04 18:41:24 -07002280static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002281handle_ip6_nd_event (u32 pool_index)
2282{
2283 vpe_api_main_t *vam = &vpe_api_main;
2284 vnet_main_t *vnm = vam->vnet_main;
2285 vlib_main_t *vm = vam->vlib_main;
2286 vl_api_ip6_nd_event_t *event;
2287 vl_api_ip6_nd_event_t *mp;
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002288 vl_api_registration_t *reg;
Neale Rannsb8d44812017-11-10 06:53:54 -08002289
2290 /* Client can cancel, die, etc. */
2291 if (pool_is_free_index (vam->nd_events, pool_index))
2292 return;
2293
2294 event = pool_elt_at_index (vam->nd_events, pool_index);
2295
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002296 reg = vl_api_client_index_to_registration (event->client_index);
2297 if (!reg)
Neale Rannsb8d44812017-11-10 06:53:54 -08002298 {
2299 (void) vnet_add_del_ip6_nd_change_event
2300 (vnm, nd_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002301 event->pid, event->ip,
Neale Rannsb8d44812017-11-10 06:53:54 -08002302 ip_resolver_process_node.index, IP6_ND_EVENT,
2303 ~0 /* pool index, notused */ , 0 /* is_add */ );
2304 return;
2305 }
2306
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002307 if (vl_api_can_send_msg (reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002308 {
2309 mp = vl_msg_api_alloc (sizeof (*mp));
2310 clib_memcpy (mp, event, sizeof (*mp));
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002311 vl_api_send_msg (reg, (u8 *) mp);
Neale Rannsb8d44812017-11-10 06:53:54 -08002312 }
2313 else
2314 {
2315 static f64 last_time;
2316 /*
2317 * Throttle syslog msgs.
2318 * It's pretty tempting to just revoke the registration...
2319 */
2320 if (vlib_time_now (vm) > last_time + 10.0)
2321 {
2322 clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
Neale Ranns37029302018-08-10 05:30:06 -07002323 format_ip6_address, event->ip, event->pid);
Neale Rannsb8d44812017-11-10 06:53:54 -08002324 last_time = vlib_time_now (vm);
2325 }
2326 }
2327}
2328
2329static uword
2330resolver_process (vlib_main_t * vm,
2331 vlib_node_runtime_t * rt, vlib_frame_t * f)
2332{
2333 volatile f64 timeout = 100.0;
2334 volatile uword *event_data = 0;
2335
2336 while (1)
2337 {
2338 vlib_process_wait_for_event_or_clock (vm, timeout);
2339
2340 uword event_type =
2341 vlib_process_get_events (vm, (uword **) & event_data);
2342
2343 int i;
2344 switch (event_type)
2345 {
2346 case IP4_ARP_EVENT:
2347 for (i = 0; i < vec_len (event_data); i++)
2348 handle_ip4_arp_event (event_data[i]);
2349 break;
2350
2351 case IP6_ND_EVENT:
2352 for (i = 0; i < vec_len (event_data); i++)
2353 handle_ip6_nd_event (event_data[i]);
2354 break;
2355
2356 case ~0: /* timeout */
2357 break;
2358 }
2359
2360 vec_reset_length (event_data);
2361 }
2362 return 0; /* or not */
2363}
2364
2365/* *INDENT-OFF* */
2366VLIB_REGISTER_NODE (ip_resolver_process_node,static) = {
2367 .function = resolver_process,
2368 .type = VLIB_NODE_TYPE_PROCESS,
2369 .name = "ip-route-resolver-process",
2370};
2371/* *INDENT-ON* */
2372
2373static int
Neale Ranns37029302018-08-10 05:30:06 -07002374nd_change_data_callback (u32 pool_index, const mac_address_t * new_mac,
2375 u32 sw_if_index, const ip6_address_t * address)
Neale Rannsb8d44812017-11-10 06:53:54 -08002376{
2377 vpe_api_main_t *am = &vpe_api_main;
2378 vl_api_ip6_nd_event_t *event;
2379
2380 if (pool_is_free_index (am->nd_events, pool_index))
2381 return 1;
2382
2383 event = pool_elt_at_index (am->nd_events, pool_index);
Neale Ranns37029302018-08-10 05:30:06 -07002384 if (ethernet_mac_address_equal (event->mac, new_mac->bytes) &&
Neale Rannsb8d44812017-11-10 06:53:54 -08002385 sw_if_index == ntohl (event->sw_if_index))
2386 {
2387 return 1;
2388 }
2389
Neale Ranns37029302018-08-10 05:30:06 -07002390 mac_address_encode (new_mac, event->mac);
Neale Rannsb8d44812017-11-10 06:53:54 -08002391 event->sw_if_index = htonl (sw_if_index);
2392 return 0;
2393}
2394
Neale Rannsb8d44812017-11-10 06:53:54 -08002395static vlib_node_registration_t wc_arp_process_node;
2396
2397enum
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002398{ WC_ARP_REPORT, WC_ND_REPORT, RA_REPORT, REPORT_MAX };
Neale Rannsb8d44812017-11-10 06:53:54 -08002399
2400static uword
2401wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
2402{
Jim Thompsonf324dec2019-04-08 03:22:21 -05002403 /* These cross the longjmp boundary (vlib_process_wait_for_event)
Neale Rannsb8d44812017-11-10 06:53:54 -08002404 * and need to be volatile - to prevent them from being optimized into
2405 * a register - which could change during suspension */
2406
2407 volatile wc_arp_report_t arp_prev = { 0 };
2408 volatile wc_nd_report_t nd_prev = { 0 };
2409 volatile f64 last_arp = vlib_time_now (vm);
2410 volatile f64 last_nd = vlib_time_now (vm);
2411
2412 while (1)
2413 {
2414 vlib_process_wait_for_event (vm);
2415 uword event_type = WC_ARP_REPORT;
2416 void *event_data = vlib_process_get_event_data (vm, &event_type);
2417
2418 f64 now = vlib_time_now (vm);
2419 int i;
2420 if (event_type == WC_ARP_REPORT)
2421 {
2422 wc_arp_report_t *arp_events = event_data;
2423 for (i = 0; i < vec_len (arp_events); i++)
2424 {
Neale Ranns37029302018-08-10 05:30:06 -07002425 /* discard dup event - cast away volatile */
2426 if (arp_prev.ip.as_u32 == arp_events[i].ip.as_u32 &&
2427 mac_address_equal ((const mac_address_t *) &arp_prev.mac,
2428 &arp_events[i].mac) &&
Neale Rannsb8d44812017-11-10 06:53:54 -08002429 arp_prev.sw_if_index == arp_events[i].sw_if_index &&
2430 (now - last_arp) < 10.0)
2431 {
2432 continue;
2433 }
2434 arp_prev = arp_events[i];
2435 last_arp = now;
2436 vpe_client_registration_t *reg;
2437 /* *INDENT-OFF* */
2438 pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations,
2439 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002440 vl_api_registration_t *vl_reg;
2441 vl_reg = vl_api_client_index_to_registration (reg->client_index);
Chris Luke30684ac2018-03-29 12:56:58 -07002442 ASSERT (vl_reg != NULL);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002443 if (reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002444 {
2445 vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event);
Dave Barachb7b92992018-10-17 10:38:51 -04002446 clib_memset (event, 0, sizeof *event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002447 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2448 event->client_index = reg->client_index;
2449 event->pid = reg->client_pid;
2450 event->mac_ip = 1;
Neale Ranns37029302018-08-10 05:30:06 -07002451 ip4_address_encode(&arp_events[i].ip, event->ip);
Neale Rannsb8d44812017-11-10 06:53:54 -08002452 event->sw_if_index = htonl(arp_events[i].sw_if_index);
Neale Ranns37029302018-08-10 05:30:06 -07002453 mac_address_encode(&arp_events[i].mac, event->mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002454 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002455 }
2456 }));
2457 /* *INDENT-ON* */
2458 }
2459 }
2460 else if (event_type == WC_ND_REPORT)
2461 {
2462 wc_nd_report_t *nd_events = event_data;
2463 for (i = 0; i < vec_len (nd_events); i++)
2464 {
Neale Ranns37029302018-08-10 05:30:06 -07002465 /* discard dup event - cast away volatile */
2466 if (ip6_address_is_equal ((const ip6_address_t *) &nd_prev.ip6,
2467 &nd_events[i].ip6)
2468 && mac_address_equal ((const mac_address_t *) &nd_prev.mac,
2469 &nd_events[i].mac)
Neale Rannsb8d44812017-11-10 06:53:54 -08002470 && nd_prev.sw_if_index == nd_events[i].sw_if_index
2471 && (now - last_nd) < 10.0)
2472 {
2473 continue;
2474 }
2475 nd_prev = nd_events[i];
2476 last_nd = now;
2477 vpe_client_registration_t *reg;
2478 /* *INDENT-OFF* */
2479 pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations,
2480 ({
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002481 vl_api_registration_t *vl_reg;
2482 vl_reg = vl_api_client_index_to_registration (reg->client_index);
2483 if (vl_reg && vl_api_can_send_msg (vl_reg))
Neale Rannsb8d44812017-11-10 06:53:54 -08002484 {
2485 vl_api_ip6_nd_event_t * event = vl_msg_api_alloc (sizeof *event);
Dave Barachb7b92992018-10-17 10:38:51 -04002486 clib_memset (event, 0, sizeof *event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002487 event->_vl_msg_id = htons (VL_API_IP6_ND_EVENT);
2488 event->client_index = reg->client_index;
2489 event->pid = reg->client_pid;
2490 event->mac_ip = 1;
Neale Ranns37029302018-08-10 05:30:06 -07002491 ip6_address_encode(&nd_events[i].ip6, event->ip);
Neale Rannsb8d44812017-11-10 06:53:54 -08002492 event->sw_if_index = htonl(nd_events[i].sw_if_index);
Neale Ranns37029302018-08-10 05:30:06 -07002493 mac_address_encode(&nd_events[i].mac, event->mac);
Florin Corasaf0ff5a2018-01-10 08:17:03 -08002494 vl_api_send_msg (vl_reg, (u8 *) event);
Neale Rannsb8d44812017-11-10 06:53:54 -08002495 }
2496 }));
2497 /* *INDENT-ON* */
2498 }
2499 }
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002500 else if (event_type == RA_REPORT)
2501 {
2502 ra_report_t *ra_events = event_data;
2503 for (i = 0; i < vec_len (ra_events); i++)
2504 {
Juraj Sloboda52574522018-05-03 10:03:50 +02002505 ip6_neighbor_public_main_t *npm = &ip6_neighbor_public_main;
2506 call_ip6_neighbor_callbacks (&ra_events[i],
2507 npm->ra_report_functions);
2508
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002509 vpe_client_registration_t *reg;
2510 /* *INDENT-OFF* */
2511 pool_foreach(reg, vpe_api_main.ip6_ra_events_registrations,
2512 ({
2513 vl_api_registration_t *vl_reg;
2514 vl_reg =
2515 vl_api_client_index_to_registration (reg->client_index);
2516 if (vl_reg && vl_api_can_send_msg (vl_reg))
2517 {
2518 u32 event_size =
2519 sizeof (vl_api_ip6_ra_event_t) +
2520 vec_len (ra_events[i].prefixes) *
2521 sizeof (vl_api_ip6_ra_prefix_info_t);
2522 vl_api_ip6_ra_event_t *event =
2523 vl_msg_api_alloc (event_size);
Dave Barachb7b92992018-10-17 10:38:51 -04002524 clib_memset (event, 0, event_size);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002525 event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT);
2526 event->client_index = reg->client_index;
2527 event->pid = reg->client_pid;
2528
2529 event->sw_if_index = clib_host_to_net_u32 (ra_events[i].sw_if_index);
2530
Neale Ranns37029302018-08-10 05:30:06 -07002531 ip6_address_encode (&ra_events[i].router_address,
2532 event->router_addr);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002533
2534 event->current_hop_limit = ra_events[i].current_hop_limit;
2535 event->flags = ra_events[i].flags;
2536 event->router_lifetime_in_sec =
2537 clib_host_to_net_u16 (ra_events
2538 [i].router_lifetime_in_sec);
2539 event->neighbor_reachable_time_in_msec =
2540 clib_host_to_net_u32 (ra_events
2541 [i].neighbor_reachable_time_in_msec);
2542 event->time_in_msec_between_retransmitted_neighbor_solicitations
2543 =
2544 clib_host_to_net_u32 (ra_events
2545 [i].time_in_msec_between_retransmitted_neighbor_solicitations);
2546
2547 event->n_prefixes =
2548 clib_host_to_net_u32 (vec_len (ra_events[i].prefixes));
2549 vl_api_ip6_ra_prefix_info_t *prefix =
2550 (typeof (prefix)) event->prefixes;
2551 u32 j;
2552 for (j = 0; j < vec_len (ra_events[i].prefixes); j++)
2553 {
2554 ra_report_prefix_info_t *info =
2555 &ra_events[i].prefixes[j];
Neale Ranns37029302018-08-10 05:30:06 -07002556 ip_prefix_encode(&info->prefix, &prefix->prefix);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002557 prefix->flags = info->flags;
2558 prefix->valid_time =
2559 clib_host_to_net_u32 (info->valid_time);
2560 prefix->preferred_time =
2561 clib_host_to_net_u32 (info->preferred_time);
2562 prefix++;
2563 }
2564
2565 vl_api_send_msg (vl_reg, (u8 *) event);
2566 }
2567 }));
Juraj Slobodad7f58cc2018-07-27 11:23:14 +02002568 /* *INDENT-ON* */
2569 vec_free (ra_events[i].prefixes);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002570 }
2571 }
Neale Rannsb8d44812017-11-10 06:53:54 -08002572 vlib_process_put_event_data (vm, event_data);
2573 }
2574
2575 return 0;
2576}
2577
2578/* *INDENT-OFF* */
2579VLIB_REGISTER_NODE (wc_arp_process_node,static) = {
2580 .function = wc_arp_process,
2581 .type = VLIB_NODE_TYPE_PROCESS,
2582 .name = "wildcard-ip4-arp-publisher-process",
2583};
2584/* *INDENT-ON* */
2585
2586static int
Neale Ranns37029302018-08-10 05:30:06 -07002587arp_change_data_callback (u32 pool_index,
2588 const mac_address_t * mac,
2589 u32 sw_if_index, const ip4_address_t * address)
Neale Rannsb8d44812017-11-10 06:53:54 -08002590{
2591 vpe_api_main_t *am = &vpe_api_main;
2592 vl_api_ip4_arp_event_t *event;
2593
2594 if (pool_is_free_index (am->arp_events, pool_index))
2595 return 1;
2596
2597 event = pool_elt_at_index (am->arp_events, pool_index);
Neale Ranns37029302018-08-10 05:30:06 -07002598 if (ethernet_mac_address_equal (event->mac, mac->bytes) &&
Neale Rannsb8d44812017-11-10 06:53:54 -08002599 sw_if_index == ntohl (event->sw_if_index))
2600 {
2601 return 1;
2602 }
2603
Neale Ranns37029302018-08-10 05:30:06 -07002604 mac_address_encode (mac, event->mac);
Neale Rannsb8d44812017-11-10 06:53:54 -08002605 event->sw_if_index = htonl (sw_if_index);
2606 return 0;
2607}
2608
2609static void
2610vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
2611{
2612 vpe_api_main_t *am = &vpe_api_main;
2613 vnet_main_t *vnm = vnet_get_main ();
2614 vl_api_want_ip4_arp_events_reply_t *rmp;
Neale Ranns37029302018-08-10 05:30:06 -07002615 ip4_address_t ip;
Neale Rannsb8d44812017-11-10 06:53:54 -08002616 int rv = 0;
2617
Neale Ranns37029302018-08-10 05:30:06 -07002618 ip4_address_decode (mp->ip, &ip);
2619
2620 if (ip.as_u32 == 0)
Neale Rannsb8d44812017-11-10 06:53:54 -08002621 {
2622 uword *p =
2623 hash_get (am->wc_ip4_arp_events_registration_hash, mp->client_index);
2624 vpe_client_registration_t *rp;
2625 if (p)
2626 {
2627 if (mp->enable_disable)
2628 {
2629 clib_warning ("pid %d: already enabled...", mp->pid);
2630 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2631 goto reply;
2632 }
2633 else
2634 {
2635 rp =
2636 pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2637 pool_put (am->wc_ip4_arp_events_registrations, rp);
2638 hash_unset (am->wc_ip4_arp_events_registration_hash,
2639 mp->client_index);
2640 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002641 wc_arp_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002642 goto reply;
2643 }
2644 }
2645 if (mp->enable_disable == 0)
2646 {
2647 clib_warning ("pid %d: already disabled...", mp->pid);
2648 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2649 goto reply;
2650 }
2651 pool_get (am->wc_ip4_arp_events_registrations, rp);
2652 rp->client_index = mp->client_index;
2653 rp->client_pid = mp->pid;
2654 hash_set (am->wc_ip4_arp_events_registration_hash, rp->client_index,
2655 rp - am->wc_ip4_arp_events_registrations);
2656 wc_arp_set_publisher_node (wc_arp_process_node.index, WC_ARP_REPORT);
2657 goto reply;
2658 }
2659
2660 if (mp->enable_disable)
2661 {
2662 vl_api_ip4_arp_event_t *event;
2663 pool_get (am->arp_events, event);
2664 rv = vnet_add_del_ip4_arp_change_event
2665 (vnm, arp_change_data_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002666 mp->pid, mp->ip /* addr, in net byte order */ ,
Neale Rannsb8d44812017-11-10 06:53:54 -08002667 ip_resolver_process_node.index,
2668 IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
2669
2670 if (rv)
2671 {
2672 pool_put (am->arp_events, event);
2673 goto reply;
2674 }
Dave Barachb7b92992018-10-17 10:38:51 -04002675 clib_memset (event, 0, sizeof (*event));
Neale Rannsb8d44812017-11-10 06:53:54 -08002676
2677 /* Python API expects events to have no context */
2678 event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT);
2679 event->client_index = mp->client_index;
Neale Ranns37029302018-08-10 05:30:06 -07002680 memcpy (event->ip, mp->ip, 4);
Neale Rannsb8d44812017-11-10 06:53:54 -08002681 event->pid = mp->pid;
Neale Ranns37029302018-08-10 05:30:06 -07002682 if (ip.as_u32 == 0)
Neale Rannsb8d44812017-11-10 06:53:54 -08002683 event->mac_ip = 1;
2684 }
2685 else
2686 {
2687 rv = vnet_add_del_ip4_arp_change_event
2688 (vnm, arp_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002689 mp->pid, mp->ip /* addr, in net byte order */ ,
Neale Rannsb8d44812017-11-10 06:53:54 -08002690 ip_resolver_process_node.index,
2691 IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2692 }
2693reply:
2694 REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
2695}
2696
Neale Rannsf12dad62018-06-04 18:41:24 -07002697static clib_error_t *
2698want_ip4_arp_events_reaper (u32 client_index)
2699{
2700 vpe_client_registration_t *rp;
2701 vl_api_ip4_arp_event_t *event;
2702 u32 *to_delete, *event_id;
2703 vpe_api_main_t *am;
2704 vnet_main_t *vnm;
2705 uword *p;
2706
2707 am = &vpe_api_main;
2708 vnm = vnet_get_main ();
2709 to_delete = NULL;
2710
2711 /* clear out all of its pending resolutions */
2712 /* *INDENT-OFF* */
2713 pool_foreach(event, am->arp_events,
2714 ({
2715 if (event->client_index == client_index)
2716 {
2717 vec_add1(to_delete, event - am->arp_events);
2718 }
2719 }));
2720 /* *INDENT-ON* */
2721
2722 vec_foreach (event_id, to_delete)
2723 {
2724 event = pool_elt_at_index (am->arp_events, *event_id);
2725 vnet_add_del_ip4_arp_change_event
2726 (vnm, arp_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002727 event->pid, event->ip,
Neale Rannsf12dad62018-06-04 18:41:24 -07002728 ip_resolver_process_node.index, IP4_ARP_EVENT,
2729 ~0 /* pool index, notused */ , 0 /* is_add */ );
2730 }
2731 vec_free (to_delete);
2732
2733 /* remove from the registration hash */
2734 p = hash_get (am->wc_ip4_arp_events_registration_hash, client_index);
2735
2736 if (p)
2737 {
2738 rp = pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]);
2739 pool_put (am->wc_ip4_arp_events_registrations, rp);
2740 hash_unset (am->wc_ip4_arp_events_registration_hash, client_index);
2741 if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
2742 wc_arp_set_publisher_node (~0, REPORT_MAX);
2743 }
2744 return (NULL);
2745}
2746
2747VL_MSG_API_REAPER_FUNCTION (want_ip4_arp_events_reaper);
2748
Neale Rannsb8d44812017-11-10 06:53:54 -08002749static void
2750vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
2751{
2752 vpe_api_main_t *am = &vpe_api_main;
2753 vnet_main_t *vnm = vnet_get_main ();
2754 vl_api_want_ip6_nd_events_reply_t *rmp;
Neale Ranns37029302018-08-10 05:30:06 -07002755 ip6_address_t ip6;
Neale Rannsb8d44812017-11-10 06:53:54 -08002756 int rv = 0;
2757
Neale Ranns37029302018-08-10 05:30:06 -07002758 ip6_address_decode (mp->ip, &ip6);
2759
2760 if (ip6_address_is_zero (&ip6))
Neale Rannsb8d44812017-11-10 06:53:54 -08002761 {
2762 uword *p =
2763 hash_get (am->wc_ip6_nd_events_registration_hash, mp->client_index);
2764 vpe_client_registration_t *rp;
2765 if (p)
2766 {
2767 if (mp->enable_disable)
2768 {
2769 clib_warning ("pid %d: already enabled...", mp->pid);
2770 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2771 goto reply;
2772 }
2773 else
2774 {
2775 rp =
2776 pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2777 pool_put (am->wc_ip6_nd_events_registrations, rp);
2778 hash_unset (am->wc_ip6_nd_events_registration_hash,
2779 mp->client_index);
2780 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002781 wc_nd_set_publisher_node (~0, REPORT_MAX);
Neale Rannsb8d44812017-11-10 06:53:54 -08002782 goto reply;
2783 }
2784 }
2785 if (mp->enable_disable == 0)
2786 {
2787 clib_warning ("pid %d: already disabled...", mp->pid);
2788 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2789 goto reply;
2790 }
2791 pool_get (am->wc_ip6_nd_events_registrations, rp);
2792 rp->client_index = mp->client_index;
2793 rp->client_pid = mp->pid;
2794 hash_set (am->wc_ip6_nd_events_registration_hash, rp->client_index,
2795 rp - am->wc_ip6_nd_events_registrations);
2796 wc_nd_set_publisher_node (wc_arp_process_node.index, WC_ND_REPORT);
2797 goto reply;
2798 }
2799
2800 if (mp->enable_disable)
2801 {
2802 vl_api_ip6_nd_event_t *event;
2803 pool_get (am->nd_events, event);
2804
2805 rv = vnet_add_del_ip6_nd_change_event
2806 (vnm, nd_change_data_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002807 mp->pid, &ip6,
Neale Rannsb8d44812017-11-10 06:53:54 -08002808 ip_resolver_process_node.index,
2809 IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
2810
2811 if (rv)
2812 {
2813 pool_put (am->nd_events, event);
2814 goto reply;
2815 }
Dave Barachb7b92992018-10-17 10:38:51 -04002816 clib_memset (event, 0, sizeof (*event));
Neale Rannsb8d44812017-11-10 06:53:54 -08002817
2818 event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
2819 event->client_index = mp->client_index;
Neale Ranns37029302018-08-10 05:30:06 -07002820 ip6_address_encode (&ip6, event->ip);
Neale Rannsb8d44812017-11-10 06:53:54 -08002821 event->pid = mp->pid;
2822 }
2823 else
2824 {
2825 rv = vnet_add_del_ip6_nd_change_event
2826 (vnm, nd_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002827 mp->pid, &ip6 /* addr, in net byte order */ ,
Neale Rannsb8d44812017-11-10 06:53:54 -08002828 ip_resolver_process_node.index,
2829 IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2830 }
2831reply:
2832 REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
2833}
2834
Neale Rannsf12dad62018-06-04 18:41:24 -07002835static clib_error_t *
2836want_ip6_nd_events_reaper (u32 client_index)
2837{
2838
2839 vpe_client_registration_t *rp;
2840 vl_api_ip6_nd_event_t *event;
2841 u32 *to_delete, *event_id;
2842 vpe_api_main_t *am;
2843 vnet_main_t *vnm;
2844 uword *p;
2845
2846 am = &vpe_api_main;
2847 vnm = vnet_get_main ();
2848 to_delete = NULL;
2849
2850 /* clear out all of its pending resolutions */
2851 /* *INDENT-OFF* */
2852 pool_foreach(event, am->nd_events,
2853 ({
2854 if (event->client_index == client_index)
2855 {
2856 vec_add1(to_delete, event - am->nd_events);
2857 }
2858 }));
2859 /* *INDENT-ON* */
2860
2861 vec_foreach (event_id, to_delete)
2862 {
2863 event = pool_elt_at_index (am->nd_events, *event_id);
2864 vnet_add_del_ip6_nd_change_event
2865 (vnm, nd_change_delete_callback,
Neale Ranns37029302018-08-10 05:30:06 -07002866 event->pid, event->ip,
Neale Rannsf12dad62018-06-04 18:41:24 -07002867 ip_resolver_process_node.index, IP6_ND_EVENT,
2868 ~0 /* pool index, notused */ , 0 /* is_add */ );
2869 }
2870 vec_free (to_delete);
2871
2872 /* remove from the registration hash */
2873 p = hash_get (am->wc_ip6_nd_events_registration_hash, client_index);
2874
2875 if (p)
2876 {
2877 rp = pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]);
2878 pool_put (am->wc_ip6_nd_events_registrations, rp);
2879 hash_unset (am->wc_ip6_nd_events_registration_hash, client_index);
2880 if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
2881 wc_nd_set_publisher_node (~0, REPORT_MAX);
2882 }
2883 return (NULL);
2884}
2885
2886VL_MSG_API_REAPER_FUNCTION (want_ip6_nd_events_reaper);
2887
Neale Rannsb8d44812017-11-10 06:53:54 -08002888static void
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002889vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
2890{
2891 vpe_api_main_t *am = &vpe_api_main;
2892 vl_api_want_ip6_ra_events_reply_t *rmp;
2893 int rv = 0;
2894
2895 uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
2896 vpe_client_registration_t *rp;
2897 if (p)
2898 {
2899 if (mp->enable_disable)
2900 {
2901 clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
2902 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2903 goto reply;
2904 }
2905 else
2906 {
2907 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2908 pool_put (am->ip6_ra_events_registrations, rp);
2909 hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002910 goto reply;
2911 }
2912 }
2913 if (mp->enable_disable == 0)
2914 {
2915 clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
2916 rv = VNET_API_ERROR_INVALID_REGISTRATION;
2917 goto reply;
2918 }
2919 pool_get (am->ip6_ra_events_registrations, rp);
2920 rp->client_index = mp->client_index;
2921 rp->client_pid = ntohl (mp->pid);
2922 hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
2923 rp - am->ip6_ra_events_registrations);
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002924
2925reply:
2926 REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
2927}
2928
Neale Rannsf12dad62018-06-04 18:41:24 -07002929static clib_error_t *
2930want_ip6_ra_events_reaper (u32 client_index)
2931{
2932 vpe_api_main_t *am = &vpe_api_main;
2933 vpe_client_registration_t *rp;
2934 uword *p;
2935
2936 p = hash_get (am->ip6_ra_events_registration_hash, client_index);
2937
2938 if (p)
2939 {
2940 rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
2941 pool_put (am->ip6_ra_events_registrations, rp);
2942 hash_unset (am->ip6_ra_events_registration_hash, client_index);
2943 }
2944 return (NULL);
2945}
2946
2947VL_MSG_API_REAPER_FUNCTION (want_ip6_ra_events_reaper);
2948
Juraj Sloboda4b9669d2018-01-15 10:39:21 +01002949static void
Neale Rannsb8d44812017-11-10 06:53:54 -08002950vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
2951{
2952 vl_api_proxy_arp_add_del_reply_t *rmp;
Neale Ranns37029302018-08-10 05:30:06 -07002953 ip4_address_t lo, hi;
Neale Rannsb8d44812017-11-10 06:53:54 -08002954 u32 fib_index;
2955 int rv;
Neale Rannsb8d44812017-11-10 06:53:54 -08002956
Neale Ranns37029302018-08-10 05:30:06 -07002957 fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->proxy.table_id));
Neale Rannsb8d44812017-11-10 06:53:54 -08002958
Neale Ranns37029302018-08-10 05:30:06 -07002959 if (~0 == fib_index)
Neale Rannsb8d44812017-11-10 06:53:54 -08002960 {
2961 rv = VNET_API_ERROR_NO_SUCH_FIB;
2962 goto out;
2963 }
2964
Neale Ranns37029302018-08-10 05:30:06 -07002965 ip4_address_decode (mp->proxy.low, &lo);
2966 ip4_address_decode (mp->proxy.hi, &hi);
Neale Rannsb8d44812017-11-10 06:53:54 -08002967
Neale Ranns37029302018-08-10 05:30:06 -07002968 rv = vnet_proxy_arp_add_del (&lo, &hi, fib_index, mp->is_add == 0);
Neale Rannsb8d44812017-11-10 06:53:54 -08002969
2970out:
Neale Rannsb8d44812017-11-10 06:53:54 -08002971 REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
2972}
2973
Neale Ranns0053de62018-05-22 08:40:52 -07002974typedef struct proxy_arp_walk_ctx_t_
2975{
2976 vl_api_registration_t *reg;
2977 u32 context;
2978} proxy_arp_walk_ctx_t;
2979
2980static walk_rc_t
2981send_proxy_arp_details (const ip4_address_t * lo_addr,
2982 const ip4_address_t * hi_addr,
2983 u32 fib_index, void *data)
2984{
2985 vl_api_proxy_arp_details_t *mp;
2986 proxy_arp_walk_ctx_t *ctx;
2987
2988 ctx = data;
2989
2990 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04002991 clib_memset (mp, 0, sizeof (*mp));
Neale Ranns0053de62018-05-22 08:40:52 -07002992 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_DETAILS);
2993 mp->context = ctx->context;
Neale Ranns37029302018-08-10 05:30:06 -07002994 mp->proxy.table_id = htonl (fib_index);
2995
2996 ip4_address_encode (lo_addr, mp->proxy.low);
2997 ip4_address_encode (hi_addr, mp->proxy.hi);
Neale Ranns0053de62018-05-22 08:40:52 -07002998
2999 vl_api_send_msg (ctx->reg, (u8 *) mp);
3000
3001 return (WALK_CONTINUE);
3002}
3003
3004static void
3005vl_api_proxy_arp_dump_t_handler (vl_api_proxy_arp_dump_t * mp)
3006{
3007 vl_api_registration_t *reg;
3008
3009 reg = vl_api_client_index_to_registration (mp->client_index);
3010 if (!reg)
3011 return;
3012
3013 proxy_arp_walk_ctx_t wctx = {
3014 .reg = reg,
3015 .context = mp->context,
3016 };
3017
3018 proxy_arp_walk (send_proxy_arp_details, &wctx);
3019}
3020
3021static walk_rc_t
Neale Ranns57e53bb2019-05-29 13:58:43 +00003022send_proxy_arp_intfc_details (u32 sw_if_index, void *data)
Neale Ranns0053de62018-05-22 08:40:52 -07003023{
3024 vl_api_proxy_arp_intfc_details_t *mp;
3025 proxy_arp_walk_ctx_t *ctx;
3026
Neale Ranns0053de62018-05-22 08:40:52 -07003027 ctx = data;
3028
3029 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -04003030 clib_memset (mp, 0, sizeof (*mp));
Neale Ranns0053de62018-05-22 08:40:52 -07003031 mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_INTFC_DETAILS);
3032 mp->context = ctx->context;
Neale Ranns57e53bb2019-05-29 13:58:43 +00003033 mp->sw_if_index = htonl (sw_if_index);
Neale Ranns0053de62018-05-22 08:40:52 -07003034
3035 vl_api_send_msg (ctx->reg, (u8 *) mp);
3036
3037 return (WALK_CONTINUE);
3038}
3039
3040static void
3041vl_api_proxy_arp_intfc_dump_t_handler (vl_api_proxy_arp_intfc_dump_t * mp)
3042{
3043 vl_api_registration_t *reg;
3044
3045 reg = vl_api_client_index_to_registration (mp->client_index);
3046 if (!reg)
3047 return;
3048
3049 proxy_arp_walk_ctx_t wctx = {
3050 .reg = reg,
3051 .context = mp->context,
3052 };
3053
Neale Ranns57e53bb2019-05-29 13:58:43 +00003054 proxy_arp_intfc_walk (send_proxy_arp_intfc_details, &wctx);
Neale Ranns0053de62018-05-22 08:40:52 -07003055}
3056
Neale Rannsb8d44812017-11-10 06:53:54 -08003057static void
3058 vl_api_proxy_arp_intfc_enable_disable_t_handler
3059 (vl_api_proxy_arp_intfc_enable_disable_t * mp)
3060{
3061 int rv = 0;
3062 vnet_main_t *vnm = vnet_get_main ();
3063 vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
3064
3065 VALIDATE_SW_IF_INDEX (mp);
3066
Neale Ranns57e53bb2019-05-29 13:58:43 +00003067 rv = vnet_proxy_arp_enable_disable (vnm,
3068 ntohl (mp->sw_if_index),
3069 mp->enable_disable);
Neale Rannsb8d44812017-11-10 06:53:54 -08003070
3071 BAD_SW_IF_INDEX_LABEL;
3072
3073 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
3074}
3075
John Loc7b43042018-04-13 16:46:22 -04003076static void
3077vl_api_ip_probe_neighbor_t_handler (vl_api_ip_probe_neighbor_t * mp)
3078{
3079 int rv = 0;
3080 vlib_main_t *vm = vlib_get_main ();
3081 vl_api_ip_probe_neighbor_reply_t *rmp;
3082 clib_error_t *error;
Neale Ranns37029302018-08-10 05:30:06 -07003083 ip46_address_t dst;
3084 ip46_type_t itype;
John Loc7b43042018-04-13 16:46:22 -04003085
3086 VALIDATE_SW_IF_INDEX (mp);
3087
3088 u32 sw_if_index = ntohl (mp->sw_if_index);
Neale Ranns37029302018-08-10 05:30:06 -07003089 itype = ip_address_decode (&mp->dst, &dst);
John Loc7b43042018-04-13 16:46:22 -04003090
Neale Ranns37029302018-08-10 05:30:06 -07003091 if (IP46_TYPE_IP6 == itype)
3092 error = ip6_probe_neighbor (vm, &dst.ip6, sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04003093 else
Neale Ranns37029302018-08-10 05:30:06 -07003094 error = ip4_probe_neighbor (vm, &dst.ip4, sw_if_index, 0);
John Loc7b43042018-04-13 16:46:22 -04003095
3096 if (error)
3097 {
3098 clib_error_report (error);
3099 rv = clib_error_get_code (error);
3100 }
3101
3102 BAD_SW_IF_INDEX_LABEL;
3103
3104 REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
3105}
3106
John Lo7f358b32018-04-28 01:19:24 -04003107static void
3108 vl_api_ip_scan_neighbor_enable_disable_t_handler
3109 (vl_api_ip_scan_neighbor_enable_disable_t * mp)
3110{
3111 int rv = 0;
3112 vl_api_ip_scan_neighbor_enable_disable_reply_t *rmp;
3113 ip_neighbor_scan_arg_t arg;
3114
3115 arg.mode = mp->mode;
3116 arg.scan_interval = mp->scan_interval;
3117 arg.max_proc_time = mp->max_proc_time;
3118 arg.max_update = mp->max_update;
3119 arg.scan_int_delay = mp->scan_int_delay;
3120 arg.stale_threshold = mp->stale_threshold;
3121 ip_neighbor_scan_enable_disable (&arg);
3122
3123 REPLY_MACRO (VL_API_IP_SCAN_NEIGHBOR_ENABLE_DISABLE_REPLY);
3124}
3125
Neale Rannsb8d44812017-11-10 06:53:54 -08003126static int
3127ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3128{
3129 vnet_main_t *vnm = vnet_get_main ();
3130 vnet_interface_main_t *im = &vnm->interface_main;
3131 ip4_main_t *im4 = &ip4_main;
3132 static u32 *sw_if_indices_to_shut;
Neale Rannsb8d44812017-11-10 06:53:54 -08003133 fib_table_t *fib_table;
3134 ip4_fib_t *fib;
3135 u32 sw_if_index;
3136 int i;
3137 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3138 u32 target_fib_id = ntohl (mp->vrf_id);
3139
Neale Rannsb8d44812017-11-10 06:53:54 -08003140 /* *INDENT-OFF* */
3141 pool_foreach (fib_table, im4->fibs,
3142 ({
3143 vnet_sw_interface_t * si;
3144
3145 fib = pool_elt_at_index (im4->v4_fibs, fib_table->ft_index);
3146
3147 if (fib->table_id != target_fib_id)
3148 continue;
3149
3150 /* remove any mpls encap/decap labels */
3151 mpls_fib_reset_labels (fib->table_id);
3152
3153 /* remove any proxy arps in this fib */
3154 vnet_proxy_arp_fib_reset (fib->table_id);
3155
3156 /* Set the flow hash for this fib to the default */
3157 vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3158
3159 vec_reset_length (sw_if_indices_to_shut);
3160
3161 /* Shut down interfaces in this FIB / clean out intfc routes */
3162 pool_foreach (si, im->sw_interfaces,
3163 ({
3164 u32 sw_if_index = si->sw_if_index;
3165
3166 if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
3167 && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
3168 fib->index))
3169 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3170 }));
3171
3172 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3173 sw_if_index = sw_if_indices_to_shut[i];
3174
3175 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3176 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3177 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3178 }
3179
3180 fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
3181
3182 rv = 0;
3183 break;
3184 })); /* pool_foreach (fib) */
3185 /* *INDENT-ON* */
3186
Neale Rannsb8d44812017-11-10 06:53:54 -08003187 return rv;
3188}
3189
3190static int
3191ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3192{
3193 vnet_main_t *vnm = vnet_get_main ();
3194 vnet_interface_main_t *im = &vnm->interface_main;
3195 ip6_main_t *im6 = &ip6_main;
Neale Rannsb8d44812017-11-10 06:53:54 -08003196 static u32 *sw_if_indices_to_shut;
3197 fib_table_t *fib_table;
3198 ip6_fib_t *fib;
3199 u32 sw_if_index;
3200 int i;
3201 int rv = VNET_API_ERROR_NO_SUCH_FIB;
3202 u32 target_fib_id = ntohl (mp->vrf_id);
3203
Neale Rannsb8d44812017-11-10 06:53:54 -08003204 /* *INDENT-OFF* */
3205 pool_foreach (fib_table, im6->fibs,
3206 ({
3207 vnet_sw_interface_t * si;
3208
3209 fib = pool_elt_at_index (im6->v6_fibs, fib_table->ft_index);
3210
3211 if (fib->table_id != target_fib_id)
3212 continue;
3213
3214 vec_reset_length (sw_if_indices_to_shut);
3215
3216 /* Set the flow hash for this fib to the default */
3217 vnet_set_ip6_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
3218
3219 /* Shut down interfaces in this FIB / clean out intfc routes */
3220 pool_foreach (si, im->sw_interfaces,
3221 ({
3222 if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
3223 fib->index)
3224 vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3225 }));
3226
3227 for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3228 sw_if_index = sw_if_indices_to_shut[i];
3229
3230 u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3231 flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3232 vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3233 }
3234
3235 fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
3236
3237 rv = 0;
3238 break;
3239 })); /* pool_foreach (fib) */
3240 /* *INDENT-ON* */
3241
Neale Rannsb8d44812017-11-10 06:53:54 -08003242 return rv;
3243}
3244
3245static void
3246vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3247{
3248 int rv;
3249 vl_api_reset_fib_reply_t *rmp;
3250
3251 if (mp->is_ipv6)
3252 rv = ip6_reset_fib_t_handler (mp);
3253 else
3254 rv = ip4_reset_fib_t_handler (mp);
3255
3256 REPLY_MACRO (VL_API_RESET_FIB_REPLY);
3257}
3258
3259static void
3260vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
3261{
3262 int rv;
3263 vl_api_set_arp_neighbor_limit_reply_t *rmp;
3264 vnet_main_t *vnm = vnet_get_main ();
3265 clib_error_t *error;
3266
3267 vnm->api_errno = 0;
3268
3269 if (mp->is_ipv6)
3270 error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
3271 else
3272 error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
3273
3274 if (error)
3275 {
3276 clib_error_report (error);
3277 rv = VNET_API_ERROR_UNSPECIFIED;
3278 }
3279 else
3280 {
3281 rv = vnm->api_errno;
3282 }
3283
3284 REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3285}
3286
Klement Sekera75e7d132017-09-20 08:26:30 +02003287void
3288vl_api_ip_reassembly_set_t_handler (vl_api_ip_reassembly_set_t * mp)
3289{
3290 vl_api_ip_reassembly_set_reply_t *rmp;
3291 int rv = 0;
3292 if (mp->is_ip6)
3293 {
3294 rv = ip6_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3295 clib_net_to_host_u32 (mp->max_reassemblies),
Klement Sekera3a343d42019-05-16 14:35:46 +02003296 clib_net_to_host_u32 (mp->max_reassembly_length),
Klement Sekera75e7d132017-09-20 08:26:30 +02003297 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3298 }
3299 else
3300 {
3301 rv = ip4_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
3302 clib_net_to_host_u32 (mp->max_reassemblies),
Klement Sekera3a343d42019-05-16 14:35:46 +02003303 clib_net_to_host_u32 (mp->max_reassembly_length),
Klement Sekera75e7d132017-09-20 08:26:30 +02003304 clib_net_to_host_u32 (mp->expire_walk_interval_ms));
3305 }
3306
3307 REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
3308}
3309
3310void
3311vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
3312{
Ole Troan2e1c8962019-04-10 09:44:23 +02003313 vl_api_registration_t *rp;
Klement Sekera75e7d132017-09-20 08:26:30 +02003314
Ole Troan2e1c8962019-04-10 09:44:23 +02003315 rp = vl_api_client_index_to_registration (mp->client_index);
3316 if (rp == 0)
Klement Sekera75e7d132017-09-20 08:26:30 +02003317 return;
3318
3319 vl_api_ip_reassembly_get_reply_t *rmp = vl_msg_api_alloc (sizeof (*rmp));
Dave Barachb7b92992018-10-17 10:38:51 -04003320 clib_memset (rmp, 0, sizeof (*rmp));
Klement Sekera75e7d132017-09-20 08:26:30 +02003321 rmp->_vl_msg_id = ntohs (VL_API_IP_REASSEMBLY_GET_REPLY);
3322 rmp->context = mp->context;
3323 rmp->retval = 0;
3324 if (mp->is_ip6)
3325 {
3326 rmp->is_ip6 = 1;
3327 ip6_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
3328 &rmp->expire_walk_interval_ms);
3329 }
3330 else
3331 {
3332 rmp->is_ip6 = 0;
3333 ip4_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
Klement Sekera3a343d42019-05-16 14:35:46 +02003334 &rmp->max_reassembly_length,
Klement Sekera75e7d132017-09-20 08:26:30 +02003335 &rmp->expire_walk_interval_ms);
3336 }
3337 rmp->timeout_ms = clib_host_to_net_u32 (rmp->timeout_ms);
3338 rmp->max_reassemblies = clib_host_to_net_u32 (rmp->max_reassemblies);
3339 rmp->expire_walk_interval_ms =
3340 clib_host_to_net_u32 (rmp->expire_walk_interval_ms);
Ole Troan2e1c8962019-04-10 09:44:23 +02003341 vl_api_send_msg (rp, (u8 *) rmp);
Klement Sekera75e7d132017-09-20 08:26:30 +02003342}
3343
Klement Sekera4c533132018-02-22 11:41:12 +01003344void
3345 vl_api_ip_reassembly_enable_disable_t_handler
3346 (vl_api_ip_reassembly_enable_disable_t * mp)
3347{
3348 vl_api_ip_reassembly_enable_disable_reply_t *rmp;
3349 int rv = 0;
3350 rv = ip4_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3351 mp->enable_ip4);
3352 if (0 == rv)
3353 {
3354 rv = ip6_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
3355 mp->enable_ip6);
3356 }
3357
Choree7f61d12018-11-28 10:27:58 +03303358 REPLY_MACRO (VL_API_IP_REASSEMBLY_ENABLE_DISABLE_REPLY);
Klement Sekera4c533132018-02-22 11:41:12 +01003359}
3360
Pavel Kotucek609e1212018-11-27 09:59:44 +01003361void
3362send_ip_punt_redirect_details (vl_api_registration_t * reg,
3363 u32 context, u32 sw_if_index,
3364 ip_punt_redirect_rx_t * pr, u8 is_ipv6)
3365{
3366 vl_api_ip_punt_redirect_details_t *mp;
3367
3368 mp = vl_msg_api_alloc (sizeof (*mp));
3369 if (!mp)
3370 return;
3371
3372 clib_memset (mp, 0, sizeof (*mp));
3373 mp->_vl_msg_id = ntohs (VL_API_IP_PUNT_REDIRECT_DETAILS);
3374 mp->context = context;
3375 mp->punt.rx_sw_if_index = htonl (sw_if_index);
3376 mp->punt.tx_sw_if_index = htonl (pr->tx_sw_if_index);
3377 if (is_ipv6)
3378 {
3379 ip_address_encode (&pr->nh, IP46_TYPE_IP6, &mp->punt.nh);
3380 }
3381 else
3382 {
3383 ip_address_encode (&pr->nh, IP46_TYPE_IP4, &mp->punt.nh);
3384 }
3385
3386 vl_api_send_msg (reg, (u8 *) mp);
3387}
3388
3389static void
3390vl_api_ip_punt_redirect_dump_t_handler (vl_api_ip_punt_redirect_dump_t * mp)
3391{
3392 vl_api_registration_t *reg;
3393 u32 sw_if_index;
3394 int rv __attribute__ ((unused)) = 0;
3395
3396 sw_if_index = ntohl (mp->sw_if_index);
3397 reg = vl_api_client_index_to_registration (mp->client_index);
3398 if (!reg)
3399 return;
3400
3401 if (~0 != sw_if_index)
3402 VALIDATE_SW_IF_INDEX (mp);
3403
3404 ip_punt_redirect_detail_t *pr, *prs;
3405 if (mp->is_ipv6)
3406 {
3407 prs = ip6_punt_redirect_entries (sw_if_index);
3408 /* *INDENT-OFF* */
3409 vec_foreach (pr, prs)
3410 {
3411 send_ip_punt_redirect_details (reg, mp->context, pr->rx_sw_if_index, &pr->punt_redirect, 1);
3412 }
3413 /* *INDENT-ON* */
3414 vec_free (prs);
3415 }
3416 else
3417 {
3418 prs = ip4_punt_redirect_entries (sw_if_index);
3419 /* *INDENT-OFF* */
3420 vec_foreach (pr, prs)
3421 {
3422 send_ip_punt_redirect_details (reg, mp->context, pr->rx_sw_if_index, &pr->punt_redirect, 0);
3423 }
3424 /* *INDENT-ON* */
3425 vec_free (prs);
3426 }
3427
3428 BAD_SW_IF_INDEX_LABEL;
3429}
3430
Dave Barachb5e8a772016-12-06 12:04:42 -05003431#define vl_msg_name_crc_list
3432#include <vnet/ip/ip.api.h>
3433#undef vl_msg_name_crc_list
3434
3435static void
3436setup_message_id_table (api_main_t * am)
3437{
3438#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
3439 foreach_vl_msg_name_crc_ip;
3440#undef _
3441}
3442
3443static clib_error_t *
3444ip_api_hookup (vlib_main_t * vm)
3445{
3446 api_main_t *am = &api_main;
3447
3448#define _(N,n) \
3449 vl_msg_api_set_handlers(VL_API_##N, #n, \
3450 vl_api_##n##_t_handler, \
3451 vl_noop_handler, \
3452 vl_api_##n##_t_endian, \
3453 vl_api_##n##_t_print, \
3454 sizeof(vl_api_##n##_t), 1);
3455 foreach_ip_api_msg;
3456#undef _
3457
3458 /*
Neale Ranns6a231a12018-10-17 06:38:00 +00003459 * Mark the route add/del API as MP safe
3460 */
3461 am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
3462 am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE_REPLY] = 1;
3463
3464 /*
Dave Barachb5e8a772016-12-06 12:04:42 -05003465 * Set up the (msg_name, crc, message-id) table
3466 */
3467 setup_message_id_table (am);
3468
Juraj Sloboda52574522018-05-03 10:03:50 +02003469 ra_set_publisher_node (wc_arp_process_node.index, RA_REPORT);
3470
Dave Barachb5e8a772016-12-06 12:04:42 -05003471 return 0;
3472}
3473
3474VLIB_API_INIT_FUNCTION (ip_api_hookup);
3475
3476/*
3477 * fd.io coding-style-patch-verification: ON
3478 *
3479 * Local Variables:
3480 * eval: (c-set-style "gnu")
3481 * End:
3482 */