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