FD.io VPP  v21.06
Vector Packet Processing
lcp_interface.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define _GNU_SOURCE
17 #include <sched.h>
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <sys/socket.h>
21 #include <net/if.h>
22 
23 #include <linux-cp/lcp_interface.h>
24 #include <netlink/route/link/vlan.h>
25 
26 #include <vnet/plugin/plugin.h>
27 #include <vnet/plugin/plugin.h>
28 
29 #include <vnet/ip/ip_punt_drop.h>
30 #include <vnet/fib/fib_table.h>
31 #include <vnet/adj/adj_mcast.h>
32 #include <vnet/udp/udp.h>
33 #include <vnet/tcp/tcp.h>
34 #include <vnet/devices/tap/tap.h>
36 #include <vnet/devices/netlink.h>
38 #include <vnet/ipsec/ipsec_punt.h>
39 
41 
42 /**
43  * Pool of LIP objects
44  */
46 
47 u32
49 {
50  return pool_elts (lcp_itf_pair_pool);
51 }
52 
53 /**
54  * DBs of interface-pair objects:
55  * - key'd by VIF (linux ID)
56  * - key'd by VPP's physical interface
57  * - number of shared uses of VPP's tap/host interface
58  */
62 
63 #define LCP_ITF_PAIR_DBG(...) \
64  vlib_log_notice (lcp_itf_pair_logger, __VA_ARGS__);
65 
66 #define LCP_ITF_PAIR_INFO(...) \
67  vlib_log_notice (lcp_itf_pair_logger, __VA_ARGS__);
68 
69 u8 *
70 format_lcp_itf_pair (u8 *s, va_list *args)
71 {
72  vnet_main_t *vnm = vnet_get_main ();
73  lcp_itf_pair_t *lip = va_arg (*args, lcp_itf_pair_t *);
74  vnet_sw_interface_t *swif_phy;
75  vnet_sw_interface_t *swif_host;
76 
77  s = format (s, "itf-pair: [%d]", lip - lcp_itf_pair_pool);
78 
80  if (!swif_phy)
81  s = format (s, " <no-phy-if>");
82  else
83  s = format (s, " %U", format_vnet_sw_interface_name, vnm, swif_phy);
84 
86  if (!swif_host)
87  s = format (s, " <no-host-if>");
88  else
89  s = format (s, " %U", format_vnet_sw_interface_name, vnm, swif_host);
90 
91  s = format (s, " %v %d type %s", lip->lip_host_name, lip->lip_vif_index,
92  (lip->lip_host_type == LCP_ITF_HOST_TAP) ? "tap" : "tun");
93 
94  if (lip->lip_namespace)
95  s = format (s, " netns %s", lip->lip_namespace);
96 
97  return s;
98 }
99 
100 static walk_rc_t
102 {
103  vlib_main_t *vm;
104  lcp_itf_pair_t *lip;
105 
106  lip = lcp_itf_pair_get (api);
107  if (!lip)
108  return WALK_STOP;
109 
110  vm = vlib_get_main ();
111  vlib_cli_output (vm, "%U\n", format_lcp_itf_pair, lip);
112 
113  return WALK_CONTINUE;
114 }
115 
116 void
117 lcp_itf_pair_show (u32 phy_sw_if_index)
118 {
119  vlib_main_t *vm;
120  u8 *ns;
121  index_t api;
122 
123  vm = vlib_get_main ();
124  ns = lcp_get_default_ns ();
125  vlib_cli_output (vm, "lcp default netns '%s'\n",
126  ns ? (char *) ns : "<unset>");
127 
128  if (phy_sw_if_index == ~0)
129  {
131  }
132  else
133  {
134  api = lcp_itf_pair_find_by_phy (phy_sw_if_index);
135  if (api != INDEX_INVALID)
136  lcp_itf_pair_walk_show_cb (api, 0);
137  }
138 }
139 
142 {
143  return pool_elt_at_index (lcp_itf_pair_pool, index);
144 }
145 
146 index_t
148 {
149  uword *p;
150 
151  p = hash_get (lip_db_by_vif, vif_index);
152 
153  if (p)
154  return p[0];
155 
156  return INDEX_INVALID;
157 }
158 
159 int
160 lcp_itf_pair_add_sub (u32 vif, u8 *host_if_name, u32 sub_sw_if_index,
161  u32 phy_sw_if_index, u8 *ns)
162 {
163  lcp_itf_pair_t *lip;
164 
165  lip = lcp_itf_pair_get (lcp_itf_pair_find_by_phy (phy_sw_if_index));
166 
167  return lcp_itf_pair_add (lip->lip_host_sw_if_index, sub_sw_if_index,
168  host_if_name, vif, lip->lip_host_type, ns);
169 }
170 
172  [LCP_ITF_HOST_TAP] = {
173  [AF_IP4] = "linux-cp-xc-ip4",
174  [AF_IP6] = "linux-cp-xc-ip6",
175  },
176  [LCP_ITF_HOST_TUN] = {
177  [AF_IP4] = "linux-cp-xc-l3-ip4",
178  [AF_IP6] = "linux-cp-xc-l3-ip6",
179  },
180 };
181 
185 };
186 
187 static void
189 {
192 }
193 
194 static void
196 {
197  if (lip->lip_host_type == LCP_ITF_HOST_TUN)
198  {
203  }
204  else
205  {
210  }
211 
212  ip_adjacency_t *adj;
213 
214  adj = adj_get (lip->lip_phy_adjs.adj_index[AF_IP4]);
215 
216  lip->lip_rewrite_len = adj->rewrite_header.data_bytes;
217 }
218 
219 int __clib_weak
221 {
222  return 0;
223 }
224 
225 int
226 lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name,
227  u32 host_index, lip_host_type_t host_type, u8 *ns)
228 {
229  index_t lipi;
230  lcp_itf_pair_t *lip;
231 
232  lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
233 
234  LCP_ITF_PAIR_INFO ("add: host:%U phy:%U, host_if:%v vif:%d ns:%v",
236  host_sw_if_index, format_vnet_sw_if_index_name,
237  vnet_get_main (), phy_sw_if_index, host_name, host_index,
238  ns);
239 
240  if (lipi != INDEX_INVALID)
241  return VNET_API_ERROR_VALUE_EXIST;
242 
243  /*
244  * Drain netlink messages before adding the new pair.
245  * This avoids unnecessarily applying messages that were generated by
246  * the creation of the tap/tun interface. By processing them before we
247  * store the pair data, we will ensure that they are ignored.
248  */
250 
251  /*
252  * Create a new pair.
253  */
254  pool_get (lcp_itf_pair_pool, lip);
255 
256  lipi = lip - lcp_itf_pair_pool;
257 
260  lip_db_by_phy[phy_sw_if_index] = lipi;
261  lip_db_by_host[host_sw_if_index] = lipi;
262  hash_set (lip_db_by_vif, host_index, lipi);
263 
264  lip->lip_host_sw_if_index = host_sw_if_index;
265  lip->lip_phy_sw_if_index = phy_sw_if_index;
266  lip->lip_host_name = vec_dup (host_name);
267  lip->lip_host_type = host_type;
268  lip->lip_vif_index = host_index;
269  lip->lip_namespace = vec_dup (ns);
271 
272  if (lip->lip_host_sw_if_index == ~0)
273  return 0;
274 
275  /*
276  * First use of this host interface.
277  * Enable the x-connect feature on the host to send
278  * all packets to the phy.
279  */
281 
283  ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT,
285  lip->lip_host_sw_if_index, 1, NULL, 0);
286 
287  /*
288  * Configure passive punt to the host interface.
289  */
290  fib_route_path_t *rpaths = NULL, rpath = {
292  .frp_proto = DPO_PROTO_IP4,
293  .frp_sw_if_index = lip->lip_host_sw_if_index,
294  .frp_weight = 1,
295  .frp_fib_index = ~0,
296  };
297 
298  vec_add1 (rpaths, rpath);
299 
301 
302  rpaths[0].frp_proto = DPO_PROTO_IP6;
303 
305 
306  vec_free (rpaths);
307 
308  lcp_itf_set_adjs (lip);
309 
310  /* enable ARP feature node for broadcast interfaces */
311  if (lip->lip_host_type != LCP_ITF_HOST_TUN)
312  {
313  vnet_feature_enable_disable ("arp", "linux-cp-arp-phy",
314  lip->lip_phy_sw_if_index, 1, NULL, 0);
315  vnet_feature_enable_disable ("arp", "linux-cp-arp-host",
316  lip->lip_host_sw_if_index, 1, NULL, 0);
317  }
318  else
319  {
320  vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 1, NULL,
321  0);
322  vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 1, NULL,
323  0);
324  }
325 
326  return 0;
327 }
328 
329 static clib_error_t *
330 lcp_netlink_add_link_vlan (int parent, u32 vlan, const char *name)
331 {
332  struct rtnl_link *link;
333  struct nl_sock *sk;
334  int err;
335 
336  sk = nl_socket_alloc ();
337  if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0)
338  return clib_error_return (NULL, "Unable to connect socket: %d", err);
339 
340  link = rtnl_link_vlan_alloc ();
341 
342  rtnl_link_set_link (link, parent);
343  rtnl_link_set_name (link, name);
344 
345  rtnl_link_vlan_set_id (link, vlan);
346 
347  if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0)
348  return clib_error_return (NULL, "Unable to add link %s: %d", name, err);
349 
350  rtnl_link_put (link);
351  nl_close (sk);
352 
353  return NULL;
354 }
355 
356 static clib_error_t *
358 {
359  struct rtnl_link *link;
360  struct nl_sock *sk;
361  int err;
362 
363  sk = nl_socket_alloc ();
364  if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0)
365  return clib_error_return (NULL, "Unable to connect socket: %d", err);
366 
367  link = rtnl_link_alloc ();
368  rtnl_link_set_name (link, name);
369 
370  if ((err = rtnl_link_delete (sk, link)) < 0)
371  return clib_error_return (NULL, "Unable to del link %s: %d", name, err);
372 
373  rtnl_link_put (link);
374  nl_close (sk);
375 
376  return NULL;
377 }
378 
379 int
380 lcp_itf_pair_del (u32 phy_sw_if_index)
381 {
383  lcp_itf_pair_t *lip;
384  u32 lipi;
385 
386  lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
387 
388  if (lipi == INDEX_INVALID)
389  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
390 
391  lip = lcp_itf_pair_get (lipi);
392 
393  LCP_ITF_PAIR_INFO ("pair delete: {%U, %U, %s}", format_vnet_sw_if_index_name,
397 
399  ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT,
401  lip->lip_host_sw_if_index, 0, NULL, 0);
402 
403  lcp_itf_unset_adjs (lip);
404 
407 
408  /* disable ARP feature node for broadcast interfaces */
409  if (lip->lip_host_type != LCP_ITF_HOST_TUN)
410  {
411  vnet_feature_enable_disable ("arp", "linux-cp-arp-phy",
412  lip->lip_phy_sw_if_index, 0, NULL, 0);
413  vnet_feature_enable_disable ("arp", "linux-cp-arp-host",
414  lip->lip_host_sw_if_index, 0, NULL, 0);
415  }
416  else
417  {
418  vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 0, NULL,
419  0);
420  vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 0, NULL,
421  0);
422  }
423 
424  lip_db_by_phy[phy_sw_if_index] = INDEX_INVALID;
426 
427  vec_free (lip->lip_host_name);
428  vec_free (lip->lip_namespace);
429  pool_put (lcp_itf_pair_pool, lip);
430 
431  return 0;
432 }
433 
434 static void
436 {
437  u32 host_sw_if_index;
438  lcp_itf_pair_t *lip;
439  u8 *host_name;
440 
441  lip = lcp_itf_pair_get (lipi);
442 
443  host_name = vec_dup (lip->lip_host_name);
444  host_sw_if_index = lip->lip_host_sw_if_index;
445 
447 
448  if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index))
449  {
450  lcp_netlink_del_link ((const char *) host_name);
451  vnet_delete_sub_interface (host_sw_if_index);
452  }
453  else
454  tap_delete_if (vlib_get_main (), host_sw_if_index);
455 
456  vec_free (host_name);
457 }
458 
459 int
460 lcp_itf_pair_delete (u32 phy_sw_if_index)
461 {
462  index_t lipi;
463 
464  lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
465 
466  if (lipi == INDEX_INVALID)
467  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
468 
470 
471  return 0;
472 }
473 
474 void
476 {
477  u32 api;
478 
479  pool_foreach_index (api, lcp_itf_pair_pool)
480  {
481  if (!cb (api, ctx))
482  break;
483  };
484 }
485 
486 typedef struct lcp_itf_pair_names_t_
487 {
493 
495 
496 static clib_error_t *
498 {
499  u8 *host, *phy;
500  u8 *ns;
501  u8 *default_ns;
502 
503  host = phy = ns = default_ns = NULL;
504 
506  {
507  vec_reset_length (host);
508 
509  if (unformat (input, "pair %s %s %s", &phy, &host, &ns))
510  {
511  lcp_itf_pair_names_t *lipn;
512 
513  if (vec_len (ns) > LCP_NS_LEN)
514  {
515  return clib_error_return (0,
516  "linux-cp IF namespace must"
517  " be less than %d characters",
518  LCP_NS_LEN);
519  }
520 
521  vec_add2 (lipn_names, lipn, 1);
522 
523  lipn->lipn_host_name = vec_dup (host);
524  lipn->lipn_phy_name = vec_dup (phy);
525  lipn->lipn_namespace = vec_dup (ns);
526  }
527  else if (unformat (input, "pair %v %v", &phy, &host))
528  {
529  lcp_itf_pair_names_t *lipn;
530 
531  vec_add2 (lipn_names, lipn, 1);
532 
533  lipn->lipn_host_name = vec_dup (host);
534  lipn->lipn_phy_name = vec_dup (phy);
535  lipn->lipn_namespace = 0;
536  }
537  else if (unformat (input, "default netns %v", &default_ns))
538  {
539  vec_add1 (default_ns, 0);
540  if (lcp_set_default_ns (default_ns) < 0)
541  {
542  return clib_error_return (0,
543  "linux-cp default namespace must"
544  " be less than %d characters",
545  LCP_NS_LEN);
546  }
547  }
548  else if (unformat (input, "interface-auto-create"))
549  lcp_set_auto_intf (1 /* is_auto */);
550  else
551  return clib_error_return (0, "interfaces not found");
552  }
553 
554  vec_free (host);
555  vec_free (phy);
556  vec_free (default_ns);
557 
558  return NULL;
559 }
560 
562 
563 /*
564  * Returns 1 if the tap name is valid.
565  * Returns 0 if the tap name is invalid.
566  */
567 static int
569 {
570  int len;
571  char *p;
572 
573  p = (char *) name;
574  len = clib_strnlen (p, IFNAMSIZ);
575  if (len >= IFNAMSIZ)
576  return 0;
577 
578  for (; *p; ++p)
579  {
580  if (isalnum (*p))
581  continue;
582 
583  switch (*p)
584  {
585  case '-':
586  case '_':
587  case '%':
588  case '@':
589  case ':':
590  case '.':
591  continue;
592  }
593 
594  return 0;
595  }
596 
597  return 1;
598 }
599 
600 static int
601 lcp_itf_get_ns_fd (char *ns_name)
602 {
603  char ns_path[256] = "/proc/self/ns/net";
604 
605  if (ns_name)
606  snprintf (ns_path, sizeof (ns_path) - 1, "/var/run/netns/%s", ns_name);
607 
608  return open (ns_path, O_RDONLY);
609 }
610 
611 static void
612 lcp_itf_set_vif_link_state (u32 vif_index, u8 up, u8 *ns)
613 {
614  int curr_ns_fd, vif_ns_fd;
615 
616  curr_ns_fd = vif_ns_fd = -1;
617 
618  if (ns)
619  {
620  u8 *ns_path = 0;
621 
622  curr_ns_fd = open ("/proc/self/ns/net", O_RDONLY);
623  ns_path = format (0, "/var/run/netns/%s%c", (char *) ns, 0);
624  vif_ns_fd = open ((char *) ns_path, O_RDONLY);
625  if (vif_ns_fd != -1)
626  setns (vif_ns_fd, CLONE_NEWNET);
627  }
628 
629  vnet_netlink_set_link_state (vif_index, up);
630 
631  if (vif_ns_fd != -1)
632  close (vif_ns_fd);
633 
634  if (curr_ns_fd != -1)
635  {
636  setns (curr_ns_fd, CLONE_NEWNET);
637  close (curr_ns_fd);
638  }
639 }
640 
641 int
642 lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
643  lip_host_type_t host_if_type, u8 *ns,
644  u32 *host_sw_if_indexp)
645 {
646  vlib_main_t *vm;
647  vnet_main_t *vnm;
648  u32 vif_index = 0, host_sw_if_index;
649  const vnet_sw_interface_t *sw;
650  const vnet_hw_interface_t *hw;
651 
652  if (!vnet_sw_if_index_is_api_valid (phy_sw_if_index))
653  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
654 
655  if (!lcp_validate_if_name (host_if_name))
656  return VNET_API_ERROR_INVALID_ARGUMENT;
657 
658  vnm = vnet_get_main ();
659  sw = vnet_get_sw_interface (vnm, phy_sw_if_index);
660  hw = vnet_get_sup_hw_interface (vnm, phy_sw_if_index);
661 
662  /*
663  * Use interface-specific netns if supplied.
664  * Otherwise, use default netns if defined.
665  * Otherwise ignore a netns and use the OS default.
666  */
667  if (ns == 0 || ns[0] == 0)
668  ns = lcp_get_default_ns ();
669 
670  /* sub interfaces do not need a tap created */
671  if (vnet_sw_interface_is_sub (vnm, phy_sw_if_index))
672  {
673  const lcp_itf_pair_t *lip;
674  int orig_ns_fd, ns_fd;
675  clib_error_t *err;
676  u16 vlan;
677 
678  /*
679  * Find the parent tap by finding the pair from the parent phy
680  */
682  vlan = sw->sub.eth.outer_vlan_id;
683 
684  /*
685  * see if the requested host interface has already been created
686  */
687  orig_ns_fd = ns_fd = -1;
688  err = NULL;
689 
690  if (ns && ns[0] != 0)
691  {
692  orig_ns_fd = lcp_itf_get_ns_fd (NULL);
693  ns_fd = lcp_itf_get_ns_fd ((char *) ns);
694  if (orig_ns_fd == -1 || ns_fd == -1)
695  goto socket_close;
696 
697  setns (ns_fd, CLONE_NEWNET);
698  }
699 
700  vif_index = if_nametoindex ((const char *) host_if_name);
701 
702  if (!vif_index)
703  {
704  /*
705  * no existing host interface, create it now
706  */
707  err = lcp_netlink_add_link_vlan (lip->lip_vif_index, vlan,
708  (const char *) host_if_name);
709 
710  if (!err && -1 != ns_fd)
711  err = vnet_netlink_set_link_netns (vif_index, ns_fd, NULL);
712 
713  if (!err)
714  vif_index = if_nametoindex ((char *) host_if_name);
715  }
716 
717  /*
718  * create a sub-interface on the tap
719  */
721  sw->sub.id, sw->sub.eth.raw_flags,
722  sw->sub.eth.inner_vlan_id, vlan,
723  &host_sw_if_index))
724  LCP_ITF_PAIR_INFO ("failed create vlan: %d on %U", vlan,
726  lip->lip_host_sw_if_index);
727 
728  socket_close:
729  if (orig_ns_fd != -1)
730  {
731  setns (orig_ns_fd, CLONE_NEWNET);
732  close (orig_ns_fd);
733  }
734  if (ns_fd != -1)
735  close (ns_fd);
736 
737  if (err)
738  return VNET_API_ERROR_INVALID_ARGUMENT;
739  }
740  else
741  {
742  tap_create_if_args_t args = {
744  .id = hw->hw_if_index,
745  .sw_if_index = ~0,
746  .rx_ring_sz = 256,
747  .tx_ring_sz = 256,
748  .host_if_name = host_if_name,
749  .host_namespace = 0,
750  };
752 
753  if (host_if_type == LCP_ITF_HOST_TUN)
754  args.tap_flags |= TAP_FLAG_TUN;
755  else
756  {
759  }
760 
761  if (sw->mtu[VNET_MTU_L3])
762  {
763  args.host_mtu_set = 1;
764  args.host_mtu_size = sw->mtu[VNET_MTU_L3];
765  }
766 
767  if (ns && ns[0] != 0)
768  args.host_namespace = ns;
769 
770  vm = vlib_get_main ();
771  tap_create_if (vm, &args);
772 
773  if (args.rv < 0)
774  {
775  return args.rv;
776  }
777 
778  /*
779  * get the hw and ethernet of the tap
780  */
781  hw = vnet_get_sup_hw_interface (vnm, args.sw_if_index);
782 
783  /*
784  * Set the interface down on the host side.
785  * This controls whether the host can RX/TX.
786  */
787  virtio_main_t *mm = &virtio_main;
789 
790  lcp_itf_set_vif_link_state (vif->ifindex, 0 /* down */,
791  args.host_namespace);
792 
793  /*
794  * Leave the TAP permanently up on the VPP side.
795  * This TAP will be shared by many sub-interface.
796  * Therefore we can't use it to manage admin state.
797  * force the tap in promiscuous mode.
798  */
799  if (host_if_type == LCP_ITF_HOST_TAP)
800  {
803  }
804 
805  vif_index = vif->ifindex;
806  host_sw_if_index = args.sw_if_index;
807  }
808 
809  if (!vif_index)
810  {
811  LCP_ITF_PAIR_INFO ("failed pair add (no vif index): {%U, %U, %s}",
813  phy_sw_if_index, format_vnet_sw_if_index_name,
814  vnet_get_main (), host_sw_if_index, host_if_name);
815  return -1;
816  }
817 
818  vnet_sw_interface_admin_up (vnm, host_sw_if_index);
819  lcp_itf_pair_add (host_sw_if_index, phy_sw_if_index, host_if_name, vif_index,
820  host_if_type, ns);
821 
822  LCP_ITF_PAIR_INFO ("pair create: {%U, %U, %s}", format_vnet_sw_if_index_name,
823  vnet_get_main (), phy_sw_if_index,
825  host_sw_if_index, host_if_name);
826 
827  if (host_sw_if_indexp)
828  *host_sw_if_indexp = host_sw_if_index;
829 
830  return 0;
831 }
832 
833 static walk_rc_t
835 {
836  lcp_itf_pair_t *lip;
837 
838  lip = lcp_itf_pair_get (lipi);
839 
840  lip->lip_flags |= LIP_FLAG_STALE;
841 
842  return (WALK_CONTINUE);
843 }
844 
845 int
847 {
849 
850  return (0);
851 }
852 
854 {
857 
858 static walk_rc_t
860 {
862  lcp_itf_pair_t *lip;
863 
864  lip = lcp_itf_pair_get (lipi);
865 
866  if (lip->lip_flags & LIP_FLAG_STALE)
867  vec_add1 (ctx->indicies, lipi);
868 
869  return (WALK_CONTINUE);
870 }
871 
872 int
874 {
876  .indicies = NULL,
877  };
878  index_t *lipi;
879 
881 
882  vec_foreach (lipi, ctx.indicies)
884 
885  vec_free (ctx.indicies);
886  return (0);
887 }
888 
889 static uword
891  vlib_frame_t *f)
892 {
893  uword *event_data = 0;
894  uword *lipn_index;
895 
896  while (1)
897  {
899 
900  vlib_process_get_events (vm, &event_data);
901 
902  vec_foreach (lipn_index, event_data)
903  {
904  lcp_itf_pair_names_t *lipn;
905 
906  lipn = &lipn_names[*lipn_index];
909  lipn->lipn_namespace, NULL);
910  }
911 
912  vec_reset_length (event_data);
913  }
914 
915  return 0;
916 }
917 
919  .function = lcp_itf_pair_process,
920  .name = "linux-cp-itf-process",
921  .type = VLIB_NODE_TYPE_PROCESS,
922 };
923 
924 static clib_error_t *
926 {
927  lcp_itf_pair_names_t *lipn;
930 
931  if (!is_create || vnet_sw_interface_is_sub (vnm, sw_if_index))
932  return NULL;
933 
934  hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
935 
936  vec_foreach (lipn, lipn_names)
937  {
938  if (!vec_cmp (hw->name, lipn->lipn_phy_name))
939  {
941 
943  lipn - lipn_names);
944  break;
945  }
946  }
947 
948  return NULL;
949 }
950 
952 
953 static clib_error_t *
955 {
958  index_t lipi;
959  lcp_itf_pair_t *lip;
960 
961  hi = vnet_get_hw_interface_or_null (vnm, hw_if_index);
962  if (!hi)
963  return 0;
964 
966  if (lipi == INDEX_INVALID)
967  return 0;
968 
969  lip = lcp_itf_pair_get (lipi);
971  if (!si)
972  return 0;
973 
974  if (!lcp_main.test_mode)
975  {
978 
979  if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
980  {
981  tap_set_speed (si->hw_if_index, hi->link_speed / 1000);
982  }
983  }
984 
985  return 0;
986 }
987 
989 
990 static clib_error_t *
992 {
994 
995  /* punt IKE */
996  vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
997  "linux-cp-punt");
998 
999  /* punt all unknown ports */
1000  udp_punt_unknown (vm, 0, 1);
1001  udp_punt_unknown (vm, 1, 1);
1002  tcp_punt_unknown (vm, 0, 1);
1003  tcp_punt_unknown (vm, 1, 1);
1004 
1005  lcp_itf_pair_logger = vlib_log_register_class ("linux-cp", "itf");
1006 
1007  return NULL;
1008 }
1009 
1011  .runs_after = VLIB_INITS ("vnet_interface_init", "tcp_init", "udp_init"),
1012 };
1013 
1014 /*
1015  * fd.io coding-style-patch-verification: ON
1016  *
1017  * Local Variables:
1018  * eval: (c-set-style "gnu")
1019  * End:
1020  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
int lcp_itf_pair_replace_end(void)
lip_host_type_t lip_host_type
Definition: lcp_interface.h:56
int lcp_itf_pair_del(u32 phy_sw_if_index)
const fib_route_path_flags_t lcp_itf_route_path_flags[N_LCP_ITF_HOST]
static walk_rc_t lcp_itf_pair_walk_show_cb(index_t api, void *ctx)
lcp_main_t lcp_main
Definition: lcp.c:24
A path that resolves via a DVR DPO.
Definition: fib_types.h:393
#define hash_set(h, key, value)
Definition: hash.h:255
virtio_if_t * interfaces
Definition: virtio.h:220
vnet_interface_output_runtime_t * rt
#define pool_foreach_index(i, v)
Definition: pool.h:576
static void lcp_itf_unset_adjs(lcp_itf_pair_t *lip)
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:660
A representation of a path as described by a route producer.
Definition: fib_types.h:500
lip_host_type_t
Definition: lcp_interface.h:33
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
void ip4_punt_redirect_del(u32 rx_sw_if_index)
A pair of interfaces.
Definition: lcp_interface.h:49
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
ethernet_interface_t * interfaces
Definition: ethernet.h:304
IP unicast adjacency.
Definition: adj.h:235
static void lcp_itf_pair_delete_by_index(index_t lipi)
index_t lcp_itf_pair_find_by_vif(u32 vif_index)
Find a interface-pair object from the host interface.
#define LCP_NS_LEN
Definition: lcp.h:20
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
int vlib_punt_hdl_t
Typedef for a client handle.
Definition: punt.h:52
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
struct lcp_itf_pair_sweep_ctx_t_ lcp_itf_pair_sweep_ctx_t
static_always_inline void mac_address_copy(mac_address_t *dst, const mac_address_t *src)
Definition: mac_address.h:128
int lcp_set_default_ns(u8 *ns)
Get/Set the default namespace for LCP host taps.
Definition: lcp.c:48
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
string name[64]
Definition: fib.api:25
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:505
walk_rc_t(* lcp_itf_pair_walk_cb_t)(index_t index, void *ctx)
Callback function invoked during a walk of all interface-pairs.
void ip4_punt_redirect_add_paths(u32 rx_sw_if_index, fib_route_path_t *paths)
static uword vnet_sw_interface_is_sub(vnet_main_t *vnm, u32 sw_if_index)
u8 test_mode
Definition: lcp.h:29
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
#define N_SAFI
Definition: ip_types.h:47
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static index_t lcp_itf_pair_find_by_phy(u32 phy_sw_if_index)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
unsigned int u32
Definition: types.h:88
u8 * lcp_get_default_ns(void)
Definition: lcp.c:27
vlib_frame_t * f
enum walk_rc_t_ walk_rc_t
Walk return code.
u32 lcp_itf_num_pairs(void)
Definition: lcp_interface.c:48
ethernet_main_t ethernet_main
Definition: init.c:45
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:470
u32 vlib_log_class_t
Definition: vlib.h:52
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:583
int ifindex
Definition: virtio.h:186
description fragment has unexpected format
Definition: map.api:433
void vnet_sw_interface_admin_up(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:533
int tap_delete_if(vlib_main_t *vm, u32 sw_if_index)
Definition: tap.c:781
#define clib_error_return(e, args...)
Definition: error.h:99
vnet_main_t * vnet_get_main(void)
int vnet_create_sub_interface(u32 sw_if_index, u32 id, u32 flags, u16 inner_vlan_id, u16 outer_vlan_id, u32 *sub_sw_if_index)
Definition: interface.c:1053
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:358
u32 mtu[VNET_N_MTU]
Definition: interface.h:889
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(lcp_itf_pair_link_up_down)
enum fib_route_path_flags_t_ fib_route_path_flags_t
Path flags from the control plane.
static clib_error_t * lcp_itf_phy_add(vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
int lcp_itf_pair_add(u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name, u32 host_index, lip_host_type_t host_type, u8 *ns)
Create an interface-pair.
vlib_punt_hdl_t vlib_punt_client_register(const char *who)
Register a new clinet.
Definition: punt.c:171
struct lcp_itf_pair_names_t_ lcp_itf_pair_names_t
description ARP replies copied to host
Definition: lcp.api:169
#define hash_get(h, key)
Definition: hash.h:249
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vnet_sub_interface_t sub
Definition: interface.h:892
lcp_itf_pair_t * lcp_itf_pair_pool
Pool of LIP objects.
Definition: lcp_interface.c:45
static void lcp_itf_set_vif_link_state(u32 vif_index, u8 up, u8 *ns)
u32 * lip_db_by_host
Definition: lcp_interface.c:61
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1019
int lcp_itf_pair_create(u32 phy_sw_if_index, u8 *host_if_name, lip_host_type_t host_if_type, u8 *ns, u32 *host_sw_if_indexp)
Create an interface-pair from PHY sw_if_index and tap name.
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
static clib_error_t * lcp_itf_pair_link_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
lip_flag_t lip_flags
Definition: lcp_interface.h:58
#define ETHERNET_INTERFACE_FLAG_STATUS_L3
Definition: ethernet.h:157
ethernet_interface_address_t address
Definition: ethernet.h:174
static clib_error_t * lcp_netlink_del_link(const char *name)
static void lcp_itf_set_adjs(lcp_itf_pair_t *lip)
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
int lcp_itf_pair_delete(u32 phy_sw_if_index)
Delete a LCP_ITF_PAIR.
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
static int lcp_itf_get_ns_fd(char *ns_name)
static lcp_itf_pair_names_t * lipn_names
static walk_rc_t lcp_itf_pair_walk_mark(index_t lipi, void *ctx)
u8 len
Definition: ip_types.api:103
u8 * format_lcp_itf_pair(u8 *s, va_list *args)
Definition: lcp_interface.c:70
void udp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
Definition: udp_local.c:545
static walk_rc_t lcp_itf_pair_walk_sweep(index_t lipi, void *arg)
static uword vnet_sw_if_index_is_api_valid(u32 sw_if_index)
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:220
vlib_punt_reason_t ipsec_punt_reason[IPSEC_PUNT_N_REASONS]
Definition: ipsec_punt.c:25
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
static int lcp_validate_if_name(u8 *name)
#define LCP_ITF_PAIR_INFO(...)
Definition: lcp_interface.c:66
static uword lcp_itf_pair_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
int vnet_delete_sub_interface(u32 sw_if_index)
Definition: interface.c:1095
static vlib_punt_hdl_t punt_hdl
Definition: ipsec_punt.c:23
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
u32 index
Definition: flow_types.api:221
u32 host_mtu_size
Definition: tap.h:64
static clib_error_t * lcp_itf_pair_init(vlib_main_t *vm)
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(lcp_itf_phy_add)
void ip6_punt_redirect_del(u32 rx_sw_if_index)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
void ip6_punt_redirect_add_paths(u32 rx_sw_if_index, fib_route_path_t *paths)
static clib_error_t * lcp_itf_pair_config(vlib_main_t *vm, unformat_input_t *input)
vnet_sw_interface_t * si
lcp_itf_phy_adj_t lip_phy_adjs
Definition: lcp_interface.h:57
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:609
#define FOR_EACH_IP_ADDRESS_FAMILY(_af)
Definition: ip_types.h:33
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:1034
static uword * lip_db_by_vif
DBs of interface-pair objects:
Definition: lcp_interface.c:59
unsigned int if_nametoindex(const char *ifname)
int lcp_itf_pair_add_sub(u32 vif, u8 *host_if_name, u32 sub_sw_if_index, u32 phy_sw_if_index, u8 *ns)
#define clib_max(x, y)
Definition: clib.h:335
virtio_main_t virtio_main
Definition: virtio.c:37
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vl_api_ip4_address_t hi
Definition: arp.api:37
void ip_feature_enable_disable(ip_address_family_t af, ip_sub_address_family_t safi, ip_feature_location_t loc, const char *feature_name, u32 sw_if_index, int enable, void *feature_config, u32 n_feature_config_bytes)
Definition: ip.c:163
enum ip_address_family_t_ ip_address_family_t
void lcp_itf_pair_walk(lcp_itf_pair_walk_cb_t cb, void *ctx)
Walk/visit each of the interface pairs.
static vlib_node_registration_t lcp_itf_pair_process_node
(constructor) VLIB_REGISTER_NODE (lcp_itf_pair_process_node)
void tap_create_if(vlib_main_t *vm, tap_create_if_args_t *args)
Definition: tap.c:137
void tcp_punt_unknown(vlib_main_t *vm, u8 is_ip4, u8 is_add)
Definition: tcp.c:1556
#define N_AF
Definition: ip_types.h:27
int vlib_punt_register(vlib_punt_hdl_t client, vlib_punt_reason_t reason, const char *node_name)
Register a node to receive particular punted buffers.
Definition: punt.c:283
void lcp_itf_pair_show(u32 phy_sw_if_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:49
u64 uword
Definition: types.h:112
adj_index_t adj_index[N_AF]
Definition: lcp_interface.h:43
mac_address_t host_mac_addr
Definition: tap.h:53
int tap_set_speed(u32 hw_if_index, u32 speed)
Definition: tap.c:1038
lcp_itf_pair_t * lcp_itf_pair_get(u32 index)
Get an interface-pair object from its VPP index.
int tap_set_carrier(u32 hw_if_index, u32 carrier_up)
Definition: tap.c:990
#define N_LCP_ITF_HOST
Definition: lcp_interface.h:39
#define clib_strnlen(s, m)
Definition: string.h:782
static vnet_hw_interface_t * vnet_get_hw_interface_or_null(vnet_main_t *vnm, u32 hw_if_index)
static u32 vlib_num_workers()
Definition: threads.h:354
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:257
#define vec_foreach(var, vec)
Vector iterator.
index_t * lip_db_by_phy
Retreive the pair in the DP.
Definition: lcp_interface.c:60
u8 * host_namespace
Definition: tap.h:51
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:571
import vnet interface_types api
Definition: sample.api:20
int lcp_itf_pair_replace_begin(void)
Begin and End the replace process.
static clib_error_t * lcp_netlink_add_link_vlan(int parent, u32 vlan, const char *name)
static vnet_sw_interface_t * vnet_get_sw_interface_or_null(vnet_main_t *vnm, u32 sw_if_index)
#define VLIB_INITS(...)
Definition: init.h:352
void lcp_set_auto_intf(u8 is_auto)
manage interface auto creation
Definition: lcp_api.c:45
const ip46_address_t zero_addr
#include <vnet/feature/feature.h>
Definition: lookup.c:182
static vlib_log_class_t lcp_itf_pair_logger
Definition: lcp_interface.c:40
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
const char * lcp_itf_l3_feat_names[N_LCP_ITF_HOST][N_AF]
struct vnet_sub_interface_t::@368 eth
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
int __clib_weak lcp_nl_drain_messages(void)
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127