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