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