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