af_xdp: workaround kernel race between poll() and sendmsg()
[vpp.git] / src / plugins / af_xdp / af_xdp.h
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 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 #ifndef _AF_XDP_H_
19 #define _AF_XDP_H_
20
21 #include <vlib/log.h>
22 #include <vnet/interface.h>
23 #include <bpf/xsk.h>
24
25 #define AF_XDP_NUM_RX_QUEUES_ALL        ((u16)-1)
26
27 #define af_xdp_log(lvl, dev, f, ...) \
28   vlib_log(lvl, af_xdp_main.log_class, "%v: " f, (dev)->name, ##__VA_ARGS__)
29
30 #define foreach_af_xdp_device_flags                                           \
31   _ (0, INITIALIZED, "initialized")                                           \
32   _ (1, ERROR, "error")                                                       \
33   _ (2, ADMIN_UP, "admin-up")                                                 \
34   _ (3, LINK_UP, "link-up")                                                   \
35   _ (4, ZEROCOPY, "zero-copy")                                                \
36   _ (5, SYSCALL_LOCK, "syscall-lock")
37
38 enum
39 {
40 #define _(a, b, c) AF_XDP_DEVICE_F_##b = (1 << a),
41   foreach_af_xdp_device_flags
42 #undef _
43 };
44
45 #define af_xdp_device_error(dev, fmt, ...) \
46   if (!(dev)->error) \
47     { \
48       clib_error_t *err_ = clib_error_return_unix (0, fmt, ## __VA_ARGS__); \
49       if (!clib_atomic_bool_cmp_and_swap (&(dev)->error, 0, err_)) \
50         clib_error_free(err_); \
51     }
52
53 typedef enum
54 {
55   AF_XDP_RXQ_MODE_UNKNOWN,
56   AF_XDP_RXQ_MODE_POLLING,
57   AF_XDP_RXQ_MODE_INTERRUPT,
58 } __clib_packed af_xdp_rxq_mode_t;
59
60 typedef struct
61 {
62   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
63
64   /* fields below are accessed in data-plane (hot) */
65
66   clib_spinlock_t syscall_lock;
67   struct xsk_ring_cons rx;
68   struct xsk_ring_prod fq;
69   int xsk_fd;
70
71   /* fields below are accessed in control-plane only (cold) */
72
73   uword file_index;
74   u32 queue_index;
75   af_xdp_rxq_mode_t mode;
76 } af_xdp_rxq_t;
77
78 typedef struct
79 {
80   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
81
82   /* fields below are accessed in data-plane (hot) */
83
84   clib_spinlock_t lock;
85   clib_spinlock_t syscall_lock;
86   struct xsk_ring_prod tx;
87   struct xsk_ring_cons cq;
88   int xsk_fd;
89 } af_xdp_txq_t;
90
91 typedef struct
92 {
93   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
94
95   /* fields below are accessed in data-plane (hot) */
96
97   af_xdp_rxq_t *rxqs;
98   af_xdp_txq_t *txqs;
99   vlib_buffer_t *buffer_template;
100   u32 per_interface_next_index;
101   u32 sw_if_index;
102   u32 hw_if_index;
103   u32 flags;
104   u8 pool;                      /* buffer pool index */
105   u8 txq_num;
106
107   /* fields below are accessed in control-plane only (cold) */
108
109   char *name;
110   char *linux_ifname;
111   u32 dev_instance;
112   u8 hwaddr[6];
113
114   u8 rxq_num;
115
116   struct xsk_umem **umem;
117   struct xsk_socket **xsk;
118
119   struct bpf_object *bpf_obj;
120   unsigned linux_ifindex;
121
122   /* error */
123   clib_error_t *error;
124 } af_xdp_device_t;
125
126 typedef struct
127 {
128   af_xdp_device_t *devices;
129   vlib_log_class_t log_class;
130   u16 msg_id_base;
131 } af_xdp_main_t;
132
133 extern af_xdp_main_t af_xdp_main;
134
135 typedef enum
136 {
137   AF_XDP_MODE_AUTO = 0,
138   AF_XDP_MODE_COPY = 1,
139   AF_XDP_MODE_ZERO_COPY = 2,
140 } af_xdp_mode_t;
141
142 typedef enum
143 {
144   AF_XDP_CREATE_FLAGS_NO_SYSCALL_LOCK = 1,
145 } af_xdp_create_flag_t;
146
147 typedef struct
148 {
149   char *linux_ifname;
150   char *name;
151   char *prog;
152   af_xdp_mode_t mode;
153   af_xdp_create_flag_t flags;
154   u32 rxq_size;
155   u32 txq_size;
156   u32 rxq_num;
157
158   /* return */
159   int rv;
160   u32 sw_if_index;
161   clib_error_t *error;
162 } af_xdp_create_if_args_t;
163
164 void af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args);
165 void af_xdp_delete_if (vlib_main_t * vm, af_xdp_device_t * ad);
166
167 extern vlib_node_registration_t af_xdp_input_node;
168 extern vnet_device_class_t af_xdp_device_class;
169
170 /* format.c */
171 format_function_t format_af_xdp_device;
172 format_function_t format_af_xdp_device_name;
173 format_function_t format_af_xdp_input_trace;
174
175 /* unformat.c */
176 unformat_function_t unformat_af_xdp_create_if_args;
177
178 typedef struct
179 {
180   u32 next_index;
181   u32 hw_if_index;
182 } af_xdp_input_trace_t;
183
184 #define foreach_af_xdp_tx_func_error                                          \
185   _ (NO_FREE_SLOTS, "no free tx slots")                                       \
186   _ (SYSCALL_REQUIRED, "syscall required")                                    \
187   _ (SYSCALL_FAILURES, "syscall failures")
188
189 typedef enum
190 {
191 #define _(f,s) AF_XDP_TX_ERROR_##f,
192   foreach_af_xdp_tx_func_error
193 #undef _
194     AF_XDP_TX_N_ERROR,
195 } af_xdp_tx_func_error_t;
196
197 #endif /* _AF_XDP_H_ */
198
199 /*
200  * fd.io coding-style-patch-verification: ON
201  *
202  * Local Variables:
203  * eval: (c-set-style "gnu")
204  * End:
205  */