a822a5498d8242e4ba92cc56954cbc68f4c4dc20
[vpp.git] / src / plugins / linux-cp / lcp_interface.c
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 <fcntl.h>
18 #include <ctype.h>
19 #include <sys/socket.h>
20 #include <net/if.h>
21
22 #include <linux-cp/lcp_interface.h>
23 #include <netlink/route/link/vlan.h>
24 #include <linux/if_ether.h>
25
26 #include <vnet/plugin/plugin.h>
27 #include <vnet/plugin/plugin.h>
28
29 #include <vppinfra/linux/netns.h>
30
31 #include <vnet/ip/ip_punt_drop.h>
32 #include <vnet/fib/fib_table.h>
33 #include <vnet/adj/adj_mcast.h>
34 #include <vnet/udp/udp.h>
35 #include <vnet/tcp/tcp.h>
36 #include <vnet/devices/tap/tap.h>
37 #include <vnet/devices/virtio/virtio.h>
38 #include <vnet/devices/netlink.h>
39 #include <vlibapi/api_helper_macros.h>
40 #include <vnet/ipsec/ipsec_punt.h>
41
42 vlib_log_class_t lcp_itf_pair_logger;
43
44 /**
45  * Pool of LIP objects
46  */
47 lcp_itf_pair_t *lcp_itf_pair_pool = NULL;
48
49 u32
50 lcp_itf_num_pairs (void)
51 {
52   return pool_elts (lcp_itf_pair_pool);
53 }
54
55 /**
56  * DBs of interface-pair objects:
57  *  - key'd by VIF (linux ID)
58  *  - key'd by VPP's physical interface
59  *  - number of shared uses of VPP's tap/host interface
60  */
61 static uword *lip_db_by_vif;
62 index_t *lip_db_by_phy;
63 u32 *lip_db_by_host;
64
65 /**
66  * vector of virtual function table
67  */
68 static lcp_itf_pair_vft_t *lcp_itf_vfts = NULL;
69
70 void
71 lcp_itf_pair_register_vft (lcp_itf_pair_vft_t *lcp_itf_vft)
72 {
73   vec_add1 (lcp_itf_vfts, *lcp_itf_vft);
74 }
75
76 u8 *
77 format_lcp_itf_pair (u8 *s, va_list *args)
78 {
79   vnet_main_t *vnm = vnet_get_main ();
80   lcp_itf_pair_t *lip = va_arg (*args, lcp_itf_pair_t *);
81   vnet_sw_interface_t *swif_phy;
82   vnet_sw_interface_t *swif_host;
83
84   s = format (s, "itf-pair: [%d]", lip - lcp_itf_pair_pool);
85
86   swif_phy = vnet_get_sw_interface_or_null (vnm, lip->lip_phy_sw_if_index);
87   if (!swif_phy)
88     s = format (s, " <no-phy-if>");
89   else
90     s = format (s, " %U", format_vnet_sw_interface_name, vnm, swif_phy);
91
92   swif_host = vnet_get_sw_interface_or_null (vnm, lip->lip_host_sw_if_index);
93   if (!swif_host)
94     s = format (s, " <no-host-if>");
95   else
96     s = format (s, " %U", format_vnet_sw_interface_name, vnm, swif_host);
97
98   s = format (s, " %v %d type %s", lip->lip_host_name, lip->lip_vif_index,
99               (lip->lip_host_type == LCP_ITF_HOST_TAP) ? "tap" : "tun");
100
101   if (lip->lip_namespace)
102     s = format (s, " netns %s", lip->lip_namespace);
103
104   return s;
105 }
106
107 static walk_rc_t
108 lcp_itf_pair_walk_show_cb (index_t api, void *ctx)
109 {
110   vlib_main_t *vm;
111   lcp_itf_pair_t *lip;
112
113   lip = lcp_itf_pair_get (api);
114   if (!lip)
115     return WALK_STOP;
116
117   vm = vlib_get_main ();
118   vlib_cli_output (vm, "%U\n", format_lcp_itf_pair, lip);
119
120   return WALK_CONTINUE;
121 }
122
123 void
124 lcp_itf_pair_show (u32 phy_sw_if_index)
125 {
126   vlib_main_t *vm;
127   u8 *ns;
128   index_t api;
129
130   vm = vlib_get_main ();
131   ns = lcp_get_default_ns ();
132   vlib_cli_output (vm, "lcp default netns '%s'\n",
133                    ns ? (char *) ns : "<unset>");
134   vlib_cli_output (vm, "lcp lcp-auto-subint %s\n",
135                    lcp_auto_subint () ? "on" : "off");
136   vlib_cli_output (vm, "lcp lcp-sync %s\n", lcp_sync () ? "on" : "off");
137
138   if (phy_sw_if_index == ~0)
139     {
140       lcp_itf_pair_walk (lcp_itf_pair_walk_show_cb, 0);
141     }
142   else
143     {
144       api = lcp_itf_pair_find_by_phy (phy_sw_if_index);
145       if (api != INDEX_INVALID)
146         lcp_itf_pair_walk_show_cb (api, 0);
147     }
148 }
149
150 lcp_itf_pair_t *
151 lcp_itf_pair_get (u32 index)
152 {
153   if (!lcp_itf_pair_pool)
154     return NULL;
155   if (index == INDEX_INVALID)
156     return NULL;
157
158   return pool_elt_at_index (lcp_itf_pair_pool, index);
159 }
160
161 index_t
162 lcp_itf_pair_find_by_vif (u32 vif_index)
163 {
164   uword *p;
165
166   p = hash_get (lip_db_by_vif, vif_index);
167
168   if (p)
169     return p[0];
170
171   return INDEX_INVALID;
172 }
173
174 const char *lcp_itf_l3_feat_names[N_LCP_ITF_HOST][N_AF] = {
175   [LCP_ITF_HOST_TAP] = {
176     [AF_IP4] = "linux-cp-xc-ip4",
177     [AF_IP6] = "linux-cp-xc-ip6",
178   },
179   [LCP_ITF_HOST_TUN] = {
180     [AF_IP4] = "linux-cp-xc-l3-ip4",
181     [AF_IP6] = "linux-cp-xc-l3-ip6",
182   },
183 };
184
185 const fib_route_path_flags_t lcp_itf_route_path_flags[N_LCP_ITF_HOST] = {
186   [LCP_ITF_HOST_TAP] = FIB_ROUTE_PATH_DVR,
187   [LCP_ITF_HOST_TUN] = FIB_ROUTE_PATH_FLAG_NONE,
188 };
189
190 static void
191 lcp_itf_unset_adjs (lcp_itf_pair_t *lip)
192 {
193   adj_unlock (lip->lip_phy_adjs.adj_index[AF_IP4]);
194   adj_unlock (lip->lip_phy_adjs.adj_index[AF_IP6]);
195 }
196
197 static void
198 lcp_itf_set_adjs (lcp_itf_pair_t *lip)
199 {
200   if (lip->lip_host_type == LCP_ITF_HOST_TUN)
201     {
202       lip->lip_phy_adjs.adj_index[AF_IP4] = adj_nbr_add_or_lock (
203         FIB_PROTOCOL_IP4, VNET_LINK_IP4, &zero_addr, lip->lip_phy_sw_if_index);
204       lip->lip_phy_adjs.adj_index[AF_IP6] = adj_nbr_add_or_lock (
205         FIB_PROTOCOL_IP6, VNET_LINK_IP6, &zero_addr, lip->lip_phy_sw_if_index);
206     }
207   else
208     {
209       lip->lip_phy_adjs.adj_index[AF_IP4] = adj_mcast_add_or_lock (
210         FIB_PROTOCOL_IP4, VNET_LINK_IP4, lip->lip_phy_sw_if_index);
211       lip->lip_phy_adjs.adj_index[AF_IP6] = adj_mcast_add_or_lock (
212         FIB_PROTOCOL_IP6, VNET_LINK_IP6, lip->lip_phy_sw_if_index);
213     }
214
215   ip_adjacency_t *adj;
216
217   adj = adj_get (lip->lip_phy_adjs.adj_index[AF_IP4]);
218
219   lip->lip_rewrite_len = adj->rewrite_header.data_bytes;
220 }
221
222 int
223 lcp_itf_pair_add (u32 host_sw_if_index, u32 phy_sw_if_index, u8 *host_name,
224                   u32 host_index, lip_host_type_t host_type, u8 *ns)
225 {
226   index_t lipi;
227   lcp_itf_pair_t *lip;
228
229   if (host_sw_if_index == ~0)
230     {
231       LCP_ITF_PAIR_ERR ("pair_add: Cannot add LIP - invalid host");
232       return VNET_API_ERROR_INVALID_SW_IF_INDEX;
233     }
234
235   lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
236
237   if (lipi != INDEX_INVALID)
238     return VNET_API_ERROR_VALUE_EXIST;
239
240   LCP_ITF_PAIR_INFO ("add: host:%U phy:%U, host_if:%v vif:%d ns:%s",
241                      format_vnet_sw_if_index_name, vnet_get_main (),
242                      host_sw_if_index, format_vnet_sw_if_index_name,
243                      vnet_get_main (), phy_sw_if_index, host_name, host_index,
244                      ns);
245
246   /*
247    * Create a new pair.
248    */
249   pool_get (lcp_itf_pair_pool, lip);
250
251   lipi = lip - lcp_itf_pair_pool;
252
253   vec_validate_init_empty (lip_db_by_phy, phy_sw_if_index, INDEX_INVALID);
254   vec_validate_init_empty (lip_db_by_host, host_sw_if_index, INDEX_INVALID);
255   lip_db_by_phy[phy_sw_if_index] = lipi;
256   lip_db_by_host[host_sw_if_index] = lipi;
257   hash_set (lip_db_by_vif, host_index, lipi);
258
259   lip->lip_host_sw_if_index = host_sw_if_index;
260   lip->lip_phy_sw_if_index = phy_sw_if_index;
261   lip->lip_host_name = vec_dup (host_name);
262   lip->lip_host_type = host_type;
263   lip->lip_vif_index = host_index;
264   lip->lip_namespace = vec_dup (ns);
265
266   /*
267    * First use of this host interface.
268    * Enable the x-connect feature on the host to send
269    * all packets to the phy.
270    */
271   ip_address_family_t af;
272
273   FOR_EACH_IP_ADDRESS_FAMILY (af)
274   ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT,
275                              lcp_itf_l3_feat_names[lip->lip_host_type][af],
276                              lip->lip_host_sw_if_index, 1, NULL, 0);
277
278   /*
279    * Configure passive punt to the host interface.
280    */
281   fib_route_path_t *rpaths = NULL, rpath = {
282     .frp_flags = lcp_itf_route_path_flags[lip->lip_host_type],
283     .frp_proto = DPO_PROTO_IP4,
284     .frp_sw_if_index = lip->lip_host_sw_if_index,
285     .frp_weight = 1,
286     .frp_fib_index = ~0,
287   };
288
289   vec_add1 (rpaths, rpath);
290
291   ip4_punt_redirect_add_paths (lip->lip_phy_sw_if_index, rpaths);
292
293   rpaths[0].frp_proto = DPO_PROTO_IP6;
294
295   ip6_punt_redirect_add_paths (lip->lip_phy_sw_if_index, rpaths);
296
297   vec_free (rpaths);
298
299   lcp_itf_set_adjs (lip);
300
301   /* enable ARP feature node for broadcast interfaces */
302   if (lip->lip_host_type != LCP_ITF_HOST_TUN)
303     {
304       vnet_feature_enable_disable ("arp", "linux-cp-arp-phy",
305                                    lip->lip_phy_sw_if_index, 1, NULL, 0);
306       vnet_feature_enable_disable ("arp", "linux-cp-arp-host",
307                                    lip->lip_host_sw_if_index, 1, NULL, 0);
308     }
309   else
310     {
311       if (hash_elts (lip_db_by_vif) == 1)
312         {
313           vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 1,
314                                        NULL, 0);
315           vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 1,
316                                        NULL, 0);
317         }
318     }
319
320   /* invoke registered callbacks for pair addition */
321   lcp_itf_pair_vft_t *vft;
322
323   vec_foreach (vft, lcp_itf_vfts)
324     {
325       if (vft->pair_add_fn)
326         vft->pair_add_fn (lip);
327     }
328
329   /* set timestamp when pair entered service */
330   lip->lip_create_ts = vlib_time_now (vlib_get_main ());
331
332   return 0;
333 }
334
335 static clib_error_t *
336 lcp_netlink_add_link_vlan (int parent, u32 vlan, u16 proto, const char *name)
337 {
338   struct rtnl_link *link;
339   struct nl_sock *sk;
340   int err;
341
342   sk = nl_socket_alloc ();
343   if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0)
344     {
345       LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: connect error: %s",
346                         nl_geterror (err));
347       return clib_error_return (NULL, "Unable to connect socket: %d", err);
348     }
349
350   link = rtnl_link_vlan_alloc ();
351
352   rtnl_link_set_link (link, parent);
353   rtnl_link_set_name (link, name);
354   rtnl_link_vlan_set_id (link, vlan);
355   rtnl_link_vlan_set_protocol (link, htons (proto));
356
357   if ((err = rtnl_link_add (sk, link, NLM_F_CREATE)) < 0)
358     {
359       LCP_ITF_PAIR_ERR ("netlink_add_link_vlan: link add error: %s",
360                         nl_geterror (err));
361       return clib_error_return (NULL, "Unable to add link %s: %d", name, err);
362     }
363
364   rtnl_link_put (link);
365   nl_close (sk);
366
367   return NULL;
368 }
369
370 static clib_error_t *
371 lcp_netlink_del_link (const char *name)
372 {
373   struct rtnl_link *link;
374   struct nl_sock *sk;
375   int err;
376
377   sk = nl_socket_alloc ();
378   if ((err = nl_connect (sk, NETLINK_ROUTE)) < 0)
379     return clib_error_return (NULL, "Unable to connect socket: %d", err);
380
381   link = rtnl_link_alloc ();
382   rtnl_link_set_name (link, name);
383
384   if ((err = rtnl_link_delete (sk, link)) < 0)
385     return clib_error_return (NULL, "Unable to del link %s: %d", name, err);
386
387   rtnl_link_put (link);
388   nl_close (sk);
389
390   return NULL;
391 }
392
393 int
394 lcp_itf_pair_del (u32 phy_sw_if_index)
395 {
396   ip_address_family_t af;
397   lcp_itf_pair_t *lip;
398   u32 lipi;
399   lcp_itf_pair_vft_t *vft;
400
401   lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
402
403   if (lipi == INDEX_INVALID)
404     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
405
406   lip = lcp_itf_pair_get (lipi);
407
408   LCP_ITF_PAIR_NOTICE (
409     "pair_del: host:%U phy:%U host_if:%s vif:%d ns:%s",
410     format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_host_sw_if_index,
411     format_vnet_sw_if_index_name, vnet_get_main (), lip->lip_phy_sw_if_index,
412     lip->lip_host_name, lip->lip_vif_index, lip->lip_namespace);
413
414   /* invoke registered callbacks for pair deletion */
415   vec_foreach (vft, lcp_itf_vfts)
416     {
417       if (vft->pair_del_fn)
418         vft->pair_del_fn (lip);
419     }
420
421   FOR_EACH_IP_ADDRESS_FAMILY (af)
422   ip_feature_enable_disable (af, N_SAFI, IP_FEATURE_INPUT,
423                              lcp_itf_l3_feat_names[lip->lip_host_type][af],
424                              lip->lip_host_sw_if_index, 0, NULL, 0);
425
426   lcp_itf_unset_adjs (lip);
427
428   ip4_punt_redirect_del (lip->lip_phy_sw_if_index);
429   ip6_punt_redirect_del (lip->lip_phy_sw_if_index);
430
431   /* disable ARP feature node for broadcast interfaces */
432   if (lip->lip_host_type != LCP_ITF_HOST_TUN)
433     {
434       vnet_feature_enable_disable ("arp", "linux-cp-arp-phy",
435                                    lip->lip_phy_sw_if_index, 0, NULL, 0);
436       vnet_feature_enable_disable ("arp", "linux-cp-arp-host",
437                                    lip->lip_host_sw_if_index, 0, NULL, 0);
438     }
439   else
440     {
441       if (hash_elts (lip_db_by_vif) == 1)
442         {
443           vnet_feature_enable_disable ("ip4-punt", "linux-cp-punt-l3", 0, 0,
444                                        NULL, 0);
445           vnet_feature_enable_disable ("ip6-punt", "linux-cp-punt-l3", 0, 0,
446                                        NULL, 0);
447         }
448     }
449   lip_db_by_phy[phy_sw_if_index] = INDEX_INVALID;
450   lip_db_by_host[lip->lip_host_sw_if_index] = INDEX_INVALID;
451   hash_unset (lip_db_by_vif, lip->lip_vif_index);
452
453   vec_free (lip->lip_host_name);
454   vec_free (lip->lip_namespace);
455   pool_put (lcp_itf_pair_pool, lip);
456
457   return 0;
458 }
459
460 static void
461 lcp_itf_pair_delete_by_index (index_t lipi)
462 {
463   u32 host_sw_if_index;
464   lcp_itf_pair_t *lip;
465   u8 *host_name, *ns;
466
467   lip = lcp_itf_pair_get (lipi);
468
469   host_name = vec_dup (lip->lip_host_name);
470   host_sw_if_index = lip->lip_host_sw_if_index;
471   ns = vec_dup (lip->lip_namespace);
472
473   lcp_itf_pair_del (lip->lip_phy_sw_if_index);
474
475   if (vnet_sw_interface_is_sub (vnet_get_main (), host_sw_if_index))
476     {
477       int curr_ns_fd = -1;
478       int vif_ns_fd = -1;
479       if (ns)
480         {
481           curr_ns_fd = clib_netns_open (NULL /* self */);
482           vif_ns_fd = clib_netns_open ((u8 *) ns);
483           if (vif_ns_fd != -1)
484             clib_setns (vif_ns_fd);
485         }
486
487       lcp_netlink_del_link ((const char *) host_name);
488       if (vif_ns_fd != -1)
489         close (vif_ns_fd);
490
491       if (curr_ns_fd != -1)
492         {
493           clib_setns (curr_ns_fd);
494           close (curr_ns_fd);
495         }
496
497       vnet_delete_sub_interface (host_sw_if_index);
498     }
499   else
500     tap_delete_if (vlib_get_main (), host_sw_if_index);
501
502   vec_free (host_name);
503   vec_free (ns);
504 }
505
506 int
507 lcp_itf_pair_delete (u32 phy_sw_if_index)
508 {
509   index_t lipi;
510
511   lipi = lcp_itf_pair_find_by_phy (phy_sw_if_index);
512
513   if (lipi == INDEX_INVALID)
514     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
515
516   lcp_itf_pair_delete_by_index (lipi);
517
518   return 0;
519 }
520
521 /**
522  * lcp_itf_interface_add_del
523  *
524  * Registered to receive interface Add and delete notifications
525  */
526 static clib_error_t *
527 lcp_itf_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
528 {
529   if (!is_add)
530     /* remove any interface pair we have for this interface */
531     lcp_itf_pair_delete (sw_if_index);
532
533   return (NULL);
534 }
535
536 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (lcp_itf_interface_add_del);
537
538 void
539 lcp_itf_pair_walk (lcp_itf_pair_walk_cb_t cb, void *ctx)
540 {
541   u32 api;
542
543   pool_foreach_index (api, lcp_itf_pair_pool)
544     {
545       if (!cb (api, ctx))
546         break;
547     };
548 }
549
550 static clib_error_t *
551 lcp_itf_pair_config (vlib_main_t *vm, unformat_input_t *input)
552 {
553   u8 *default_ns;
554
555   default_ns = NULL;
556
557   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
558     {
559       if (unformat (input, "default netns %v", &default_ns))
560         {
561           vec_add1 (default_ns, 0);
562           if (lcp_set_default_ns (default_ns) < 0)
563             {
564               return clib_error_return (0,
565                                         "linux-cp default namespace must"
566                                         " be less than %d characters",
567                                         LCP_NS_LEN);
568             }
569         }
570       else if (unformat (input, "lcp-auto-subint"))
571         lcp_set_auto_subint (1 /* is_auto */);
572       else if (unformat (input, "lcp-sync"))
573         lcp_set_sync (1 /* is_auto */);
574       else
575         return clib_error_return (0, "interfaces not found");
576     }
577
578   vec_free (default_ns);
579
580   return NULL;
581 }
582
583 VLIB_EARLY_CONFIG_FUNCTION (lcp_itf_pair_config, "linux-cp");
584
585 /*
586  * Returns 1 if the tap name is valid.
587  * Returns 0 if the tap name is invalid.
588  */
589 static int
590 lcp_validate_if_name (u8 *name)
591 {
592   int len;
593   char *p;
594
595   p = (char *) name;
596   len = clib_strnlen (p, IFNAMSIZ);
597   if (len >= IFNAMSIZ)
598     return 0;
599
600   for (; *p; ++p)
601     {
602       if (isalnum (*p))
603         continue;
604
605       switch (*p)
606         {
607         case '-':
608         case '_':
609         case '%':
610         case '@':
611         case ':':
612         case '.':
613           continue;
614         }
615
616       return 0;
617     }
618
619   return 1;
620 }
621
622 void
623 lcp_itf_set_link_state (const lcp_itf_pair_t *lip, u8 state)
624 {
625   int curr_ns_fd, vif_ns_fd;
626
627   if (!lip)
628     return;
629
630   curr_ns_fd = vif_ns_fd = -1;
631
632   if (lip->lip_namespace)
633     {
634       curr_ns_fd = clib_netns_open (NULL /* self */);
635       vif_ns_fd = clib_netns_open (lip->lip_namespace);
636       if (vif_ns_fd != -1)
637         clib_setns (vif_ns_fd);
638     }
639
640   /* Set the same link state on the netlink interface
641    */
642   vnet_netlink_set_link_state (lip->lip_vif_index, state);
643
644   if (vif_ns_fd != -1)
645     close (vif_ns_fd);
646
647   if (curr_ns_fd != -1)
648     {
649       clib_setns (curr_ns_fd);
650       close (curr_ns_fd);
651     }
652
653   return;
654 }
655
656 void
657 lcp_itf_set_interface_addr (const lcp_itf_pair_t *lip)
658 {
659   ip4_main_t *im4 = &ip4_main;
660   ip6_main_t *im6 = &ip6_main;
661   ip_lookup_main_t *lm4 = &im4->lookup_main;
662   ip_lookup_main_t *lm6 = &im6->lookup_main;
663   ip_interface_address_t *ia = 0;
664   int vif_ns_fd = -1;
665   int curr_ns_fd = -1;
666
667   if (!lip)
668     return;
669
670   if (lip->lip_namespace)
671     {
672       curr_ns_fd = clib_netns_open (NULL /* self */);
673       vif_ns_fd = clib_netns_open (lip->lip_namespace);
674       if (vif_ns_fd != -1)
675         clib_setns (vif_ns_fd);
676     }
677
678   /* Sync any IP4 addressing info into LCP */
679   foreach_ip_interface_address (
680     lm4, ia, lip->lip_phy_sw_if_index, 1 /* honor unnumbered */, ({
681       ip4_address_t *r4 = ip_interface_address_get_address (lm4, ia);
682       LCP_ITF_PAIR_NOTICE ("set_interface_addr: %U add ip4 %U/%d",
683                            format_lcp_itf_pair, lip, format_ip4_address, r4,
684                            ia->address_length);
685       vnet_netlink_add_ip4_addr (lip->lip_vif_index, r4, ia->address_length);
686     }));
687
688   /* Sync any IP6 addressing info into LCP */
689   foreach_ip_interface_address (
690     lm6, ia, lip->lip_phy_sw_if_index, 1 /* honor unnumbered */, ({
691       ip6_address_t *r6 = ip_interface_address_get_address (lm6, ia);
692       LCP_ITF_PAIR_NOTICE ("set_interface_addr: %U add ip6 %U/%d",
693                            format_lcp_itf_pair, lip, format_ip6_address, r6,
694                            ia->address_length);
695       vnet_netlink_add_ip6_addr (lip->lip_vif_index, r6, ia->address_length);
696     }));
697
698   if (vif_ns_fd != -1)
699     close (vif_ns_fd);
700
701   if (curr_ns_fd != -1)
702     {
703       clib_setns (curr_ns_fd);
704       close (curr_ns_fd);
705     }
706 }
707
708 typedef struct
709 {
710   u32 vlan;
711   bool dot1ad;
712
713   u32 matched_sw_if_index;
714 } lcp_itf_match_t;
715
716 static walk_rc_t
717 lcp_itf_pair_find_walk (vnet_main_t *vnm, u32 sw_if_index, void *arg)
718 {
719   lcp_itf_match_t *match = arg;
720   const vnet_sw_interface_t *sw;
721
722   sw = vnet_get_sw_interface (vnm, sw_if_index);
723   if (sw && (sw->sub.eth.inner_vlan_id == 0) &&
724       (sw->sub.eth.outer_vlan_id == match->vlan) &&
725       (sw->sub.eth.flags.dot1ad == match->dot1ad))
726     {
727       LCP_ITF_PAIR_DBG ("find_walk: found match outer %d dot1ad %d "
728                         "inner-dot1q %d: interface %U",
729                         sw->sub.eth.outer_vlan_id, sw->sub.eth.flags.dot1ad,
730                         sw->sub.eth.inner_vlan_id,
731                         format_vnet_sw_if_index_name, vnet_get_main (),
732                         sw->sw_if_index);
733       match->matched_sw_if_index = sw->sw_if_index;
734       return WALK_STOP;
735     }
736
737   return WALK_CONTINUE;
738 }
739
740 /* Return the index of the sub-int on the phy that has the given vlan and
741  * proto,
742  */
743 static index_t
744 lcp_itf_pair_find_by_outer_vlan (u32 sup_if_index, u16 vlan, bool dot1ad)
745 {
746   lcp_itf_match_t match;
747   const vnet_hw_interface_t *hw;
748
749   match.vlan = vlan;
750   match.dot1ad = dot1ad;
751   match.matched_sw_if_index = INDEX_INVALID;
752   hw = vnet_get_sup_hw_interface (vnet_get_main (), sup_if_index);
753
754   vnet_hw_interface_walk_sw (vnet_get_main (), hw->hw_if_index,
755                              lcp_itf_pair_find_walk, &match);
756
757   if (match.matched_sw_if_index >= vec_len (lip_db_by_phy))
758     return INDEX_INVALID;
759
760   return lip_db_by_phy[match.matched_sw_if_index];
761 }
762
763 static clib_error_t *lcp_itf_pair_link_up_down (vnet_main_t *vnm,
764                                                 u32 hw_if_index, u32 flags);
765
766 int
767 lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
768                      lip_host_type_t host_if_type, u8 *ns,
769                      u32 *host_sw_if_indexp)
770 {
771   vlib_main_t *vm;
772   vnet_main_t *vnm;
773   u32 vif_index = 0, host_sw_if_index;
774   const vnet_sw_interface_t *sw;
775   const vnet_hw_interface_t *hw;
776   const lcp_itf_pair_t *lip;
777
778   if (!vnet_sw_if_index_is_api_valid (phy_sw_if_index))
779     {
780       LCP_ITF_PAIR_ERR ("pair_create: invalid phy index %u", phy_sw_if_index);
781       return VNET_API_ERROR_INVALID_SW_IF_INDEX;
782     }
783
784   if (!lcp_validate_if_name (host_if_name))
785     {
786       LCP_ITF_PAIR_ERR ("pair_create: invalid host-if-name '%s'",
787                         host_if_name);
788       return VNET_API_ERROR_INVALID_ARGUMENT;
789     }
790
791   vnm = vnet_get_main ();
792   sw = vnet_get_sw_interface (vnm, phy_sw_if_index);
793   hw = vnet_get_sup_hw_interface (vnm, phy_sw_if_index);
794   if (!sw || !hw)
795     {
796       LCP_ITF_PAIR_ERR ("pair_create: invalid interface");
797       return VNET_API_ERROR_INVALID_SW_IF_INDEX;
798     }
799
800   /*
801    * Use interface-specific netns if supplied.
802    * Otherwise, use netns if defined, otherwise use the OS default.
803    */
804   if (ns == 0 || ns[0] == 0)
805     ns = lcp_get_default_ns ();
806
807   /* sub interfaces do not need a tap created */
808   if (vnet_sw_interface_is_sub (vnm, phy_sw_if_index))
809     {
810       index_t parent_if_index;
811       int orig_ns_fd, ns_fd;
812       clib_error_t *err;
813       u16 outer_vlan, inner_vlan;
814       u16 outer_proto, inner_proto;
815       u16 vlan, proto;
816       u32 parent_vif_index;
817
818       err = vnet_sw_interface_supports_addressing (vnm, phy_sw_if_index);
819       if (err)
820         {
821           LCP_ITF_PAIR_ERR ("pair_create: can't create LCP for a "
822                             "sub-interface without exact-match set");
823           return VNET_API_ERROR_INVALID_ARGUMENT;
824         }
825
826       outer_vlan = sw->sub.eth.outer_vlan_id;
827       inner_vlan = sw->sub.eth.inner_vlan_id;
828       outer_proto = inner_proto = ETH_P_8021Q;
829       if (1 == sw->sub.eth.flags.dot1ad)
830         outer_proto = ETH_P_8021AD;
831
832       LCP_ITF_PAIR_INFO ("pair_create: subif: dot1%s outer %d inner %d on %U",
833                          sw->sub.eth.flags.dot1ad ? "ad" : "q", outer_vlan,
834                          inner_vlan, format_vnet_sw_if_index_name, vnm,
835                          hw->sw_if_index);
836
837       parent_if_index = lcp_itf_pair_find_by_phy (sw->sup_sw_if_index);
838       if (INDEX_INVALID == parent_if_index)
839         {
840           LCP_ITF_PAIR_ERR ("pair_create: can't find LCP for %U",
841                             format_vnet_sw_if_index_name, vnet_get_main (),
842                             sw->sup_sw_if_index);
843           return VNET_API_ERROR_INVALID_SW_IF_INDEX;
844         }
845       lip = lcp_itf_pair_get (parent_if_index);
846       if (!lip)
847         {
848           LCP_ITF_PAIR_ERR ("pair_create: can't create LCP for a "
849                             "sub-interface without an LCP on the parent");
850           return VNET_API_ERROR_INVALID_ARGUMENT;
851         }
852       LCP_ITF_PAIR_DBG ("pair_create: parent %U", format_lcp_itf_pair, lip);
853       parent_vif_index = lip->lip_vif_index;
854
855       /*
856        * see if the requested host interface has already been created
857        */
858       orig_ns_fd = ns_fd = -1;
859       err = NULL;
860
861       if (ns && ns[0] != 0)
862         {
863           orig_ns_fd = clib_netns_open (NULL /* self */);
864           ns_fd = clib_netns_open (ns);
865           if (orig_ns_fd == -1 || ns_fd == -1)
866             goto socket_close;
867
868           clib_setns (ns_fd);
869         }
870
871       vif_index = if_nametoindex ((const char *) host_if_name);
872
873       if (!vif_index)
874         {
875           /*
876            * no existing host interface, create it now
877            */
878
879           /*
880            * Find the parent tap:
881            * - if this is an outer VLAN, use the pair from the parent phy
882            * - if this is an inner VLAN, find the pair from the outer sub-int,
883            * which must exist.
884            */
885           if (inner_vlan)
886             {
887               index_t linux_parent_if_index;
888               const lcp_itf_pair_t *llip;
889
890               vlan = inner_vlan;
891               proto = inner_proto;
892               linux_parent_if_index = lcp_itf_pair_find_by_outer_vlan (
893                 hw->sw_if_index, sw->sub.eth.outer_vlan_id,
894                 sw->sub.eth.flags.dot1ad);
895               if (INDEX_INVALID == linux_parent_if_index ||
896                   !(llip = lcp_itf_pair_get (linux_parent_if_index)))
897                 {
898                   LCP_ITF_PAIR_ERR (
899                     "pair_create: can't find LCP for outer vlan %d "
900                     "proto %s on %U",
901                     outer_vlan,
902                     outer_proto == ETH_P_8021AD ? "dot1ad" : "dot1q",
903                     format_vnet_sw_if_index_name, vnm, hw->sw_if_index);
904                   err = clib_error_return (0, "parent pair not found");
905                   goto socket_close;
906                 }
907
908               LCP_ITF_PAIR_DBG ("pair_create: linux parent %U",
909                                 format_lcp_itf_pair, llip);
910               parent_vif_index = llip->lip_vif_index;
911             }
912           else
913             {
914               vlan = outer_vlan;
915               proto = outer_proto;
916             }
917
918           err = lcp_netlink_add_link_vlan (parent_vif_index, vlan, proto,
919                                            (const char *) host_if_name);
920           if (err != 0)
921             {
922               LCP_ITF_PAIR_ERR ("pair_create: cannot create link "
923                                 "outer(proto:0x%04x,vlan:%u).inner(proto:0x%"
924                                 "04x,vlan:%u) name:'%s'",
925                                 outer_proto, outer_vlan, inner_proto,
926                                 inner_vlan, host_if_name);
927             }
928
929           if (!err)
930             vif_index = if_nametoindex ((char *) host_if_name);
931         }
932
933       /*
934        * create a sub-interface on the tap
935        */
936       if (!err &&
937           vnet_create_sub_interface (lip->lip_host_sw_if_index, sw->sub.id,
938                                      sw->sub.eth.raw_flags, inner_vlan,
939                                      outer_vlan, &host_sw_if_index))
940         {
941           LCP_ITF_PAIR_ERR (
942             "pair_create: failed to create tap subint: %d.%d on %U",
943             outer_vlan, inner_vlan, format_vnet_sw_if_index_name, vnm,
944             lip->lip_host_sw_if_index);
945           err = clib_error_return (
946             0, "failed to create tap subint: %d.%d. on %U", outer_vlan,
947             inner_vlan, format_vnet_sw_if_index_name, vnm,
948             lip->lip_host_sw_if_index);
949         }
950
951     socket_close:
952       if (orig_ns_fd != -1)
953         {
954           clib_setns (orig_ns_fd);
955           close (orig_ns_fd);
956         }
957       if (ns_fd != -1)
958         close (ns_fd);
959
960       if (err)
961         return VNET_API_ERROR_INVALID_ARGUMENT;
962     }
963   else
964     {
965       tap_create_if_args_t args = {
966         .num_rx_queues = clib_max (1, vlib_num_workers ()),
967         .num_tx_queues = 1,
968         .id = hw->hw_if_index,
969         .sw_if_index = ~0,
970         .rx_ring_sz = 256,
971         .tx_ring_sz = 256,
972         .host_if_name = host_if_name,
973         .host_namespace = 0,
974       };
975       ethernet_interface_t *ei;
976
977       if (host_if_type == LCP_ITF_HOST_TUN)
978         args.tap_flags |= TAP_FLAG_TUN;
979       else
980         {
981           ei = pool_elt_at_index (ethernet_main.interfaces, hw->hw_instance);
982           mac_address_copy (&args.host_mac_addr, &ei->address.mac);
983         }
984
985       if (sw->mtu[VNET_MTU_L3])
986         {
987           args.host_mtu_set = 1;
988           args.host_mtu_size = sw->mtu[VNET_MTU_L3];
989         }
990
991       if (ns && ns[0] != 0)
992         args.host_namespace = ns;
993
994       vm = vlib_get_main ();
995       tap_create_if (vm, &args);
996
997       if (args.rv < 0)
998         {
999           LCP_ITF_PAIR_ERR ("pair_create: could not create tap, retval:%d",
1000                             args.rv);
1001           return args.rv;
1002         }
1003
1004       /*
1005        * The TAP interface does copy forward the host MTU based on the VPP
1006        * interface's L3 MTU, but it should also ensure that the VPP tap
1007        * interface has an MTU that is greater-or-equal to those. Considering
1008        * users can set the interfaces at runtime (set interface mtu packet ...)
1009        * ensure that the tap MTU is large enough, taking the VPP interface L3
1010        * if it's set, and otherwise a sensible default.
1011        */
1012       if (sw->mtu[VNET_MTU_L3])
1013         vnet_sw_interface_set_mtu (vnm, args.sw_if_index,
1014                                    sw->mtu[VNET_MTU_L3]);
1015       else
1016         vnet_sw_interface_set_mtu (vnm, args.sw_if_index,
1017                                    ETHERNET_MAX_PACKET_BYTES);
1018
1019       /*
1020        * get the hw and ethernet of the tap
1021        */
1022       hw = vnet_get_sup_hw_interface (vnm, args.sw_if_index);
1023       virtio_main_t *mm = &virtio_main;
1024       virtio_if_t *vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
1025
1026       /*
1027        * Leave the TAP permanently up on the VPP side.
1028        * This TAP will be shared by many sub-interface.
1029        * Therefore we can't use it to manage admin state.
1030        * force the tap in promiscuous mode.
1031        */
1032       if (host_if_type == LCP_ITF_HOST_TAP)
1033         {
1034           ei = pool_elt_at_index (ethernet_main.interfaces, hw->hw_instance);
1035           ei->flags |= ETHERNET_INTERFACE_FLAG_STATUS_L3;
1036         }
1037
1038       vif_index = vif->ifindex;
1039       host_sw_if_index = args.sw_if_index;
1040     }
1041
1042   if (!vif_index)
1043     {
1044       LCP_ITF_PAIR_INFO ("failed pair add (no vif index): {%U, %U, %s}",
1045                          format_vnet_sw_if_index_name, vnet_get_main (),
1046                          phy_sw_if_index, format_vnet_sw_if_index_name,
1047                          vnet_get_main (), host_sw_if_index, host_if_name);
1048       return -1;
1049     }
1050
1051   LCP_ITF_PAIR_INFO ("pair create: {%U, %U, %s}", format_vnet_sw_if_index_name,
1052                      vnet_get_main (), phy_sw_if_index,
1053                      format_vnet_sw_if_index_name, vnet_get_main (),
1054                      host_sw_if_index, host_if_name);
1055   lcp_itf_pair_add (host_sw_if_index, phy_sw_if_index, host_if_name, vif_index,
1056                     host_if_type, ns);
1057
1058   /*
1059    * Copy the link state from VPP into the host side.
1060    * The TAP is shared by many interfaces, always keep it up.
1061    * This controls whether the host can RX/TX.
1062    */
1063
1064   lip = lcp_itf_pair_get (lcp_itf_pair_find_by_vif (vif_index));
1065   LCP_ITF_PAIR_INFO ("pair create: %U sw-flags %u hw-flags %u",
1066                      format_lcp_itf_pair, lip, sw->flags, hw->flags);
1067   vnet_sw_interface_admin_up (vnm, host_sw_if_index);
1068   lcp_itf_set_link_state (lip, sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1069
1070   /*
1071    * Reflect current link state and link speed of the hardware interface on the
1072    * TAP interface.
1073    */
1074   if (host_if_type == LCP_ITF_HOST_TAP &&
1075       !vnet_sw_interface_is_sub (vnm, phy_sw_if_index))
1076     {
1077       hw = vnet_get_sup_hw_interface (vnm, phy_sw_if_index);
1078       lcp_itf_pair_link_up_down (vnm, hw->hw_if_index, hw->flags);
1079     }
1080
1081   if (host_sw_if_indexp)
1082     *host_sw_if_indexp = host_sw_if_index;
1083
1084   return 0;
1085 }
1086
1087 static walk_rc_t
1088 lcp_itf_pair_walk_mark (index_t lipi, void *ctx)
1089 {
1090   lcp_itf_pair_t *lip;
1091
1092   lip = lcp_itf_pair_get (lipi);
1093
1094   lip->lip_flags |= LIP_FLAG_STALE;
1095
1096   return (WALK_CONTINUE);
1097 }
1098
1099 int
1100 lcp_itf_pair_replace_begin (void)
1101 {
1102   lcp_itf_pair_walk (lcp_itf_pair_walk_mark, NULL);
1103
1104   return (0);
1105 }
1106
1107 typedef struct lcp_itf_pair_sweep_ctx_t_
1108 {
1109   index_t *indicies;
1110 } lcp_itf_pair_sweep_ctx_t;
1111
1112 static walk_rc_t
1113 lcp_itf_pair_walk_sweep (index_t lipi, void *arg)
1114 {
1115   lcp_itf_pair_sweep_ctx_t *ctx = arg;
1116   lcp_itf_pair_t *lip;
1117
1118   lip = lcp_itf_pair_get (lipi);
1119
1120   if (lip->lip_flags & LIP_FLAG_STALE)
1121     vec_add1 (ctx->indicies, lipi);
1122
1123   return (WALK_CONTINUE);
1124 }
1125
1126 int
1127 lcp_itf_pair_replace_end (void)
1128 {
1129   lcp_itf_pair_sweep_ctx_t ctx = {
1130     .indicies = NULL,
1131   };
1132   index_t *lipi;
1133
1134   lcp_itf_pair_walk (lcp_itf_pair_walk_sweep, &ctx);
1135
1136   vec_foreach (lipi, ctx.indicies)
1137     lcp_itf_pair_delete_by_index (*lipi);
1138
1139   vec_free (ctx.indicies);
1140   return (0);
1141 }
1142
1143 static clib_error_t *
1144 lcp_itf_pair_link_up_down (vnet_main_t *vnm, u32 hw_if_index, u32 flags)
1145 {
1146   vnet_hw_interface_t *hi;
1147   vnet_sw_interface_t *si;
1148   index_t lipi;
1149   lcp_itf_pair_t *lip;
1150
1151   hi = vnet_get_hw_interface_or_null (vnm, hw_if_index);
1152   if (!hi)
1153     return 0;
1154
1155   lipi = lcp_itf_pair_find_by_phy (hi->sw_if_index);
1156   if (lipi == INDEX_INVALID)
1157     return 0;
1158
1159   lip = lcp_itf_pair_get (lipi);
1160   si = vnet_get_sw_interface_or_null (vnm, lip->lip_host_sw_if_index);
1161   if (!si)
1162     return 0;
1163
1164   if (!lcp_main.test_mode)
1165     {
1166       tap_set_carrier (si->hw_if_index,
1167                        (flags & VNET_HW_INTERFACE_FLAG_LINK_UP));
1168
1169       if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
1170         {
1171           tap_set_speed (si->hw_if_index, hi->link_speed / 1000);
1172         }
1173     }
1174
1175   return 0;
1176 }
1177
1178 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (lcp_itf_pair_link_up_down);
1179
1180 static clib_error_t *
1181 lcp_interface_init (vlib_main_t *vm)
1182 {
1183   vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("linux-cp");
1184
1185   /* punt IKE */
1186   vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
1187                       "linux-cp-punt");
1188
1189   /* punt all unknown ports */
1190   udp_punt_unknown (vm, 0, 1);
1191   udp_punt_unknown (vm, 1, 1);
1192   tcp_punt_unknown (vm, 0, 1);
1193   tcp_punt_unknown (vm, 1, 1);
1194
1195   lcp_itf_pair_logger = vlib_log_register_class ("linux-cp", "itf");
1196
1197   return NULL;
1198 }
1199
1200 VLIB_INIT_FUNCTION (lcp_interface_init) = {
1201   .runs_after = VLIB_INITS ("vnet_interface_init", "tcp_init", "udp_init"),
1202 };
1203
1204 /*
1205  * fd.io coding-style-patch-verification: ON
1206  *
1207  * Local Variables:
1208  * eval: (c-set-style "gnu")
1209  * End:
1210  */