Files
NE_YuR/openflow/include/click/dpdkdevice.hh

211 lines
5.4 KiB
C++

#ifndef CLICK_DPDKDEVICE_HH
#define CLICK_DPDKDEVICE_HH
/**
* Prevent bug under some configurations
* (like travis-ci's one) where these
* macros get undefined.
*/
#ifndef UINT8_MAX
#define UINT8_MAX 255
#endif
#ifndef UINT16_MAX
#define UINT16_MAX 65535
#endif
#include <rte_common.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_lcore.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
#include <rte_pci.h>
#include <rte_version.h>
#include <click/packet.hh>
#include <click/error.hh>
#include <click/hashtable.hh>
#include <click/vector.hh>
#include <click/args.hh>
#include <click/etheraddress.hh>
#if RTE_VERSION < RTE_VERSION_NUM(19,8,0,0)
#define rte_ipv4_hdr ipv4_hdr
#define rte_ether_addr ether_addr
#endif
/**
* Unified type for DPDK port IDs.
* Until DPDK v17.05 was uint8_t
* After DPDK v17.05 has been uint16_t
*/
#if RTE_VERSION >= RTE_VERSION_NUM(17,05,0,0)
typedef uint16_t portid_t;
#else
typedef uint8_t portid_t;
#endif
CLICK_DECLS
class DPDKDeviceArg;
extern bool dpdk_enabled;
class DPDKDevice {
public:
portid_t port_id;
DPDKDevice() CLICK_COLD;
DPDKDevice(portid_t port_id) CLICK_COLD;
int add_rx_queue(
unsigned &queue_id, bool promisc,
unsigned n_desc, ErrorHandler *errh
) CLICK_COLD;
int add_tx_queue(
unsigned &queue_id, unsigned n_desc,
ErrorHandler *errh
) CLICK_COLD;
EtherAddress get_mac();
void set_init_mac(EtherAddress mac);
void set_init_mtu(uint16_t mtu);
unsigned int get_nb_txdesc();
int nbRXQueues();
int nbTXQueues();
const char *get_device_driver();
static unsigned int dev_count() {
#if RTE_VERSION >= RTE_VERSION_NUM(18,05,0,0)
return rte_eth_dev_count_avail();
#else
return rte_eth_dev_count();
#endif
}
static struct rte_mempool *get_mpool(unsigned int);
static int get_port_numa_node(portid_t port_id);
static int initialize(ErrorHandler *errh);
inline static bool is_dpdk_packet(Packet* p) {
return p->buffer_destructor() == DPDKDevice::free_pkt || (p->data_packet() && is_dpdk_packet(p->data_packet()));
}
inline static rte_mbuf* get_pkt(unsigned numa_node);
inline static rte_mbuf* get_pkt();
static void free_pkt(unsigned char *, size_t, void *pktmbuf);
static int NB_MBUF;
static int MBUF_DATA_SIZE;
static int MBUF_SIZE;
static int MBUF_CACHE_SIZE;
static int RX_PTHRESH;
static int RX_HTHRESH;
static int RX_WTHRESH;
static int TX_PTHRESH;
static int TX_HTHRESH;
static int TX_WTHRESH;
static String MEMPOOL_PREFIX;
static unsigned DEF_DEV_RXDESC;
static unsigned DEF_DEV_TXDESC;
static unsigned DEF_BURST_SIZE;
private:
enum Dir { RX, TX };
struct DevInfo {
inline DevInfo() :
rx_queues(0,false), tx_queues(0,false), promisc(false), n_rx_descs(0),
n_tx_descs(0), init_mac(), init_mtu(0) {
rx_queues.reserve(128);
tx_queues.reserve(128);
}
const char* driver;
Vector<bool> rx_queues;
Vector<bool> tx_queues;
bool promisc;
unsigned n_rx_descs;
unsigned n_tx_descs;
EtherAddress init_mac;
uint16_t init_mtu;
};
DevInfo info;
static bool _is_initialized;
static HashTable<portid_t, DPDKDevice> _devs;
static struct rte_mempool** _pktmbuf_pools;
static unsigned _nr_pktmbuf_pools;
static bool no_more_buffer_msg_printed;
int initialize_device(ErrorHandler *errh) CLICK_COLD;
int add_queue(Dir dir, unsigned &queue_id, bool promisc,
unsigned n_desc, ErrorHandler *errh) CLICK_COLD;
static bool alloc_pktmbufs() CLICK_COLD;
static DPDKDevice* get_device(const portid_t &port_id) {
return &(_devs.find_insert(port_id, DPDKDevice(port_id)).value());
}
#if RTE_VERSION < RTE_VERSION_NUM(18,05,0,0)
static int get_port_from_pci(uint32_t domain, uint8_t bus, uint8_t dev_id, uint8_t function) {
struct rte_eth_dev_info dev_info;
uint16_t count = rte_eth_dev_count();
for (portid_t port_id = 0 ; port_id < count; ++port_id) {
rte_eth_dev_info_get(port_id, &dev_info);
struct rte_pci_addr addr = dev_info.pci_dev->addr;
if (addr.domain == domain &&
addr.bus == bus &&
addr.devid == dev_id &&
addr.function == function)
return port_id;
}
return -1;
}
#endif
friend class DPDKDeviceArg;
friend class DPDKInfo;
};
inline rte_mbuf* DPDKDevice::get_pkt(unsigned numa_node) {
struct rte_mbuf* mbuf = rte_pktmbuf_alloc(get_mpool(numa_node));
if (unlikely(!mbuf)) {
if (!DPDKDevice::no_more_buffer_msg_printed)
click_chatter("No more DPDK buffer available ! Try using "
"DPDKInfo to allocate more.");
else
DPDKDevice::no_more_buffer_msg_printed = true;
}
return mbuf;
}
inline rte_mbuf* DPDKDevice::get_pkt() {
return get_pkt(rte_socket_id());
}
/** @class DPDKPortArg
@brief Parser class for DPDK Port, either an integer or a PCI address. */
class DPDKDeviceArg { public:
static bool parse(const String &str, DPDKDevice* &result, const ArgContext &args = ArgContext());
static String unparse(DPDKDevice* dev) {
return String(dev->port_id);
}
};
template<> struct DefaultArg<DPDKDevice*> : public DPDKDeviceArg {};
CLICK_ENDDECLS
#endif