FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
virtio.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 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 #include <linux/if_tun.h>
23 #include <sys/ioctl.h>
24 #include <linux/virtio_net.h>
25 #include <linux/vhost.h>
26 #include <sys/eventfd.h>
27 
28 #include <vlib/vlib.h>
29 #include <vlib/unix/unix.h>
30 #include <vnet/ethernet/ethernet.h>
31 #include <vnet/ip/ip4_packet.h>
32 #include <vnet/ip/ip6_packet.h>
34 
36 
37 #define _IOCTL(fd,a,...) \
38  if (ioctl (fd, a, __VA_ARGS__) < 0) \
39  { \
40  err = clib_error_return_unix (0, "ioctl(" #a ")"); \
41  goto error; \
42  }
43 
44 static clib_error_t *
46 {
48  vnet_main_t *vnm = vnet_get_main ();
49  u16 qid = uf->private_data & 0xFFFF;
50  virtio_if_t *vif =
51  vec_elt_at_index (nm->interfaces, uf->private_data >> 16);
52  u64 b;
53 
54  CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
55  if ((qid & 1) == 0)
57 
58  return 0;
59 }
60 
61 
64 {
65  clib_error_t *err = 0;
66  virtio_vring_t *vring;
67  struct vhost_vring_state state = { 0 };
68  struct vhost_vring_addr addr = { 0 };
69  struct vhost_vring_file file = { 0 };
70  clib_file_t t = { 0 };
71  int i;
72 
73  if (!is_pow2 (sz))
74  return clib_error_return (0, "ring size must be power of 2");
75 
76  if (sz > 32768)
77  return clib_error_return (0, "ring size must be 32768 or lower");
78 
79  if (sz == 0)
80  sz = 256;
81 
83  vring = vec_elt_at_index (vif->vrings, idx);
84 
85  i = sizeof (struct vring_desc) * sz;
88  memset (vring->desc, 0, i);
89 
90  i = sizeof (struct vring_avail) + sz * sizeof (vring->avail->ring[0]);
93  memset (vring->avail, 0, i);
94  // tell kernel that we don't need interrupt
95  vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
96 
97  i = sizeof (struct vring_used) + sz * sizeof (struct vring_used_elem);
100  memset (vring->used, 0, i);
101 
102  ASSERT (vring->buffers == 0);
104 
105  vring->size = sz;
106  vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
107  vring->kick_fd = eventfd (0, EFD_CLOEXEC);
108 
110  t.file_descriptor = vring->call_fd;
111  t.private_data = vif->dev_instance << 16 | idx;
112  t.description = format (0, "%U vring %u", format_virtio_device_name,
113  vif->dev_instance, idx);
114  vring->call_file_index = clib_file_add (&file_main, &t);
115 
116  state.index = idx;
117  state.num = sz;
118  _IOCTL (vif->fd, VHOST_SET_VRING_NUM, &state);
119 
120  addr.index = idx;
121  addr.flags = 0;
122  addr.desc_user_addr = pointer_to_uword (vring->desc);
123  addr.avail_user_addr = pointer_to_uword (vring->avail);
124  addr.used_user_addr = pointer_to_uword (vring->used);
125  _IOCTL (vif->fd, VHOST_SET_VRING_ADDR, &addr);
126 
127  file.index = idx;
128  file.fd = vring->kick_fd;
129  _IOCTL (vif->fd, VHOST_SET_VRING_KICK, &file);
130  file.fd = vring->call_fd;
131  _IOCTL (vif->fd, VHOST_SET_VRING_CALL, &file);
132  file.fd = vif->tap_fd;
133  _IOCTL (vif->fd, VHOST_NET_SET_BACKEND, &file);
134 
135 error:
136  return err;
137 }
138 
141 {
142  u16 used = vring->desc_in_use;
143  u16 last = vring->last_used_idx;
144  u16 mask = vring->size - 1;
145 
146  while (used)
147  {
148  vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
149  last++;
150  used--;
151  }
152 }
153 
154 clib_error_t *
156 {
157  virtio_vring_t *vring = vec_elt_at_index (vif->vrings, idx);
158 
160  close (vring->kick_fd);
161  close (vring->call_fd);
162  if (vring->used)
163  {
164  if ((idx & 1) == 1)
165  virtio_free_used_desc (vm, vring);
166  else
167  virtio_free_rx_buffers (vm, vring);
168  clib_mem_free (vring->used);
169  }
170  if (vring->desc)
171  clib_mem_free (vring->desc);
172  if (vring->avail)
173  clib_mem_free (vring->avail);
174  vec_free (vring->buffers);
175  return 0;
176 }
177 
178 /*
179  * fd.io coding-style-patch-verification: ON
180  *
181  * Local Variables:
182  * eval: (c-set-style "gnu")
183  * End:
184  */
struct vring_used * used
Definition: virtio.h:77
virtio_if_t * interfaces
Definition: virtio.h:124
#define CLIB_UNUSED(x)
Definition: clib.h:79
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:534
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
unsigned long u64
Definition: types.h:89
u32 dev_instance
Definition: virtio.h:97
int kick_fd
Definition: virtio.h:81
u32 file_descriptor
Definition: file.h:54
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:448
static_always_inline void virtio_free_rx_buffers(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:140
int call_fd
Definition: virtio.h:82
virtio_vring_t * vrings
Definition: virtio.h:103
clib_file_function_t * read_function
Definition: file.h:67
struct vring_avail * avail
Definition: virtio.h:78
#define static_always_inline
Definition: clib.h:93
u32 hw_if_index
Definition: virtio.h:98
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:136
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
clib_file_main_t file_main
Definition: main.c:63
unsigned int u32
Definition: types.h:88
u8 * description
Definition: file.h:70
uword size
int tap_fd
Definition: virtio.h:102
unsigned short u16
Definition: types.h:57
format_function_t format_virtio_device_name
Definition: virtio.h:137
u16 last_used_idx
Definition: virtio.h:88
vlib_main_t * vm
Definition: buffer.c:294
#define VIRTIO_RING_FLAG_MASK_INT
Definition: virtio.h:84
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
u32 call_file_index
Definition: virtio.h:86
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:235
void virtio_free_used_desc(vlib_main_t *vm, virtio_vring_t *vring)
Definition: device.c:92
#define ASSERT(truth)
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
Definition: file.h:96
static void clib_file_del_by_index(clib_file_main_t *um, uword index)
Definition: file.h:119
clib_error_t * virtio_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 idx, u16 sz)
Definition: virtio.c:63
static void clib_mem_free(void *p)
Definition: mem.h:179
clib_error_t * virtio_vring_free(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:155
static uword pointer_to_uword(const void *p)
Definition: types.h:131
virtio_main_t virtio_main
Definition: virtio.c:35
static uword is_pow2(uword x)
Definition: clib.h:229
int fd
Definition: virtio.h:101
u32 * buffers
Definition: virtio.h:87
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:120
uword private_data
Definition: file.h:64
struct vring_desc * desc
Definition: virtio.h:76
Definition: file.h:51
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
u16 desc_in_use
Definition: virtio.h:79
static clib_error_t * call_read_ready(clib_file_t *uf)
Definition: virtio.c:45