1#ifndef CLICK_DPDKDEVICE_HH
2#define CLICK_DPDKDEVICE_HH
13#define UINT16_MAX 65535
16#include <rte_common.h>
18#include <rte_ethdev.h>
21#include <rte_mempool.h>
23#include <rte_version.h>
25#if RTE_VERSION >= RTE_VERSION_NUM(21, 02, 0, 0)
26#include <rte_power_pmd_mgmt.h>
32 #include <click/flowruleparser.hh>
35#if RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0) && RTE_VERSION < RTE_VERSION_NUM(19,2,0,0)
36 #include <rte_bus_pci.h>
43#include <click/args.hh>
48#if RTE_VERSION < RTE_VERSION_NUM(19,8,0,0)
49#define rte_ipv4_hdr ipv4_hdr
50#define rte_ether_addr ether_addr
52#include <nicscheduler/ethernetdevice.hh>
54#if RTE_VERSION < RTE_VERSION_NUM(19,8,0,0)
55#define rte_ipv4_hdr ipv4_hdr
56#define rte_ether_addr ether_addr
64#ifndef PORTID_T_DEFINED
65 #define PORTID_T_DEFINED
66 typedef uint8_t portid_t;
73enum FlowControlMode {FC_UNSET, FC_NONE, FC_RX, FC_TX, FC_FULL};
78typedef uint64_t counter_t;
80typedef uint32_t counter_t;
83extern bool dpdk_enabled;
86#define MY_PCI_ANY_ID RTE_PCI_ANY_ID
88#define MY_PCI_ANY_ID PCI_ANY_ID
91class DPDKDevice :
public DPDKEthernetDevice {
95 DPDKDevice(portid_t port_id = -1) CLICK_COLD;
99 vendor_id(MY_PCI_ANY_ID), vendor_name(), device_id(MY_PCI_ANY_ID), driver(0),
100 init_mac(), init_mtu(0), init_rss(-1), init_reta_size(-1), init_fc_mode(FC_UNSET),
101 rx_queues(0, false), tx_queues(0, false), n_rx_descs(0), n_tx_descs(0),
102 num_pools(0), promisc(false),
103 mq_mode((enum rte_eth_rx_mq_mode)-1), mq_mode_str(
""),
104 rx_offload(0), tx_offload(0),
106 vlan_filter(false), vlan_strip(false), vlan_extend(false), vf_vlan(),
107 lro(false), jumbo(false)
108#if RTE_VERSION >= RTE_VERSION_NUM(21, 02, 0, 0)
109 , power_mgmt_mode(-1)
112 rx_queues.reserve(128);
113 tx_queues.reserve(128);
116 void print_device_info() {
117 if (device_id == MY_PCI_ANY_ID) {
120 click_chatter(
" Vendor ID: %d", vendor_id);
121 click_chatter(
" Vendor Name: %s", vendor_name.c_str());
122 click_chatter(
" Device ID: %d", device_id);
123 click_chatter(
" Driver Name: %s", driver);
124 click_chatter(
" MAC Address: %s", init_mac.unparse().c_str());
125 click_chatter(
" Maximum Transfer Unit: %u", init_mtu);
126 click_chatter(
"Receive Side Scaling queues: %d", init_rss);
127 click_chatter(
" RETA Size: %d", init_reta_size);
128 click_chatter(
" Flow Control Mode: %d", init_fc_mode);
129 click_chatter(
" # of Rx Queues: %d", rx_queues.size());
130 click_chatter(
" # of Tx Queues: %d", tx_queues.size());
131 click_chatter(
" # of Rx Descs: %d", n_rx_descs);
132 click_chatter(
" # of Tx Descs: %d", n_tx_descs);
133 click_chatter(
" # of memory pools: %d", num_pools);
134 click_chatter(
" Reception Mode: %s", mq_mode_str.c_str());
135 click_chatter(
" Promiscuous Mode: %s", promisc?
"true":
"false");
136 click_chatter(
" Flow API Isolation: %s", flow_isolate?
"true":
"false");
137 click_chatter(
" Rx Offloads flag: %" PRIu64, rx_offload);
138 click_chatter(
" Tx Offloads flag: %" PRIu64, tx_offload);
139 click_chatter(
" VLAN Filtering: %s", vlan_filter?
"true":
"false");
140 click_chatter(
" VLAN Stripping: %s", vlan_strip?
"true":
"false");
141 click_chatter(
" VLAN QinQ(extend): %s", vlan_extend?
"true":
"false");
142 click_chatter(
" Virtual Function VLAN: %d", vf_vlan.size());
143 click_chatter(
"Large Receive Offload (LRO): %s", lro ?
"true":
"false");
144 click_chatter(
" Rx Jumbo Frames Offload: %s", jumbo ?
"true":
"false");
155 FlowControlMode init_fc_mode;
162 enum rte_eth_rx_mq_mode mq_mode;
174#if RTE_VERSION >= RTE_VERSION_NUM(21, 02, 0, 0)
180 void initialize_flow_rule_manager(
181 const portid_t &port_id,
186 portid_t get_port_id() {
return port_id; }
189 unsigned &queue_id,
bool promisc,
bool vlan_filter,
bool vlan_strip,
bool vlan_extend,
190 bool lro,
bool jumbo,
unsigned n_desc,
ErrorHandler *errh
194 unsigned &queue_id,
unsigned n_desc,
200 void set_init_mtu(uint16_t mtu);
201 void set_init_rss_max(
int rss_max);
202 void set_init_reta_size(
int reta_size);
203 void set_init_fc_mode(FlowControlMode fc);
204 void set_rx_offload(uint64_t offload);
205 void set_tx_offload(uint64_t offload);
207#if RTE_VERSION >= RTE_VERSION_NUM(21, 02, 0, 0)
208 void set_power_mgmt(
enum rte_power_pmd_mgmt_type mode);
211#if RTE_VERSION >= RTE_VERSION_NUM(18,05,0,0)
212 void set_init_flow_isolate(
const bool &flow_isolate);
214 inline void set_isolation_mode(
const bool &isolated) {
215 info.flow_isolate = isolated;
216 if (info.flow_isolate) {
217 rte_flow_isolate(port_id, 1, 0);
219 rte_flow_isolate(port_id, 0, 0);
222 inline bool isolated() {
return info.flow_isolate; };
226 unsigned int get_nb_rxdesc();
227 unsigned int get_nb_txdesc();
229 uint16_t get_device_vendor_id();
230 String get_device_vendor_name();
231 uint16_t get_device_id();
232 const char *get_device_driver();
234 int dpdk_set_rss_max(
int max,
unsigned reta_sz = -1);
235 int dpdk_set_rss_reta(
unsigned* reta,
unsigned reta_sz);
236 int dpdk_get_rss_reta_size()
const;
239 EthernetDevice* get_eth_device();
241 static unsigned int dev_count() {
242#if RTE_VERSION >= RTE_VERSION_NUM(18,05,0,0)
243 return rte_eth_dev_count_avail();
245 return rte_eth_dev_count();
249 static struct rte_mempool *get_mpool(
unsigned int);
251 static int get_port_numa_node(portid_t port_id);
253 static Router::ChildrenFuture all_initialized;
266 rte_eth_rx_mq_mode get_mode();
273 static int static_cleanup();
275#if CLICK_PACKET_USE_DPDK
276 inline static bool is_dpdk_packet(
Packet* p) {
280 inline static bool is_dpdk_buffer(
Packet* p) {
284 inline static bool is_dpdk_packet(
Packet* p) {
285 return p->buffer_destructor() == DPDKDevice::free_pkt;
288 inline static bool is_dpdk_buffer(
Packet* p) {
289 return is_dpdk_packet(p)
290#ifndef CLICK_NOINDIRECT
291 || (p->data_packet() && is_dpdk_packet(p->data_packet()))
298 inline void kill_ref(
Packet* p);
300 inline static rte_mbuf* get_pkt(
unsigned numa_node);
301 inline static rte_mbuf* get_pkt();
302 inline static struct rte_mbuf* get_mbuf(
Packet* p,
bool create,
int node,
bool reset =
true);
304 static WritablePacket* make_extbuf(
unsigned char *data, uint32_t length,
305 Packet::buffer_destructor_type destructor,
void* argument,
int headroom,
int tailroom,
bool clear);
307 static void free_pkt(
unsigned char *,
size_t,
void *pktmbuf);
309 static unsigned int get_nb_txdesc(
const portid_t &port_id);
312 static int configure_nic(
const portid_t &port_id);
318 static int DEFAULT_NB_MBUF;
319 static int MBUF_DATA_SIZE;
320 static int MBUF_SIZE;
321 static int MBUF_CACHE_SIZE;
322 static int RX_PTHRESH;
323 static int RX_HTHRESH;
324 static int RX_WTHRESH;
325 static int TX_PTHRESH;
326 static int TX_HTHRESH;
327 static int TX_WTHRESH;
328 static String MEMPOOL_PREFIX;
330 static unsigned DEF_DEV_RXDESC;
331 static unsigned DEF_DEV_TXDESC;
333 static unsigned DEF_RING_NDESC;
334 static unsigned DEF_BURST_SIZE;
336 static unsigned RING_FLAGS;
337 static unsigned RING_SIZE;
338 static unsigned RING_POOL_CACHE_SIZE;
339 static unsigned RING_PRIV_DATA_SIZE;
341 static struct rte_mempool** _pktmbuf_pools;
343 inline struct DevInfo get_info() {
return info; };
344 inline int nb_rx_queues();
345 inline int nb_tx_queues();
346 inline int nb_vf_pools();
348 struct rte_ether_addr gen_mac(int a, int b);
359 class TXInternalQueue {
361 TXInternalQueue() : pkts(0), index(0), nr_pending(0), timeout() { }
364 struct rte_mbuf **pkts;
368 unsigned int nr_pending;
372 } __attribute__((aligned(64)));
374 static bool initialized() {
375 return _is_initialized;
385 static int get_nb_mbuf(
int socket);
386 static bool _is_initialized;
388 static unsigned _nr_pktmbuf_pools;
389 static bool no_more_buffer_msg_printed;
392 int add_queue(Dir dir,
unsigned &queue_id,
393 bool promisc,
bool vlan_filter,
bool vlan_strip,
bool vlan_extend,
394 bool lro,
bool jumbo,
unsigned n_desc,
ErrorHandler *errh) CLICK_COLD;
396 static int alloc_pktmbufs(
ErrorHandler* errh) CLICK_COLD;
398 static DPDKDevice *ensure_device(
const portid_t &port_id) {
399 auto it = _devs.
find_insert(port_id,
new DPDKDevice(port_id));
404 static DPDKDevice* get_device(
const portid_t &port_id) {
405 return _devs.
find(port_id).value();
408#if RTE_VERSION < RTE_VERSION_NUM(18,05,0,0)
409 static int get_port_from_pci(uint32_t domain, uint8_t bus, uint8_t dev_id, uint8_t function) {
410 struct rte_eth_dev_info dev_info;
412 uint16_t count = rte_eth_dev_count();
413 for (portid_t port_id = 0 ; port_id < count; ++port_id) {
414 rte_eth_dev_info_get(port_id, &dev_info);
415 struct rte_pci_addr addr = dev_info.pci_dev->addr;
416 if (addr.domain == domain &&
418 addr.devid == dev_id &&
419 addr.function == function)
428 friend class DPDKInfo;
431class DPDKRing {
public:
433 DPDKRing() CLICK_COLD;
434 ~DPDKRing() CLICK_COLD;
436 int parse(
Args* args);
438 struct rte_mempool *_message_pool;
444 unsigned _burst_size;
448 struct rte_ring *_ring;
460 static String unparse(DPDKDevice* dev) {
461 return String(dev->port_id);
465template<>
struct DefaultArg<DPDKDevice*> :
public DPDKDeviceArg {};
471 static String unparse(FlowControlMode mode);
483inline struct rte_mbuf* DPDKDevice::get_mbuf(
Packet* p,
bool create,
int node,
bool reset) {
484 struct rte_mbuf* mbuf;
485 #if CLICK_PACKET_USE_DPDK
487 #elif CLICK_PACKET_INSIDE_DPDK
488 mbuf = ((
struct rte_mbuf*)p) - 1;
489 rte_pktmbuf_pkt_len(mbuf) = p->
length();
490 rte_pktmbuf_data_len(mbuf) = p->
length();
493 if (likely(DPDKDevice::is_dpdk_packet(p) && (mbuf = (
struct rte_mbuf *)((
unsigned char*) p->
buffer() -
sizeof(rte_mbuf)) ))
494#ifndef CLICK_NOINDIRECT
495 || unlikely(p->data_packet() && DPDKDevice::is_dpdk_packet(p->data_packet()) && (mbuf = (
struct rte_mbuf *) p->data_packet()->destructor_argument()))
500 rte_pktmbuf_pkt_len(mbuf) = p->
length();
501 rte_pktmbuf_data_len(mbuf) = p->
length();
503#ifndef CLICK_NOINDIRECT
507 rte_mbuf_refcnt_update(mbuf, 1);
519 mbuf = DPDKDevice::get_pkt(node);
523 memcpy((
void*)rte_pktmbuf_mtod(mbuf,
unsigned char *),p->
data(),p->
length());
524 rte_pktmbuf_pkt_len(mbuf) = p->
length();
525 rte_pktmbuf_data_len(mbuf) = p->
length();
533inline void DPDKDevice::kill_ref(
Packet* p) {
534 struct rte_mbuf* mbuf = get_mbuf(p,
false,-1);
535 if (rte_mbuf_refcnt_read(mbuf) > 1)
536 rte_mbuf_refcnt_update(mbuf, -1);
541inline rte_mbuf* DPDKDevice::get_pkt(
unsigned numa_node) {
542 struct rte_mbuf* mbuf = rte_pktmbuf_alloc(get_mpool(numa_node));
543 if (unlikely(!mbuf)) {
544 if (!DPDKDevice::no_more_buffer_msg_printed)
545 click_chatter(
"No more DPDK buffer available ! Try using "
546 "DPDKInfo to allocate more.");
548 DPDKDevice::no_more_buffer_msg_printed =
true;
553inline rte_mbuf* DPDKDevice::get_pkt() {
554 return get_pkt(rte_socket_id());
557int DPDKDevice::nb_rx_queues() {
558 return info.rx_queues.size();
561int DPDKDevice::nb_tx_queues() {
562 return info.tx_queues.size();
565int DPDKDevice::nb_vf_pools() {
566 return info.num_pools;
Argument context class.
Definition args.hh:31
Argument parser class.
Definition args.hh:249
Parser class for DPDK Port, either an integer or a PCI address.
Definition dpdkdevice.hh:458
Error reporting class.
Definition error.hh:90
An Ethernet address.
Definition etheraddress.hh:9
Parser class for flow control mode.
Definition dpdkdevice.hh:469
Hash table template.
Definition hashtable.hh:570
iterator find_insert(key_const_reference key)
Ensure an element with key key and return its iterator.
Definition hashtable.hh:778
const_iterator find(key_const_reference key) const
Return an iterator for the element with key key, if any.
Definition hashtable.hh:693
A network packet.
Definition packet.hh:68
void kill()
Delete this packet.
Definition packet.hh:1804
const unsigned char * buffer() const
Return a pointer to the packet's data buffer.
Definition packet.hh:1243
const unsigned char * data() const
Return the packet's data pointer.
Definition packet.hh:1207
uint32_t length() const
Return the packet's length.
Definition packet.hh:1276
uint32_t headroom() const
Return the packet's headroom.
Definition packet.hh:1293
bool shared() const
Test whether this packet's data is shared.
Definition packet.hh:1985
A string of characters.
Definition string.hh:22
Triggers execution at a given time.
Definition timer.hh:14
Vector template.
Definition vector.hh:111
A network packet believed not to be shared.
Definition packet.hh:1004
Flexible error handling classes.
The EtherAddress type for Ethernet addresses.
Click's hash table container template.
The Packet class models packets in Click.
The Router class implementing a router configuration.
Support for Timer, which triggers execution at a given time.
Click's vector container template.