FD.io VPP  v18.01.1-37-g7ea3975
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 <fcntl.h>
22 #include <net/if.h>
23 #include <linux/if_tun.h>
24 #include <sys/ioctl.h>
25 #include <linux/virtio_net.h>
26 #include <linux/vhost.h>
27 #include <sys/eventfd.h>
28 #include <sched.h>
29 
30 #include <linux/netlink.h>
31 #include <linux/rtnetlink.h>
32 
33 #include <vlib/vlib.h>
34 #include <vlib/unix/unix.h>
35 #include <vnet/ethernet/ethernet.h>
36 #include <vnet/ip/ip4_packet.h>
37 #include <vnet/ip/ip6_packet.h>
38 #include <vnet/devices/netlink.h>
40 #include <vnet/devices/tap/tap.h>
41 
43 
44 #define _IOCTL(fd,a,...) \
45  if (ioctl (fd, a, __VA_ARGS__) < 0) \
46  { \
47  err = clib_error_return_unix (0, "ioctl(" #a ")"); \
48  goto error; \
49  }
50 
51 static u32
53  u32 flags)
54 {
55  /* nothing for now */
56  //TODO On MTU change call vnet_netlink_set_if_mtu
57  return 0;
58 }
59 
60 static int
61 open_netns_fd (char *netns)
62 {
63  u8 *s = 0;
64  int fd;
65 
66  if (strncmp (netns, "pid:", 4) == 0)
67  s = format (0, "/proc/%u/ns/net%c", atoi (netns + 4), 0);
68  else if (netns[0] == '/')
69  s = format (0, "%s%c", netns, 0);
70  else
71  s = format (0, "/var/run/netns/%s%c", netns, 0);
72 
73  fd = open ((char *) s, O_RDONLY);
74  vec_free (s);
75  return fd;
76 }
77 
78 
79 void
81 {
82  vnet_main_t *vnm = vnet_get_main ();
84  virtio_main_t *vim = &virtio_main;
85  tap_main_t *tm = &tap_main;
88  int i;
89  int old_netns_fd = -1;
90  struct ifreq ifr;
91  size_t hdrsz;
92  struct vhost_memory *vhost_mem = 0;
93  virtio_if_t *vif = 0;
94  clib_error_t *err = 0;
95  uword *p;
96 
97  if (args->id != ~0)
98  {
99  p = hash_get (tm->dev_instance_by_interface_id, args->id);
100  if (p)
101  {
102  args->rv = VNET_API_ERROR_INVALID_INTERFACE;
103  args->error = clib_error_return (0, "interface already exists");
104  return;
105  }
106  }
107  else
108  {
109  int tries = 1000;
110  while (--tries)
111  {
112  args->id = tm->last_used_interface_id++;
113  p = hash_get (tm->dev_instance_by_interface_id, args->id);
114  if (!p)
115  break;
116  }
117 
118  if (!tries)
119  {
120  args->rv = VNET_API_ERROR_UNSPECIFIED;
121  args->error =
122  clib_error_return (0, "cannot find free interface id");
123  return;
124  }
125  }
126 
127  memset (&ifr, 0, sizeof (ifr));
128  pool_get (vim->interfaces, vif);
129  vif->dev_instance = vif - vim->interfaces;
130  vif->tap_fd = -1;
131  vif->id = args->id;
132 
134 
135  if ((vif->fd = open ("/dev/vhost-net", O_RDWR | O_NONBLOCK)) < 0)
136  {
137  args->rv = VNET_API_ERROR_SYSCALL_ERROR_1;
138  args->error = clib_error_return_unix (0, "open '/dev/vhost-net'");
139  goto error;
140  }
141 
142  _IOCTL (vif->fd, VHOST_GET_FEATURES, &vif->remote_features);
143 
144  if ((vif->remote_features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) == 0)
145  {
146  args->rv = VNET_API_ERROR_UNSUPPORTED;
147  args->error = clib_error_return (0, "vhost-net backend doesn't support "
148  "VIRTIO_NET_F_MRG_RXBUF feature");
149  goto error;
150  }
151 
152  if ((vif->remote_features & (1ULL << VIRTIO_RING_F_INDIRECT_DESC)) == 0)
153  {
154  args->rv = VNET_API_ERROR_UNSUPPORTED;
155  args->error = clib_error_return (0, "vhost-net backend doesn't support "
156  "VIRTIO_RING_F_INDIRECT_DESC feature");
157  goto error;
158  }
159 
160  if ((vif->remote_features & (1ULL << VIRTIO_F_VERSION_1)) == 0)
161  {
162  args->rv = VNET_API_ERROR_UNSUPPORTED;
163  args->error = clib_error_return (0, "vhost-net backend doesn't support "
164  "VIRTIO_F_VERSION_1 features");
165  goto error;
166  }
167 
168  vif->features |= 1ULL << VIRTIO_NET_F_MRG_RXBUF;
169  vif->features |= 1ULL << VIRTIO_F_VERSION_1;
170  vif->features |= 1ULL << VIRTIO_RING_F_INDIRECT_DESC;
171 
172  _IOCTL (vif->fd, VHOST_SET_FEATURES, &vif->features);
173 
174  if ((vif->tap_fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
175  {
176  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
177  args->error = clib_error_return_unix (0, "open '/dev/net/tun'");
178  goto error;
179  }
180 
181  ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR;
182  _IOCTL (vif->tap_fd, TUNSETIFF, (void *) &ifr);
183  vif->ifindex = if_nametoindex (ifr.ifr_ifrn.ifrn_name);
184 
185  unsigned int offload = 0;
186  hdrsz = sizeof (struct virtio_net_hdr_v1);
187  _IOCTL (vif->tap_fd, TUNSETOFFLOAD, offload);
188  _IOCTL (vif->tap_fd, TUNSETVNETHDRSZ, &hdrsz);
189  _IOCTL (vif->fd, VHOST_SET_OWNER, 0);
190 
191  /* if namespace is specified, all further netlink messages should be excuted
192  after we change our net namespace */
193  if (args->host_namespace)
194  {
195  int fd;
196  old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
197  if ((fd = open_netns_fd ((char *) args->host_namespace)) == -1)
198  {
199  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
200  args->error = clib_error_return_unix (0, "open_netns_fd '%s'",
201  args->host_namespace);
202  goto error;
203  }
204  args->error = vnet_netlink_set_link_netns (vif->ifindex, fd,
205  (char *) args->host_if_name);
206  if (args->error)
207  {
208  args->rv = VNET_API_ERROR_NETLINK_ERROR;
209  goto error;
210  }
211  if (setns (fd, CLONE_NEWNET) == -1)
212  {
213  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
214  args->error = clib_error_return_unix (0, "setns '%s'",
215  args->host_namespace);
216  goto error;
217  }
218  close (fd);
219  if ((vif->ifindex = if_nametoindex ((char *) args->host_if_name)) == 0)
220  {
221  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
222  args->error = clib_error_return_unix (0, "if_nametoindex '%s'",
223  args->host_if_name);
224  goto error;
225  }
226  }
227  else
228  {
229  if (args->host_if_name)
230  {
232  (char *)
233  args->host_if_name);
234  if (args->error)
235  {
236  args->rv = VNET_API_ERROR_NETLINK_ERROR;
237  goto error;
238  }
239  }
240  }
241 
243  {
245  args->host_mac_addr);
246  if (args->error)
247  {
248  args->rv = VNET_API_ERROR_NETLINK_ERROR;
249  goto error;
250  }
251  }
252 
253  if (args->host_bridge)
254  {
256  (char *) args->host_bridge);
257  if (args->error)
258  {
259  args->rv = VNET_API_ERROR_NETLINK_ERROR;
260  goto error;
261  }
262  }
263 
264 
265  if (args->host_ip4_prefix_len)
266  {
268  &args->host_ip4_addr,
269  args->host_ip4_prefix_len);
270  if (args->error)
271  {
272  args->rv = VNET_API_ERROR_NETLINK_ERROR;
273  goto error;
274  }
275  }
276 
277  if (args->host_ip6_prefix_len)
278  {
280  &args->host_ip6_addr,
281  args->host_ip6_prefix_len);
282  if (args->error)
283  {
284  args->rv = VNET_API_ERROR_NETLINK_ERROR;
285  goto error;
286  }
287  }
288 
289  args->error = vnet_netlink_set_link_state (vif->ifindex, 1 /* UP */ );
290  if (args->error)
291  {
292  args->rv = VNET_API_ERROR_NETLINK_ERROR;
293  goto error;
294  }
295 
296  /* switch back to old net namespace */
297  if (args->host_namespace)
298  {
299  if (setns (old_netns_fd, CLONE_NEWNET) == -1)
300  {
301  args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
302  args->error = clib_error_return_unix (0, "setns '%s'",
303  args->host_namespace);
304  goto error;
305  }
306  }
307 
308  /* Set vhost memory table */
309  i = sizeof (struct vhost_memory) + sizeof (struct vhost_memory_region);
310  vhost_mem = clib_mem_alloc (i);
311  memset (vhost_mem, 0, i);
312  vhost_mem->nregions = 1;
313  vhost_mem->regions[0].memory_size = (1ULL << 47) - 4096;
314  _IOCTL (vif->fd, VHOST_SET_MEM_TABLE, vhost_mem);
315 
316  if ((args->error = virtio_vring_init (vm, vif, 0, args->rx_ring_sz)))
317  {
318  args->rv = VNET_API_ERROR_INIT_FAILED;
319  goto error;
320  }
321 
322  if ((args->error = virtio_vring_init (vm, vif, 1, args->tx_ring_sz)))
323  {
324  args->rv = VNET_API_ERROR_INIT_FAILED;
325  goto error;
326  }
327 
328  if (!args->mac_addr_set)
329  {
330  f64 now = vlib_time_now (vm);
331  u32 rnd;
332  rnd = (u32) (now * 1e6);
333  rnd = random_u32 (&rnd);
334 
335  memcpy (args->mac_addr + 2, &rnd, sizeof (rnd));
336  args->mac_addr[0] = 2;
337  args->mac_addr[1] = 0xfe;
338  }
339  vif->rx_ring_sz = args->rx_ring_sz != 0 ? args->rx_ring_sz : 256;
340  vif->tx_ring_sz = args->tx_ring_sz != 0 ? args->tx_ring_sz : 256;
341  vif->host_if_name = args->host_if_name;
342  args->host_if_name = 0;
343  vif->net_ns = args->host_namespace;
344  args->host_namespace = 0;
345  vif->host_bridge = args->host_bridge;
346  args->host_bridge = 0;
347  clib_memcpy (vif->host_mac_addr, args->host_mac_addr, 6);
350  if (args->host_ip4_prefix_len)
351  clib_memcpy (&vif->host_ip4_addr, &args->host_ip4_addr, 4);
352  if (args->host_ip6_prefix_len)
353  clib_memcpy (&vif->host_ip6_addr, &args->host_ip6_addr, 16);
354 
356  vif->dev_instance,
357  args->mac_addr,
358  &vif->hw_if_index,
360  if (args->error)
361  {
362  args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
363  goto error;
364  }
365 
366  sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
367  vif->sw_if_index = sw->sw_if_index;
368  args->sw_if_index = vif->sw_if_index;
369  hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
372  virtio_input_node.index);
376  vif->per_interface_next_index = ~0;
377  vif->type = VIRTIO_IF_TYPE_TAP;
378  vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
381  if (thm->n_vlib_mains > 1)
382  clib_spinlock_init (&vif->lockp);
383  goto done;
384 
385 error:
386  if (err)
387  {
388  ASSERT (args->error == 0);
389  args->error = err;
390  args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
391  }
392  if (vif->tap_fd != -1)
393  close (vif->tap_fd);
394  if (vif->fd != -1)
395  close (vif->fd);
396  vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
397  memset (vif, 0, sizeof (virtio_if_t));
398  pool_put (vim->interfaces, vif);
399 
400 done:
401  if (vhost_mem)
402  clib_mem_free (vhost_mem);
403  if (old_netns_fd != -1)
404  close (old_netns_fd);
405 }
406 
407 int
408 tap_delete_if (vlib_main_t * vm, u32 sw_if_index)
409 {
410  vnet_main_t *vnm = vnet_get_main ();
411  virtio_main_t *mm = &virtio_main;
412  tap_main_t *tm = &tap_main;
413  int i;
414  virtio_if_t *vif;
416 
417  hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
418  if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
419  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
420 
421  vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
422 
423  /* bring down the interface */
427 
429  vif->hw_if_index = ~0;
430 
431  if (vif->tap_fd != -1)
432  close (vif->tap_fd);
433  if (vif->fd != -1)
434  close (vif->fd);
435 
436  vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
437  vec_free (vif->vrings);
438 
440  clib_spinlock_free (&vif->lockp);
441  memset (vif, 0, sizeof (*vif));
442  pool_put (mm->interfaces, vif);
443 
444  return 0;
445 }
446 
447 int
449 {
450  vnet_main_t *vnm = vnet_get_main ();
451  virtio_main_t *mm = &virtio_main;
452  virtio_if_t *vif;
454  tap_interface_details_t *r_tapids = NULL;
455  tap_interface_details_t *tapid = NULL;
456 
457  /* *INDENT-OFF* */
458  pool_foreach (vif, mm->interfaces,
459  vec_add2(r_tapids, tapid, 1);
460  memset (tapid, 0, sizeof (*tapid));
461  tapid->id = vif->id;
462  tapid->sw_if_index = vif->sw_if_index;
463  hi = vnet_get_hw_interface (vnm, vif->hw_if_index);
464  clib_memcpy(tapid->dev_name, hi->name,
465  MIN (ARRAY_LEN (tapid->dev_name) - 1,
466  strlen ((const char *) hi->name)));
467  tapid->rx_ring_sz = vif->rx_ring_sz;
468  tapid->tx_ring_sz = vif->tx_ring_sz;
469  clib_memcpy(tapid->host_mac_addr, vif->host_mac_addr, 6);
470  if (vif->host_if_name)
471  {
473  MIN (ARRAY_LEN (tapid->host_if_name) - 1,
474  strlen ((const char *) vif->host_if_name)));
475  }
476  if (vif->net_ns)
477  {
478  clib_memcpy(tapid->host_namespace, vif->net_ns,
479  MIN (ARRAY_LEN (tapid->host_namespace) - 1,
480  strlen ((const char *) vif->net_ns)));
481  }
482  if (vif->host_bridge)
483  {
484  clib_memcpy(tapid->host_bridge, vif->host_bridge,
485  MIN (ARRAY_LEN (tapid->host_bridge) - 1,
486  strlen ((const char *) vif->host_bridge)));
487  }
488  if (vif->host_ip4_prefix_len)
489  clib_memcpy(tapid->host_ip4_addr, &vif->host_ip4_addr, 4);
491  if (vif->host_ip6_prefix_len)
492  clib_memcpy(tapid->host_ip6_addr, &vif->host_ip6_addr, 16);
494  );
495  /* *INDENT-ON* */
496 
497  *out_tapids = r_tapids;
498 
499  return 0;
500 }
501 
502 static clib_error_t *
504 {
505  tap_main_t *tm = &tap_main;
506  tm->dev_instance_by_interface_id = hash_create (0, sizeof (uword));
507  return 0;
508 }
509 
511 
512 /*
513  * fd.io coding-style-patch-verification: ON
514  *
515  * Local Variables:
516  * eval: (c-set-style "gnu")
517  * End:
518  */
u32 per_interface_next_index
Definition: virtio.h:100
vmrglw vmrglh hi
#define vec_foreach_index(var, v)
Iterate over vector indices.
vlib_node_registration_t virtio_input_node
(constructor) VLIB_REGISTER_NODE (virtio_input_node)
Definition: node.c:284
#define hash_set(h, key, value)
Definition: hash.h:254
virtio_if_t * interfaces
Definition: virtio.h:124
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static u32 virtio_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: tap.c:52
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:538
ip4_address_t host_ip4_addr
Definition: virtio.h:114
u8 host_if_name[64]
Definition: tap.h:55
#define hash_unset(h, key)
Definition: hash.h:260
u8 host_namespace[64]
Definition: tap.h:56
ip4_address_t host_ip4_addr
Definition: tap.h:36
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:322
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 dev_instance
Definition: virtio.h:97
#define NULL
Definition: clib.h:55
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:224
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:39
vnet_device_class_t virtio_device_class
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:557
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:394
virtio_vring_t * vrings
Definition: virtio.h:103
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
int tap_dump_ifs(tap_interface_details_t **out_tapids)
Definition: tap.c:448
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:40
#define MIN(x, y)
Definition: tap.h:22
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
u8 host_bridge[64]
Definition: tap.h:57
u8 host_ip6_addr[16]
Definition: tap.h:60
u64 features
Definition: virtio.h:105
u32 hw_if_index
Definition: virtio.h:98
u8 host_mac_addr[6]
Definition: tap.h:54
u8 host_ip6_prefix_len
Definition: virtio.h:117
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:438
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u8 * host_bridge
Definition: virtio.h:112
int ifindex
Definition: virtio.h:119
u32 last_used_interface_id
Definition: tap.h:66
int tap_delete_if(vlib_main_t *vm, u32 sw_if_index)
Definition: tap.c:408
#define clib_error_return(e, args...)
Definition: error.h:99
u8 host_mac_addr[6]
Definition: tap.h:34
u32 id
Definition: virtio.h:96
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:33
u8 host_ip4_addr[4]
Definition: tap.h:58
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:459
int tap_fd
Definition: virtio.h:102
#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:271
u16 tx_ring_sz
Definition: virtio.h:108
clib_spinlock_t lockp
Definition: virtio.h:94
ip6_address_t host_ip6_addr
Definition: tap.h:38
#define VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE
Definition: interface.h:420
u8 host_ip4_prefix_len
Definition: tap.h:37
static int ethernet_mac_address_is_zero(u8 *mac)
Definition: ethernet.h:65
vlib_main_t * vm
Definition: buffer.c:283
static int open_netns_fd(char *netns)
Definition: tap.c:61
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
ip6_address_t host_ip6_addr
Definition: virtio.h:116
#define clib_memcpy(a, b, c)
Definition: string.h:75
u8 * net_ns
Definition: virtio.h:111
u32 flags
Definition: virtio.h:93
#define ARRAY_LEN(x)
Definition: clib.h:59
u16 rx_ring_sz
Definition: virtio.h:109
#define hash_create(elts, value_bytes)
Definition: hash.h:681
u8 * host_bridge
Definition: tap.h:35
virtio_if_type_t type
Definition: virtio.h:107
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
void vnet_hw_interface_assign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, uword thread_index)
Definition: devices.c:138
u64 remote_features
Definition: virtio.h:105
clib_error_t * virtio_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 idx, u16 sz)
Definition: virtio.c:63
u8 * host_if_name
Definition: tap.h:33
u8 host_mac_addr[6]
Definition: virtio.h:113
static void clib_mem_free(void *p)
Definition: mem.h:179
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:273
clib_error_t * virtio_vring_free(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:153
unsigned int if_nametoindex(const char *ifname)
static void * clib_mem_alloc(uword size)
Definition: mem.h:112
virtio_main_t virtio_main
Definition: virtio.c:35
u64 uword
Definition: types.h:112
void tap_create_if(vlib_main_t *vm, tap_create_if_args_t *args)
Definition: tap.c:80
tap_main_t tap_main
Definition: tap.c:42
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
int fd
Definition: virtio.h:101
u8 mac_addr[6]
Definition: tap.h:29
Definition: tap.h:64
clib_error_t * error
Definition: tap.h:43
u8 host_ip4_prefix_len
Definition: virtio.h:115
int vnet_hw_interface_unassign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.c:187
u32 sw_if_index
Definition: virtio.h:99
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
TAP interface details struct.
Definition: tap.h:47
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:546
int vnet_hw_interface_set_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_interface_rx_mode mode)
Definition: devices.c:252
u8 * host_namespace
Definition: tap.h:32
u32 flags
Definition: vhost-user.h:77
static void vnet_hw_interface_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: devices.h:79
uword * dev_instance_by_interface_id
Definition: tap.h:67
static clib_error_t * tap_init(vlib_main_t *vm)
Definition: tap.c:503
u8 * host_if_name
Definition: virtio.h:110