build: fix clang-16 build
[vpp.git] / src / vnet / interface_api.c
1 /*
2  *------------------------------------------------------------------
3  * interface_api.c - vnet interface 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 #define _GNU_SOURCE
21 #include <string.h>
22
23 #include <vnet/vnet.h>
24 #include <vlibmemory/api.h>
25
26 #include <vnet/interface.h>
27 #include <vnet/interface/rx_queue_funcs.h>
28 #include <vnet/interface/tx_queue_funcs.h>
29 #include <vnet/api_errno.h>
30 #include <vnet/ethernet/ethernet.h>
31 #include <vnet/ip/ip.h>
32 #include <vnet/fib/fib_table.h>
33 #include <vnet/mfib/mfib_table.h>
34 #include <vnet/l2/l2_vtr.h>
35 #include <vnet/fib/fib_api.h>
36 #include <vnet/mfib/mfib_table.h>
37 #include <vlibapi/api_types.h>
38
39 #include <vnet/format_fns.h>
40 #include <vnet/ip/ip_types_api.h>
41 #include <vnet/ethernet/ethernet_types_api.h>
42
43 #include <interface.api_enum.h>
44 #include <interface.api_types.h>
45
46 #define REPLY_MSG_ID_BASE msg_id_base
47 #include <vlibapi/api_helper_macros.h>
48
49 static u16 msg_id_base;
50
51 vpe_api_main_t vpe_api_main;
52
53 #define foreach_vpe_api_msg                                                   \
54   _ (SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                          \
55   _ (SW_INTERFACE_SET_PROMISC, sw_interface_set_promisc)                      \
56   _ (HW_INTERFACE_SET_MTU, hw_interface_set_mtu)                              \
57   _ (SW_INTERFACE_SET_MTU, sw_interface_set_mtu)                              \
58   _ (WANT_INTERFACE_EVENTS, want_interface_events)                            \
59   _ (SW_INTERFACE_DUMP, sw_interface_dump)                                    \
60   _ (SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address)              \
61   _ (SW_INTERFACE_SET_RX_MODE, sw_interface_set_rx_mode)                      \
62   _ (SW_INTERFACE_RX_PLACEMENT_DUMP, sw_interface_rx_placement_dump)          \
63   _ (SW_INTERFACE_TX_PLACEMENT_GET, sw_interface_tx_placement_get)            \
64   _ (SW_INTERFACE_SET_RX_PLACEMENT, sw_interface_set_rx_placement)            \
65   _ (SW_INTERFACE_SET_TX_PLACEMENT, sw_interface_set_tx_placement)            \
66   _ (SW_INTERFACE_SET_TABLE, sw_interface_set_table)                          \
67   _ (SW_INTERFACE_GET_TABLE, sw_interface_get_table)                          \
68   _ (SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)                \
69   _ (SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                      \
70   _ (SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del)                      \
71   _ (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, sw_interface_add_del_mac_address)      \
72   _ (SW_INTERFACE_SET_MAC_ADDRESS, sw_interface_set_mac_address)              \
73   _ (SW_INTERFACE_GET_MAC_ADDRESS, sw_interface_get_mac_address)              \
74   _ (CREATE_VLAN_SUBIF, create_vlan_subif)                                    \
75   _ (CREATE_SUBIF, create_subif)                                              \
76   _ (DELETE_SUBIF, delete_subif)                                              \
77   _ (CREATE_LOOPBACK, create_loopback)                                        \
78   _ (CREATE_LOOPBACK_INSTANCE, create_loopback_instance)                      \
79   _ (DELETE_LOOPBACK, delete_loopback)                                        \
80   _ (INTERFACE_NAME_RENUMBER, interface_name_renumber)                        \
81   _ (COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats)      \
82   _ (SW_INTERFACE_SET_IP_DIRECTED_BROADCAST,                                  \
83      sw_interface_set_ip_directed_broadcast)                                  \
84   _ (SW_INTERFACE_ADDRESS_REPLACE_BEGIN, sw_interface_address_replace_begin)  \
85   _ (SW_INTERFACE_ADDRESS_REPLACE_END, sw_interface_address_replace_end)
86
87 static void
88 vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp)
89 {
90   vl_api_sw_interface_set_flags_reply_t *rmp;
91   vnet_main_t *vnm = vnet_get_main ();
92   int rv = 0;
93   clib_error_t *error;
94   u16 flags;
95
96   VALIDATE_SW_IF_INDEX (mp);
97
98   flags =
99     ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
100     VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
101
102   error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags);
103   if (error)
104     {
105       rv = -1;
106       clib_error_report (error);
107     }
108
109   BAD_SW_IF_INDEX_LABEL;
110   REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
111 }
112
113 static void
114 vl_api_sw_interface_set_promisc_t_handler (
115   vl_api_sw_interface_set_promisc_t *mp)
116 {
117   vl_api_sw_interface_set_promisc_reply_t *rmp;
118   vnet_main_t *vnm = vnet_get_main ();
119   ethernet_main_t *em = &ethernet_main;
120   int rv = 0;
121   ethernet_interface_t *eif;
122   vnet_sw_interface_t *swif;
123   u32 flags, sw_if_index;
124
125   VALIDATE_SW_IF_INDEX (mp);
126
127   sw_if_index = ntohl (mp->sw_if_index);
128   swif = vnet_get_sw_interface (vnm, sw_if_index);
129   eif = ethernet_get_interface (em, swif->hw_if_index);
130   if (!eif)
131     {
132       rv = VNET_API_ERROR_INVALID_VALUE;
133       goto done;
134     }
135
136   flags = mp->promisc_on ? ETHERNET_INTERFACE_FLAG_ACCEPT_ALL : 0;
137   rv = ethernet_set_flags (vnm, swif->hw_if_index, flags);
138
139 done:
140   BAD_SW_IF_INDEX_LABEL;
141   REPLY_MACRO (VL_API_SW_INTERFACE_SET_PROMISC_REPLY);
142 }
143
144 static void
145 vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp)
146 {
147   vl_api_hw_interface_set_mtu_reply_t *rmp;
148   vnet_main_t *vnm = vnet_get_main ();
149   u32 sw_if_index = ntohl (mp->sw_if_index);
150   u16 mtu = ntohs (mp->mtu);
151   ethernet_main_t *em = &ethernet_main;
152   clib_error_t *err;
153   int rv = 0;
154
155   VALIDATE_SW_IF_INDEX (mp);
156
157   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
158   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
159     {
160       rv = VNET_API_ERROR_INVALID_VALUE;
161       goto bad_sw_if_index;
162     }
163
164   ethernet_interface_t *eif = ethernet_get_interface (em, si->hw_if_index);
165
166   if (!eif)
167     {
168       rv = VNET_API_ERROR_FEATURE_DISABLED;
169       goto bad_sw_if_index;
170     }
171
172   if ((err = vnet_hw_interface_set_mtu (vnm, si->hw_if_index, mtu)))
173     {
174       rv = vnet_api_error (err);
175       clib_error_free (err);
176       goto bad_sw_if_index;
177     }
178
179   BAD_SW_IF_INDEX_LABEL;
180   REPLY_MACRO (VL_API_HW_INTERFACE_SET_MTU_REPLY);
181 }
182
183 static void
184 vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp)
185 {
186   vl_api_sw_interface_set_mtu_reply_t *rmp;
187   vnet_main_t *vnm = vnet_get_main ();
188   u32 sw_if_index = ntohl (mp->sw_if_index);
189   int rv = 0;
190   int i;
191   u32 per_protocol_mtu[VNET_N_MTU];
192
193   VALIDATE_SW_IF_INDEX (mp);
194
195   for (i = 0; i < VNET_N_MTU; i++)
196     {
197       per_protocol_mtu[i] = ntohl (mp->mtu[i]);
198     }
199   vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, per_protocol_mtu);
200
201   BAD_SW_IF_INDEX_LABEL;
202   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY);
203 }
204
205 static void
206   vl_api_sw_interface_set_ip_directed_broadcast_t_handler
207   (vl_api_sw_interface_set_ip_directed_broadcast_t * mp)
208 {
209   vl_api_sw_interface_set_ip_directed_broadcast_reply_t *rmp;
210   u32 sw_if_index = ntohl (mp->sw_if_index);
211   int rv = 0;
212
213   VALIDATE_SW_IF_INDEX (mp);
214
215   vnet_sw_interface_ip_directed_broadcast (vnet_get_main (),
216                                            sw_if_index, mp->enable);
217
218   BAD_SW_IF_INDEX_LABEL;
219   REPLY_MACRO (VL_API_SW_INTERFACE_SET_IP_DIRECTED_BROADCAST_REPLY);
220 }
221
222 static void
223 send_sw_interface_details (vpe_api_main_t * am,
224                            vl_api_registration_t * rp,
225                            vnet_sw_interface_t * swif,
226                            u8 * interface_name, u32 context)
227 {
228   vnet_hw_interface_t *hi =
229     vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
230   vnet_device_class_t *dev_class =
231     vnet_get_device_class (am->vnet_main, hi->dev_class_index);
232
233   vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
234   clib_memset (mp, 0, sizeof (*mp));
235   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS);
236   mp->sw_if_index = ntohl (swif->sw_if_index);
237   mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
238
239   mp->flags |= (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
240     IF_STATUS_API_FLAG_ADMIN_UP : 0;
241   mp->flags |= (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
242     IF_STATUS_API_FLAG_LINK_UP : 0;
243   mp->flags = ntohl (mp->flags);
244
245   switch (swif->type)
246     {
247     case VNET_SW_INTERFACE_TYPE_SUB:
248       mp->type = IF_API_TYPE_SUB;
249       break;
250     case VNET_SW_INTERFACE_TYPE_P2P:
251       mp->type = IF_API_TYPE_P2P;
252       break;
253     case VNET_SW_INTERFACE_TYPE_PIPE:
254       mp->type = IF_API_TYPE_PIPE;
255       break;
256     default:
257       mp->type = IF_API_TYPE_HARDWARE;
258     }
259   mp->type = ntohl (mp->type);
260
261   mp->link_duplex = ntohl (((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
262                             VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT));
263   mp->link_speed = ntohl (hi->link_speed);
264   mp->link_mtu = ntohs (hi->max_frame_size - hi->frame_overhead);
265   mp->mtu[VNET_MTU_L3] = ntohl (swif->mtu[VNET_MTU_L3]);
266   mp->mtu[VNET_MTU_IP4] = ntohl (swif->mtu[VNET_MTU_IP4]);
267   mp->mtu[VNET_MTU_IP6] = ntohl (swif->mtu[VNET_MTU_IP6]);
268   mp->mtu[VNET_MTU_MPLS] = ntohl (swif->mtu[VNET_MTU_MPLS]);
269
270   mp->context = context;
271
272   strncpy ((char *) mp->interface_name,
273            (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
274
275   if (dev_class && dev_class->name)
276     strncpy ((char *) mp->interface_dev_type, (char *) dev_class->name,
277              ARRAY_LEN (mp->interface_dev_type) - 1);
278
279   /* Send the L2 address for ethernet physical intfcs */
280   if (swif->sup_sw_if_index == swif->sw_if_index
281       && hi->hw_class_index == ethernet_hw_interface_class.index)
282     {
283       ethernet_main_t *em = ethernet_get_main (am->vlib_main);
284       ethernet_interface_t *ei;
285
286       ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
287       ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address.mac));
288       mac_address_encode (&ei->address.mac, mp->l2_address);
289     }
290   else if (swif->sup_sw_if_index != swif->sw_if_index)
291     {
292       vnet_sub_interface_t *sub = &swif->sub;
293       mp->sub_id = ntohl (sub->id);
294       mp->sub_number_of_tags =
295         sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
296       mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
297       mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
298       mp->sub_if_flags =
299         ntohl (sub->eth.raw_flags & SUB_IF_API_FLAG_MASK_VNET);
300     }
301
302   /* vlan tag rewrite data */
303   u32 vtr_op = L2_VTR_DISABLED;
304   u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
305
306   if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
307                  &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
308     {
309       // error - default to disabled
310       mp->vtr_op = ntohl (L2_VTR_DISABLED);
311       clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
312                     swif->sw_if_index);
313     }
314   else
315     {
316       mp->vtr_op = ntohl (vtr_op);
317       mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
318       mp->vtr_tag1 = ntohl (vtr_tag1);
319       mp->vtr_tag2 = ntohl (vtr_tag2);
320     }
321
322   /* pbb tag rewrite data */
323   ethernet_header_t eth_hdr;
324   u32 pbb_vtr_op = L2_VTR_DISABLED;
325   u16 outer_tag = 0;
326   u16 b_vlanid = 0;
327   u32 i_sid = 0;
328   clib_memset (&eth_hdr, 0, sizeof (eth_hdr));
329
330   if (!l2pbb_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
331                   &pbb_vtr_op, &outer_tag, &eth_hdr, &b_vlanid, &i_sid))
332     {
333       mp->sub_if_flags |= ntohl (SUB_IF_API_FLAG_DOT1AH);
334       mac_address_encode ((mac_address_t *) eth_hdr.dst_address, mp->b_dmac);
335       mac_address_encode ((mac_address_t *) eth_hdr.src_address, mp->b_smac);
336       mp->b_vlanid = b_vlanid;
337       mp->i_sid = i_sid;
338     }
339
340   u8 *tag = vnet_get_sw_interface_tag (vnet_get_main (), swif->sw_if_index);
341   if (tag)
342     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
343
344   vl_api_send_msg (rp, (u8 *) mp);
345 }
346
347 static void
348 vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp)
349 {
350   vpe_api_main_t *am = &vpe_api_main;
351   vnet_sw_interface_t *swif;
352   vnet_interface_main_t *im = &am->vnet_main->interface_main;
353   vl_api_registration_t *rp;
354   u32 sw_if_index;
355
356   rp = vl_api_client_index_to_registration (mp->client_index);
357
358   if (rp == 0)
359     {
360       clib_warning ("Client %d AWOL", mp->client_index);
361       return;
362     }
363
364   u8 *filter = 0, *name = 0;
365   sw_if_index = ntohl (mp->sw_if_index);
366
367   if (!mp->name_filter_valid && sw_if_index != ~0 && sw_if_index != 0)
368     {
369       /* is it a valid sw_if_index? */
370       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
371         return;
372
373       swif = vec_elt_at_index (im->sw_interfaces, sw_if_index);
374
375       vec_reset_length (name);
376       name =
377         format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
378                 swif, 0);
379       send_sw_interface_details (am, rp, swif, name, mp->context);
380       vec_free (name);
381       return;
382     }
383
384   if (mp->name_filter_valid)
385     {
386       filter = vl_api_from_api_to_new_vec (mp, &mp->name_filter);
387       vec_add1 (filter, 0);     /* Ensure it's a C string for strcasecmp() */
388     }
389
390   /* *INDENT-OFF* */
391   pool_foreach (swif, im->sw_interfaces)
392    {
393     if (!vnet_swif_is_api_visible (swif))
394         continue;
395     vec_reset_length(name);
396     name = format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
397                    swif, 0);
398
399     if (filter && !strcasestr((char *) name, (char *) filter))
400         continue;
401
402     send_sw_interface_details (am, rp, swif, name, mp->context);
403   }
404   /* *INDENT-ON* */
405
406   vec_free (name);
407   vec_free (filter);
408 }
409
410 static void
411   vl_api_sw_interface_add_del_address_t_handler
412   (vl_api_sw_interface_add_del_address_t * mp)
413 {
414   vlib_main_t *vm = vlib_get_main ();
415   vnet_main_t *vnm = vnet_get_main ();
416   vl_api_sw_interface_add_del_address_reply_t *rmp;
417   int rv = 0;
418   u32 is_del;
419   clib_error_t *error = 0;
420   ip46_address_t address;
421
422   VALIDATE_SW_IF_INDEX (mp);
423
424   is_del = mp->is_add == 0;
425   vnm->api_errno = 0;
426
427   if (mp->del_all)
428     ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index));
429   else if (ip_address_decode (&mp->prefix.address, &address) == IP46_TYPE_IP6)
430     error = ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
431                                            (void *) &address.ip6,
432                                            mp->prefix.len, is_del);
433   else
434     error = ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
435                                            (void *) &address.ip4,
436                                            mp->prefix.len, is_del);
437
438   if (error)
439     {
440       rv = vnm->api_errno;
441       clib_error_report (error);
442       goto done;
443     }
444
445   BAD_SW_IF_INDEX_LABEL;
446
447 done:
448   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
449 }
450
451 static void
452 vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
453 {
454   vl_api_sw_interface_set_table_reply_t *rmp;
455   u32 sw_if_index = ntohl (mp->sw_if_index);
456   u32 table_id = ntohl (mp->vrf_id);
457   int rv = 0;
458
459   VALIDATE_SW_IF_INDEX (mp);
460
461   if (mp->is_ipv6)
462     rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id);
463   else
464     rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id);
465
466   BAD_SW_IF_INDEX_LABEL;
467
468   REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
469 }
470
471 void
472 fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index)
473 {
474   u32 table_id;
475
476   table_id = fib_table_get_table_id (fib_index, fproto);
477   ASSERT (table_id != ~0);
478
479   if (FIB_PROTOCOL_IP6 == fproto)
480     {
481       /*
482        * tell those that are interested that the binding is changing.
483        */
484       ip6_table_bind_callback_t *cb;
485       vec_foreach (cb, ip6_main.table_bind_callbacks)
486         cb->function (&ip6_main, cb->function_opaque,
487                       sw_if_index,
488                       fib_index,
489                       ip6_main.fib_index_by_sw_if_index[sw_if_index]);
490
491       /* unlock currently assigned tables */
492       if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
493         fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
494                           FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
495
496       if (0 != table_id)
497         {
498           /* we need to lock the table now it's inuse */
499           fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
500         }
501
502       ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
503     }
504   else
505     {
506       /*
507        * tell those that are interested that the binding is changing.
508        */
509       ip4_table_bind_callback_t *cb;
510       vec_foreach (cb, ip4_main.table_bind_callbacks)
511         cb->function (&ip4_main, cb->function_opaque,
512                       sw_if_index,
513                       fib_index,
514                       ip4_main.fib_index_by_sw_if_index[sw_if_index]);
515
516       /* unlock currently assigned tables */
517       if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
518         fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
519                           FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
520
521       if (0 != table_id)
522         {
523           /* we need to lock the table now it's inuse */
524           fib_index = fib_table_find_or_create_and_lock (
525             FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE);
526         }
527
528       ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
529     }
530 }
531
532 void
533 mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index)
534 {
535   u32 table_id;
536
537   table_id = mfib_table_get_table_id (mfib_index, fproto);
538   ASSERT (table_id != ~0);
539
540   if (FIB_PROTOCOL_IP6 == fproto)
541     {
542       if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
543         mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
544                            FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
545
546       if (0 != table_id)
547         {
548           /* we need to lock the table now it's inuse */
549           mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
550                            MFIB_SOURCE_INTERFACE);
551         }
552
553       ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
554     }
555   else
556     {
557       if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
558         mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
559                            FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
560
561       if (0 != table_id)
562         {
563           /* we need to lock the table now it's inuse */
564           mfib_index = mfib_table_find_or_create_and_lock (
565             FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE);
566         }
567
568       ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
569     }
570 }
571
572 int
573 ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
574 {
575   CLIB_UNUSED (ip_interface_address_t * ia);
576   u32 fib_index, mfib_index;
577
578   /*
579    * This if table does not exist = error is what we want in the end.
580    */
581   fib_index = fib_table_find (fproto, table_id);
582   mfib_index = mfib_table_find (fproto, table_id);
583
584   if (~0 == fib_index || ~0 == mfib_index)
585     {
586       return (VNET_API_ERROR_NO_SUCH_FIB);
587     }
588
589   /*
590    * If the interface already has in IP address, then a change int
591    * VRF is not allowed. The IP address applied must first be removed.
592    * We do not do that automatically here, since VPP has no knowledge
593    * of whether those subnets are valid in the destination VRF.
594    */
595   /* clang-format off */
596   foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ?
597                                 &ip6_main.lookup_main : &ip4_main.lookup_main,
598                                 ia, sw_if_index,
599                                 1 /* honor unnumbered */ ,
600   ({
601     return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
602   }));
603   /* clang-format on */
604
605   fib_table_bind (fproto, sw_if_index, fib_index);
606   mfib_table_bind (fproto, sw_if_index, mfib_index);
607
608   return (0);
609 }
610
611 static void
612 send_sw_interface_get_table_reply (vl_api_registration_t * reg,
613                                    u32 context, int retval, u32 vrf_id)
614 {
615   vl_api_sw_interface_get_table_reply_t *mp;
616
617   mp = vl_msg_api_alloc (sizeof (*mp));
618   clib_memset (mp, 0, sizeof (*mp));
619   mp->_vl_msg_id =
620     ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_TABLE_REPLY);
621   mp->context = context;
622   mp->retval = htonl (retval);
623   mp->vrf_id = htonl (vrf_id);
624
625   vl_api_send_msg (reg, (u8 *) mp);
626 }
627
628 static void
629 vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp)
630 {
631   vl_api_registration_t *reg;
632   fib_table_t *fib_table = 0;
633   u32 sw_if_index = ~0;
634   u32 fib_index = ~0;
635   u32 table_id = ~0;
636   fib_protocol_t fib_proto = FIB_PROTOCOL_IP4;
637   int rv = 0;
638
639   reg = vl_api_client_index_to_registration (mp->client_index);
640   if (!reg)
641     return;
642
643   VALIDATE_SW_IF_INDEX (mp);
644
645   sw_if_index = ntohl (mp->sw_if_index);
646
647   if (mp->is_ipv6)
648     fib_proto = FIB_PROTOCOL_IP6;
649
650   fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
651   if (fib_index != ~0)
652     {
653       fib_table = fib_table_get (fib_index, fib_proto);
654       table_id = fib_table->ft_table_id;
655     }
656
657   BAD_SW_IF_INDEX_LABEL;
658
659   send_sw_interface_get_table_reply (reg, mp->context, rv, table_id);
660 }
661
662 static void vl_api_sw_interface_set_unnumbered_t_handler
663   (vl_api_sw_interface_set_unnumbered_t * mp)
664 {
665   vl_api_sw_interface_set_unnumbered_reply_t *rmp;
666   int rv = 0;
667   vnet_main_t *vnm = vnet_get_main ();
668   u32 sw_if_index = ntohl (mp->sw_if_index);
669   u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
670
671   /*
672    * The API message field names are backwards from
673    * the underlying data structure names.
674    * It's not worth changing them now.
675    */
676   if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index))
677     {
678       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
679       goto done;
680     }
681
682   /* Only check the "use loop0" field when setting the binding */
683   if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index))
684     {
685       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
686       goto done;
687     }
688
689   rv = vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
690                                             sw_if_index, mp->is_add);
691 done:
692   REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
693 }
694
695 static void
696 vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
697                                            mp)
698 {
699   vl_api_sw_interface_clear_stats_reply_t *rmp;
700
701   vnet_main_t *vnm = vnet_get_main ();
702   vnet_interface_main_t *im = &vnm->interface_main;
703   vlib_simple_counter_main_t *sm;
704   vlib_combined_counter_main_t *cm;
705   int j, n_counters;
706   int rv = 0;
707
708   if (mp->sw_if_index != ~0)
709     VALIDATE_SW_IF_INDEX (mp);
710
711   n_counters = vec_len (im->combined_sw_if_counters);
712
713   for (j = 0; j < n_counters; j++)
714     {
715       im = &vnm->interface_main;
716       cm = im->combined_sw_if_counters + j;
717       if (mp->sw_if_index == (u32) ~ 0)
718         vlib_clear_combined_counters (cm);
719       else
720         vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
721     }
722
723   n_counters = vec_len (im->sw_if_counters);
724
725   for (j = 0; j < n_counters; j++)
726     {
727       im = &vnm->interface_main;
728       sm = im->sw_if_counters + j;
729       if (mp->sw_if_index == (u32) ~ 0)
730         vlib_clear_simple_counters (sm);
731       else
732         vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
733     }
734
735   BAD_SW_IF_INDEX_LABEL;
736
737   REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
738 }
739
740 /*
741  * Events used for sw_interface_events
742  */
743 enum api_events
744 {
745   API_LINK_STATE_UP_EVENT = 1 << 1,
746   API_LINK_STATE_DOWN_EVENT = 1 << 2,
747   API_ADMIN_UP_EVENT = 1 << 3,
748   API_ADMIN_DOWN_EVENT = 1 << 4,
749   API_SW_INTERFACE_ADD_EVENT = 1 << 5,
750   API_SW_INTERFACE_DEL_EVENT = 1 << 6,
751 };
752
753 static void
754 send_sw_interface_event (vpe_api_main_t * am,
755                          vpe_client_registration_t * reg,
756                          vl_api_registration_t * vl_reg,
757                          u32 sw_if_index, enum api_events events)
758 {
759   vl_api_sw_interface_event_t *mp;
760
761   mp = vl_msg_api_alloc (sizeof (*mp));
762   clib_memset (mp, 0, sizeof (*mp));
763   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_EVENT);
764   mp->sw_if_index = ntohl (sw_if_index);
765   mp->client_index = reg->client_index;
766   mp->pid = reg->client_pid;
767   mp->flags = 0;
768   mp->flags |= (events & API_ADMIN_UP_EVENT) ?
769     IF_STATUS_API_FLAG_ADMIN_UP : 0;
770   mp->flags |= (events & API_LINK_STATE_UP_EVENT) ?
771     IF_STATUS_API_FLAG_LINK_UP : 0;
772   mp->flags = ntohl (mp->flags);
773   mp->deleted = events & API_SW_INTERFACE_DEL_EVENT ? true : false;
774   vl_api_send_msg (vl_reg, (u8 *) mp);
775 }
776
777 static uword
778 link_state_process (vlib_main_t * vm,
779                     vlib_node_runtime_t * rt, vlib_frame_t * f)
780 {
781   vpe_api_main_t *vam = &vpe_api_main;
782   uword *event_by_sw_if_index = 0;
783   vpe_client_registration_t *reg;
784   int i;
785   vl_api_registration_t *vl_reg;
786   uword event_type;
787   uword *event_data = 0;
788   u32 sw_if_index;
789
790   vam->link_state_process_up = 1;
791
792   while (1)
793     {
794       vlib_process_wait_for_event (vm);
795
796       /* Batch up events */
797       while ((event_type = vlib_process_get_events (vm, &event_data)) != ~0)
798         {
799           for (i = 0; i < vec_len (event_data); i++)
800             {
801               sw_if_index = event_data[i];
802               vec_validate_init_empty (event_by_sw_if_index, sw_if_index, 0);
803               event_by_sw_if_index[sw_if_index] |= event_type;
804             }
805           vec_reset_length (event_data);
806         }
807
808       for (i = 0; i < vec_len (event_by_sw_if_index); i++)
809         {
810           if (event_by_sw_if_index[i] == 0)
811             continue;
812
813           /* *INDENT-OFF* */
814           pool_foreach (reg, vam->interface_events_registrations)
815            {
816             vl_reg = vl_api_client_index_to_registration (reg->client_index);
817             if (vl_reg)
818               send_sw_interface_event (vam, reg, vl_reg, i, event_by_sw_if_index[i]);
819           }
820           /* *INDENT-ON* */
821         }
822       vec_reset_length (event_by_sw_if_index);
823     }
824
825   return 0;
826 }
827
828 static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
829                                             u32 flags);
830 static clib_error_t *admin_up_down_function (vnet_main_t * vm,
831                                              u32 hw_if_index, u32 flags);
832 static clib_error_t *sw_interface_add_del_function (vnet_main_t * vm,
833                                                     u32 sw_if_index,
834                                                     u32 flags);
835
836 /* *INDENT-OFF* */
837 VLIB_REGISTER_NODE (link_state_process_node,static) = {
838   .function = link_state_process,
839   .type = VLIB_NODE_TYPE_PROCESS,
840   .name = "vpe-link-state-process",
841 };
842 /* *INDENT-ON* */
843
844 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
845 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
846 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (sw_interface_add_del_function);
847
848 static clib_error_t *
849 link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
850 {
851   vpe_api_main_t *vam = &vpe_api_main;
852   vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
853
854   if (vam->link_state_process_up)
855     {
856       enum api_events event = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
857                                API_LINK_STATE_UP_EVENT :
858                                API_LINK_STATE_DOWN_EVENT);
859       vlib_process_signal_event (vam->vlib_main,
860                                  link_state_process_node.index, event,
861                                  hi->sw_if_index);
862     }
863   return 0;
864 }
865
866 static clib_error_t *
867 admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
868 {
869   vpe_api_main_t *vam = &vpe_api_main;
870
871   /*
872    * Note: it's perfectly fair to set a subif admin up / admin down.
873    * Note the subtle distinction between this routine and the previous
874    * routine.
875    */
876   if (vam->link_state_process_up)
877     {
878       enum api_events event = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
879                                API_ADMIN_UP_EVENT : API_ADMIN_DOWN_EVENT);
880       vlib_process_signal_event (vam->vlib_main,
881                                  link_state_process_node.index, event,
882                                  sw_if_index);
883     }
884   return 0;
885 }
886
887 static clib_error_t *
888 sw_interface_add_del_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
889 {
890   vpe_api_main_t *vam = &vpe_api_main;
891
892   if (vam->link_state_process_up)
893     {
894       enum api_events event =
895         flags ? API_SW_INTERFACE_ADD_EVENT : API_SW_INTERFACE_DEL_EVENT;
896       vlib_process_signal_event (vam->vlib_main,
897                                  link_state_process_node.index, event,
898                                  sw_if_index);
899     }
900   return 0;
901 }
902
903 static void vl_api_sw_interface_tag_add_del_t_handler
904   (vl_api_sw_interface_tag_add_del_t * mp)
905 {
906   vnet_main_t *vnm = vnet_get_main ();
907   vl_api_sw_interface_tag_add_del_reply_t *rmp;
908   int rv = 0;
909   u8 *tag;
910   u32 sw_if_index = ntohl (mp->sw_if_index);
911
912   VALIDATE_SW_IF_INDEX (mp);
913
914   if (mp->is_add)
915     {
916       if (mp->tag[0] == 0)
917         {
918           rv = VNET_API_ERROR_INVALID_VALUE;
919           goto out;
920         }
921
922       mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
923       tag = format (0, "%s%c", mp->tag, 0);
924       vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
925     }
926   else
927     vnet_clear_sw_interface_tag (vnm, sw_if_index);
928
929   BAD_SW_IF_INDEX_LABEL;
930 out:
931   REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY);
932 }
933
934 static void vl_api_sw_interface_add_del_mac_address_t_handler
935   (vl_api_sw_interface_add_del_mac_address_t * mp)
936 {
937   vl_api_sw_interface_add_del_mac_address_reply_t *rmp;
938   vnet_main_t *vnm = vnet_get_main ();
939   u32 sw_if_index = ntohl (mp->sw_if_index);
940   vnet_hw_interface_t *hi;
941   clib_error_t *error;
942   int rv = 0;
943
944   VALIDATE_SW_IF_INDEX (mp);
945
946   /* for subifs, the MAC should be changed on the actual hw if */
947   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
948   error = vnet_hw_interface_add_del_mac_address (vnm, hi->hw_if_index,
949                                                  mp->addr, mp->is_add);
950   if (error)
951     {
952       rv = VNET_API_ERROR_UNIMPLEMENTED;
953       clib_error_report (error);
954       goto out;
955     }
956
957   BAD_SW_IF_INDEX_LABEL;
958 out:
959   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY);
960 }
961
962 static void vl_api_sw_interface_set_mac_address_t_handler
963   (vl_api_sw_interface_set_mac_address_t * mp)
964 {
965   vl_api_sw_interface_set_mac_address_reply_t *rmp;
966   vnet_main_t *vnm = vnet_get_main ();
967   u32 sw_if_index = ntohl (mp->sw_if_index);
968   vnet_sw_interface_t *si;
969   clib_error_t *error;
970   int rv = 0;
971   mac_address_t mac;
972
973   VALIDATE_SW_IF_INDEX (mp);
974
975   si = vnet_get_sw_interface (vnm, sw_if_index);
976   mac_address_decode (mp->mac_address, &mac);
977   error =
978     vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, (u8 *) & mac);
979   if (error)
980     {
981       rv = VNET_API_ERROR_UNIMPLEMENTED;
982       clib_error_report (error);
983       goto out;
984     }
985
986   BAD_SW_IF_INDEX_LABEL;
987 out:
988   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY);
989 }
990
991 static void vl_api_sw_interface_get_mac_address_t_handler
992   (vl_api_sw_interface_get_mac_address_t * mp)
993 {
994   vl_api_sw_interface_get_mac_address_reply_t *rmp;
995   vl_api_registration_t *reg;
996   vnet_main_t *vnm = vnet_get_main ();
997   u32 sw_if_index = ntohl (mp->sw_if_index);
998   vnet_sw_interface_t *si;
999   ethernet_interface_t *eth_if = 0;
1000   int rv = 0;
1001
1002   VALIDATE_SW_IF_INDEX (mp);
1003
1004   si = vnet_get_sup_sw_interface (vnm, sw_if_index);
1005   if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
1006     eth_if = ethernet_get_interface (&ethernet_main, si->hw_if_index);
1007
1008   BAD_SW_IF_INDEX_LABEL;
1009
1010   reg = vl_api_client_index_to_registration (mp->client_index);
1011   if (!reg)
1012     return;
1013   rmp = vl_msg_api_alloc (sizeof (*rmp));
1014   rmp->_vl_msg_id =
1015     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY);
1016   rmp->context = mp->context;
1017   rmp->retval = htonl (rv);
1018   if (!rv && eth_if)
1019     mac_address_encode (&eth_if->address.mac, rmp->mac_address);
1020   vl_api_send_msg (reg, (u8 *) rmp);
1021 }
1022
1023 static void
1024 vl_api_sw_interface_set_interface_name_t_handler (
1025   vl_api_sw_interface_set_interface_name_t *mp)
1026 {
1027   vl_api_sw_interface_set_interface_name_reply_t *rmp;
1028   vnet_main_t *vnm = vnet_get_main ();
1029   u32 sw_if_index = ntohl (mp->sw_if_index);
1030   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
1031   clib_error_t *error;
1032   int rv = 0;
1033
1034   if (mp->name[0] == 0)
1035     {
1036       rv = VNET_API_ERROR_INVALID_VALUE;
1037       goto out;
1038     }
1039   if (si == 0)
1040     {
1041       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1042       goto out;
1043     }
1044
1045   error = vnet_rename_interface (vnm, si->hw_if_index, (char *) mp->name);
1046   if (error)
1047     {
1048       clib_error_free (error);
1049       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1050     }
1051
1052 out:
1053   REPLY_MACRO (VL_API_SW_INTERFACE_SET_INTERFACE_NAME_REPLY);
1054 }
1055
1056 static void vl_api_sw_interface_set_rx_mode_t_handler
1057   (vl_api_sw_interface_set_rx_mode_t * mp)
1058 {
1059   vl_api_sw_interface_set_rx_mode_reply_t *rmp;
1060   vnet_main_t *vnm = vnet_get_main ();
1061   u32 sw_if_index = ntohl (mp->sw_if_index);
1062   vnet_sw_interface_t *si;
1063   clib_error_t *error;
1064   int rv = 0;
1065   vnet_hw_if_rx_mode rx_mode;
1066
1067   VALIDATE_SW_IF_INDEX (mp);
1068
1069   si = vnet_get_sw_interface (vnm, sw_if_index);
1070   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1071     {
1072       rv = VNET_API_ERROR_INVALID_VALUE;
1073       goto bad_sw_if_index;
1074     }
1075
1076   rx_mode = (vnet_hw_if_rx_mode) ntohl (mp->mode);
1077   error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index,
1078                                            mp->queue_id_valid,
1079                                            ntohl (mp->queue_id),
1080                                            (vnet_hw_if_rx_mode) rx_mode);
1081
1082   if (error)
1083     {
1084       rv = VNET_API_ERROR_UNIMPLEMENTED;
1085       clib_error_report (error);
1086       goto out;
1087     }
1088
1089   BAD_SW_IF_INDEX_LABEL;
1090 out:
1091   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_MODE_REPLY);
1092 }
1093
1094 static void
1095 send_interface_rx_placement_details (vpe_api_main_t * am,
1096                                      vl_api_registration_t * rp,
1097                                      u32 sw_if_index, u32 worker_id,
1098                                      u32 queue_id, u8 mode, u32 context)
1099 {
1100   vl_api_sw_interface_rx_placement_details_t *mp;
1101   mp = vl_msg_api_alloc (sizeof (*mp));
1102   clib_memset (mp, 0, sizeof (*mp));
1103
1104   mp->_vl_msg_id =
1105     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_RX_PLACEMENT_DETAILS);
1106   mp->sw_if_index = htonl (sw_if_index);
1107   mp->queue_id = htonl (queue_id);
1108   mp->worker_id = htonl (worker_id);
1109   mp->mode = htonl (mode);
1110   mp->context = context;
1111
1112   vl_api_send_msg (rp, (u8 *) mp);
1113 }
1114
1115 static void vl_api_sw_interface_rx_placement_dump_t_handler
1116   (vl_api_sw_interface_rx_placement_dump_t * mp)
1117 {
1118   vnet_main_t *vnm = vnet_get_main ();
1119   vpe_api_main_t *am = &vpe_api_main;
1120   u32 sw_if_index = ntohl (mp->sw_if_index);
1121   vl_api_registration_t *reg;
1122
1123   reg = vl_api_client_index_to_registration (mp->client_index);
1124   if (!reg)
1125     return;
1126
1127   if (sw_if_index == ~0)
1128     {
1129       vnet_hw_if_rx_queue_t **all_queues = 0;
1130       vnet_hw_if_rx_queue_t **qptr;
1131       vnet_hw_if_rx_queue_t *q;
1132       pool_foreach (q, vnm->interface_main.hw_if_rx_queues)
1133         vec_add1 (all_queues, q);
1134       vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api);
1135
1136       vec_foreach (qptr, all_queues)
1137         {
1138           u32 current_thread = qptr[0]->thread_index;
1139           u32 hw_if_index = qptr[0]->hw_if_index;
1140           vnet_hw_interface_t *hw_if =
1141             vnet_get_hw_interface (vnm, hw_if_index);
1142           send_interface_rx_placement_details (
1143             am, reg, hw_if->sw_if_index, current_thread, qptr[0]->queue_id,
1144             qptr[0]->mode, mp->context);
1145         }
1146       vec_free (all_queues);
1147     }
1148   else
1149     {
1150       int i;
1151       vnet_sw_interface_t *si;
1152
1153       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
1154         {
1155           clib_warning ("sw_if_index %u does not exist", sw_if_index);
1156           goto bad_sw_if_index;
1157         }
1158
1159       si = vnet_get_sw_interface (vnm, sw_if_index);
1160       if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1161         {
1162           clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
1163                         " interfaces are not supported");
1164           goto bad_sw_if_index;
1165         }
1166
1167       vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
1168
1169       for (i = 0; i < vec_len (hw->rx_queue_indices); i++)
1170         {
1171           vnet_hw_if_rx_queue_t *rxq =
1172             vnet_hw_if_get_rx_queue (vnm, hw->rx_queue_indices[i]);
1173           send_interface_rx_placement_details (
1174             am, reg, hw->sw_if_index, rxq->thread_index, rxq->queue_id,
1175             rxq->mode, mp->context);
1176         }
1177     }
1178
1179   BAD_SW_IF_INDEX_LABEL;
1180 }
1181
1182 static void vl_api_sw_interface_set_rx_placement_t_handler
1183   (vl_api_sw_interface_set_rx_placement_t * mp)
1184 {
1185   vl_api_sw_interface_set_rx_placement_reply_t *rmp;
1186   vnet_main_t *vnm = vnet_get_main ();
1187   u32 sw_if_index = ntohl (mp->sw_if_index);
1188   vnet_sw_interface_t *si;
1189   clib_error_t *error = 0;
1190   int rv = 0;
1191
1192   VALIDATE_SW_IF_INDEX (mp);
1193
1194   si = vnet_get_sw_interface (vnm, sw_if_index);
1195   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1196     {
1197       rv = VNET_API_ERROR_INVALID_VALUE;
1198       goto bad_sw_if_index;
1199     }
1200
1201   error = set_hw_interface_rx_placement (si->hw_if_index,
1202                                          ntohl (mp->queue_id),
1203                                          ntohl (mp->worker_id), mp->is_main);
1204   if (error)
1205     {
1206       rv = VNET_API_ERROR_UNIMPLEMENTED;
1207       clib_error_report (error);
1208       goto out;
1209     }
1210
1211   BAD_SW_IF_INDEX_LABEL;
1212 out:
1213   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY);
1214 }
1215
1216 static void
1217 send_interface_tx_placement_details (vnet_hw_if_tx_queue_t **all_queues,
1218                                      u32 index, vl_api_registration_t *rp,
1219                                      u32 context)
1220 {
1221   vnet_main_t *vnm = vnet_get_main ();
1222   vl_api_sw_interface_tx_placement_details_t *rmp;
1223   u32 n_bits = 0, v = ~0;
1224   vnet_hw_if_tx_queue_t **q = vec_elt_at_index (all_queues, index);
1225   uword *bitmap = q[0]->threads;
1226   u32 hw_if_index = q[0]->hw_if_index;
1227   vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1228
1229   n_bits = clib_bitmap_count_set_bits (bitmap);
1230   u32 n = n_bits * sizeof (u32);
1231
1232   REPLY_MACRO_DETAILS5_END (VL_API_SW_INTERFACE_TX_PLACEMENT_DETAILS, n, rp,
1233                             context, ({
1234                               rmp->sw_if_index = hw_if->sw_if_index;
1235                               rmp->queue_id = q[0]->queue_id;
1236                               rmp->shared = q[0]->shared_queue;
1237                               rmp->array_size = n_bits;
1238
1239                               v = clib_bitmap_first_set (bitmap);
1240                               for (u32 i = 0; i < n_bits; i++)
1241                                 {
1242                                   rmp->threads[i] = v;
1243                                   v = clib_bitmap_next_set (bitmap, v + 1);
1244                                 }
1245                             }));
1246 }
1247
1248 static void
1249 vl_api_sw_interface_tx_placement_get_t_handler (
1250   vl_api_sw_interface_tx_placement_get_t *mp)
1251 {
1252   vnet_main_t *vnm = vnet_get_main ();
1253   vl_api_sw_interface_tx_placement_get_reply_t *rmp = 0;
1254   vnet_hw_if_tx_queue_t **all_queues = 0;
1255   vnet_hw_if_tx_queue_t *q;
1256   u32 sw_if_index = mp->sw_if_index;
1257   i32 rv = 0;
1258
1259   if (pool_elts (vnm->interface_main.hw_if_tx_queues) == 0)
1260     {
1261       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1262       goto err;
1263     }
1264
1265   if (sw_if_index == ~0)
1266     {
1267       pool_foreach (q, vnm->interface_main.hw_if_tx_queues)
1268         vec_add1 (all_queues, q);
1269       vec_sort_with_function (all_queues, vnet_hw_if_txq_cmp_cli_api);
1270     }
1271   else
1272     {
1273       u32 qi = ~0;
1274       vnet_sw_interface_t *si;
1275
1276       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
1277         {
1278           clib_warning ("sw_if_index %u does not exist", sw_if_index);
1279           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1280           goto err;
1281         }
1282
1283       si = vnet_get_sw_interface (vnm, sw_if_index);
1284       if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1285         {
1286           clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
1287                         " interfaces are not supported");
1288           rv = VNET_API_ERROR_INVALID_INTERFACE;
1289           goto err;
1290         }
1291
1292       vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
1293       for (qi = 0; qi < vec_len (hw->tx_queue_indices); qi++)
1294         {
1295           q = vnet_hw_if_get_tx_queue (vnm, hw->tx_queue_indices[qi]);
1296           vec_add1 (all_queues, q);
1297         }
1298     }
1299
1300   REPLY_AND_DETAILS_VEC_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY,
1301                                    all_queues, mp, rmp, rv, ({
1302                                      send_interface_tx_placement_details (
1303                                        all_queues, cursor, rp, mp->context);
1304                                    }));
1305
1306   vec_free (all_queues);
1307   return;
1308
1309 err:
1310   REPLY_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY);
1311 }
1312
1313 static void
1314 vl_api_sw_interface_set_tx_placement_t_handler (
1315   vl_api_sw_interface_set_tx_placement_t *mp)
1316 {
1317   vl_api_sw_interface_set_tx_placement_reply_t *rmp;
1318   vnet_main_t *vnm = vnet_get_main ();
1319   u32 sw_if_index = mp->sw_if_index;
1320   vnet_sw_interface_t *si;
1321   uword *bitmap = 0;
1322   u32 queue_id = ~0;
1323   u32 size = 0;
1324   clib_error_t *error = 0;
1325   int rv = 0;
1326
1327   VALIDATE_SW_IF_INDEX_END (mp);
1328
1329   si = vnet_get_sw_interface (vnm, sw_if_index);
1330   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1331     {
1332       rv = VNET_API_ERROR_INVALID_VALUE;
1333       goto bad_sw_if_index;
1334     }
1335
1336   size = mp->array_size;
1337   for (u32 i = 0; i < size; i++)
1338     {
1339       u32 thread_index = mp->threads[i];
1340       bitmap = clib_bitmap_set (bitmap, thread_index, 1);
1341     }
1342
1343   queue_id = mp->queue_id;
1344   rv = set_hw_interface_tx_queue (si->hw_if_index, queue_id, bitmap);
1345
1346   switch (rv)
1347     {
1348     case VNET_API_ERROR_INVALID_VALUE:
1349       error = clib_error_return (
1350         0, "please specify valid thread(s) - last thread index %u",
1351         clib_bitmap_last_set (bitmap));
1352       break;
1353     case VNET_API_ERROR_INVALID_QUEUE:
1354       error = clib_error_return (
1355         0, "unknown queue %u on interface %s", queue_id,
1356         vnet_get_hw_interface (vnet_get_main (), si->hw_if_index)->name);
1357       break;
1358     default:
1359       break;
1360     }
1361
1362   if (error)
1363     {
1364       clib_error_report (error);
1365       goto out;
1366     }
1367
1368   BAD_SW_IF_INDEX_LABEL;
1369 out:
1370   REPLY_MACRO_END (VL_API_SW_INTERFACE_SET_TX_PLACEMENT_REPLY);
1371   clib_bitmap_free (bitmap);
1372 }
1373
1374 static void
1375 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1376 {
1377   vl_api_create_vlan_subif_reply_t *rmp;
1378   vnet_main_t *vnm = vnet_get_main ();
1379   u32 sw_if_index = (u32) ~ 0;
1380   vnet_hw_interface_t *hi;
1381   int rv = 0;
1382   u32 id;
1383   vnet_sw_interface_t template;
1384   uword *p;
1385   vnet_interface_main_t *im = &vnm->interface_main;
1386   u64 sup_and_sub_key;
1387   vl_api_registration_t *reg;
1388   clib_error_t *error;
1389
1390   VALIDATE_SW_IF_INDEX (mp);
1391
1392   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1393
1394   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1395     {
1396       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1397       goto out;
1398     }
1399
1400   id = ntohl (mp->vlan_id);
1401   if (id == 0 || id > 4095)
1402     {
1403       rv = VNET_API_ERROR_INVALID_VLAN;
1404       goto out;
1405     }
1406
1407   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1408
1409   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1410   if (p)
1411     {
1412       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1413       goto out;
1414     }
1415
1416   clib_memset (&template, 0, sizeof (template));
1417   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1418   template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1419   template.sup_sw_if_index = hi->sw_if_index;
1420   template.sub.id = id;
1421   template.sub.eth.raw_flags = 0;
1422   template.sub.eth.flags.one_tag = 1;
1423   template.sub.eth.outer_vlan_id = id;
1424   template.sub.eth.flags.exact_match = 1;
1425
1426   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1427   if (error)
1428     {
1429       clib_error_report (error);
1430       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1431       goto out;
1432     }
1433
1434   u64 *kp = clib_mem_alloc (sizeof (*kp));
1435   *kp = sup_and_sub_key;
1436
1437   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1438   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1439
1440   BAD_SW_IF_INDEX_LABEL;
1441
1442 out:
1443   reg = vl_api_client_index_to_registration (mp->client_index);
1444   if (!reg)
1445     return;
1446
1447   rmp = vl_msg_api_alloc (sizeof (*rmp));
1448   rmp->_vl_msg_id = htons (REPLY_MSG_ID_BASE + VL_API_CREATE_VLAN_SUBIF_REPLY);
1449   rmp->context = mp->context;
1450   rmp->retval = htonl (rv);
1451   rmp->sw_if_index = htonl (sw_if_index);
1452   vl_api_send_msg (reg, (u8 *) rmp);
1453 }
1454
1455 static void
1456 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1457 {
1458   vl_api_create_subif_reply_t *rmp;
1459   vnet_main_t *vnm = vnet_get_main ();
1460   u32 sub_sw_if_index = ~0;
1461   vnet_hw_interface_t *hi;
1462   int rv = 0;
1463
1464   VALIDATE_SW_IF_INDEX (mp);
1465
1466   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1467
1468   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1469     rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1470   else
1471     rv = vnet_create_sub_interface (ntohl (mp->sw_if_index),
1472                                     ntohl (mp->sub_id),
1473                                     ntohl (mp->sub_if_flags),
1474                                     ntohs (mp->inner_vlan_id),
1475                                     ntohs (mp->outer_vlan_id),
1476                                     &sub_sw_if_index);
1477
1478   BAD_SW_IF_INDEX_LABEL;
1479
1480   /* *INDENT-OFF* */
1481   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1482   ({
1483     rmp->sw_if_index = ntohl(sub_sw_if_index);
1484   }));
1485   /* *INDENT-ON* */
1486 }
1487
1488 static void
1489 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
1490 {
1491   vl_api_delete_subif_reply_t *rmp;
1492   int rv;
1493
1494   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
1495
1496   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
1497 }
1498
1499 static void
1500 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
1501                                           mp)
1502 {
1503   vl_api_interface_name_renumber_reply_t *rmp;
1504   int rv = 0;
1505
1506   VALIDATE_SW_IF_INDEX (mp);
1507
1508   rv = vnet_interface_name_renumber
1509     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
1510
1511   BAD_SW_IF_INDEX_LABEL;
1512
1513   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
1514 }
1515
1516 static void
1517 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1518 {
1519   vl_api_create_loopback_reply_t *rmp;
1520   u32 sw_if_index;
1521   int rv;
1522   mac_address_t mac;
1523
1524   mac_address_decode (mp->mac_address, &mac);
1525   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 0, 0);
1526
1527   /* *INDENT-OFF* */
1528   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1529   ({
1530     rmp->sw_if_index = ntohl (sw_if_index);
1531   }));
1532   /* *INDENT-ON* */
1533 }
1534
1535 static void vl_api_create_loopback_instance_t_handler
1536   (vl_api_create_loopback_instance_t * mp)
1537 {
1538   vl_api_create_loopback_instance_reply_t *rmp;
1539   u32 sw_if_index;
1540   u8 is_specified = mp->is_specified;
1541   u32 user_instance = ntohl (mp->user_instance);
1542   int rv;
1543   mac_address_t mac;
1544
1545   mac_address_decode (mp->mac_address, &mac);
1546   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac,
1547                                        is_specified, user_instance);
1548
1549   /* *INDENT-OFF* */
1550   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_INSTANCE_REPLY,
1551   ({
1552     rmp->sw_if_index = ntohl (sw_if_index);
1553   }));
1554   /* *INDENT-ON* */
1555 }
1556
1557 static void
1558 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1559 {
1560   vl_api_delete_loopback_reply_t *rmp;
1561   u32 sw_if_index;
1562   int rv;
1563
1564   sw_if_index = ntohl (mp->sw_if_index);
1565   rv = vnet_delete_loopback_interface (sw_if_index);
1566
1567   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1568 }
1569
1570 static void
1571   vl_api_collect_detailed_interface_stats_t_handler
1572   (vl_api_collect_detailed_interface_stats_t * mp)
1573 {
1574   vl_api_collect_detailed_interface_stats_reply_t *rmp;
1575   int rv = 0;
1576
1577   rv =
1578     vnet_sw_interface_stats_collect_enable_disable (ntohl (mp->sw_if_index),
1579                                                     mp->enable_disable);
1580
1581   REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY);
1582 }
1583
1584 static void
1585   vl_api_sw_interface_address_replace_begin_t_handler
1586   (vl_api_sw_interface_address_replace_begin_t * mp)
1587 {
1588   vl_api_sw_interface_address_replace_begin_reply_t *rmp;
1589   int rv = 0;
1590
1591   ip_interface_address_mark ();
1592
1593   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_BEGIN_REPLY);
1594 }
1595
1596 static void
1597   vl_api_sw_interface_address_replace_end_t_handler
1598   (vl_api_sw_interface_address_replace_end_t * mp)
1599 {
1600   vl_api_sw_interface_address_replace_end_reply_t *rmp;
1601   int rv = 0;
1602
1603   ip_interface_address_sweep ();
1604
1605   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY);
1606 }
1607
1608 static void
1609 vl_api_pcap_set_filter_function_t_handler (
1610   vl_api_pcap_set_filter_function_t *mp)
1611 {
1612   vnet_main_t *vnm = vnet_get_main ();
1613   vnet_pcap_t *pp = &vnm->pcap;
1614   vl_api_pcap_set_filter_function_reply_t *rmp;
1615   unformat_input_t input = { 0 };
1616   vlib_is_packet_traced_fn_t *f;
1617   char *filter_name;
1618   int rv = 0;
1619   filter_name = vl_api_from_api_to_new_c_string (&mp->filter_function_name);
1620   unformat_init_cstring (&input, filter_name);
1621   if (unformat (&input, "%U", unformat_vlib_trace_filter_function, &f) == 0)
1622     {
1623       rv = -1;
1624       goto done;
1625     }
1626
1627   pp->current_filter_function = f;
1628
1629 done:
1630   unformat_free (&input);
1631   vec_free (filter_name);
1632   REPLY_MACRO (VL_API_PCAP_SET_FILTER_FUNCTION_REPLY);
1633 }
1634
1635 static void
1636 vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp)
1637 {
1638   vl_api_pcap_trace_on_reply_t *rmp;
1639   unformat_input_t filename, drop_err_name;
1640   vnet_pcap_dispatch_trace_args_t capture_args;
1641   int rv = 0;
1642
1643   VALIDATE_SW_IF_INDEX (mp);
1644
1645   unformat_init_cstring (&filename, (char *) mp->filename);
1646   if (!unformat_user (&filename, unformat_vlib_tmpfile,
1647                       &capture_args.filename))
1648     {
1649       rv = VNET_API_ERROR_ILLEGAL_NAME;
1650       goto out;
1651     }
1652
1653   capture_args.rx_enable = mp->capture_rx;
1654   capture_args.tx_enable = mp->capture_tx;
1655   capture_args.preallocate_data = mp->preallocate_data;
1656   capture_args.free_data = mp->free_data;
1657   capture_args.drop_enable = mp->capture_drop;
1658   capture_args.status = 0;
1659   capture_args.packets_to_capture = ntohl (mp->max_packets);
1660   capture_args.sw_if_index = ntohl (mp->sw_if_index);
1661   capture_args.filter = mp->filter;
1662   capture_args.max_bytes_per_pkt = ntohl (mp->max_bytes_per_packet);
1663   capture_args.drop_err = ~0;
1664
1665   unformat_init_cstring (&drop_err_name, (char *) mp->error);
1666   unformat_user (&drop_err_name, unformat_vlib_error, vlib_get_main (),
1667                  &capture_args.drop_err);
1668
1669   rv = vnet_pcap_dispatch_trace_configure (&capture_args);
1670
1671   BAD_SW_IF_INDEX_LABEL;
1672
1673 out:
1674   unformat_free (&filename);
1675   unformat_free (&drop_err_name);
1676
1677   REPLY_MACRO (VL_API_PCAP_TRACE_ON_REPLY);
1678 }
1679
1680 static void
1681 vl_api_pcap_trace_off_t_handler (vl_api_pcap_trace_off_t *mp)
1682 {
1683   vl_api_pcap_trace_off_reply_t *rmp;
1684   vnet_pcap_dispatch_trace_args_t capture_args;
1685   int rv = 0;
1686
1687   clib_memset (&capture_args, 0, sizeof (capture_args));
1688
1689   rv = vnet_pcap_dispatch_trace_configure (&capture_args);
1690
1691   REPLY_MACRO (VL_API_PCAP_TRACE_OFF_REPLY);
1692 }
1693
1694 /*
1695  * vpe_api_hookup
1696  * Add vpe's API message handlers to the table.
1697  * vlib has already mapped shared memory and
1698  * added the client registration handlers.
1699  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1700  */
1701
1702 pub_sub_handler (interface_events, INTERFACE_EVENTS);
1703
1704 #include <vnet/interface.api.c>
1705 static clib_error_t *
1706 interface_api_hookup (vlib_main_t * vm)
1707 {
1708   api_main_t *am = vlibapi_get_main ();
1709
1710   /*
1711    * Set up the (msg_name, crc, message-id) table
1712    */
1713   REPLY_MSG_ID_BASE = setup_message_id_table ();
1714
1715   /* Mark these APIs as mp safe */
1716   vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
1717                               1);
1718   vl_api_set_msg_thread_safe (
1719     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS, 1);
1720   vl_api_set_msg_thread_safe (
1721     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL, 1);
1722   vl_api_set_msg_thread_safe (
1723     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME, 1);
1724
1725   /* Do not replay VL_API_SW_INTERFACE_DUMP messages */
1726   vl_api_allow_msg_replay (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
1727                            0);
1728
1729   /* Mark these APIs as autoendian */
1730   vl_api_set_msg_autoendian (
1731     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT, 1);
1732   vl_api_set_msg_autoendian (
1733     am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET, 1);
1734
1735   return 0;
1736 }
1737
1738 VLIB_API_INIT_FUNCTION (interface_api_hookup);
1739
1740 /*
1741  * fd.io coding-style-patch-verification: ON
1742  *
1743  * Local Variables:
1744  * eval: (c-set-style "gnu")
1745  * End:
1746  */