http_static: fix memory hss_session using after be freed
[vpp.git] / src / vnet / devices / virtio / virtio_inline.h
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef __VIRTIO_INLINE_H__
16 #define __VIRTIO_INLINE_H__
17
18 #define foreach_virtio_input_error                                            \
19   _ (BUFFER_ALLOC, "buffer alloc error")                                      \
20   _ (FULL_RX_QUEUE, "full rx queue (driver tx drop)")                         \
21   _ (UNKNOWN, "unknown")
22
23 typedef enum
24 {
25 #define _(f, s) VIRTIO_INPUT_ERROR_##f,
26   foreach_virtio_input_error
27 #undef _
28     VIRTIO_INPUT_N_ERROR,
29 } virtio_input_error_t;
30
31 static_always_inline void
32 virtio_refill_vring_split (vlib_main_t *vm, virtio_if_t *vif,
33                            virtio_if_type_t type, vnet_virtio_vring_t *vring,
34                            const int hdr_sz, u32 node_index)
35 {
36   u16 used, next, avail, n_slots, n_refill;
37   u16 sz = vring->queue_size;
38   u16 mask = sz - 1;
39
40 more:
41   used = vring->desc_in_use;
42
43   if (sz - used < sz / 8)
44     return;
45
46   /* deliver free buffers in chunks of 64 */
47   n_refill = clib_min (sz - used, 64);
48
49   next = vring->desc_next;
50   avail = vring->avail->idx;
51   n_slots = vlib_buffer_alloc_to_ring_from_pool (vm, vring->buffers, next,
52                                                  vring->queue_size, n_refill,
53                                                  vring->buffer_pool_index);
54
55   if (PREDICT_FALSE (n_slots != n_refill))
56     {
57       vlib_error_count (vm, node_index, VIRTIO_INPUT_ERROR_BUFFER_ALLOC,
58                         n_refill - n_slots);
59       if (n_slots == 0)
60         return;
61     }
62
63   while (n_slots)
64     {
65       vnet_virtio_vring_desc_t *d = &vring->desc[next];
66       ;
67       vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]);
68       /*
69        * current_data may not be initialized with 0 and may contain
70        * previous offset. Here we want to make sure, it should be 0
71        * initialized.
72        */
73       b->current_data = -hdr_sz;
74       clib_memset (vlib_buffer_get_current (b), 0, hdr_sz);
75       d->addr = ((type == VIRTIO_IF_TYPE_PCI) ?
76                    vlib_buffer_get_current_pa (vm, b) :
77                    pointer_to_uword (vlib_buffer_get_current (b)));
78       d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz;
79       d->flags = VRING_DESC_F_WRITE;
80       vring->avail->ring[avail & mask] = next;
81       avail++;
82       next = (next + 1) & mask;
83       n_slots--;
84       used++;
85     }
86   clib_atomic_store_seq_cst (&vring->avail->idx, avail);
87   vring->desc_next = next;
88   vring->desc_in_use = used;
89   if ((clib_atomic_load_seq_cst (&vring->used->flags) &
90        VRING_USED_F_NO_NOTIFY) == 0)
91     {
92       virtio_kick (vm, vring, vif);
93     }
94   goto more;
95 }
96
97 static_always_inline void
98 virtio_refill_vring_packed (vlib_main_t *vm, virtio_if_t *vif,
99                             virtio_if_type_t type, vnet_virtio_vring_t *vring,
100                             const int hdr_sz, u32 node_index)
101 {
102   u16 used, next, n_slots, n_refill, flags = 0, first_desc_flags;
103   u16 sz = vring->queue_size;
104
105 more:
106   used = vring->desc_in_use;
107
108   if (sz == used)
109     return;
110
111   /* deliver free buffers in chunks of 64 */
112   n_refill = clib_min (sz - used, 64);
113
114   next = vring->desc_next;
115   first_desc_flags = vring->packed_desc[next].flags;
116   n_slots = vlib_buffer_alloc_to_ring_from_pool (
117     vm, vring->buffers, next, sz, n_refill, vring->buffer_pool_index);
118
119   if (PREDICT_FALSE (n_slots != n_refill))
120     {
121       vlib_error_count (vm, node_index, VIRTIO_INPUT_ERROR_BUFFER_ALLOC,
122                         n_refill - n_slots);
123       if (n_slots == 0)
124         return;
125     }
126
127   while (n_slots)
128     {
129       vnet_virtio_vring_packed_desc_t *d = &vring->packed_desc[next];
130       vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]);
131       /*
132        * current_data may not be initialized with 0 and may contain
133        * previous offset. Here we want to make sure, it should be 0
134        * initialized.
135        */
136       b->current_data = -hdr_sz;
137       clib_memset (vlib_buffer_get_current (b), 0, hdr_sz);
138       d->addr = ((type == VIRTIO_IF_TYPE_PCI) ?
139                    vlib_buffer_get_current_pa (vm, b) :
140                    pointer_to_uword (vlib_buffer_get_current (b)));
141       d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz;
142
143       if (vring->avail_wrap_counter)
144         flags = (VRING_DESC_F_AVAIL | VRING_DESC_F_WRITE);
145       else
146         flags = (VRING_DESC_F_USED | VRING_DESC_F_WRITE);
147
148       d->id = next;
149       if (vring->desc_next == next)
150         first_desc_flags = flags;
151       else
152         d->flags = flags;
153
154       next++;
155       if (next >= sz)
156         {
157           next = 0;
158           vring->avail_wrap_counter ^= 1;
159         }
160       n_slots--;
161       used++;
162     }
163   CLIB_MEMORY_STORE_BARRIER ();
164   vring->packed_desc[vring->desc_next].flags = first_desc_flags;
165   vring->desc_next = next;
166   vring->desc_in_use = used;
167   CLIB_MEMORY_BARRIER ();
168   if (vring->device_event->flags != VRING_EVENT_F_DISABLE)
169     {
170       virtio_kick (vm, vring, vif);
171     }
172
173   goto more;
174 }
175
176 #endif
177
178 /*
179  * fd.io coding-style-patch-verification: ON
180  *
181  * Local Variables:
182  * eval: (c-set-style "gnu")
183  * End:
184  */