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