FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
interface_api.c
Go to the documentation of this file.
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 #define vl_typedefs /* define message structures */
35 #include <vnet/vnet_all_api_h.h>
36 #undef vl_typedefs
37 
38 #define vl_endianfun /* define message structures */
39 #include <vnet/vnet_all_api_h.h>
40 #undef vl_endianfun
41 
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <vnet/vnet_all_api_h.h>
46 #undef vl_printfun
47 
50 
51 #define foreach_vpe_api_msg \
52 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \
53 _(SW_INTERFACE_SET_MTU, sw_interface_set_mtu) \
54 _(WANT_INTERFACE_EVENTS, want_interface_events) \
55 _(SW_INTERFACE_DUMP, sw_interface_dump) \
56 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \
57 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \
58 _(SW_INTERFACE_GET_TABLE, sw_interface_get_table) \
59 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \
60 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \
61 _(SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del) \
62 _(SW_INTERFACE_SET_MAC_ADDRESS, sw_interface_set_mac_address)
63 
64 static void
66 {
67  vl_api_sw_interface_set_flags_reply_t *rmp;
68  vnet_main_t *vnm = vnet_get_main ();
69  int rv = 0;
70  clib_error_t *error;
71  u16 flags;
72 
74 
76 
77  error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags);
78  if (error)
79  {
80  rv = -1;
81  clib_error_report (error);
82  }
83 
85  REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
86 }
87 
88 static void
90 {
91  vl_api_sw_interface_set_mtu_reply_t *rmp;
92  vnet_main_t *vnm = vnet_get_main ();
94  u32 sw_if_index = ntohl (mp->sw_if_index);
95  u16 mtu = ntohs (mp->mtu);
97  int rv = 0;
98 
100 
101  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
103  {
104  rv = VNET_API_ERROR_INVALID_VALUE;
105  goto bad_sw_if_index;
106  }
107 
110 
111  if (!eif)
112  {
113  rv = VNET_API_ERROR_FEATURE_DISABLED;
114  goto bad_sw_if_index;
115  }
116 
117  if (mtu < hi->min_supported_packet_bytes)
118  {
119  rv = VNET_API_ERROR_INVALID_VALUE;
120  goto bad_sw_if_index;
121  }
122 
123  if (mtu > hi->max_supported_packet_bytes)
124  {
125  rv = VNET_API_ERROR_INVALID_VALUE;
126  goto bad_sw_if_index;
127  }
128 
129  if (hi->max_packet_bytes != mtu)
130  {
131  hi->max_packet_bytes = mtu;
132  ethernet_set_flags (vnm, si->hw_if_index, flags);
133  }
134 
136  REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY);
137 }
138 
139 static void
142  vnet_sw_interface_t * swif,
143  u8 * interface_name, u32 context)
144 {
147 
148  vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
149  memset (mp, 0, sizeof (*mp));
150  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_DETAILS);
151  mp->sw_if_index = ntohl (swif->sw_if_index);
152  mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
153  mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
154  mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
159  mp->link_mtu = ntohs (hi->max_packet_bytes);
160  mp->context = context;
161 
162  strncpy ((char *) mp->interface_name,
163  (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
164 
165  /* Send the L2 address for ethernet physical intfcs */
166  if (swif->sup_sw_if_index == swif->sw_if_index
168  {
171 
172  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
173  ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
174  clib_memcpy (mp->l2_address, ei->address, sizeof (ei->address));
175  mp->l2_address_length = ntohl (sizeof (ei->address));
176  }
177  else if (swif->sup_sw_if_index != swif->sw_if_index)
178  {
179  vnet_sub_interface_t *sub = &swif->sub;
180  mp->sub_id = ntohl (sub->id);
181  mp->sub_dot1ad = sub->eth.flags.dot1ad;
182  mp->sub_number_of_tags =
183  sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
184  mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
185  mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
186  mp->sub_exact_match = sub->eth.flags.exact_match;
187  mp->sub_default = sub->eth.flags.default_sub;
188  mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
189  mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
190 
191  /* vlan tag rewrite data */
192  u32 vtr_op = L2_VTR_DISABLED;
193  u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
194 
195  if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
196  &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
197  {
198  // error - default to disabled
199  mp->vtr_op = ntohl (L2_VTR_DISABLED);
200  clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
201  swif->sw_if_index);
202  }
203  else
204  {
205  mp->vtr_op = ntohl (vtr_op);
206  mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
207  mp->vtr_tag1 = ntohl (vtr_tag1);
208  mp->vtr_tag2 = ntohl (vtr_tag2);
209  }
210  }
211 
212  /* pbb tag rewrite data */
213  ethernet_header_t eth_hdr;
214  u32 vtr_op = L2_VTR_DISABLED;
215  u16 outer_tag = 0;
216  u16 b_vlanid = 0;
217  u32 i_sid = 0;
218  memset (&eth_hdr, 0, sizeof (eth_hdr));
219 
220  if (!l2pbb_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
221  &vtr_op, &outer_tag, &eth_hdr, &b_vlanid, &i_sid))
222  {
223  mp->sub_dot1ah = 1;
224  clib_memcpy (mp->b_dmac, eth_hdr.dst_address,
225  sizeof (eth_hdr.dst_address));
226  clib_memcpy (mp->b_smac, eth_hdr.src_address,
227  sizeof (eth_hdr.src_address));
228  mp->b_vlanid = b_vlanid;
229  mp->i_sid = i_sid;
230  }
231 
233  if (tag)
234  strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
235 
236  vl_msg_api_send_shmem (q, (u8 *) & mp);
237 }
238 
239 static void
241 {
243  vnet_sw_interface_t *swif;
245 
248  if (q == 0)
249  return;
250 
251  u8 *filter = 0, *name = 0;
252  if (mp->name_filter_valid)
253  {
254  mp->name_filter[ARRAY_LEN (mp->name_filter) - 1] = 0;
255  filter = format (0, "%s%c", mp->name_filter, 0);
256  }
257 
258  char *strcasestr (char *, char *); /* lnx hdr file botch */
259  /* *INDENT-OFF* */
260  pool_foreach (swif, im->sw_interfaces,
261  ({
262  if (!vnet_swif_is_api_visible (swif))
263  continue;
264  vec_reset_length(name);
265  name = format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
266  swif, 0);
267 
268  if (filter && !strcasestr((char *) name, (char *) filter))
269  continue;
270 
271  send_sw_interface_details (am, q, swif, name, mp->context);
272  }));
273  /* *INDENT-ON* */
274 
275  vec_free (name);
276  vec_free (filter);
277 }
278 
279 static void
282 {
283  vlib_main_t *vm = vlib_get_main ();
284  vnet_main_t *vnm = vnet_get_main ();
285  vl_api_sw_interface_add_del_address_reply_t *rmp;
286  int rv = 0;
287  u32 is_del;
288  clib_error_t *error = 0;
289 
291 
292  is_del = mp->is_add == 0;
293  vnm->api_errno = 0;
294 
295  if (mp->del_all)
297  else if (mp->is_ipv6)
298  error = ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
299  (void *) mp->address,
300  mp->address_length, is_del);
301  else
302  error = ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
303  (void *) mp->address,
304  mp->address_length, is_del);
305 
306  if (error)
307  {
308  rv = vnm->api_errno;
309  clib_error_report (error);
310  goto done;
311  }
312 
314 
315 done:
316  REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
317 }
318 
319 void stats_dslock_with_hint (int hint, int tag) __attribute__ ((weak));
320 void
321 stats_dslock_with_hint (int hint, int tag)
322 {
323 }
324 
325 void stats_dsunlock (void) __attribute__ ((weak));
326 void
328 {
329 }
330 
331 static void
333 {
334  vl_api_sw_interface_set_table_reply_t *rmp;
335  u32 sw_if_index = ntohl (mp->sw_if_index);
336  u32 table_id = ntohl (mp->vrf_id);
337  int rv = 0;
338 
340 
341  stats_dslock_with_hint (1 /* release hint */ , 4 /* tag */ );
342 
343  if (mp->is_ipv6)
344  rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id, 1);
345  else
346  rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id, 1);
347 
348  stats_dsunlock ();
349 
351 
352  REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
353 }
354 
355 int
357  u32 sw_if_index, u32 table_id, u8 is_api)
358 {
360  u32 fib_index, mfib_index;
361  fib_source_t src;
362  mfib_source_t msrc;
363 
364  if (is_api)
365  {
366  src = FIB_SOURCE_API;
367  msrc = MFIB_SOURCE_API;
368  }
369  else
370  {
371  src = FIB_SOURCE_CLI;
372  msrc = MFIB_SOURCE_CLI;
373  }
374 
375  /*
376  * This is temporary whilst I do the song and dance with the CSIT version
377  */
378  if (0 != table_id)
379  {
380  fib_index = fib_table_find_or_create_and_lock (fproto, table_id, src);
381  mfib_index =
382  mfib_table_find_or_create_and_lock (fproto, table_id, msrc);
383  }
384  else
385  {
386  fib_index = 0;
387  mfib_index = 0;
388  }
389 
390  /*
391  * This if table does not exist = error is what we want in the end.
392  */
393  /* fib_index = fib_table_find (fproto, table_id); */
394  /* mfib_index = mfib_table_find (fproto, table_id); */
395 
396  /* if (~0 == fib_index || ~0 == mfib_index) */
397  /* { */
398  /* return (VNET_API_ERROR_NO_SUCH_FIB); */
399  /* } */
400 
401  if (FIB_PROTOCOL_IP6 == fproto)
402  {
403  /*
404  * If the interface already has in IP address, then a change int
405  * VRF is not allowed. The IP address applied must first be removed.
406  * We do not do that automatically here, since VPP has no knowledge
407  * of whether thoses subnets are valid in the destination VRF.
408  */
409  /* *INDENT-OFF* */
411  ia, sw_if_index,
412  1 /* honor unnumbered */ ,
413  ({
414  return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
415  }));
416  /* *INDENT-ON* */
417 
420 
421  /*
422  * tell those that are interested that the binding is changing.
423  */
426  cb->function (&ip6_main, cb->function_opaque,
427  sw_if_index,
428  fib_index,
429  ip6_main.fib_index_by_sw_if_index[sw_if_index]);
430 
431  if (0 == table_id)
432  {
433  /* reset back to default */
434  if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
436  FIB_PROTOCOL_IP6, src);
437  if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
439  [sw_if_index], FIB_PROTOCOL_IP6, msrc);
440 
441  }
442  else
443  {
444  /* we need to lock the table now it's inuse */
445  fib_table_lock (fib_index, FIB_PROTOCOL_IP6, src);
446  mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6, msrc);
447  }
448 
449  ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
450  ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
451  }
452  else
453  {
454  /*
455  * If the interface already has in IP address, then a change int
456  * VRF is not allowed. The IP address applied must first be removed.
457  * We do not do that automatically here, since VPP has no knowledge
458  * of whether thoses subnets are valid in the destination VRF.
459  */
460  /* *INDENT-OFF* */
462  ia, sw_if_index,
463  1 /* honor unnumbered */ ,
464  ({
465  return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
466  }));
467  /* *INDENT-ON* */
468 
471 
472  /*
473  * tell those that are interested that the binding is changing.
474  */
477  cb->function (&ip4_main, cb->function_opaque,
478  sw_if_index,
479  fib_index,
480  ip4_main.fib_index_by_sw_if_index[sw_if_index]);
481 
482  if (0 == table_id)
483  {
484  /* reset back to default */
485  if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
487  FIB_PROTOCOL_IP4, src);
488  if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
490  [sw_if_index], FIB_PROTOCOL_IP4, msrc);
491 
492  }
493  else
494  {
495  /* we need to lock the table now it's inuse */
497  table_id, src);
498 
500  table_id, msrc);
501  }
502 
503  ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
504  ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
505  }
506 
507  /*
508  * Temporary. undo the locks from the find and create at the staart
509  */
510  if (0 != table_id)
511  {
512  fib_table_unlock (fib_index, fproto, src);
513  mfib_table_unlock (mfib_index, fproto, msrc);
514  }
515 
516  return (0);
517 }
518 
519 static void
521  u32 context, int retval, u32 vrf_id)
522 {
524 
525  mp = vl_msg_api_alloc (sizeof (*mp));
526  memset (mp, 0, sizeof (*mp));
527  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_GET_TABLE_REPLY);
528  mp->context = context;
529  mp->retval = htonl (retval);
530  mp->vrf_id = htonl (vrf_id);
531 
532  vl_msg_api_send_shmem (q, (u8 *) & mp);
533 }
534 
535 static void
537 {
539  fib_table_t *fib_table = 0;
540  u32 sw_if_index = ~0;
541  u32 fib_index = ~0;
542  u32 table_id = ~0;
543  fib_protocol_t fib_proto = FIB_PROTOCOL_IP4;
544  int rv = 0;
545 
547  if (q == 0)
548  return;
549 
551 
552  sw_if_index = ntohl (mp->sw_if_index);
553 
554  if (mp->is_ipv6)
555  fib_proto = FIB_PROTOCOL_IP6;
556 
557  fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
558  if (fib_index != ~0)
559  {
560  fib_table = fib_table_get (fib_index, fib_proto);
561  table_id = fib_table->ft_table_id;
562  }
563 
565 
566  send_sw_interface_get_table_reply (q, mp->context, rv, table_id);
567 }
568 
571 {
572  vl_api_sw_interface_set_unnumbered_reply_t *rmp;
573  int rv = 0;
574  vnet_main_t *vnm = vnet_get_main ();
575  u32 sw_if_index = ntohl (mp->sw_if_index);
576  u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
577  u32 was_unnum;
578 
579  /*
580  * The API message field names are backwards from
581  * the underlying data structure names.
582  * It's not worth changing them now.
583  */
584  if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index))
585  {
586  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
587  goto done;
588  }
589 
590  /* Only check the "use loop0" field when setting the binding */
591  if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index))
592  {
593  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
594  goto done;
595  }
596 
597  vnet_sw_interface_t *si =
598  vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
599  was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED);
600 
601  if (mp->is_add)
602  {
604  si->unnumbered_sw_if_index = sw_if_index;
605 
607  [unnumbered_sw_if_index] =
608  ip4_main.
609  lookup_main.if_address_pool_index_by_sw_if_index[sw_if_index];
610  ip6_main.
611  lookup_main.if_address_pool_index_by_sw_if_index
612  [unnumbered_sw_if_index] =
613  ip6_main.
614  lookup_main.if_address_pool_index_by_sw_if_index[sw_if_index];
615  }
616  else
617  {
619  si->unnumbered_sw_if_index = (u32) ~ 0;
620 
622  [unnumbered_sw_if_index] = ~0;
624  [unnumbered_sw_if_index] = ~0;
625  }
626 
627  if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
628  {
629  ip4_sw_interface_enable_disable (unnumbered_sw_if_index, mp->is_add);
630  ip6_sw_interface_enable_disable (unnumbered_sw_if_index, mp->is_add);
631  }
632 
633 done:
634  REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
635 }
636 
637 static void
639  mp)
640 {
641  vl_api_sw_interface_clear_stats_reply_t *rmp;
642 
643  vnet_main_t *vnm = vnet_get_main ();
647  static vnet_main_t **my_vnet_mains;
648  int i, j, n_counters;
649  int rv = 0;
650 
651  if (mp->sw_if_index != ~0)
653 
654  vec_reset_length (my_vnet_mains);
655 
656  for (i = 0; i < vec_len (vnet_mains); i++)
657  {
658  if (vnet_mains[i])
659  vec_add1 (my_vnet_mains, vnet_mains[i]);
660  }
661 
662  if (vec_len (vnet_mains) == 0)
663  vec_add1 (my_vnet_mains, vnm);
664 
665  n_counters = vec_len (im->combined_sw_if_counters);
666 
667  for (j = 0; j < n_counters; j++)
668  {
669  for (i = 0; i < vec_len (my_vnet_mains); i++)
670  {
671  im = &my_vnet_mains[i]->interface_main;
672  cm = im->combined_sw_if_counters + j;
673  if (mp->sw_if_index == (u32) ~ 0)
675  else
676  vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
677  }
678  }
679 
680  n_counters = vec_len (im->sw_if_counters);
681 
682  for (j = 0; j < n_counters; j++)
683  {
684  for (i = 0; i < vec_len (my_vnet_mains); i++)
685  {
686  im = &my_vnet_mains[i]->interface_main;
687  sm = im->sw_if_counters + j;
688  if (mp->sw_if_index == (u32) ~ 0)
690  else
691  vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
692  }
693  }
694 
696 
697  REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
698 }
699 
700 #define API_LINK_STATE_EVENT 1
701 #define API_ADMIN_UP_DOWN_EVENT 2
702 
703 static int
704 event_data_cmp (void *a1, void *a2)
705 {
706  uword *e1 = a1;
707  uword *e2 = a2;
708 
709  return (word) e1[0] - (word) e2[0];
710 }
711 
712 static void
716  vnet_sw_interface_t * swif)
717 {
719  vnet_main_t *vnm = am->vnet_main;
720 
722  swif->sw_if_index);
723  mp = vl_msg_api_alloc (sizeof (*mp));
724  memset (mp, 0, sizeof (*mp));
725  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_EVENT);
726  mp->sw_if_index = ntohl (swif->sw_if_index);
727  mp->client_index = reg->client_index;
728  mp->pid = reg->client_pid;
729 
730  mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
731  mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
732  vl_msg_api_send_shmem (q, (u8 *) & mp);
733 }
734 
735 static uword
738 {
740  vnet_main_t *vnm = vam->vnet_main;
741  vnet_sw_interface_t *swif;
742  uword *event_data = 0;
744  int i;
745  u32 prev_sw_if_index;
747 
748  vam->link_state_process_up = 1;
749 
750  while (1)
751  {
753 
754  /* Unified list of changed link or admin state sw_if_indices */
756  (vm, &event_data, API_LINK_STATE_EVENT);
758  (vm, &event_data, API_ADMIN_UP_DOWN_EVENT);
759 
760  /* Sort, so we can eliminate duplicates */
762 
763  prev_sw_if_index = ~0;
764 
765  for (i = 0; i < vec_len (event_data); i++)
766  {
767  /* Only one message per swif */
768  if (prev_sw_if_index == event_data[i])
769  continue;
770  prev_sw_if_index = event_data[i];
771 
772  /* *INDENT-OFF* */
773  pool_foreach(reg, vam->interface_events_registrations,
774  ({
775  q = vl_api_client_index_to_input_queue (reg->client_index);
776  if (q)
777  {
778  /* sw_interface may be deleted already */
779  if (!pool_is_free_index (vnm->interface_main.sw_interfaces,
780  event_data[i]))
781  {
782  swif = vnet_get_sw_interface (vnm, event_data[i]);
783  send_sw_interface_event (vam, reg, q, swif);
784  }
785  }
786  }));
787  /* *INDENT-ON* */
788  }
789  vec_reset_length (event_data);
790  }
791 
792  return 0;
793 }
794 
795 static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
796  u32 flags);
798  u32 hw_if_index, u32 flags);
799 
800 /* *INDENT-OFF* */
801 VLIB_REGISTER_NODE (link_state_process_node,static) = {
802  .function = link_state_process,
803  .type = VLIB_NODE_TYPE_PROCESS,
804  .name = "vpe-link-state-process",
805 };
806 /* *INDENT-ON* */
807 
808 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
809 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
810 
811 static clib_error_t *
812 link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
813 {
815  vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
816 
817  if (vam->link_state_process_up)
819  link_state_process_node.index,
821  return 0;
822 }
823 
824 static clib_error_t *
825 admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
826 {
828 
829  /*
830  * Note: it's perfectly fair to set a subif admin up / admin down.
831  * Note the subtle distinction between this routine and the previous
832  * routine.
833  */
834  if (vam->link_state_process_up)
836  link_state_process_node.index,
837  API_ADMIN_UP_DOWN_EVENT, sw_if_index);
838  return 0;
839 }
840 
843 {
844  vnet_main_t *vnm = vnet_get_main ();
845  vl_api_sw_interface_tag_add_del_reply_t *rmp;
846  int rv = 0;
847  u8 *tag;
848  u32 sw_if_index = ntohl (mp->sw_if_index);
849 
851 
852  if (mp->is_add)
853  {
854  if (mp->tag[0] == 0)
855  {
856  rv = VNET_API_ERROR_INVALID_VALUE;
857  goto out;
858  }
859 
860  mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
861  tag = format (0, "%s%c", mp->tag, 0);
862  vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
863  }
864  else
865  vnet_clear_sw_interface_tag (vnm, sw_if_index);
866 
868 out:
869  REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY);
870 }
871 
874 {
875  vl_api_sw_interface_set_mac_address_reply_t *rmp;
876  vnet_main_t *vnm = vnet_get_main ();
877  u32 sw_if_index = ntohl (mp->sw_if_index);
879  u64 mac;
880  clib_error_t *error;
881  int rv = 0;
882 
884 
885  mac = ((u64) mp->mac_address[0] << (8 * 0)
886  | (u64) mp->mac_address[1] << (8 * 1)
887  | (u64) mp->mac_address[2] << (8 * 2)
888  | (u64) mp->mac_address[3] << (8 * 3)
889  | (u64) mp->mac_address[4] << (8 * 4)
890  | (u64) mp->mac_address[5] << (8 * 5));
891 
892  si = vnet_get_sw_interface (vnm, sw_if_index);
893  error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mac);
894  if (error)
895  {
896  rv = VNET_API_ERROR_UNIMPLEMENTED;
897  clib_error_report (error);
898  goto out;
899  }
900 
902 out:
903  REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY);
904 }
905 
906 /*
907  * vpe_api_hookup
908  * Add vpe's API message handlers to the table.
909  * vlib has alread mapped shared memory and
910  * added the client registration handlers.
911  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
912  */
913 #define vl_msg_name_crc_list
914 #include <vnet/interface.api.h>
915 #undef vl_msg_name_crc_list
916 
917 static void
919 {
920 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
921  foreach_vl_msg_name_crc_interface;
922 #undef _
923 }
924 
925 pub_sub_handler (interface_events, INTERFACE_EVENTS);
926 
927 static clib_error_t *
929 {
930  api_main_t *am = &api_main;
931 
932 #define _(N,n) \
933  vl_msg_api_set_handlers(VL_API_##N, #n, \
934  vl_api_##n##_t_handler, \
935  vl_noop_handler, \
936  vl_api_##n##_t_endian, \
937  vl_api_##n##_t_print, \
938  sizeof(vl_api_##n##_t), 1);
940 #undef _
941 
942  /*
943  * Set up the (msg_name, crc, message-id) table
944  */
946 
947  return 0;
948 }
949 
951 
952 /*
953  * fd.io coding-style-patch-verification: ON
954  *
955  * Local Variables:
956  * eval: (c-set-style "gnu")
957  * End:
958  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:179
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:579
static int event_data_cmp(void *a1, void *a2)
vmrglw vmrglh hi
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, mfib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:467
struct vnet_sub_interface_t::@153 eth
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
ip4_table_bind_function_t * function
Definition: ip4.h:82
vnet_main_t * vnet_main
#define CLIB_UNUSED(x)
Definition: clib.h:79
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:619
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip6.h:176
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
void stats_dsunlock(void)
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(link_up_down_function)
ethernet_main_t * ethernet_get_main(vlib_main_t *vm)
Definition: init.c:116
Set flags on the interface.
Definition: interface.api:8
vnet_interface_main_t interface_main
Definition: vnet.h:56
static void vl_api_sw_interface_add_del_address_t_handler(vl_api_sw_interface_add_del_address_t *mp)
clib_error_t * vnet_hw_interface_change_mac_address(vnet_main_t *vnm, u32 hw_if_index, u64 mac_address)
Definition: interface.c:1375
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:929
u8 src_address[6]
Definition: packet.h:54
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_main_t ** vnet_mains
Definition: vnet.h:82
From the CLI.
Definition: fib_entry.h:66
add_epi add_epi sub
Definition: vector_sse2.h:283
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
static void vnet_clear_sw_interface_tag(vnet_main_t *vnm, u32 sw_if_index)
VLIB_API_INIT_FUNCTION(interface_api_hookup)
ip_lookup_main_t lookup_main
Definition: ip4.h:97
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vlib_main
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:111
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void vl_api_sw_interface_set_unnumbered_t_handler(vl_api_sw_interface_set_unnumbered_t *mp)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:394
vpe_api_main_t vpe_api_main
Definition: interface_api.c:49
static void send_sw_interface_details(vpe_api_main_t *am, unix_shared_memory_queue_t *q, vnet_sw_interface_t *swif, u8 *interface_name, u32 context)
static void vl_api_sw_interface_dump_t_handler(vl_api_sw_interface_dump_t *mp)
#define VNET_HW_INTERFACE_FLAG_DUPLEX_MASK
Definition: interface.h:399
static clib_error_t * interface_api_hookup(vlib_main_t *vm)
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static uword link_state_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
int ip_table_bind(fib_protocol_t fproto, u32 sw_if_index, u32 table_id, u8 is_api)
static void send_sw_interface_get_table_reply(unix_shared_memory_queue_t *q, u32 context, int retval, u32 vrf_id)
#define VNET_HW_INTERFACE_FLAG_SPEED_MASK
Definition: interface.h:411
enum mfib_source_t_ mfib_source_t
Possible [control plane] sources of MFIB entries.
ethernet_main_t ethernet_main
Definition: ethernet.h:274
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:114
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Clear a collection of combined counters.
Definition: counter.c:60
Clear interface statistics.
Definition: interface.api:355
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:437
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:668
u8 dst_address[6]
Definition: packet.h:53
Get VRF id assigned to interface.
Definition: interface.api:205
unsigned long u64
Definition: types.h:89
A collection of simple counters.
Definition: counter.h:58
void * vl_msg_api_alloc(int nbytes)
u32 max_supported_packet_bytes
Definition: interface.h:454
clib_error_t * ip4_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 is_del)
Definition: ip4_forward.c:982
vnet_api_error_t api_errno
Definition: vnet.h:76
static clib_error_t * link_up_down_function(vnet_main_t *vm, u32 hw_if_index, u32 flags)
#define VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT
Definition: interface.h:396
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:276
vnet_sub_interface_t sub
Definition: interface.h:608
void ip4_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip4_forward.c:860
static void vl_api_sw_interface_get_table_t_handler(vl_api_sw_interface_get_table_t *mp)
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:950
enum fib_source_t_ fib_source_t
The different sources that can create a route.
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Take a reference counting lock on the table.
Definition: mfib_table.c:558
#define VNET_HW_INTERFACE_FLAG_SPEED_SHIFT
Definition: interface.h:404
Set interface MTU.
Definition: interface.api:23
static void vl_api_sw_interface_set_mac_address_t_handler(vl_api_sw_interface_set_mac_address_t *mp)
ip6_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip6.h:197
Reply to get_sw_interface_vrf.
Definition: interface.api:217
#define REPLY_MACRO(t)
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:667
void mfib_table_lock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Release a reference counting lock on the table.
Definition: mfib_table.c:587
void ip_del_all_interface_addresses(vlib_main_t *vm, u32 sw_if_index)
Definition: ip46_cli.c:80
Set or delete one or all ip addresses on a specified interface.
Definition: interface.api:172
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1177
vnet_hw_interface_class_t ethernet_hw_interface_class
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:182
static void setup_message_id_table(api_main_t *am)
static uword vlib_process_get_events_with_type(vlib_main_t *vm, uword **data_vector, uword with_type_opaque)
Definition: node_funcs.h:597
#define BAD_SW_IF_INDEX_LABEL
api_main_t api_main
Definition: api_shared.c:35
static void vl_api_sw_interface_set_flags_t_handler(vl_api_sw_interface_set_flags_t *mp)
Definition: interface_api.c:65
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:50
void stats_dslock_with_hint(int hint, int tag)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
static clib_error_t * admin_up_down_function(vnet_main_t *vm, u32 hw_if_index, u32 flags)
#define API_ADMIN_UP_DOWN_EVENT
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:69
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
#define ETHERNET_INTERFACE_FLAG_MTU
Definition: ethernet.h:118
#define ARRAY_LEN(x)
Definition: clib.h:59
#define foreach_vpe_api_msg
Definition: interface_api.c:51
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(admin_up_down_function)
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1206
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:129
foreach_registration_hash u8 link_state_process_up
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:572
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:3043
ip_lookup_main_t lookup_main
Definition: ip6.h:158
static void vnet_set_sw_interface_tag(vnet_main_t *vnm, u8 *tag, u32 sw_if_index)
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1084
static void vl_api_sw_interface_tag_add_del_t_handler(vl_api_sw_interface_tag_add_del_t *mp)
#define API_LINK_STATE_EVENT
#define clib_error_report(e)
Definition: error.h:113
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:123
static u8 * vnet_get_sw_interface_tag(vnet_main_t *vnm, u32 sw_if_index)
From the control plane API.
Definition: fib_entry.h:62
static void vl_api_sw_interface_clear_stats_t_handler(vl_api_sw_interface_clear_stats_t *mp)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Interface Event generated by want_interface_events.
Definition: interface.api:39
static void vl_api_sw_interface_set_mtu_t_handler(vl_api_sw_interface_set_mtu_t *mp)
Definition: interface_api.c:89
u64 uword
Definition: types.h:112
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:132
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:700
struct vnet_sub_interface_t::@153::@154::@156 flags
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:956
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:659
ip6_table_bind_function_t * function
Definition: ip6.h:112
Set unnumbered interface add / del request.
Definition: interface.api:341
fib_table_t * fib_table_get(fib_node_index_t index, fib_protocol_t proto)
Get a pointer to a FIB table.
Definition: fib_table.c:27
A collection of combined counters.
Definition: counter.h:180
u32 l2vtr_get(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 *vtr_op, u32 *push_dot1q, u32 *vtr_tag1, u32 *vtr_tag2)
Get vtag tag rewrite on the given interface.
Definition: l2_vtr.c:347
Set an interface&#39;s MAC address.
Definition: interface.api:384
void vlib_clear_simple_counters(vlib_simple_counter_main_t *cm)
Clear a collection of simple counters.
Definition: counter.c:43
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vnet_sw_interface_type_t type
Definition: interface.h:567
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1175
pub_sub_handler(interface_events, INTERFACE_EVENTS)
static void send_sw_interface_event(vpe_api_main_t *am, vpe_client_registration_t *reg, unix_shared_memory_queue_t *q, vnet_sw_interface_t *swif)
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:546
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
Definition: ip6_forward.c:472
Interface details structure (fix this)
Definition: interface.api:92
static void vl_api_sw_interface_set_table_t_handler(vl_api_sw_interface_set_table_t *mp)
u32 flags
Definition: vhost-user.h:77
Set / clear software interface tag.
Definition: interface.api:369
ethernet_interface_t * interfaces
Definition: ethernet.h:244
Associate the specified interface with a fib table.
Definition: interface.api:191
u32 * fib_index_by_sw_if_index
Definition: ip6.h:173
void ip6_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip6_forward.c:421
u32 l2pbb_get(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 *vtr_op, u16 *outer_tag, ethernet_header_t *eth_hdr, u16 *b_vlanid, u32 *i_sid)
Get pbb tag rewrite on the given interface.
Definition: l2_vtr.c:686
#define VALIDATE_SW_IF_INDEX(mp)
A protocol Independent FIB table.
Definition: fib_table.h:35
struct _unix_shared_memory_queue unix_shared_memory_queue_t
u32 ethernet_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:366