]> git.proxmox.com Git - mirror_ovs.git/blob - lib/netdev-afxdp-pool.c
netdev-offload-tc: Use single 'once' variable for probing tc features
[mirror_ovs.git] / lib / netdev-afxdp-pool.c
1 /*
2 * Copyright (c) 2018, 2019 Nicira, Inc.
3 *
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 #include <config.h>
17
18 #include "dp-packet.h"
19 #include "netdev-afxdp-pool.h"
20 #include "openvswitch/util.h"
21
22 /* Note:
23 * umem_elem_push* shouldn't overflow because we always pop
24 * elem first, then push back to the stack.
25 */
26 static inline void
27 umem_elem_push_n__(struct umem_pool *umemp, int n, void **addrs)
28 {
29 void *ptr;
30
31 ovs_assert(umemp->index + n <= umemp->size);
32
33 ptr = &umemp->array[umemp->index];
34 memcpy(ptr, addrs, n * sizeof(void *));
35 umemp->index += n;
36 }
37
38 void umem_elem_push_n(struct umem_pool *umemp, int n, void **addrs)
39 {
40 ovs_spin_lock(&umemp->lock);
41 umem_elem_push_n__(umemp, n, addrs);
42 ovs_spin_unlock(&umemp->lock);
43 }
44
45 static inline void
46 umem_elem_push__(struct umem_pool *umemp, void *addr)
47 {
48 ovs_assert(umemp->index + 1 <= umemp->size);
49
50 umemp->array[umemp->index++] = addr;
51 }
52
53 void
54 umem_elem_push(struct umem_pool *umemp, void *addr)
55 {
56 ovs_spin_lock(&umemp->lock);
57 umem_elem_push__(umemp, addr);
58 ovs_spin_unlock(&umemp->lock);
59 }
60
61 static inline int
62 umem_elem_pop_n__(struct umem_pool *umemp, int n, void **addrs)
63 {
64 void *ptr;
65
66 if (OVS_UNLIKELY(umemp->index - n < 0)) {
67 return -ENOMEM;
68 }
69
70 umemp->index -= n;
71 ptr = &umemp->array[umemp->index];
72 memcpy(addrs, ptr, n * sizeof(void *));
73
74 return 0;
75 }
76
77 int
78 umem_elem_pop_n(struct umem_pool *umemp, int n, void **addrs)
79 {
80 int ret;
81
82 ovs_spin_lock(&umemp->lock);
83 ret = umem_elem_pop_n__(umemp, n, addrs);
84 ovs_spin_unlock(&umemp->lock);
85
86 return ret;
87 }
88
89 static inline void *
90 umem_elem_pop__(struct umem_pool *umemp)
91 {
92 if (OVS_UNLIKELY(umemp->index - 1 < 0)) {
93 return NULL;
94 }
95
96 return umemp->array[--umemp->index];
97 }
98
99 void *
100 umem_elem_pop(struct umem_pool *umemp)
101 {
102 void *ptr;
103
104 ovs_spin_lock(&umemp->lock);
105 ptr = umem_elem_pop__(umemp);
106 ovs_spin_unlock(&umemp->lock);
107
108 return ptr;
109 }
110
111 static void **
112 umem_pool_alloc__(unsigned int size)
113 {
114 void **bufs;
115
116 bufs = xmalloc_pagealign(size * sizeof *bufs);
117 memset(bufs, 0, size * sizeof *bufs);
118
119 return bufs;
120 }
121
122 int
123 umem_pool_init(struct umem_pool *umemp, unsigned int size)
124 {
125 umemp->array = umem_pool_alloc__(size);
126 if (!umemp->array) {
127 return -ENOMEM;
128 }
129
130 umemp->size = size;
131 umemp->index = 0;
132 ovs_spin_init(&umemp->lock);
133 return 0;
134 }
135
136 void
137 umem_pool_cleanup(struct umem_pool *umemp)
138 {
139 free_pagealign(umemp->array);
140 umemp->array = NULL;
141 ovs_spin_destroy(&umemp->lock);
142 }
143
144 unsigned int
145 umem_pool_count(struct umem_pool *umemp)
146 {
147 return umemp->index;
148 }
149
150 /* AF_XDP metadata init/destroy. */
151 int
152 xpacket_pool_init(struct xpacket_pool *xp, unsigned int size)
153 {
154 xp->array = xmalloc_pagealign(size * sizeof *xp->array);
155 xp->size = size;
156
157 memset(xp->array, 0, size * sizeof *xp->array);
158
159 return 0;
160 }
161
162 void
163 xpacket_pool_cleanup(struct xpacket_pool *xp)
164 {
165 free_pagealign(xp->array);
166 xp->array = NULL;
167 }