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