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