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