FD.io VPP  v21.01.1
Vector Packet Processing
tap.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #define _GNU_SOURCE
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <fcntl.h>
23 #include <net/if.h>
24 #include <linux/if_tun.h>
25 #include <sys/ioctl.h>
26 #include <linux/ethtool.h>
27 #include <linux/sockios.h>
28 #include <sys/eventfd.h>
29 #include <net/if_arp.h>
30 #include <sched.h>
31 #include <limits.h>
32 
33 #include <linux/netlink.h>
34 #include <linux/rtnetlink.h>
35 
36 #include <vlib/vlib.h>
37 #include <vlib/physmem.h>
38 #include <vlib/unix/unix.h>
39 #include <vnet/ethernet/ethernet.h>
40 #include <vnet/ip/ip4_packet.h>
41 #include <vnet/ip/ip6_packet.h>
42 #include <vnet/devices/netlink.h>
44 #include <vnet/devices/tap/tap.h>
45 
47 
48 #define tap_log_err(dev, f, ...) \
49  vlib_log (VLIB_LOG_LEVEL_ERR, tap_main.log_default, "tap%u: " f, dev->dev_instance, ## __VA_ARGS__)
50 #define tap_log_dbg(dev, f, ...) \
51  vlib_log (VLIB_LOG_LEVEL_DEBUG, tap_main.log_default, "tap%u: " f, dev->dev_instance, ## __VA_ARGS__)
52 
53 #define _IOCTL(fd,a,...) \
54  if (ioctl (fd, a, __VA_ARGS__) < 0) \
55  { \
56  err = clib_error_return_unix (0, "ioctl(" #a ")"); \
57  tap_log_err (vif, "%U", format_clib_error, err); \
58  goto error; \
59  }
60 
61  /* *INDENT-OFF* */
62 VNET_HW_INTERFACE_CLASS (tun_device_hw_interface_class, static) =
63 {
64  .name = "tun-device",
66 };
67  /* *INDENT-ON* */
68 
69 static u32
71  u32 flags)
72 {
73  /* nothing for now */
74  //TODO On MTU change call vnet_netlink_set_if_mtu
75  return 0;
76 }
77 
78 static int
79 open_netns_fd (char *netns)
80 {
81  u8 *s = 0;
82  int fd;
83 
84  if (strncmp (netns, "pid:", 4) == 0)
85  s = format (0, "/proc/%u/ns/net%c", atoi (netns + 4), 0);
86  else if (netns[0] == '/')
87  s = format (0, "%s%c", netns, 0);
88  else
89  s = format (0, "/var/run/netns/%s%c", netns, 0);
90 
91  fd = open ((char *) s, O_RDONLY);
92  vec_free (s);
93  return fd;
94 }
95 
96 #define TAP_MAX_INSTANCE 1024
97 
98 static void
100 {
101  virtio_main_t *mm = &virtio_main;
102  tap_main_t *tm = &tap_main;
103  clib_error_t *err = 0;
104  int i;
105 
106  /* *INDENT-OFF* */
107  vec_foreach_index (i, vif->vhost_fds) if (vif->vhost_fds[i] != -1)
108  close (vif->vhost_fds[i]);
109  vec_foreach_index (i, vif->rxq_vrings)
110  virtio_vring_free_rx (vm, vif, RX_QUEUE (i));
111  vec_foreach_index (i, vif->txq_vrings)
112  virtio_vring_free_tx (vm, vif, TX_QUEUE (i));
113  /* *INDENT-ON* */
114 
115  if (vif->tap_fds)
116  {
117  _IOCTL (vif->tap_fds[0], TUNSETPERSIST, (void *) (uintptr_t) 0);
118  tap_log_dbg (vif, "TUNSETPERSIST: unset");
119  }
120 error:
121  vec_foreach_index (i, vif->tap_fds) close (vif->tap_fds[i]);
122 
123  vec_free (vif->vhost_fds);
124  vec_free (vif->rxq_vrings);
125  vec_free (vif->txq_vrings);
126  vec_free (vif->host_if_name);
127  vec_free (vif->net_ns);
128  vec_free (vif->host_bridge);
129  clib_error_free (vif->error);
130 
131  tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 0);
132  clib_memset (vif, 0, sizeof (*vif));
133  pool_put (mm->interfaces, vif);
134 }
135 
136 void
138 {
140  vlib_physmem_main_t *vpm = &vm->physmem_main;
141  vnet_main_t *vnm = vnet_get_main ();
142  virtio_main_t *vim = &virtio_main;
143  tap_main_t *tm = &tap_main;
146  int i, num_vhost_queues;
147  int old_netns_fd = -1;
148  struct ifreq ifr = {.ifr_flags = IFF_NO_PI | IFF_VNET_HDR };
149  struct ifreq get_ifr = {.ifr_flags = 0 };
150  size_t hdrsz;
151  vhost_memory_t *vhost_mem = 0;
152  virtio_if_t *vif = 0;
153  clib_error_t *err = 0;
154  unsigned int tap_features;
155  int tfd = -1, qfd = -1, vfd = -1, nfd = -1;
156  char *host_if_name = 0;
157  unsigned int offload = 0;
158  int sndbuf = 0;
159 
160  if (args->id != ~0)
161  {
162  if (clib_bitmap_get (tm->tap_ids, args->id))
163  {
164  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
165  args->error = clib_error_return (0, "interface already exists");
166  return;
167  }
168  }
169  else
170  {
171  args->id = clib_bitmap_first_clear (tm->tap_ids);
172  }
173 
174  if (args->id > TAP_MAX_INSTANCE)
175  {
176  args->rv = VNET_API_ERROR_UNSPECIFIED;
177  args->error = clib_error_return (0, "cannot find free interface id");
178  return;
179  }
180 
181  pool_get_zero (vim->interfaces, vif);
182 
183  if (args->tap_flags & TAP_FLAG_TUN)
184  {
185  vif->type = VIRTIO_IF_TYPE_TUN;
186  ifr.ifr_flags |= IFF_TUN;
187 
188  /*
189  * From kernel 4.20, xdp support has been added in tun_sendmsg.
190  * If sndbuf == INT_MAX, vhost batches the packet and processes
191  * them using xdp data path for tun driver. It assumes packets
192  * are ethernet frames (It needs to be fixed).
193  * To avoid xdp data path in tun driver, sndbuf value should
194  * be < INT_MAX.
195  */
196  sndbuf = INT_MAX - 1;
197  }
198  else
199  {
200  vif->type = VIRTIO_IF_TYPE_TAP;
201  ifr.ifr_flags |= IFF_TAP;
202  sndbuf = INT_MAX;
203  }
204 
205  vif->dev_instance = vif - vim->interfaces;
206  vif->id = args->id;
207  vif->num_txqs = thm->n_vlib_mains;
208  vif->num_rxqs = clib_max (args->num_rx_queues, 1);
209 
210  if (args->tap_flags & TAP_FLAG_ATTACH)
211  {
212  if (args->host_if_name != NULL)
213  {
214  host_if_name = (char *) args->host_if_name;
215  clib_memcpy (ifr.ifr_name, host_if_name,
216  clib_min (IFNAMSIZ, vec_len (host_if_name)));
217  }
218  else
219  {
220  args->rv = VNET_API_ERROR_NO_MATCHING_INTERFACE;
221  err = clib_error_return (0, "host_if_name is not provided");
222  goto error;
223  }
224  if (args->host_namespace)
225  {
226  old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
227  if ((nfd = open_netns_fd ((char *) args->host_namespace)) == -1)
228  {
229  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
230  args->error = clib_error_return_unix (0, "open_netns_fd '%s'",
231  args->host_namespace);
232  goto error;
233  }
234  if (setns (nfd, CLONE_NEWNET) == -1)
235  {
236  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
237  args->error = clib_error_return_unix (0, "setns '%s'",
238  args->host_namespace);
239  goto error;
240  }
241  }
242  }
243 
244  if ((tfd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
245  {
246  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
247  args->error = clib_error_return_unix (0, "open '/dev/net/tun'");
248  goto error;
249  }
250  vec_add1 (vif->tap_fds, tfd);
251  tap_log_dbg (vif, "open tap fd %d", tfd);
252 
253  _IOCTL (tfd, TUNGETFEATURES, &tap_features);
254  tap_log_dbg (vif, "TUNGETFEATURES: features 0x%lx", tap_features);
255  if ((tap_features & IFF_VNET_HDR) == 0)
256  {
257  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
258  args->error = clib_error_return (0, "vhost-net backend not available");
259  goto error;
260  }
261 
262  if ((tap_features & IFF_MULTI_QUEUE) == 0)
263  {
264  if (vif->num_rxqs > 1)
265  {
266  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
267  args->error = clib_error_return (0, "multiqueue not supported");
268  goto error;
269  }
270  vif->num_rxqs = vif->num_txqs = 1;
271  }
272  else
273  ifr.ifr_flags |= IFF_MULTI_QUEUE;
274 
275  hdrsz = sizeof (virtio_net_hdr_v1_t);
276  if (args->tap_flags & TAP_FLAG_GSO)
277  {
278  offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
279  vif->gso_enabled = 1;
280  }
281  else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
282  {
283  offload = TUN_F_CSUM;
284  vif->csum_offload_enabled = 1;
285  }
286 
287  _IOCTL (tfd, TUNSETIFF, (void *) &ifr);
288  tap_log_dbg (vif, "TUNSETIFF fd %d name %s flags 0x%x", tfd,
289  ifr.ifr_ifrn.ifrn_name, ifr.ifr_flags);
290 
291  vif->ifindex = if_nametoindex (ifr.ifr_ifrn.ifrn_name);
292  tap_log_dbg (vif, "ifindex %d", vif->ifindex);
293 
294  if (!args->host_if_name)
295  host_if_name = ifr.ifr_ifrn.ifrn_name;
296  else
297  host_if_name = (char *) args->host_if_name;
298 
299  /*
300  * unset the persistence when attaching to existing
301  * interface
302  */
303  if (args->tap_flags & TAP_FLAG_ATTACH)
304  {
305  _IOCTL (tfd, TUNSETPERSIST, (void *) (uintptr_t) 0);
306  tap_log_dbg (vif, "TUNSETPERSIST: unset");
307  }
308 
309  /* set the persistence */
310  if (args->tap_flags & TAP_FLAG_PERSIST)
311  {
312  _IOCTL (tfd, TUNSETPERSIST, (void *) (uintptr_t) 1);
313  tap_log_dbg (vif, "TUNSETPERSIST: set");
314 
315  /* verify persistence is set, read the flags */
316  _IOCTL (tfd, TUNGETIFF, (void *) &get_ifr);
317  tap_log_dbg (vif, "TUNGETIFF: flags 0x%lx", get_ifr.ifr_flags);
318  if ((get_ifr.ifr_flags & IFF_PERSIST) == 0)
319  {
320  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
321  args->error = clib_error_return (0, "persistence not supported");
322  goto error;
323  }
324  }
325 
326  /* create additional queues on the linux side.
327  * we create as many linux queue pairs as we have rx queues
328  */
329  for (i = 1; i < vif->num_rxqs; i++)
330  {
331  if ((qfd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
332  {
333  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
334  args->error = clib_error_return_unix (0, "open '/dev/net/tun'");
335  goto error;
336  }
337  _IOCTL (qfd, TUNSETIFF, (void *) &ifr);
338  tap_log_dbg (vif, "TUNSETIFF fd %d name %s flags 0x%x", qfd,
339  ifr.ifr_ifrn.ifrn_name, ifr.ifr_flags);
340  vec_add1 (vif->tap_fds, qfd);
341  }
342 
343  for (i = 0; i < vif->num_rxqs; i++)
344  {
345  tap_log_dbg (vif, "TUNSETVNETHDRSZ: fd %d vnet_hdr_sz %u",
346  vif->tap_fds[i], hdrsz);
347  _IOCTL (vif->tap_fds[i], TUNSETVNETHDRSZ, &hdrsz);
348 
349  tap_log_dbg (vif, "TUNSETSNDBUF: fd %d sndbuf %d", vif->tap_fds[i],
350  sndbuf);
351  _IOCTL (vif->tap_fds[i], TUNSETSNDBUF, &sndbuf);
352 
353  tap_log_dbg (vif, "TUNSETOFFLOAD: fd %d offload 0x%lx", vif->tap_fds[i],
354  offload);
355  _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload);
356 
357  if (fcntl (vif->tap_fds[i], F_SETFL, O_NONBLOCK) < 0)
358  {
359  err = clib_error_return_unix (0, "fcntl(tfd, F_SETFL, O_NONBLOCK)");
360  tap_log_err (vif, "set nonblocking: %U", format_clib_error, err);
361  goto error;
362  }
363  }
364 
365  /* open as many vhost-net fds as required and set ownership */
366  num_vhost_queues = clib_max (vif->num_rxqs, vif->num_txqs);
367  for (i = 0; i < num_vhost_queues; i++)
368  {
369  if ((vfd = open ("/dev/vhost-net", O_RDWR | O_NONBLOCK)) < 0)
370  {
371  args->rv = VNET_API_ERROR_SYSCALL_ERROR_1;
372  args->error = clib_error_return_unix (0, "open '/dev/vhost-net'");
373  goto error;
374  }
375  vec_add1 (vif->vhost_fds, vfd);
376  virtio_log_debug (vif, "open vhost-net fd %d qpair %u", vfd, i);
377  _IOCTL (vfd, VHOST_SET_OWNER, 0);
378  virtio_log_debug (vif, "VHOST_SET_OWNER: fd %u", vfd);
379  }
380 
381  _IOCTL (vif->vhost_fds[0], VHOST_GET_FEATURES, &vif->remote_features);
382  virtio_log_debug (vif, "VHOST_GET_FEATURES: features 0x%lx",
383  vif->remote_features);
384 
385  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0)
386  {
387  args->rv = VNET_API_ERROR_UNSUPPORTED;
388  args->error = clib_error_return (0, "vhost-net backend doesn't support "
389  "VIRTIO_NET_F_MRG_RXBUF feature");
390  goto error;
391  }
392 
393  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) ==
394  0)
395  {
396  args->rv = VNET_API_ERROR_UNSUPPORTED;
397  args->error = clib_error_return (0, "vhost-net backend doesn't support "
398  "VIRTIO_RING_F_INDIRECT_DESC feature");
399  goto error;
400  }
401 
402  if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1)) == 0)
403  {
404  args->rv = VNET_API_ERROR_UNSUPPORTED;
405  args->error = clib_error_return (0, "vhost-net backend doesn't support "
406  "VIRTIO_F_VERSION_1 features");
407  goto error;
408  }
409 
410  vif->features |= VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF);
411  vif->features |= VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
412  vif->features |= VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC);
413 
415 
416  if (!(args->tap_flags & TAP_FLAG_ATTACH))
417  {
418  /* if namespace is specified, all further netlink messages should be executed
419  after we change our net namespace */
420  if (args->host_namespace)
421  {
422  old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
423  if ((nfd = open_netns_fd ((char *) args->host_namespace)) == -1)
424  {
425  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
426  args->error = clib_error_return_unix (0, "open_netns_fd '%s'",
427  args->host_namespace);
428  goto error;
429  }
430  args->error = vnet_netlink_set_link_netns (vif->ifindex, nfd,
431  host_if_name);
432  if (args->error)
433  {
434  args->rv = VNET_API_ERROR_NETLINK_ERROR;
435  goto error;
436  }
437  if (setns (nfd, CLONE_NEWNET) == -1)
438  {
439  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
440  args->error = clib_error_return_unix (0, "setns '%s'",
441  args->host_namespace);
442  goto error;
443  }
444  if ((vif->ifindex = if_nametoindex (host_if_name)) == 0)
445  {
446  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
447  args->error = clib_error_return_unix (0, "if_nametoindex '%s'",
448  host_if_name);
449  goto error;
450  }
451  }
452  else if (host_if_name)
453  {
454  args->error =
455  vnet_netlink_set_link_name (vif->ifindex, host_if_name);
456  if (args->error)
457  {
458  args->rv = VNET_API_ERROR_NETLINK_ERROR;
459  goto error;
460  }
461  }
462  }
463 
464  if (vif->type == VIRTIO_IF_TYPE_TAP)
465  {
469  args->host_mac_addr.bytes);
470  if (args->error)
471  {
472  args->rv = VNET_API_ERROR_NETLINK_ERROR;
473  goto error;
474  }
475 
476  if (args->host_bridge)
477  {
479  (char *)
480  args->host_bridge);
481  if (args->error)
482  {
483  args->rv = VNET_API_ERROR_NETLINK_ERROR;
484  goto error;
485  }
486  }
487  }
488 
489  if (args->host_ip4_prefix_len)
490  {
492  &args->host_ip4_addr,
493  args->host_ip4_prefix_len);
494  if (args->error)
495  {
496  args->rv = VNET_API_ERROR_NETLINK_ERROR;
497  goto error;
498  }
499  }
500 
501  if (args->host_ip6_prefix_len)
502  {
504  &args->host_ip6_addr,
505  args->host_ip6_prefix_len);
506  if (args->error)
507  {
508  args->rv = VNET_API_ERROR_NETLINK_ERROR;
509  goto error;
510  }
511  }
512 
513  args->error = vnet_netlink_set_link_state (vif->ifindex, 1 /* UP */ );
514  if (args->error)
515  {
516  args->rv = VNET_API_ERROR_NETLINK_ERROR;
517  goto error;
518  }
519 
520  if (args->host_ip4_gw_set)
521  {
522  args->error = vnet_netlink_add_ip4_route (0, 0, &args->host_ip4_gw);
523  if (args->error)
524  {
525  args->rv = VNET_API_ERROR_NETLINK_ERROR;
526  goto error;
527  }
528  }
529 
530  if (args->host_ip6_gw_set)
531  {
532  args->error = vnet_netlink_add_ip6_route (0, 0, &args->host_ip6_gw);
533  if (args->error)
534  {
535  args->rv = VNET_API_ERROR_NETLINK_ERROR;
536  goto error;
537  }
538  }
539 
540  if (args->host_mtu_set)
541  {
542  args->error =
544  if (args->error)
545  {
546  args->rv = VNET_API_ERROR_NETLINK_ERROR;
547  goto error;
548  }
549  }
550  else if (tm->host_mtu_size != 0)
551  {
552  args->error =
554  if (args->error)
555  {
556  args->rv = VNET_API_ERROR_NETLINK_ERROR;
557  goto error;
558  }
559  args->host_mtu_set = 1;
560  args->host_mtu_size = tm->host_mtu_size;
561  }
562 
563  /* switch back to old net namespace */
564  if (args->host_namespace)
565  {
566  if (setns (old_netns_fd, CLONE_NEWNET) == -1)
567  {
568  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
569  args->error = clib_error_return_unix (0, "setns '%s'",
570  args->host_namespace);
571  goto error;
572  }
573  }
574 
575  for (i = 0; i < num_vhost_queues; i++)
576  {
577  if (i < vif->num_rxqs && (args->error =
578  virtio_vring_init (vm, vif, RX_QUEUE (i),
579  args->rx_ring_sz)))
580  {
581  args->rv = VNET_API_ERROR_INIT_FAILED;
582  goto error;
583  }
584 
585  if (i < vif->num_txqs && (args->error =
586  virtio_vring_init (vm, vif, TX_QUEUE (i),
587  args->tx_ring_sz)))
588  {
589  args->rv = VNET_API_ERROR_INIT_FAILED;
590  goto error;
591  }
592  }
593 
594  /* setup features and memtable */
595  i = sizeof (vhost_memory_t) + sizeof (vhost_memory_region_t);
596  vhost_mem = clib_mem_alloc (i);
597  clib_memset (vhost_mem, 0, i);
598  vhost_mem->nregions = 1;
599  vhost_mem->regions[0].memory_size = vpm->max_size;
600  vhost_mem->regions[0].guest_phys_addr = vpm->base_addr;
601  vhost_mem->regions[0].userspace_addr =
602  vhost_mem->regions[0].guest_phys_addr;
603 
604  for (i = 0; i < vhost_mem->nregions; i++)
605  virtio_log_debug (vif, "memtable region %u memory_size 0x%lx "
606  "guest_phys_addr 0x%lx userspace_addr 0x%lx", i,
607  vhost_mem->regions[0].memory_size,
608  vhost_mem->regions[0].guest_phys_addr,
609  vhost_mem->regions[0].userspace_addr);
610 
611 
612  for (i = 0; i < num_vhost_queues; i++)
613  {
614  int fd = vif->vhost_fds[i];
615  _IOCTL (fd, VHOST_SET_FEATURES, &vif->features);
616  virtio_log_debug (vif, "VHOST_SET_FEATURES: fd %u features 0x%lx",
617  fd, vif->features);
618  _IOCTL (fd, VHOST_SET_MEM_TABLE, vhost_mem);
619  virtio_log_debug (vif, "VHOST_SET_MEM_TABLE: fd %u", fd);
620  }
621 
622  /* finish initializing queue pair */
623  for (i = 0; i < num_vhost_queues * 2; i++)
624  {
625  vhost_vring_addr_t addr = { 0 };
626  vhost_vring_state_t state = { 0 };
627  vhost_vring_file_t file = { 0 };
628  virtio_vring_t *vring;
629  u16 qp = i >> 1;
630  int fd = vif->vhost_fds[qp];
631 
632  if (i & 1)
633  {
634  if (qp >= vif->num_txqs)
635  continue;
636  vring = vec_elt_at_index (vif->txq_vrings, qp);
637  }
638  else
639  {
640  if (qp >= vif->num_rxqs)
641  continue;
642  vring = vec_elt_at_index (vif->rxq_vrings, qp);
643  }
644 
645  addr.index = state.index = file.index = vring->queue_id & 1;
646  state.num = vring->size;
647  virtio_log_debug (vif, "VHOST_SET_VRING_NUM fd %d index %u num %u", fd,
648  state.index, state.num);
649  _IOCTL (fd, VHOST_SET_VRING_NUM, &state);
650 
651  addr.flags = 0;
652  addr.desc_user_addr = pointer_to_uword (vring->desc);
653  addr.avail_user_addr = pointer_to_uword (vring->avail);
654  addr.used_user_addr = pointer_to_uword (vring->used);
655 
656  virtio_log_debug (vif, "VHOST_SET_VRING_ADDR fd %d index %u flags 0x%x "
657  "desc_user_addr 0x%lx avail_user_addr 0x%lx "
658  "used_user_addr 0x%lx", fd, addr.index,
659  addr.flags, addr.desc_user_addr, addr.avail_user_addr,
660  addr.used_user_addr);
661  _IOCTL (fd, VHOST_SET_VRING_ADDR, &addr);
662 
663  file.fd = vring->call_fd;
664  virtio_log_debug (vif, "VHOST_SET_VRING_CALL fd %d index %u call_fd %d",
665  fd, file.index, file.fd);
666  _IOCTL (fd, VHOST_SET_VRING_CALL, &file);
667 
668  file.fd = vring->kick_fd;
669  virtio_log_debug (vif, "VHOST_SET_VRING_KICK fd %d index %u kick_fd %d",
670  fd, file.index, file.fd);
671  _IOCTL (fd, VHOST_SET_VRING_KICK, &file);
672 
673  file.fd = vif->tap_fds[qp % vif->num_rxqs];
674  virtio_log_debug (vif, "VHOST_NET_SET_BACKEND fd %d index %u tap_fd %d",
675  fd, file.index, file.fd);
676  _IOCTL (fd, VHOST_NET_SET_BACKEND, &file);
677  }
678 
679  if (vif->type == VIRTIO_IF_TYPE_TAP)
680  {
681  if (!args->mac_addr_set)
683 
684  clib_memcpy (vif->mac_addr, args->mac_addr.bytes, 6);
685  vif->host_bridge = format (0, "%s%c", args->host_bridge, 0);
686  }
687  vif->host_if_name = format (0, "%s%c", host_if_name, 0);
688  vif->net_ns = format (0, "%s%c", args->host_namespace, 0);
689  vif->host_mtu_size = args->host_mtu_size;
690  vif->tap_flags = args->tap_flags;
691  clib_memcpy (vif->host_mac_addr, args->host_mac_addr.bytes, 6);
694  if (args->host_ip4_prefix_len)
695  clib_memcpy (&vif->host_ip4_addr, &args->host_ip4_addr, 4);
696  if (args->host_ip6_prefix_len)
697  clib_memcpy (&vif->host_ip6_addr, &args->host_ip6_addr, 16);
698 
699  if (vif->type != VIRTIO_IF_TYPE_TUN)
700  {
701  args->error =
703  vif->dev_instance, vif->mac_addr,
704  &vif->hw_if_index,
706  if (args->error)
707  {
708  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
709  goto error;
710  }
711 
712  }
713  else
714  {
716  (vnm, virtio_device_class.index,
717  vif->dev_instance /* device instance */ ,
718  tun_device_hw_interface_class.index, vif->dev_instance);
719 
720  }
721  tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 1);
722  sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
723  vif->sw_if_index = sw->sw_if_index;
724  args->sw_if_index = vif->sw_if_index;
725  args->rv = 0;
726  hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
728  if (args->tap_flags & TAP_FLAG_GSO)
729  {
732  }
733  else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
734  {
736  }
737  if ((args->tap_flags & TAP_FLAG_GSO)
738  && (args->tap_flags & TAP_FLAG_GRO_COALESCE))
739  {
741  }
743  virtio_input_node.index);
744 
745  for (i = 0; i < vif->num_rxqs; i++)
746  {
750  virtio_vring_set_numa_node (vm, vif, RX_QUEUE (i));
751  }
752 
753  vif->per_interface_next_index = ~0;
754  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
757  /*
758  * Host tun/tap driver link carrier state is "up" at creation. The
759  * driver never changes this unless the backend (VPP) changes it using
760  * TUNSETCARRIER ioctl(). See tap_set_carrier().
761  */
762  vif->host_carrier_up = 1;
763  vif->cxq_vring = NULL;
764 
765  goto done;
766 
767 error:
768  if (err)
769  {
770  ASSERT (args->error == 0);
771  args->error = err;
772  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
773  }
774 
775  tap_log_err (vif, "%U", format_clib_error, args->error);
776  tap_free (vm, vif);
777 done:
778  if (vhost_mem)
779  clib_mem_free (vhost_mem);
780  if (old_netns_fd != -1)
781  close (old_netns_fd);
782  if (nfd != -1)
783  close (nfd);
784 }
785 
786 int
788 {
789  vnet_main_t *vnm = vnet_get_main ();
790  virtio_main_t *mm = &virtio_main;
791  int i;
792  virtio_if_t *vif;
794 
795  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
796  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
797  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
798 
799  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
800 
801  if ((vif->type != VIRTIO_IF_TYPE_TAP) && (vif->type != VIRTIO_IF_TYPE_TUN))
802  return VNET_API_ERROR_INVALID_INTERFACE;
803 
804  /* bring down the interface */
807  for (i = 0; i < vif->num_rxqs; i++)
809 
810  if (vif->type == VIRTIO_IF_TYPE_TAP)
812  else /* VIRTIO_IF_TYPE_TUN */
814  vif->hw_if_index = ~0;
815 
816  tap_free (vm, vif);
817 
818  return 0;
819 }
820 
821 int
823  int enable_disable)
824 {
825  vnet_main_t *vnm = vnet_get_main ();
826  virtio_main_t *mm = &virtio_main;
827  virtio_if_t *vif;
829  clib_error_t *err = 0;
830  int i = 0;
831 
832  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
833 
834  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
835  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
836 
837  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
838 
839  const unsigned int csum_offload_on = TUN_F_CSUM;
840  const unsigned int csum_offload_off = 0;
841  unsigned int offload = enable_disable ? csum_offload_on : csum_offload_off;
842  vec_foreach_index (i, vif->tap_fds)
843  _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload);
844  vif->gso_enabled = 0;
845  vif->packet_coalesce = 0;
846  vif->csum_offload_enabled = enable_disable ? 1 : 0;
847 
849  {
851  }
852 
853  if (enable_disable)
854  {
856  0)
857  {
859  }
860  }
861  else
862  {
864  0)
865  {
867  }
868  }
869 
870 error:
871  if (err)
872  {
873  clib_warning ("Error %s checksum offload on sw_if_index %d",
874  enable_disable ? "enabling" : "disabling", sw_if_index);
875  return VNET_API_ERROR_SYSCALL_ERROR_3;
876  }
877  return 0;
878 }
879 
880 int
882  int is_packet_coalesce)
883 {
884  vnet_main_t *vnm = vnet_get_main ();
885  virtio_main_t *mm = &virtio_main;
886  virtio_if_t *vif;
888  clib_error_t *err = 0;
889  int i = 0;
890 
891  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
892 
893  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
894  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
895 
896  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
897 
898  const unsigned int gso_on = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
899  const unsigned int gso_off = 0;
900  unsigned int offload = enable_disable ? gso_on : gso_off;
901  vec_foreach_index (i, vif->tap_fds)
902  _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload);
903  vif->gso_enabled = enable_disable ? 1 : 0;
904  vif->csum_offload_enabled = 0;
905  if (enable_disable)
906  {
908  {
911  }
912  if (is_packet_coalesce)
913  {
915  }
916  }
917  else
918  {
920  {
923  }
924  vif->packet_coalesce = 0;
925  }
926 
927 error:
928  if (err)
929  {
930  clib_warning ("Error %s gso on sw_if_index %d",
931  enable_disable ? "enabling" : "disabling", sw_if_index);
932  return VNET_API_ERROR_SYSCALL_ERROR_3;
933  }
934  return 0;
935 }
936 
937 int
939 {
940  vnet_main_t *vnm = vnet_get_main ();
941  virtio_main_t *mm = &virtio_main;
942  virtio_if_t *vif;
943  virtio_vring_t *vring;
945  tap_interface_details_t *r_tapids = NULL;
946  tap_interface_details_t *tapid = NULL;
947 
948  /* *INDENT-OFF* */
949  pool_foreach (vif, mm->interfaces) {
950  if ((vif->type != VIRTIO_IF_TYPE_TAP)
951  && (vif->type != VIRTIO_IF_TYPE_TUN))
952  continue;
953  vec_add2(r_tapids, tapid, 1);
954  clib_memset (tapid, 0, sizeof (*tapid));
955  tapid->id = vif->id;
956  tapid->sw_if_index = vif->sw_if_index;
957  hi = vnet_get_hw_interface (vnm, vif->hw_if_index);
958  clib_memcpy(tapid->dev_name, hi->name,
959  MIN (ARRAY_LEN (tapid->dev_name) - 1, vec_len (hi->name)));
960  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0));
961  tapid->rx_ring_sz = vring->size;
962  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0));
963  tapid->tx_ring_sz = vring->size;
964  tapid->tap_flags = vif->tap_flags;
965  clib_memcpy(&tapid->host_mac_addr, vif->host_mac_addr, 6);
966  if (vif->host_if_name)
967  {
969  MIN (ARRAY_LEN (tapid->host_if_name) - 1,
970  vec_len (vif->host_if_name)));
971  }
972  if (vif->net_ns)
973  {
974  clib_memcpy(tapid->host_namespace, vif->net_ns,
975  MIN (ARRAY_LEN (tapid->host_namespace) - 1,
976  vec_len (vif->net_ns)));
977  }
978  if (vif->host_bridge)
979  {
980  clib_memcpy(tapid->host_bridge, vif->host_bridge,
981  MIN (ARRAY_LEN (tapid->host_bridge) - 1,
982  vec_len (vif->host_bridge)));
983  }
984  if (vif->host_ip4_prefix_len)
985  clib_memcpy(tapid->host_ip4_addr.as_u8, &vif->host_ip4_addr, 4);
987  if (vif->host_ip6_prefix_len)
988  clib_memcpy(tapid->host_ip6_addr.as_u8, &vif->host_ip6_addr, 16);
990  tapid->host_mtu_size = vif->host_mtu_size;
991  }
992  /* *INDENT-ON* */
993 
994  *out_tapids = r_tapids;
995 
996  return 0;
997 }
998 
999 /*
1000  * Set host tap/tun interface carrier state so it will appear to host
1001  * applications that the interface's link state changed.
1002  *
1003  * If the kernel we're building against does not have support for the
1004  * TUNSETCARRIER ioctl command, do nothing.
1005  */
1006 int
1007 tap_set_carrier (u32 hw_if_index, u32 carrier_up)
1008 {
1009  int ret = 0;
1010 #ifdef TUNSETCARRIER
1011  vnet_main_t *vnm = vnet_get_main ();
1012  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1013  virtio_main_t *mm = &virtio_main;
1014  virtio_if_t *vif;
1015  int *fd;
1016 
1017  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
1018  vec_foreach (fd, vif->tap_fds)
1019  {
1020  ret = ioctl (*fd, TUNSETCARRIER, &carrier_up);
1021  if (ret < 0)
1022  {
1023  clib_warning ("ioctl (TUNSETCARRIER) returned %d", ret);
1024  break;
1025  }
1026  }
1027  if (!ret)
1028  vif->host_carrier_up = (carrier_up != 0);
1029 #endif
1030 
1031  return ret;
1032 }
1033 
1034 static clib_error_t *
1036 {
1037  tap_main_t *tm = &tap_main;
1038 
1039  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1040  {
1041  if (unformat (input, "host-mtu %d", &tm->host_mtu_size))
1042  ;
1043  else
1044  return clib_error_return (0, "unknown input `%U'",
1045  format_unformat_error, input);
1046  }
1047 
1048  return 0;
1049 }
1050 
1051 /*
1052  * Set host tap/tun interface speed in Mbps.
1053  */
1054 int
1055 tap_set_speed (u32 hw_if_index, u32 speed)
1056 {
1057  vnet_main_t *vnm = vnet_get_main ();
1058  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1059  virtio_main_t *mm = &virtio_main;
1060  virtio_if_t *vif;
1061  int old_netns_fd = -1;
1062  int nfd = -1;
1063  int ctl_fd = -1;
1064  struct ifreq ifr;
1065  struct ethtool_cmd ecmd;
1066  int ret = -1;
1067 
1068  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
1069 
1070  if (vif->net_ns)
1071  {
1072  old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
1073  if ((nfd = open_netns_fd ((char *) vif->net_ns)) == -1)
1074  {
1075  clib_warning ("Cannot open netns");
1076  goto done;
1077  }
1078  if (setns (nfd, CLONE_NEWNET) == -1)
1079  {
1080  clib_warning ("Cannot set ns");
1081  goto done;
1082  }
1083  }
1084 
1085  if ((ctl_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1086  {
1087  clib_warning ("Cannot open control socket");
1088  goto done;
1089  }
1090 
1091  ecmd.cmd = ETHTOOL_GSET;
1092  clib_memset (&ifr, 0, sizeof (ifr));
1093  clib_memcpy (ifr.ifr_name, vif->host_if_name,
1094  strlen ((const char *) vif->host_if_name));
1095  ifr.ifr_data = (void *) &ecmd;
1096  if ((ret = ioctl (ctl_fd, SIOCETHTOOL, &ifr)) < 0)
1097  {
1098  clib_warning ("Cannot get device settings");
1099  goto done;
1100  }
1101 
1102  if (ethtool_cmd_speed (&ecmd) != speed)
1103  {
1104  ecmd.cmd = ETHTOOL_SSET;
1105  ethtool_cmd_speed_set (&ecmd, speed);
1106  if ((ret = ioctl (ctl_fd, SIOCETHTOOL, &ifr)) < 0)
1107  {
1108  clib_warning ("Cannot set device settings");
1109  goto done;
1110  }
1111  }
1112 
1113 done:
1114  if (old_netns_fd != -1)
1115  {
1116  if (setns (old_netns_fd, CLONE_NEWNET) == -1)
1117  {
1118  clib_warning ("Cannot set old ns");
1119  }
1120  close (old_netns_fd);
1121  }
1122  if (nfd != -1)
1123  close (nfd);
1124  if (ctl_fd != -1)
1125  close (ctl_fd);
1126 
1127  return ret;
1128 }
1129 
1130 /* tap { host-mtu <size> } configuration. */
1132 
1133 static clib_error_t *
1135 {
1136  tap_main_t *tm = &tap_main;
1137  clib_error_t *error = 0;
1138 
1139  tm->log_default = vlib_log_register_class ("tap", 0);
1140  vlib_log_debug (tm->log_default, "initialized");
1141 
1142  tm->host_mtu_size = 0;
1143 
1144  return error;
1145 }
1146 
1148 
1149 /*
1150  * fd.io coding-style-patch-verification: ON
1151  *
1152  * Local Variables:
1153  * eval: (c-set-style "gnu")
1154  * End:
1155  */
u32 per_interface_next_index
Definition: virtio.h:132
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:338
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:670
#define vec_foreach_index(var, v)
Iterate over vector indices.
uword * tap_ids
Definition: tap.h:97
int host_mtu_size
Definition: tap.h:100
void virtio_set_net_hdr_size(virtio_if_t *vif)
Definition: virtio.c:252
virtio_if_t * interfaces
Definition: virtio.h:219
#define clib_min(x, y)
Definition: clib.h:328
static u32 virtio_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: tap.c:70
static void tap_free(vlib_main_t *vm, virtio_if_t *vif)
Definition: tap.c:99
VNET_HW_INTERFACE_CLASS(tun_device_hw_interface_class, static)
vlib_log_class_t log_default
Definition: tap.h:94
ip4_address_t host_ip4_addr
Definition: virtio.h:186
u8 host_if_name[64]
Definition: tap.h:81
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags)
Definition: interface.c:519
u8 host_namespace[64]
Definition: tap.h:82
ip4_address_t host_ip4_addr
Definition: tap.h:55
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
u8 host_carrier_up
Definition: virtio.h:189
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:254
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
vlib_physmem_main_t physmem_main
Definition: main.h:185
#define VHOST_SET_OWNER
Definition: vhost_std.h:65
int gso_enabled
Definition: virtio.h:137
u32 host_mtu_size
Definition: virtio.h:183
u32 dev_instance
Definition: virtio.h:157
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
int kick_fd
Definition: virtio.h:93
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u8 host_ip6_prefix_len
Definition: tap.h:60
vnet_device_class_t virtio_device_class
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
void virtio_vring_set_numa_node(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:236
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:794
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define tap_log_dbg(dev, f,...)
Definition: tap.c:50
int tap_csum_offload_enable_disable(vlib_main_t *vm, u32 sw_if_index, int enable_disable)
Definition: tap.c:822
#define VHOST_SET_MEM_TABLE
Definition: vhost_std.h:67
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:509
int call_fd
Definition: virtio.h:94
vhost_vring_addr_t addr
Definition: vhost_user.h:111
int tap_dump_ifs(tap_interface_details_t **out_tapids)
Definition: tap.c:938
u8 host_ip4_gw_set
Definition: tap.h:58
unsigned char u8
Definition: types.h:56
clib_error_t * virtio_vring_free_tx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:174
#define VIRTIO_FEATURE(X)
Definition: virtio_std.h:69
vring_desc_t * desc
Definition: virtio.h:71
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define clib_memcpy(d, s, n)
Definition: string.h:180
u8 host_bridge[64]
Definition: tap.h:83
u64 features
Definition: virtio.h:130
u32 hw_if_index
Definition: virtio.h:151
u8 host_ip6_prefix_len
Definition: virtio.h:188
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:39
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
u8 * host_bridge
Definition: virtio.h:180
int ifindex
Definition: virtio.h:185
description fragment has unexpected format
Definition: map.api:433
vnet_hw_interface_flags_t flags
Definition: interface.h:538
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
int tap_delete_if(vlib_main_t *vm, u32 sw_if_index)
Definition: tap.c:787
#define clib_error_return(e, args...)
Definition: error.h:99
#define VHOST_SET_VRING_ADDR
Definition: vhost_std.h:71
unsigned int u32
Definition: types.h:88
#define vlib_log_debug(...)
Definition: log.h:136
#define MIN(x, y)
Definition: node.h:31
u32 id
Definition: virtio.h:182
u16 queue_id
Definition: virtio.h:84
u16 num_txqs
Definition: virtio.h:134
Definition: cJSON.c:84
#define TX_QUEUE(X)
Definition: virtio.h:37
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
int * vhost_fds
Definition: virtio.h:177
mac_address_t host_mac_addr
Definition: tap.h:80
vring_avail_t * avail
Definition: virtio.h:73
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define clib_error_return_unix(e, args...)
Definition: error.h:102
int vnet_hw_interface_set_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_if_rx_mode mode)
Definition: devices.c:253
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:182
ip4_address_t host_ip4_gw
Definition: tap.h:57
ip6_address_t host_ip6_addr
Definition: tap.h:59
u8 host_ip4_prefix_len
Definition: tap.h:56
#define virtio_log_debug(vif, f,...)
Definition: virtio.h:272
int packet_coalesce
Definition: virtio.h:155
vring_used_t * used
Definition: virtio.h:72
ip4_address_t host_ip4_addr
Definition: tap.h:84
u16 num_rxqs
Definition: virtio.h:133
virtio_vring_t * rxq_vrings
Definition: virtio.h:135
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
#define TAP_MAX_INSTANCE
Definition: tap.c:96
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static int open_netns_fd(char *netns)
Definition: tap.c:79
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
u32 host_mtu_size
Definition: tap.h:64
ip6_address_t host_ip6_addr
Definition: virtio.h:176
static vnet_hw_interface_t * vnet_get_sup_hw_interface_api_visible_or_null(vnet_main_t *vnm, u32 sw_if_index)
#define clib_warning(format, args...)
Definition: error.h:59
u8 * net_ns
Definition: virtio.h:179
#define VHOST_NET_SET_BACKEND
Definition: vhost_std.h:77
u8 mac_addr[6]
Definition: virtio.h:170
u32 flags
Definition: virtio.h:131
#define ARRAY_LEN(x)
Definition: clib.h:67
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
clib_error_t * error
Definition: virtio.h:162
u32 tap_flags
Definition: virtio.h:184
#define VHOST_SET_VRING_CALL
Definition: vhost_std.h:75
u8 * host_bridge
Definition: tap.h:54
virtio_if_type_t type
Definition: virtio.h:149
#define VHOST_GET_FEATURES
Definition: vhost_std.h:63
#define ASSERT(truth)
void vnet_hw_interface_assign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, uword thread_index)
Definition: devices.c:139
u64 remote_features
Definition: virtio.h:159
ip6_address_t host_ip6_gw
Definition: tap.h:61
clib_error_t * virtio_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 idx, u16 sz)
Definition: virtio.c:64
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1011
u8 * host_if_name
Definition: tap.h:52
u8 host_mac_addr[6]
Definition: virtio.h:181
static void clib_mem_free(void *p)
Definition: mem.h:311
void virtio_set_packet_coalesce(virtio_if_t *vif)
Definition: virtio.c:199
unsigned int if_nametoindex(const char *ifname)
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define clib_max(x, y)
Definition: clib.h:321
virtio_main_t virtio_main
Definition: virtio.c:35
vl_api_ip4_address_t hi
Definition: arp.api:37
u8 host_ip6_gw_set
Definition: tap.h:62
void tap_create_if(vlib_main_t *vm, tap_create_if_args_t *args)
Definition: tap.c:137
#define RX_QUEUE_ACCESS(X)
Definition: virtio.h:40
tap_main_t tap_main
Definition: tap.c:46
int csum_offload_enabled
Definition: virtio.h:138
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define tap_log_err(dev, f,...)
Definition: tap.c:48
static void ethernet_mac_address_generate(u8 *mac)
Definition: mac_address.h:74
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:348
Definition: tap.h:91
mac_address_t host_mac_addr
Definition: tap.h:53
int tap_gso_enable_disable(vlib_main_t *vm, u32 sw_if_index, int enable_disable, int is_packet_coalesce)
Definition: tap.c:881
int tap_set_speed(u32 hw_if_index, u32 speed)
Definition: tap.c:1055
a point 2 point interface
Definition: interface.h:387
mac_address_t mac_addr
Definition: tap.h:46
#define clib_error_free(e)
Definition: error.h:86
clib_error_t * error
Definition: tap.h:68
ip6_address_t host_ip6_addr
Definition: tap.h:86
u8 host_ip4_prefix_len
Definition: virtio.h:187
int vnet_hw_interface_unassign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.c:188
u32 sw_if_index
Definition: virtio.h:152
int tap_set_carrier(u32 hw_if_index, u32 carrier_up)
Definition: tap.c:1007
virtio_vring_t * cxq_vring
Definition: virtio.h:194
#define VHOST_SET_VRING_NUM
Definition: vhost_std.h:70
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static int ethernet_mac_address_is_zero(const u8 *mac)
Definition: mac_address.h:68
clib_error_t * virtio_vring_free_rx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:152
TAP interface details struct.
Definition: tap.h:72
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
vl_api_dhcp_client_state_t state
Definition: dhcp.api:201
#define vec_foreach(var, vec)
Vector iterator.
static clib_error_t * tap_mtu_config(vlib_main_t *vm, unformat_input_t *input)
Definition: tap.c:1035
vhost_memory_region_t regions[0]
Definition: vhost_std.h:30
u8 * host_namespace
Definition: tap.h:51
#define VHOST_SET_VRING_KICK
Definition: vhost_std.h:74
#define VHOST_SET_FEATURES
Definition: vhost_std.h:64
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:451
#define RX_QUEUE(X)
Definition: virtio.h:38
__clib_export u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
int * tap_fds
Definition: virtio.h:141
static void vnet_hw_interface_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: devices.h:79
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
virtio_vring_t * txq_vrings
Definition: virtio.h:136
static clib_error_t * tap_init(vlib_main_t *vm)
Definition: tap.c:1134
u8 * host_if_name
Definition: virtio.h:178