1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
// Bindgen generates functions with u128 return types
#![allow(improper_ctypes)]

include!(concat!(env!("OUT_DIR"), "/dpdk.rs"));

use std::os::raw::{c_char, c_int, c_uint, c_void};

#[cfg(dpdk_ge_2311)]
impl std::fmt::Debug for rte_gtp_psc_generic_hdr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("rte_gtp_psc_generic_hdr")
            .field("ext_hdr_len", &self.ext_hdr_len)
            .field("_bitfield_align_1", &self._bitfield_align_1)
            .field("_bitfield_1", &self._bitfield_1)
            .field("data", &self.data)
            .finish()
    }
}

impl rte_ipv4_hdr {
    #[cfg(not(dpdk_ge_2311))]
    pub fn set_version_ihl(&mut self, version_ihl: u8) {
        self.version_ihl = version_ihl;
    }

    #[cfg(dpdk_ge_2311)]
    pub fn set_version_ihl(&mut self, version_ihl: u8) {
        self.__bindgen_anon_1.version_ihl = version_ihl;
    }
}

/*
 * DPDK v23.11 uses RTE_BIT64(x) macro to define RSS values, so we use
 * bindgen clang_macro_fallback to access them.
 * There may be a bug in clang_macro_fallback impacting values >u32_max:
 * https://github.com/rust-lang/rust-bindgen/issues/2944
 * This is okay for the RSS values we use here, but it should be consulted
 * before adding new RSS offload types.
 */
#[cfg(dpdk_ge_2311)]
pub use rte_eth_fc_mode_RTE_ETH_FC_NONE as rte_eth_fc_mode_RTE_FC_NONE;
#[cfg(dpdk_ge_2311)]
pub use rte_eth_rx_mq_mode_RTE_ETH_MQ_RX_RSS as rte_eth_rx_mq_mode_ETH_MQ_RX_RSS;
#[cfg(dpdk_ge_2311)]
pub use RTE_ETH_RETA_GROUP_SIZE as RTE_RETA_GROUP_SIZE;
#[cfg(dpdk_ge_2311)]
pub use RTE_ETH_RSS_IP as ETH_RSS_IP;
#[cfg(dpdk_ge_2311)]
pub use RTE_ETH_RSS_TCP as ETH_RSS_TCP;
#[cfg(dpdk_ge_2311)]
pub use RTE_ETH_RSS_UDP as ETH_RSS_UDP;
#[cfg(dpdk_ge_2311)]
pub use RTE_ETH_VLAN_STRIP_OFFLOAD as DEV_RX_OFFLOAD_VLAN_STRIP;

#[link(name = "inlined")]
extern "C" {
    fn rte_pktmbuf_free_(packet: *const rte_mbuf);
    fn rte_pktmbuf_alloc_(mp: *mut rte_mempool) -> *mut rte_mbuf;
    fn rte_eth_tx_burst_(
        port_id: u16,
        queue_id: u16,
        tx_pkts: *mut *mut rte_mbuf,
        nb_pkts: u16,
    ) -> u16;
    fn rte_eth_rx_burst_(
        port_id: u16,
        queue_id: u16,
        rx_pkts: *mut *mut rte_mbuf,
        nb_pkts: u16,
    ) -> u16;
    fn rte_mbuf_refcnt_read_(m: *const rte_mbuf) -> u16;
    fn rte_mbuf_refcnt_update_(m: *mut rte_mbuf, value: i16) -> u16;
    fn rte_mbuf_refcnt_set_(m: *mut rte_mbuf, value: i16);
    fn rte_pktmbuf_adj_(packet: *mut rte_mbuf, len: u16) -> *mut c_char;
    fn rte_pktmbuf_trim_(packet: *mut rte_mbuf, len: u16) -> c_int;
    fn rte_lcore_id_() -> u16;
    fn rte_rdtsc_() -> u64;
    fn rte_ring_enqueue_(ring: *mut rte_ring, obj: *mut c_void) -> c_int;
    fn rte_ring_sp_enqueue_(ring: *mut rte_ring, obj: *mut c_void) -> c_int;
    fn rte_ring_mp_enqueue_(ring: *mut rte_ring, obj: *mut c_void) -> c_int;
    fn rte_ring_dequeue_(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int;
    fn rte_ring_sc_dequeue_(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int;
    fn rte_ring_mc_dequeue_(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int;
    fn rte_ring_count_(ring: *const rte_ring) -> c_uint;
    fn rte_ring_free_count_(ring: *const rte_ring) -> c_uint;
    fn rte_ring_full_(ring: *const rte_ring) -> c_int;
    fn rte_ring_empty_(ring: *const rte_ring) -> c_int;
    fn rte_ring_get_size_(ring: *const rte_ring) -> c_uint;
    fn rte_ring_get_capacity_(ring: *const rte_ring) -> c_uint;
}

#[cfg(feature = "mlx5")]
#[link(name = "rte_net_mlx5")]
extern "C" {
    fn rte_pmd_mlx5_get_dyn_flag_names();
}

#[cfg(feature = "mlx5")]
#[inline(never)]
pub fn load_drivers() {
    if std::env::var("DONT_SET_THIS").is_ok() {
        unsafe {
            rte_pmd_mlx5_get_dyn_flag_names();
        }
    }
}

#[cfg(not(feature = "mlx5"))]
#[inline(never)]
pub fn load_drivers() {}

#[inline]
pub unsafe fn rte_pktmbuf_free(packet: *const rte_mbuf) {
    rte_pktmbuf_free_(packet)
}

#[inline]
pub unsafe fn rte_pktmbuf_alloc(mp: *mut rte_mempool) -> *mut rte_mbuf {
    rte_pktmbuf_alloc_(mp)
}

#[inline]
pub unsafe fn rte_eth_tx_burst(
    port_id: u16,
    queue_id: u16,
    tx_pkts: *mut *mut rte_mbuf,
    nb_pkts: u16,
) -> u16 {
    rte_eth_tx_burst_(port_id, queue_id, tx_pkts, nb_pkts)
}

#[inline]
pub unsafe fn rte_eth_rx_burst(
    port_id: u16,
    queue_id: u16,
    rx_pkts: *mut *mut rte_mbuf,
    nb_pkts: u16,
) -> u16 {
    rte_eth_rx_burst_(port_id, queue_id, rx_pkts, nb_pkts)
}

#[inline]
pub unsafe fn rte_mbuf_refcnt_read(m: *const rte_mbuf) -> u16 {
    rte_mbuf_refcnt_read_(m)
}

#[inline]
pub unsafe fn rte_mbuf_refcnt_update(m: *mut rte_mbuf, value: i16) -> u16 {
    rte_mbuf_refcnt_update_(m, value)
}

#[inline]
pub unsafe fn rte_mbuf_refcnt_set(m: *mut rte_mbuf, value: i16) {
    rte_mbuf_refcnt_set_(m, value)
}

#[inline]
pub unsafe fn rte_pktmbuf_adj(packet: *mut rte_mbuf, len: u16) -> *mut c_char {
    rte_pktmbuf_adj_(packet, len)
}

#[inline]
pub unsafe fn rte_pktmbuf_trim(packet: *mut rte_mbuf, len: u16) -> c_int {
    rte_pktmbuf_trim_(packet, len)
}
/// Returns the application thread ID of the execution unit.
///
/// In most cases, the lcore ID returned will correspond to the processor ID of the CPU
/// on which the thread is pinned, but this will not be the case if the user has explicitly
/// changed the thread-to-core affinities.
///
/// ## Remarks
/// This is `unsafe` because it calls the DPDK `rte_lcore_id()` function via FFI. Use at your
/// own risk.
#[inline]
pub unsafe fn rte_lcore_id() -> u16 {
    rte_lcore_id_()
}

/// Reads the timestamp counter (TSC) register.
///
/// This is a low-overhead way to get CPU timing information, but may not be available on all
/// platforms and could be imprecise. It should only be used to approximate cycle counts.
///
/// ## Remarks
/// This is `unsafe` because it calls the DPDK `rte_rdtsc()` function via FFI. Use at your own risk.
#[inline]
pub unsafe fn rte_rdtsc() -> u64 {
    rte_rdtsc_()
}

/* RTE_RING functions */

#[inline]
pub unsafe fn rte_ring_enqueue(ring: *mut rte_ring, obj: *mut c_void) -> c_int {
    rte_ring_enqueue_(ring, obj)
}

#[inline]
pub unsafe fn rte_ring_sp_enqueue(ring: *mut rte_ring, obj: *mut c_void) -> c_int {
    rte_ring_sp_enqueue_(ring, obj)
}

#[inline]
pub unsafe fn rte_ring_mp_enqueue(ring: *mut rte_ring, obj: *mut c_void) -> c_int {
    rte_ring_mp_enqueue_(ring, obj)
}

#[inline]
pub unsafe fn rte_ring_dequeue(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int {
    rte_ring_dequeue_(ring, obj_p)
}

#[inline]
pub unsafe fn rte_ring_sc_dequeue(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int {
    rte_ring_sc_dequeue_(ring, obj_p)
}

#[inline]
pub unsafe fn rte_ring_mc_dequeue(ring: *mut rte_ring, obj_p: *mut *mut c_void) -> c_int {
    rte_ring_mc_dequeue_(ring, obj_p)
}

#[inline]
pub unsafe fn rte_ring_count(ring: *const rte_ring) -> c_uint {
    rte_ring_count_(ring)
}

#[inline]
pub unsafe fn rte_ring_free_count(ring: *const rte_ring) -> c_uint {
    rte_ring_free_count_(ring)
}

#[inline]
pub unsafe fn rte_ring_full(ring: *const rte_ring) -> c_int {
    rte_ring_full_(ring)
}

#[inline]
pub unsafe fn rte_ring_empty(ring: *const rte_ring) -> c_int {
    rte_ring_empty_(ring)
}

#[inline]
pub unsafe fn rte_ring_get_size(ring: *const rte_ring) -> c_uint {
    rte_ring_get_size_(ring)
}

#[inline]
pub unsafe fn rte_ring_get_capacity(ring: *const rte_ring) -> c_uint {
    rte_ring_get_capacity_(ring)
}