FD.io VPP  v21.06
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  {
733  }
734  else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
735  {
738  }
739  if ((args->tap_flags & TAP_FLAG_GSO)
740  && (args->tap_flags & TAP_FLAG_GRO_COALESCE))
741  {
743  }
744 
745  virtio_vring_set_rx_queues (vm, vif);
746 
747  vif->per_interface_next_index = ~0;
748  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
751  /*
752  * Host tun/tap driver link carrier state is "up" at creation. The
753  * driver never changes this unless the backend (VPP) changes it using
754  * TUNSETCARRIER ioctl(). See tap_set_carrier().
755  */
756  vif->host_carrier_up = 1;
757  vif->cxq_vring = NULL;
758 
759  goto done;
760 
761 error:
762  if (err)
763  {
764  ASSERT (args->error == 0);
765  args->error = err;
766  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
767  }
768 
769  tap_log_err (vif, "%U", format_clib_error, args->error);
770  tap_free (vm, vif);
771 done:
772  if (vhost_mem)
773  clib_mem_free (vhost_mem);
774  if (old_netns_fd != -1)
775  close (old_netns_fd);
776  if (nfd != -1)
777  close (nfd);
778 }
779 
780 int
782 {
783  vnet_main_t *vnm = vnet_get_main ();
784  virtio_main_t *mm = &virtio_main;
785  virtio_if_t *vif;
787 
788  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
789  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
790  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
791 
792  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
793 
794  if ((vif->type != VIRTIO_IF_TYPE_TAP) && (vif->type != VIRTIO_IF_TYPE_TUN))
795  return VNET_API_ERROR_INVALID_INTERFACE;
796 
797  /* bring down the interface */
800 
801  if (vif->type == VIRTIO_IF_TYPE_TAP)
803  else /* VIRTIO_IF_TYPE_TUN */
805  vif->hw_if_index = ~0;
806 
807  tap_free (vm, vif);
808 
809  return 0;
810 }
811 
812 int
814  int enable_disable)
815 {
816  vnet_main_t *vnm = vnet_get_main ();
817  virtio_main_t *mm = &virtio_main;
818  virtio_if_t *vif;
820  clib_error_t *err = 0;
821  int i = 0;
822 
823  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
824 
825  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
826  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
827 
828  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
829 
830  const unsigned int csum_offload_on = TUN_F_CSUM;
831  const unsigned int csum_offload_off = 0;
832  unsigned int offload = enable_disable ? csum_offload_on : csum_offload_off;
833  vec_foreach_index (i, vif->tap_fds)
834  _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload);
835  vif->gso_enabled = 0;
836  vif->packet_coalesce = 0;
837  vif->csum_offload_enabled = enable_disable ? 1 : 0;
838 
840  {
842  }
843 
844  if (enable_disable)
845  {
847  }
848  else
849  {
851  }
852 
853 error:
854  if (err)
855  {
856  clib_warning ("Error %s checksum offload on sw_if_index %d",
857  enable_disable ? "enabling" : "disabling", sw_if_index);
858  return VNET_API_ERROR_SYSCALL_ERROR_3;
859  }
860  return 0;
861 }
862 
863 int
865  int is_packet_coalesce)
866 {
867  vnet_main_t *vnm = vnet_get_main ();
868  virtio_main_t *mm = &virtio_main;
869  virtio_if_t *vif;
871  clib_error_t *err = 0;
872  int i = 0;
873 
874  hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
875 
876  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
877  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
878 
879  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
880 
881  const unsigned int gso_on = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
882  const unsigned int gso_off = 0;
883  unsigned int offload = enable_disable ? gso_on : gso_off;
884  vec_foreach_index (i, vif->tap_fds)
885  _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload);
886  vif->gso_enabled = enable_disable ? 1 : 0;
887  vif->csum_offload_enabled = 0;
888  if (enable_disable)
889  {
891  {
894  }
895  if (is_packet_coalesce)
896  {
898  }
899  }
900  else
901  {
903  {
906  }
907  vif->packet_coalesce = 0;
908  }
909 
910 error:
911  if (err)
912  {
913  clib_warning ("Error %s gso on sw_if_index %d",
914  enable_disable ? "enabling" : "disabling", sw_if_index);
915  return VNET_API_ERROR_SYSCALL_ERROR_3;
916  }
917  return 0;
918 }
919 
920 int
922 {
923  vnet_main_t *vnm = vnet_get_main ();
924  virtio_main_t *mm = &virtio_main;
925  virtio_if_t *vif;
926  virtio_vring_t *vring;
928  tap_interface_details_t *r_tapids = NULL;
929  tap_interface_details_t *tapid = NULL;
930 
931  /* *INDENT-OFF* */
932  pool_foreach (vif, mm->interfaces) {
933  if ((vif->type != VIRTIO_IF_TYPE_TAP)
934  && (vif->type != VIRTIO_IF_TYPE_TUN))
935  continue;
936  vec_add2(r_tapids, tapid, 1);
937  clib_memset (tapid, 0, sizeof (*tapid));
938  tapid->id = vif->id;
939  tapid->sw_if_index = vif->sw_if_index;
940  hi = vnet_get_hw_interface (vnm, vif->hw_if_index);
941  clib_memcpy(tapid->dev_name, hi->name,
942  MIN (ARRAY_LEN (tapid->dev_name) - 1, vec_len (hi->name)));
943  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0));
944  tapid->rx_ring_sz = vring->size;
945  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0));
946  tapid->tx_ring_sz = vring->size;
947  tapid->tap_flags = vif->tap_flags;
948  clib_memcpy(&tapid->host_mac_addr, vif->host_mac_addr, 6);
949  if (vif->host_if_name)
950  {
952  MIN (ARRAY_LEN (tapid->host_if_name) - 1,
953  vec_len (vif->host_if_name)));
954  }
955  if (vif->net_ns)
956  {
957  clib_memcpy(tapid->host_namespace, vif->net_ns,
958  MIN (ARRAY_LEN (tapid->host_namespace) - 1,
959  vec_len (vif->net_ns)));
960  }
961  if (vif->host_bridge)
962  {
963  clib_memcpy(tapid->host_bridge, vif->host_bridge,
964  MIN (ARRAY_LEN (tapid->host_bridge) - 1,
965  vec_len (vif->host_bridge)));
966  }
967  if (vif->host_ip4_prefix_len)
968  clib_memcpy(tapid->host_ip4_addr.as_u8, &vif->host_ip4_addr, 4);
970  if (vif->host_ip6_prefix_len)
971  clib_memcpy(tapid->host_ip6_addr.as_u8, &vif->host_ip6_addr, 16);
973  tapid->host_mtu_size = vif->host_mtu_size;
974  }
975  /* *INDENT-ON* */
976 
977  *out_tapids = r_tapids;
978 
979  return 0;
980 }
981 
982 /*
983  * Set host tap/tun interface carrier state so it will appear to host
984  * applications that the interface's link state changed.
985  *
986  * If the kernel we're building against does not have support for the
987  * TUNSETCARRIER ioctl command, do nothing.
988  */
989 int
990 tap_set_carrier (u32 hw_if_index, u32 carrier_up)
991 {
992  int ret = 0;
993 #ifdef TUNSETCARRIER
994  vnet_main_t *vnm = vnet_get_main ();
995  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
996  virtio_main_t *mm = &virtio_main;
997  virtio_if_t *vif;
998  int *fd;
999 
1000  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
1001  vec_foreach (fd, vif->tap_fds)
1002  {
1003  ret = ioctl (*fd, TUNSETCARRIER, &carrier_up);
1004  if (ret < 0)
1005  {
1006  clib_warning ("ioctl (TUNSETCARRIER) returned %d", ret);
1007  break;
1008  }
1009  }
1010  if (!ret)
1011  vif->host_carrier_up = (carrier_up != 0);
1012 #endif
1013 
1014  return ret;
1015 }
1016 
1017 static clib_error_t *
1019 {
1020  tap_main_t *tm = &tap_main;
1021 
1022  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1023  {
1024  if (unformat (input, "host-mtu %d", &tm->host_mtu_size))
1025  ;
1026  else
1027  return clib_error_return (0, "unknown input `%U'",
1028  format_unformat_error, input);
1029  }
1030 
1031  return 0;
1032 }
1033 
1034 /*
1035  * Set host tap/tun interface speed in Mbps.
1036  */
1037 int
1038 tap_set_speed (u32 hw_if_index, u32 speed)
1039 {
1040  vnet_main_t *vnm = vnet_get_main ();
1041  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1042  virtio_main_t *mm = &virtio_main;
1043  virtio_if_t *vif;
1044  int old_netns_fd = -1;
1045  int nfd = -1;
1046  int ctl_fd = -1;
1047  struct ifreq ifr;
1048  struct ethtool_cmd ecmd;
1049  int ret = -1;
1050 
1051  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
1052 
1053  if (vif->net_ns)
1054  {
1055  old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
1056  if ((nfd = open_netns_fd ((char *) vif->net_ns)) == -1)
1057  {
1058  clib_warning ("Cannot open netns");
1059  goto done;
1060  }
1061  if (setns (nfd, CLONE_NEWNET) == -1)
1062  {
1063  clib_warning ("Cannot set ns");
1064  goto done;
1065  }
1066  }
1067 
1068  if ((ctl_fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
1069  {
1070  clib_warning ("Cannot open control socket");
1071  goto done;
1072  }
1073 
1074  ecmd.cmd = ETHTOOL_GSET;
1075  clib_memset (&ifr, 0, sizeof (ifr));
1076  clib_memcpy (ifr.ifr_name, vif->host_if_name,
1077  strlen ((const char *) vif->host_if_name));
1078  ifr.ifr_data = (void *) &ecmd;
1079  if ((ret = ioctl (ctl_fd, SIOCETHTOOL, &ifr)) < 0)
1080  {
1081  clib_warning ("Cannot get device settings");
1082  goto done;
1083  }
1084 
1085  if (ethtool_cmd_speed (&ecmd) != speed)
1086  {
1087  ecmd.cmd = ETHTOOL_SSET;
1088  ethtool_cmd_speed_set (&ecmd, speed);
1089  if ((ret = ioctl (ctl_fd, SIOCETHTOOL, &ifr)) < 0)
1090  {
1091  clib_warning ("Cannot set device settings");
1092  goto done;
1093  }
1094  }
1095 
1096 done:
1097  if (old_netns_fd != -1)
1098  {
1099  if (setns (old_netns_fd, CLONE_NEWNET) == -1)
1100  {
1101  clib_warning ("Cannot set old ns");
1102  }
1103  close (old_netns_fd);
1104  }
1105  if (nfd != -1)
1106  close (nfd);
1107  if (ctl_fd != -1)
1108  close (ctl_fd);
1109 
1110  return ret;
1111 }
1112 
1113 /* tap { host-mtu <size> } configuration. */
1115 
1116 static clib_error_t *
1118 {
1119  tap_main_t *tm = &tap_main;
1120  clib_error_t *error = 0;
1121 
1122  tm->log_default = vlib_log_register_class ("tap", 0);
1123  vlib_log_debug (tm->log_default, "initialized");
1124 
1125  tm->host_mtu_size = 0;
1126 
1127  return error;
1128 }
1129 
1131 
1132 /*
1133  * fd.io coding-style-patch-verification: ON
1134  *
1135  * Local Variables:
1136  * eval: (c-set-style "gnu")
1137  * End:
1138  */
u32 per_interface_next_index
Definition: virtio.h:133
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
#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:288
virtio_if_t * interfaces
Definition: virtio.h:220
#define clib_min(x, y)
Definition: clib.h:342
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:187
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:523
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:190
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:258
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vlib_physmem_main_t physmem_main
Definition: main.h:168
#define VHOST_SET_OWNER
Definition: vhost_std.h:65
int gso_enabled
Definition: virtio.h:138
u32 host_mtu_size
Definition: virtio.h:184
u32 dev_instance
Definition: virtio.h:158
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
int kick_fd
Definition: virtio.h:94
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:607
#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
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:812
#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:813
#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:513
int call_fd
Definition: virtio.h:95
vhost_vring_addr_t addr
Definition: vhost_user.h:130
int tap_dump_ifs(tap_interface_details_t **out_tapids)
Definition: tap.c:921
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:165
#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)
unsigned int u32
Definition: types.h:88
#define clib_memcpy(d, s, n)
Definition: string.h:197
u8 host_bridge[64]
Definition: tap.h:83
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
u64 features
Definition: virtio.h:131
u32 hw_if_index
Definition: virtio.h:152
u8 host_ip6_prefix_len
Definition: virtio.h:189
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:39
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
u8 * host_bridge
Definition: virtio.h:181
int ifindex
Definition: virtio.h:186
description fragment has unexpected format
Definition: map.api:433
#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:781
#define clib_error_return(e, args...)
Definition: error.h:99
vnet_main_t * vnet_get_main(void)
#define VHOST_SET_VRING_ADDR
Definition: vhost_std.h:71
#define MIN(x, y)
Definition: node.h:31
u32 id
Definition: virtio.h:183
u16 queue_id
Definition: virtio.h:84
u16 num_txqs
Definition: virtio.h:135
Definition: cJSON.c:88
void virtio_vring_set_rx_queues(vlib_main_t *vm, virtio_if_t *vif)
Definition: virtio.c:238
#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:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
int * vhost_fds
Definition: virtio.h:178
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
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:181
ip4_address_t host_ip4_gw
Definition: tap.h:57
ip6_address_t host_ip6_addr
Definition: tap.h:59
#define vlib_log_debug(...)
Definition: log.h:137
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
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:156
vring_used_t * used
Definition: virtio.h:72
ip4_address_t host_ip4_addr
Definition: tap.h:84
u16 num_rxqs
Definition: virtio.h:134
virtio_vring_t * rxq_vrings
Definition: virtio.h:136
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
#define TAP_MAX_INSTANCE
Definition: tap.c:96
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
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:395
u32 host_mtu_size
Definition: tap.h:64
ip6_address_t host_ip6_addr
Definition: virtio.h:177
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:180
#define VHOST_NET_SET_BACKEND
Definition: vhost_std.h:77
u8 mac_addr[6]
Definition: virtio.h:171
u32 flags
Definition: virtio.h:132
#define ARRAY_LEN(x)
Definition: clib.h:70
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:163
u32 tap_flags
Definition: virtio.h:185
#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:150
#define VHOST_GET_FEATURES
Definition: vhost_std.h:63
#define ASSERT(truth)
u64 remote_features
Definition: virtio.h:160
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:60
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1052
u8 * host_if_name
Definition: tap.h:52
u8 host_mac_addr[6]
Definition: virtio.h:182
static void clib_mem_free(void *p)
Definition: mem.h:311
void virtio_set_packet_coalesce(virtio_if_t *vif)
Definition: virtio.c:188
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:335
virtio_main_t virtio_main
Definition: virtio.c:37
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:139
#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:864
int tap_set_speed(u32 hw_if_index, u32 speed)
Definition: tap.c:1038
a point 2 point interface
Definition: interface.h:394
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:188
u32 sw_if_index
Definition: virtio.h:153
int tap_set_carrier(u32 hw_if_index, u32 carrier_up)
Definition: tap.c:990
virtio_vring_t * cxq_vring
Definition: virtio.h:195
#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:143
TAP interface details struct.
Definition: tap.h:72
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
vl_api_dhcp_client_state_t state
Definition: dhcp.api:201
#define VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM
Definition: interface.h:555
#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:1018
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:142
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:163
virtio_vring_t * txq_vrings
Definition: virtio.h:137
static clib_error_t * tap_init(vlib_main_t *vm)
Definition: tap.c:1117
u8 * host_if_name
Definition: virtio.h:179