ip: unlock_fib on if delete
[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);
465   else
466     rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id);
467
468   BAD_SW_IF_INDEX_LABEL;
469
470   REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
471 }
472
473 void
474 fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index)
475 {
476   u32 table_id;
477
478   table_id = fib_table_get_table_id (fib_index, fproto);
479   ASSERT (table_id != ~0);
480
481   if (FIB_PROTOCOL_IP6 == fproto)
482     {
483       /*
484        * tell those that are interested that the binding is changing.
485        */
486       ip6_table_bind_callback_t *cb;
487       vec_foreach (cb, ip6_main.table_bind_callbacks)
488         cb->function (&ip6_main, cb->function_opaque,
489                       sw_if_index,
490                       fib_index,
491                       ip6_main.fib_index_by_sw_if_index[sw_if_index]);
492
493       /* unlock currently assigned tables */
494       if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
495         fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
496                           FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
497
498       if (0 != table_id)
499         {
500           /* we need to lock the table now it's inuse */
501           fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
502         }
503
504       ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
505     }
506   else
507     {
508       /*
509        * tell those that are interested that the binding is changing.
510        */
511       ip4_table_bind_callback_t *cb;
512       vec_foreach (cb, ip4_main.table_bind_callbacks)
513         cb->function (&ip4_main, cb->function_opaque,
514                       sw_if_index,
515                       fib_index,
516                       ip4_main.fib_index_by_sw_if_index[sw_if_index]);
517
518       /* unlock currently assigned tables */
519       if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
520         fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
521                           FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
522
523       if (0 != table_id)
524         {
525           /* we need to lock the table now it's inuse */
526           fib_index = fib_table_find_or_create_and_lock (
527             FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE);
528         }
529
530       ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
531     }
532 }
533
534 void
535 mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index)
536 {
537   u32 table_id;
538
539   table_id = mfib_table_get_table_id (mfib_index, fproto);
540   ASSERT (table_id != ~0);
541
542   if (FIB_PROTOCOL_IP6 == fproto)
543     {
544       if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
545         mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
546                            FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
547
548       if (0 != table_id)
549         {
550           /* we need to lock the table now it's inuse */
551           mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
552                            MFIB_SOURCE_INTERFACE);
553         }
554
555       ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
556     }
557   else
558     {
559       if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
560         mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
561                            FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
562
563       if (0 != table_id)
564         {
565           /* we need to lock the table now it's inuse */
566           mfib_index = mfib_table_find_or_create_and_lock (
567             FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE);
568         }
569
570       ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
571     }
572 }
573
574 int
575 ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
576 {
577   CLIB_UNUSED (ip_interface_address_t * ia);
578   u32 fib_index, mfib_index;
579
580   /*
581    * This if table does not exist = error is what we want in the end.
582    */
583   fib_index = fib_table_find (fproto, table_id);
584   mfib_index = mfib_table_find (fproto, table_id);
585
586   if (~0 == fib_index || ~0 == mfib_index)
587     {
588       return (VNET_API_ERROR_NO_SUCH_FIB);
589     }
590
591   /*
592    * If the interface already has in IP address, then a change int
593    * VRF is not allowed. The IP address applied must first be removed.
594    * We do not do that automatically here, since VPP has no knowledge
595    * of whether those subnets are valid in the destination VRF.
596    */
597   /* clang-format off */
598   foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ?
599                                 &ip6_main.lookup_main : &ip4_main.lookup_main,
600                                 ia, sw_if_index,
601                                 1 /* honor unnumbered */ ,
602   ({
603     return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
604   }));
605   /* clang-format on */
606
607   fib_table_bind (fproto, sw_if_index, fib_index);
608   mfib_table_bind (fproto, sw_if_index, mfib_index);
609
610   return (0);
611 }
612
613 static void
614 send_sw_interface_get_table_reply (vl_api_registration_t * reg,
615                                    u32 context, int retval, u32 vrf_id)
616 {
617   vl_api_sw_interface_get_table_reply_t *mp;
618
619   mp = vl_msg_api_alloc (sizeof (*mp));
620   clib_memset (mp, 0, sizeof (*mp));
621   mp->_vl_msg_id =
622     ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_TABLE_REPLY);
623   mp->context = context;
624   mp->retval = htonl (retval);
625   mp->vrf_id = htonl (vrf_id);
626
627   vl_api_send_msg (reg, (u8 *) mp);
628 }
629
630 static void
631 vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp)
632 {
633   vl_api_registration_t *reg;
634   fib_table_t *fib_table = 0;
635   u32 sw_if_index = ~0;
636   u32 fib_index = ~0;
637   u32 table_id = ~0;
638   fib_protocol_t fib_proto = FIB_PROTOCOL_IP4;
639   int rv = 0;
640
641   reg = vl_api_client_index_to_registration (mp->client_index);
642   if (!reg)
643     return;
644
645   VALIDATE_SW_IF_INDEX (mp);
646
647   sw_if_index = ntohl (mp->sw_if_index);
648
649   if (mp->is_ipv6)
650     fib_proto = FIB_PROTOCOL_IP6;
651
652   fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
653   if (fib_index != ~0)
654     {
655       fib_table = fib_table_get (fib_index, fib_proto);
656       table_id = fib_table->ft_table_id;
657     }
658
659   BAD_SW_IF_INDEX_LABEL;
660
661   send_sw_interface_get_table_reply (reg, mp->context, rv, table_id);
662 }
663
664 static void vl_api_sw_interface_set_unnumbered_t_handler
665   (vl_api_sw_interface_set_unnumbered_t * mp)
666 {
667   vl_api_sw_interface_set_unnumbered_reply_t *rmp;
668   int rv = 0;
669   vnet_main_t *vnm = vnet_get_main ();
670   u32 sw_if_index = ntohl (mp->sw_if_index);
671   u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
672
673   /*
674    * The API message field names are backwards from
675    * the underlying data structure names.
676    * It's not worth changing them now.
677    */
678   if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index))
679     {
680       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
681       goto done;
682     }
683
684   /* Only check the "use loop0" field when setting the binding */
685   if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index))
686     {
687       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
688       goto done;
689     }
690
691   rv = vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
692                                             sw_if_index, mp->is_add);
693 done:
694   REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
695 }
696
697 static void
698 vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
699                                            mp)
700 {
701   vl_api_sw_interface_clear_stats_reply_t *rmp;
702
703   vnet_main_t *vnm = vnet_get_main ();
704   vnet_interface_main_t *im = &vnm->interface_main;
705   vlib_simple_counter_main_t *sm;
706   vlib_combined_counter_main_t *cm;
707   int j, n_counters;
708   int rv = 0;
709
710   if (mp->sw_if_index != ~0)
711     VALIDATE_SW_IF_INDEX (mp);
712
713   n_counters = vec_len (im->combined_sw_if_counters);
714
715   for (j = 0; j < n_counters; j++)
716     {
717       im = &vnm->interface_main;
718       cm = im->combined_sw_if_counters + j;
719       if (mp->sw_if_index == (u32) ~ 0)
720         vlib_clear_combined_counters (cm);
721       else
722         vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
723     }
724
725   n_counters = vec_len (im->sw_if_counters);
726
727   for (j = 0; j < n_counters; j++)
728     {
729       im = &vnm->interface_main;
730       sm = im->sw_if_counters + j;
731       if (mp->sw_if_index == (u32) ~ 0)
732         vlib_clear_simple_counters (sm);
733       else
734         vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
735     }
736
737   BAD_SW_IF_INDEX_LABEL;
738
739   REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
740 }
741
742 /*
743  * Events used for sw_interface_events
744  */
745 enum api_events
746 {
747   API_LINK_STATE_UP_EVENT = 1 << 1,
748   API_LINK_STATE_DOWN_EVENT = 1 << 2,
749   API_ADMIN_UP_EVENT = 1 << 3,
750   API_ADMIN_DOWN_EVENT = 1 << 4,
751   API_SW_INTERFACE_ADD_EVENT = 1 << 5,
752   API_SW_INTERFACE_DEL_EVENT = 1 << 6,
753 };
754
755 static void
756 send_sw_interface_event (vpe_api_main_t * am,
757                          vpe_client_registration_t * reg,
758                          vl_api_registration_t * vl_reg,
759                          u32 sw_if_index, enum api_events events)
760 {
761   vl_api_sw_interface_event_t *mp;
762
763   mp = vl_msg_api_alloc (sizeof (*mp));
764   clib_memset (mp, 0, sizeof (*mp));
765   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_EVENT);
766   mp->sw_if_index = ntohl (sw_if_index);
767   mp->client_index = reg->client_index;
768   mp->pid = reg->client_pid;
769   mp->flags = 0;
770   mp->flags |= (events & API_ADMIN_UP_EVENT) ?
771     IF_STATUS_API_FLAG_ADMIN_UP : 0;
772   mp->flags |= (events & API_LINK_STATE_UP_EVENT) ?
773     IF_STATUS_API_FLAG_LINK_UP : 0;
774   mp->flags = ntohl (mp->flags);
775   mp->deleted = events & API_SW_INTERFACE_DEL_EVENT ? true : false;
776   vl_api_send_msg (vl_reg, (u8 *) mp);
777 }
778
779 static uword
780 link_state_process (vlib_main_t * vm,
781                     vlib_node_runtime_t * rt, vlib_frame_t * f)
782 {
783   vpe_api_main_t *vam = &vpe_api_main;
784   uword *event_by_sw_if_index = 0;
785   vpe_client_registration_t *reg;
786   int i;
787   vl_api_registration_t *vl_reg;
788   uword event_type;
789   uword *event_data = 0;
790   u32 sw_if_index;
791
792   vam->link_state_process_up = 1;
793
794   while (1)
795     {
796       vlib_process_wait_for_event (vm);
797
798       /* Batch up events */
799       while ((event_type = vlib_process_get_events (vm, &event_data)) != ~0)
800         {
801           for (i = 0; i < vec_len (event_data); i++)
802             {
803               sw_if_index = event_data[i];
804               vec_validate_init_empty (event_by_sw_if_index, sw_if_index, 0);
805               event_by_sw_if_index[sw_if_index] |= event_type;
806             }
807           vec_reset_length (event_data);
808         }
809
810       for (i = 0; i < vec_len (event_by_sw_if_index); i++)
811         {
812           if (event_by_sw_if_index[i] == 0)
813             continue;
814
815           /* *INDENT-OFF* */
816           pool_foreach (reg, vam->interface_events_registrations)
817            {
818             vl_reg = vl_api_client_index_to_registration (reg->client_index);
819             if (vl_reg)
820               send_sw_interface_event (vam, reg, vl_reg, i, event_by_sw_if_index[i]);
821           }
822           /* *INDENT-ON* */
823         }
824       vec_reset_length (event_by_sw_if_index);
825     }
826
827   return 0;
828 }
829
830 static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
831                                             u32 flags);
832 static clib_error_t *admin_up_down_function (vnet_main_t * vm,
833                                              u32 hw_if_index, u32 flags);
834 static clib_error_t *sw_interface_add_del_function (vnet_main_t * vm,
835                                                     u32 sw_if_index,
836                                                     u32 flags);
837
838 /* *INDENT-OFF* */
839 VLIB_REGISTER_NODE (link_state_process_node,static) = {
840   .function = link_state_process,
841   .type = VLIB_NODE_TYPE_PROCESS,
842   .name = "vpe-link-state-process",
843 };
844 /* *INDENT-ON* */
845
846 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
847 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
848 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (sw_interface_add_del_function);
849
850 static clib_error_t *
851 link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
852 {
853   vpe_api_main_t *vam = &vpe_api_main;
854   vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
855
856   if (vam->link_state_process_up)
857     {
858       enum api_events event = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
859                                API_LINK_STATE_UP_EVENT :
860                                API_LINK_STATE_DOWN_EVENT);
861       vlib_process_signal_event (vam->vlib_main,
862                                  link_state_process_node.index, event,
863                                  hi->sw_if_index);
864     }
865   return 0;
866 }
867
868 static clib_error_t *
869 admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
870 {
871   vpe_api_main_t *vam = &vpe_api_main;
872
873   /*
874    * Note: it's perfectly fair to set a subif admin up / admin down.
875    * Note the subtle distinction between this routine and the previous
876    * routine.
877    */
878   if (vam->link_state_process_up)
879     {
880       enum api_events event = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
881                                API_ADMIN_UP_EVENT : API_ADMIN_DOWN_EVENT);
882       vlib_process_signal_event (vam->vlib_main,
883                                  link_state_process_node.index, event,
884                                  sw_if_index);
885     }
886   return 0;
887 }
888
889 static clib_error_t *
890 sw_interface_add_del_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
891 {
892   vpe_api_main_t *vam = &vpe_api_main;
893
894   if (vam->link_state_process_up)
895     {
896       enum api_events event =
897         flags ? API_SW_INTERFACE_ADD_EVENT : API_SW_INTERFACE_DEL_EVENT;
898       vlib_process_signal_event (vam->vlib_main,
899                                  link_state_process_node.index, event,
900                                  sw_if_index);
901     }
902   return 0;
903 }
904
905 static void vl_api_sw_interface_tag_add_del_t_handler
906   (vl_api_sw_interface_tag_add_del_t * mp)
907 {
908   vnet_main_t *vnm = vnet_get_main ();
909   vl_api_sw_interface_tag_add_del_reply_t *rmp;
910   int rv = 0;
911   u8 *tag;
912   u32 sw_if_index = ntohl (mp->sw_if_index);
913
914   VALIDATE_SW_IF_INDEX (mp);
915
916   if (mp->is_add)
917     {
918       if (mp->tag[0] == 0)
919         {
920           rv = VNET_API_ERROR_INVALID_VALUE;
921           goto out;
922         }
923
924       mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
925       tag = format (0, "%s%c", mp->tag, 0);
926       vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
927     }
928   else
929     vnet_clear_sw_interface_tag (vnm, sw_if_index);
930
931   BAD_SW_IF_INDEX_LABEL;
932 out:
933   REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY);
934 }
935
936 static void vl_api_sw_interface_add_del_mac_address_t_handler
937   (vl_api_sw_interface_add_del_mac_address_t * mp)
938 {
939   vl_api_sw_interface_add_del_mac_address_reply_t *rmp;
940   vnet_main_t *vnm = vnet_get_main ();
941   u32 sw_if_index = ntohl (mp->sw_if_index);
942   vnet_hw_interface_t *hi;
943   clib_error_t *error;
944   int rv = 0;
945
946   VALIDATE_SW_IF_INDEX (mp);
947
948   /* for subifs, the MAC should be changed on the actual hw if */
949   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
950   error = vnet_hw_interface_add_del_mac_address (vnm, hi->hw_if_index,
951                                                  mp->addr, mp->is_add);
952   if (error)
953     {
954       rv = VNET_API_ERROR_UNIMPLEMENTED;
955       clib_error_report (error);
956       goto out;
957     }
958
959   BAD_SW_IF_INDEX_LABEL;
960 out:
961   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY);
962 }
963
964 static void vl_api_sw_interface_set_mac_address_t_handler
965   (vl_api_sw_interface_set_mac_address_t * mp)
966 {
967   vl_api_sw_interface_set_mac_address_reply_t *rmp;
968   vnet_main_t *vnm = vnet_get_main ();
969   u32 sw_if_index = ntohl (mp->sw_if_index);
970   vnet_sw_interface_t *si;
971   clib_error_t *error;
972   int rv = 0;
973   mac_address_t mac;
974
975   VALIDATE_SW_IF_INDEX (mp);
976
977   si = vnet_get_sw_interface (vnm, sw_if_index);
978   mac_address_decode (mp->mac_address, &mac);
979   error =
980     vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, (u8 *) & mac);
981   if (error)
982     {
983       rv = VNET_API_ERROR_UNIMPLEMENTED;
984       clib_error_report (error);
985       goto out;
986     }
987
988   BAD_SW_IF_INDEX_LABEL;
989 out:
990   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY);
991 }
992
993 static void vl_api_sw_interface_get_mac_address_t_handler
994   (vl_api_sw_interface_get_mac_address_t * mp)
995 {
996   vl_api_sw_interface_get_mac_address_reply_t *rmp;
997   vl_api_registration_t *reg;
998   vnet_main_t *vnm = vnet_get_main ();
999   u32 sw_if_index = ntohl (mp->sw_if_index);
1000   vnet_sw_interface_t *si;
1001   ethernet_interface_t *eth_if = 0;
1002   int rv = 0;
1003
1004   VALIDATE_SW_IF_INDEX (mp);
1005
1006   si = vnet_get_sup_sw_interface (vnm, sw_if_index);
1007   if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
1008     eth_if = ethernet_get_interface (&ethernet_main, si->hw_if_index);
1009
1010   BAD_SW_IF_INDEX_LABEL;
1011
1012   reg = vl_api_client_index_to_registration (mp->client_index);
1013   if (!reg)
1014     return;
1015   rmp = vl_msg_api_alloc (sizeof (*rmp));
1016   rmp->_vl_msg_id =
1017     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY);
1018   rmp->context = mp->context;
1019   rmp->retval = htonl (rv);
1020   if (!rv && eth_if)
1021     mac_address_encode (&eth_if->address.mac, rmp->mac_address);
1022   vl_api_send_msg (reg, (u8 *) rmp);
1023 }
1024
1025 static void
1026 vl_api_sw_interface_set_interface_name_t_handler (
1027   vl_api_sw_interface_set_interface_name_t *mp)
1028 {
1029   vl_api_sw_interface_set_interface_name_reply_t *rmp;
1030   vnet_main_t *vnm = vnet_get_main ();
1031   u32 sw_if_index = ntohl (mp->sw_if_index);
1032   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
1033   clib_error_t *error;
1034   int rv = 0;
1035
1036   if (mp->name[0] == 0)
1037     {
1038       rv = VNET_API_ERROR_INVALID_VALUE;
1039       goto out;
1040     }
1041   if (si == 0)
1042     {
1043       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1044       goto out;
1045     }
1046
1047   error = vnet_rename_interface (vnm, si->hw_if_index, (char *) mp->name);
1048   if (error)
1049     {
1050       clib_error_free (error);
1051       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1052     }
1053
1054 out:
1055   REPLY_MACRO (VL_API_SW_INTERFACE_SET_INTERFACE_NAME_REPLY);
1056 }
1057
1058 static void vl_api_sw_interface_set_rx_mode_t_handler
1059   (vl_api_sw_interface_set_rx_mode_t * mp)
1060 {
1061   vl_api_sw_interface_set_rx_mode_reply_t *rmp;
1062   vnet_main_t *vnm = vnet_get_main ();
1063   u32 sw_if_index = ntohl (mp->sw_if_index);
1064   vnet_sw_interface_t *si;
1065   clib_error_t *error;
1066   int rv = 0;
1067   vnet_hw_if_rx_mode rx_mode;
1068
1069   VALIDATE_SW_IF_INDEX (mp);
1070
1071   si = vnet_get_sw_interface (vnm, sw_if_index);
1072   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1073     {
1074       rv = VNET_API_ERROR_INVALID_VALUE;
1075       goto bad_sw_if_index;
1076     }
1077
1078   rx_mode = (vnet_hw_if_rx_mode) ntohl (mp->mode);
1079   error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index,
1080                                            mp->queue_id_valid,
1081                                            ntohl (mp->queue_id),
1082                                            (vnet_hw_if_rx_mode) rx_mode);
1083
1084   if (error)
1085     {
1086       rv = VNET_API_ERROR_UNIMPLEMENTED;
1087       clib_error_report (error);
1088       goto out;
1089     }
1090
1091   BAD_SW_IF_INDEX_LABEL;
1092 out:
1093   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_MODE_REPLY);
1094 }
1095
1096 static void
1097 send_interface_rx_placement_details (vpe_api_main_t * am,
1098                                      vl_api_registration_t * rp,
1099                                      u32 sw_if_index, u32 worker_id,
1100                                      u32 queue_id, u8 mode, u32 context)
1101 {
1102   vl_api_sw_interface_rx_placement_details_t *mp;
1103   mp = vl_msg_api_alloc (sizeof (*mp));
1104   clib_memset (mp, 0, sizeof (*mp));
1105
1106   mp->_vl_msg_id =
1107     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_RX_PLACEMENT_DETAILS);
1108   mp->sw_if_index = htonl (sw_if_index);
1109   mp->queue_id = htonl (queue_id);
1110   mp->worker_id = htonl (worker_id);
1111   mp->mode = htonl (mode);
1112   mp->context = context;
1113
1114   vl_api_send_msg (rp, (u8 *) mp);
1115 }
1116
1117 static void vl_api_sw_interface_rx_placement_dump_t_handler
1118   (vl_api_sw_interface_rx_placement_dump_t * mp)
1119 {
1120   vnet_main_t *vnm = vnet_get_main ();
1121   vpe_api_main_t *am = &vpe_api_main;
1122   u32 sw_if_index = ntohl (mp->sw_if_index);
1123   vl_api_registration_t *reg;
1124
1125   reg = vl_api_client_index_to_registration (mp->client_index);
1126   if (!reg)
1127     return;
1128
1129   if (sw_if_index == ~0)
1130     {
1131       vnet_hw_if_rx_queue_t **all_queues = 0;
1132       vnet_hw_if_rx_queue_t **qptr;
1133       vnet_hw_if_rx_queue_t *q;
1134       pool_foreach (q, vnm->interface_main.hw_if_rx_queues)
1135         vec_add1 (all_queues, q);
1136       vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api);
1137
1138       vec_foreach (qptr, all_queues)
1139         {
1140           u32 current_thread = qptr[0]->thread_index;
1141           u32 hw_if_index = qptr[0]->hw_if_index;
1142           vnet_hw_interface_t *hw_if =
1143             vnet_get_hw_interface (vnm, hw_if_index);
1144           send_interface_rx_placement_details (
1145             am, reg, hw_if->sw_if_index, current_thread, qptr[0]->queue_id,
1146             qptr[0]->mode, mp->context);
1147         }
1148       vec_free (all_queues);
1149     }
1150   else
1151     {
1152       int i;
1153       vnet_sw_interface_t *si;
1154
1155       if (!vnet_sw_if_index_is_api_valid (sw_if_index))
1156         {
1157           clib_warning ("sw_if_index %u does not exist", sw_if_index);
1158           goto bad_sw_if_index;
1159         }
1160
1161       si = vnet_get_sw_interface (vnm, sw_if_index);
1162       if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1163         {
1164           clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
1165                         " interfaces are not supported");
1166           goto bad_sw_if_index;
1167         }
1168
1169       vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
1170
1171       for (i = 0; i < vec_len (hw->rx_queue_indices); i++)
1172         {
1173           vnet_hw_if_rx_queue_t *rxq =
1174             vnet_hw_if_get_rx_queue (vnm, hw->rx_queue_indices[i]);
1175           send_interface_rx_placement_details (
1176             am, reg, hw->sw_if_index, rxq->thread_index, rxq->queue_id,
1177             rxq->mode, mp->context);
1178         }
1179     }
1180
1181   BAD_SW_IF_INDEX_LABEL;
1182 }
1183
1184 static void vl_api_sw_interface_set_rx_placement_t_handler
1185   (vl_api_sw_interface_set_rx_placement_t * mp)
1186 {
1187   vl_api_sw_interface_set_rx_placement_reply_t *rmp;
1188   vnet_main_t *vnm = vnet_get_main ();
1189   u32 sw_if_index = ntohl (mp->sw_if_index);
1190   vnet_sw_interface_t *si;
1191   clib_error_t *error = 0;
1192   int rv = 0;
1193
1194   VALIDATE_SW_IF_INDEX (mp);
1195
1196   si = vnet_get_sw_interface (vnm, sw_if_index);
1197   if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1198     {
1199       rv = VNET_API_ERROR_INVALID_VALUE;
1200       goto bad_sw_if_index;
1201     }
1202
1203   error = set_hw_interface_rx_placement (si->hw_if_index,
1204                                          ntohl (mp->queue_id),
1205                                          ntohl (mp->worker_id), mp->is_main);
1206   if (error)
1207     {
1208       rv = VNET_API_ERROR_UNIMPLEMENTED;
1209       clib_error_report (error);
1210       goto out;
1211     }
1212
1213   BAD_SW_IF_INDEX_LABEL;
1214 out:
1215   REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY);
1216 }
1217
1218 static void
1219 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1220 {
1221   vl_api_create_vlan_subif_reply_t *rmp;
1222   vnet_main_t *vnm = vnet_get_main ();
1223   u32 sw_if_index = (u32) ~ 0;
1224   vnet_hw_interface_t *hi;
1225   int rv = 0;
1226   u32 id;
1227   vnet_sw_interface_t template;
1228   uword *p;
1229   vnet_interface_main_t *im = &vnm->interface_main;
1230   u64 sup_and_sub_key;
1231   vl_api_registration_t *reg;
1232   clib_error_t *error;
1233
1234   VALIDATE_SW_IF_INDEX (mp);
1235
1236   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1237
1238   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1239     {
1240       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1241       goto out;
1242     }
1243
1244   id = ntohl (mp->vlan_id);
1245   if (id == 0 || id > 4095)
1246     {
1247       rv = VNET_API_ERROR_INVALID_VLAN;
1248       goto out;
1249     }
1250
1251   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1252
1253   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1254   if (p)
1255     {
1256       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1257       goto out;
1258     }
1259
1260   clib_memset (&template, 0, sizeof (template));
1261   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1262   template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1263   template.sup_sw_if_index = hi->sw_if_index;
1264   template.sub.id = id;
1265   template.sub.eth.raw_flags = 0;
1266   template.sub.eth.flags.one_tag = 1;
1267   template.sub.eth.outer_vlan_id = id;
1268   template.sub.eth.flags.exact_match = 1;
1269
1270   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1271   if (error)
1272     {
1273       clib_error_report (error);
1274       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1275       goto out;
1276     }
1277
1278   u64 *kp = clib_mem_alloc (sizeof (*kp));
1279   *kp = sup_and_sub_key;
1280
1281   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1282   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1283
1284   BAD_SW_IF_INDEX_LABEL;
1285
1286 out:
1287   reg = vl_api_client_index_to_registration (mp->client_index);
1288   if (!reg)
1289     return;
1290
1291   rmp = vl_msg_api_alloc (sizeof (*rmp));
1292   rmp->_vl_msg_id = htons (REPLY_MSG_ID_BASE + VL_API_CREATE_VLAN_SUBIF_REPLY);
1293   rmp->context = mp->context;
1294   rmp->retval = htonl (rv);
1295   rmp->sw_if_index = htonl (sw_if_index);
1296   vl_api_send_msg (reg, (u8 *) rmp);
1297 }
1298
1299 static void
1300 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1301 {
1302   vl_api_create_subif_reply_t *rmp;
1303   vnet_main_t *vnm = vnet_get_main ();
1304   u32 sub_sw_if_index = ~0;
1305   vnet_hw_interface_t *hi;
1306   int rv = 0;
1307
1308   VALIDATE_SW_IF_INDEX (mp);
1309
1310   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1311
1312   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1313     rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1314   else
1315     rv = vnet_create_sub_interface (ntohl (mp->sw_if_index),
1316                                     ntohl (mp->sub_id),
1317                                     ntohl (mp->sub_if_flags),
1318                                     ntohs (mp->inner_vlan_id),
1319                                     ntohs (mp->outer_vlan_id),
1320                                     &sub_sw_if_index);
1321
1322   BAD_SW_IF_INDEX_LABEL;
1323
1324   /* *INDENT-OFF* */
1325   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1326   ({
1327     rmp->sw_if_index = ntohl(sub_sw_if_index);
1328   }));
1329   /* *INDENT-ON* */
1330 }
1331
1332 static void
1333 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
1334 {
1335   vl_api_delete_subif_reply_t *rmp;
1336   int rv;
1337
1338   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
1339
1340   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
1341 }
1342
1343 static void
1344 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
1345                                           mp)
1346 {
1347   vl_api_interface_name_renumber_reply_t *rmp;
1348   int rv = 0;
1349
1350   VALIDATE_SW_IF_INDEX (mp);
1351
1352   rv = vnet_interface_name_renumber
1353     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
1354
1355   BAD_SW_IF_INDEX_LABEL;
1356
1357   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
1358 }
1359
1360 static void
1361 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1362 {
1363   vl_api_create_loopback_reply_t *rmp;
1364   u32 sw_if_index;
1365   int rv;
1366   mac_address_t mac;
1367
1368   mac_address_decode (mp->mac_address, &mac);
1369   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 0, 0);
1370
1371   /* *INDENT-OFF* */
1372   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1373   ({
1374     rmp->sw_if_index = ntohl (sw_if_index);
1375   }));
1376   /* *INDENT-ON* */
1377 }
1378
1379 static void vl_api_create_loopback_instance_t_handler
1380   (vl_api_create_loopback_instance_t * mp)
1381 {
1382   vl_api_create_loopback_instance_reply_t *rmp;
1383   u32 sw_if_index;
1384   u8 is_specified = mp->is_specified;
1385   u32 user_instance = ntohl (mp->user_instance);
1386   int rv;
1387   mac_address_t mac;
1388
1389   mac_address_decode (mp->mac_address, &mac);
1390   rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac,
1391                                        is_specified, user_instance);
1392
1393   /* *INDENT-OFF* */
1394   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_INSTANCE_REPLY,
1395   ({
1396     rmp->sw_if_index = ntohl (sw_if_index);
1397   }));
1398   /* *INDENT-ON* */
1399 }
1400
1401 static void
1402 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1403 {
1404   vl_api_delete_loopback_reply_t *rmp;
1405   u32 sw_if_index;
1406   int rv;
1407
1408   sw_if_index = ntohl (mp->sw_if_index);
1409   rv = vnet_delete_loopback_interface (sw_if_index);
1410
1411   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1412 }
1413
1414 static void
1415   vl_api_collect_detailed_interface_stats_t_handler
1416   (vl_api_collect_detailed_interface_stats_t * mp)
1417 {
1418   vl_api_collect_detailed_interface_stats_reply_t *rmp;
1419   int rv = 0;
1420
1421   rv =
1422     vnet_sw_interface_stats_collect_enable_disable (ntohl (mp->sw_if_index),
1423                                                     mp->enable_disable);
1424
1425   REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY);
1426 }
1427
1428 static void
1429   vl_api_sw_interface_address_replace_begin_t_handler
1430   (vl_api_sw_interface_address_replace_begin_t * mp)
1431 {
1432   vl_api_sw_interface_address_replace_begin_reply_t *rmp;
1433   int rv = 0;
1434
1435   ip_interface_address_mark ();
1436
1437   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_BEGIN_REPLY);
1438 }
1439
1440 static void
1441   vl_api_sw_interface_address_replace_end_t_handler
1442   (vl_api_sw_interface_address_replace_end_t * mp)
1443 {
1444   vl_api_sw_interface_address_replace_end_reply_t *rmp;
1445   int rv = 0;
1446
1447   ip_interface_address_sweep ();
1448
1449   REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY);
1450 }
1451
1452 /*
1453  * vpe_api_hookup
1454  * Add vpe's API message handlers to the table.
1455  * vlib has already mapped shared memory and
1456  * added the client registration handlers.
1457  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1458  */
1459
1460 pub_sub_handler (interface_events, INTERFACE_EVENTS);
1461
1462 #include <vnet/interface.api.c>
1463 static clib_error_t *
1464 interface_api_hookup (vlib_main_t * vm)
1465 {
1466   api_main_t *am = vlibapi_get_main ();
1467
1468   /* Mark these APIs as mp safe */
1469   am->is_mp_safe[VL_API_SW_INTERFACE_DUMP] = 1;
1470   am->is_mp_safe[VL_API_SW_INTERFACE_DETAILS] = 1;
1471   am->is_mp_safe[VL_API_SW_INTERFACE_TAG_ADD_DEL] = 1;
1472   am->is_mp_safe[VL_API_SW_INTERFACE_SET_INTERFACE_NAME] = 1;
1473
1474   /* Do not replay VL_API_SW_INTERFACE_DUMP messages */
1475   am->api_trace_cfg[VL_API_SW_INTERFACE_DUMP].replay_enable = 0;
1476
1477   /*
1478    * Set up the (msg_name, crc, message-id) table
1479    */
1480   REPLY_MSG_ID_BASE = setup_message_id_table ();
1481
1482   return 0;
1483 }
1484
1485 VLIB_API_INIT_FUNCTION (interface_api_hookup);
1486
1487 /*
1488  * fd.io coding-style-patch-verification: ON
1489  *
1490  * Local Variables:
1491  * eval: (c-set-style "gnu")
1492  * End:
1493  */