Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
fastclick
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
SDN PP
fastclick
Commits
266d542a
Commit
266d542a
authored
Apr 13, 2018
by
Tom Barbette
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Sync style and few not important things with Metron
parent
785624ea
Pipeline
#1822
passed with stage
in 10 minutes and 9 seconds
Changes
9
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
188 additions
and
169 deletions
+188
-169
elements/userlevel/fromdpdkdevice.cc
elements/userlevel/fromdpdkdevice.cc
+14
-13
elements/userlevel/fromdpdkdevice.hh
elements/userlevel/fromdpdkdevice.hh
+0
-1
elements/userlevel/fromdpdkring.cc
elements/userlevel/fromdpdkring.cc
+1
-3
elements/userlevel/todpdkdevice.cc
elements/userlevel/todpdkdevice.cc
+5
-5
elements/userlevel/todpdkdevice.hh
elements/userlevel/todpdkdevice.hh
+6
-27
elements/userlevel/todpdkring.cc
elements/userlevel/todpdkring.cc
+5
-5
elements/userlevel/todpdkring.hh
elements/userlevel/todpdkring.hh
+5
-28
include/click/dpdkdevice.hh
include/click/dpdkdevice.hh
+95
-55
lib/dpdkdevice.cc
lib/dpdkdevice.cc
+57
-32
No files found.
elements/userlevel/fromdpdkdevice.cc
View file @
266d542a
// -*- c-basic-offset: 4; related-file-name: "fromdpdkdevice.hh" -*-
/*
* fromdpdkdevice.{cc,hh} -- element reads packets live from network via
*
Intel's DPDK
*
the DPDK.
*
* Copyright (c) 2014-2015 Cyril Soldani, University of Liège
* Copyright (c) 2016 Tom Barbette, University of Liège
* Copyright (c) 2016-2017 Tom Barbette, University of Liège
* Copyright (c) 2017 Georgios Katsikas, RISE SICS
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
...
...
@@ -30,13 +31,13 @@
CLICK_DECLS
FromDPDKDevice
::
FromDPDKDevice
()
:
_dev
(
0
)
,
_active
(
true
)
_dev
(
0
)
{
#if HAVE_BATCH
in_batch_mode
=
BATCH_MODE_YES
;
#endif
_burst
=
32
;
ndesc
=
DPDKDevice
::
DEF_DEV_RXDESC
;
#if HAVE_BATCH
in_batch_mode
=
BATCH_MODE_YES
;
#endif
_burst
=
32
;
ndesc
=
DPDKDevice
::
DEF_DEV_RXDESC
;
}
FromDPDKDevice
::~
FromDPDKDevice
()
...
...
@@ -67,7 +68,7 @@ int FromDPDKDevice::configure(Vector<String> &conf, ErrorHandler *errh)
if
(
allow_nonexistent
)
return
0
;
else
return
errh
->
error
(
"%s
: Unknown or invalid PORT"
,
dev
.
c_str
());
return
errh
->
error
(
"%s: Unknown or invalid PORT"
,
dev
.
c_str
());
}
if
(
_use_numa
)
{
...
...
@@ -87,9 +88,10 @@ int FromDPDKDevice::configure(Vector<String> &conf, ErrorHandler *errh)
}
else
{
if
(
firstqueue
==
-
1
)
firstqueue
=
0
;
r
=
configure_rx
(
numa_node
,
n_queues
,
n_queues
,
errh
);
r
=
configure_rx
(
numa_node
,
n_queues
,
n_queues
,
errh
);
}
if
(
r
!=
0
)
return
r
;
if
(
r
!=
0
)
return
r
;
if
(
has_mac
)
_dev
->
set_init_mac
(
mac
);
...
...
@@ -136,7 +138,7 @@ int FromDPDKDevice::initialize(ErrorHandler *errh)
void
FromDPDKDevice
::
cleanup
(
CleanupStage
)
{
cleanup_tasks
();
cleanup_tasks
();
}
bool
FromDPDKDevice
::
run_task
(
Task
*
t
)
...
...
@@ -293,7 +295,6 @@ String FromDPDKDevice::statistics_handler(Element *e, void *thunk)
}
}
int
FromDPDKDevice
::
write_handler
(
const
String
&
input
,
Element
*
e
,
void
*
thunk
,
ErrorHandler
*
errh
)
{
FromDPDKDevice
*
fd
=
static_cast
<
FromDPDKDevice
*>
(
e
);
...
...
elements/userlevel/fromdpdkdevice.hh
View file @
266d542a
...
...
@@ -150,7 +150,6 @@ private:
};
DPDKDevice
*
_dev
;
bool
_active
;
};
CLICK_ENDDECLS
...
...
elements/userlevel/fromdpdkring.cc
View file @
266d542a
...
...
@@ -32,8 +32,6 @@ FromDPDKRing::FromDPDKRing() :
#if HAVE_BATCH
in_batch_mode
=
BATCH_MODE_YES
;
#endif
_ndesc
=
DPDKDevice
::
DEF_RING_NDESC
;
}
FromDPDKRing
::~
FromDPDKRing
()
...
...
@@ -90,7 +88,6 @@ FromDPDKRing::initialize(ErrorHandler *errh)
_message_pool
=
rte_mempool_lookup
(
_MEM_POOL
.
c_str
());
if
(
!
_message_pool
)
{
click_chatter
(
"Creating %s"
,
_MEM_POOL
.
c_str
());
_message_pool
=
rte_mempool_create
(
_MEM_POOL
.
c_str
(),
_ndesc
,
DPDKDevice
::
MBUF_DATA_SIZE
,
...
...
@@ -132,6 +129,7 @@ FromDPDKRing::run_task(Task *t)
#endif
struct
rte_mbuf
*
pkts
[
_burst_size
];
#if RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0)
int
n
=
rte_ring_dequeue_burst
(
_ring
,
(
void
**
)
pkts
,
_burst_size
,
&
avail
);
#else
...
...
elements/userlevel/todpdkdevice.cc
View file @
266d542a
...
...
@@ -58,7 +58,7 @@ int ToDPDKDevice::configure(Vector<String> &conf, ErrorHandler *errh)
//TODO : If user put multiple ToDPDKDevice with the same port and without the QUEUE parameter, try to share the available queues among them
if
(
firstqueue
==
-
1
)
firstqueue
=
0
;
firstqueue
=
0
;
configure_tx
(
1
,
maxqueues
,
errh
);
return
0
;
}
...
...
@@ -158,7 +158,7 @@ void ToDPDKDevice::add_handlers()
add_read_handler
(
"hw_errors"
,
statistics_handler
,
h_oerrors
);
}
inline
void
ToDPDKDevice
::
set_flush_timer
(
TXInternalQueue
&
iqueue
)
{
inline
void
ToDPDKDevice
::
set_flush_timer
(
DPDKDevice
::
TXInternalQueue
&
iqueue
)
{
if
(
_timeout
>=
0
||
iqueue
.
nr_pending
)
{
if
(
iqueue
.
timeout
.
scheduled
())
{
//No more pending packets, remove timer
...
...
@@ -183,7 +183,7 @@ void ToDPDKDevice::run_timer(Timer *)
/* Flush as much as possible packets from a given internal queue to the DPDK
* device. */
void
ToDPDKDevice
::
flush_internal_tx_queue
(
TXInternalQueue
&
iqueue
)
{
void
ToDPDKDevice
::
flush_internal_tx_queue
(
DPDKDevice
::
TXInternalQueue
&
iqueue
)
{
unsigned
sent
=
0
;
unsigned
r
;
/* sub_burst is the number of packets DPDK should send in one call if
...
...
@@ -221,7 +221,7 @@ void ToDPDKDevice::flush_internal_tx_queue(TXInternalQueue &iqueue) {
void
ToDPDKDevice
::
push
(
int
,
Packet
*
p
)
{
// Get the thread-local internal queue
TXInternalQueue
&
iqueue
=
_iqueues
.
get
();
DPDKDevice
::
TXInternalQueue
&
iqueue
=
_iqueues
.
get
();
bool
congestioned
;
do
{
...
...
@@ -277,7 +277,7 @@ void ToDPDKDevice::push(int, Packet *p)
void
ToDPDKDevice
::
push_batch
(
int
,
PacketBatch
*
head
)
{
// Get the thread-local internal queue
TXInternalQueue
&
iqueue
=
_iqueues
.
get
();
DPDKDevice
::
TXInternalQueue
&
iqueue
=
_iqueues
.
get
();
Packet
*
p
=
head
;
Packet
*
next
;
...
...
elements/userlevel/todpdkdevice.hh
View file @
266d542a
...
...
@@ -128,8 +128,8 @@ public:
}
bool
can_live_reconfigure
()
const
{
return
false
;
}
int
configure
(
Vector
<
String
>
&
,
ErrorHandler
*
)
CLICK_COLD
;
int
initialize
(
ErrorHandler
*
)
CLICK_COLD
;
int
configure
(
Vector
<
String
>
&
,
ErrorHandler
*
)
override
CLICK_COLD
;
int
initialize
(
ErrorHandler
*
)
override
CLICK_COLD
;
void
cleanup
(
CleanupStage
stage
)
override
CLICK_COLD
;
...
...
@@ -148,31 +148,10 @@ public:
private:
/* TXInternalQueue is a ring of DPDK buffers pointers (rte_mbuf *) awaiting
* to be sent. It is used as an internal buffer to be passed to DPDK device
* queue.
* index is the index of the first valid packets awaiting to be sent, while
* nr_pending is the number of packets. index + nr_pending may be greater
* than _internal_tx_queue_size but index should be wrapped-around. */
class
TXInternalQueue
{
public:
TXInternalQueue
()
:
pkts
(
0
),
index
(
0
),
nr_pending
(
0
)
{
}
// Array of DPDK Buffers
struct
rte_mbuf
**
pkts
;
// Index of the first valid packet in the pkts array
unsigned
int
index
;
// Number of valid packets awaiting to be sent after index
unsigned
int
nr_pending
;
// Timer to limit time a batch will take to be completed
Timer
timeout
;
}
__attribute__
((
aligned
(
64
)));
inline
void
set_flush_timer
(
TXInternalQueue
&
iqueue
);
void
flush_internal_tx_queue
(
TXInternalQueue
&
);
per_thread
<
TXInternalQueue
>
_iqueues
;
inline
void
set_flush_timer
(
DPDKDevice
::
TXInternalQueue
&
iqueue
);
void
flush_internal_tx_queue
(
DPDKDevice
::
TXInternalQueue
&
);
per_thread
<
DPDKDevice
::
TXInternalQueue
>
_iqueues
;
DPDKDevice
*
_dev
;
int
_timeout
;
...
...
elements/userlevel/todpdkring.cc
View file @
266d542a
...
...
@@ -30,7 +30,7 @@ ToDPDKRing::ToDPDKRing() :
_blocking
(
false
),
_congestion_warning_printed
(
false
),
_dropped
(
0
)
{
_ndesc
=
DPDKDevice
::
DEF_RING_NDESC
;
}
ToDPDKRing
::~
ToDPDKRing
()
...
...
@@ -140,7 +140,7 @@ ToDPDKRing::run_timer(Timer *)
}
inline
void
ToDPDKRing
::
set_flush_timer
(
TXInternalQueue
&
iqueue
)
ToDPDKRing
::
set_flush_timer
(
DPDKDevice
::
TXInternalQueue
&
iqueue
)
{
if
(
_timeout
>=
0
)
{
if
(
iqueue
.
timeout
.
scheduled
()
)
{
...
...
@@ -162,7 +162,7 @@ ToDPDKRing::set_flush_timer(TXInternalQueue &iqueue)
/* Flush as many packets as possible from the internal queue of the DPDK ring. */
void
ToDPDKRing
::
flush_internal_tx_ring
(
TXInternalQueue
&
iqueue
)
ToDPDKRing
::
flush_internal_tx_ring
(
DPDKDevice
::
TXInternalQueue
&
iqueue
)
{
unsigned
n
;
unsigned
sent
=
0
;
...
...
@@ -217,7 +217,7 @@ void
ToDPDKRing
::
push
(
int
,
Packet
*
p
)
{
// Get the internal queue
TXInternalQueue
&
iqueue
=
_iqueue
;
DPDKDevice
::
TXInternalQueue
&
iqueue
=
_iqueue
;
bool
congestioned
;
do
{
...
...
@@ -277,7 +277,7 @@ void
ToDPDKRing
::
push_batch
(
int
,
PacketBatch
*
head
)
{
// Get the internal queue
TXInternalQueue
&
iqueue
=
_iqueue
;
DPDKDevice
::
TXInternalQueue
&
iqueue
=
_iqueue
;
Packet
*
p
=
head
;
Packet
*
next
=
NULL
;
...
...
elements/userlevel/todpdkring.hh
View file @
266d542a
...
...
@@ -133,34 +133,11 @@ class ToDPDKRing : public BatchElement, DPDKRing {
void
push
(
int
port
,
Packet
*
p
);
private:
/*
* TXInternalQueue is a ring of DPDK buffers pointers (rte_mbuf *) awaiting
* to be sent. It is used as an internal buffer to be passed to DPDK ring
* queue.
* |-> index is the index of the first valid packet awaiting to be sent, while
* nr_pending is the number of packets.
* |-> index + nr_pending may be greater than
* _internal_tx_queue_size but index should be wrapped-around.
*/
class
TXInternalQueue
{
public:
TXInternalQueue
()
:
pkts
(
0
),
index
(
0
),
nr_pending
(
0
)
{
}
// Array of DPDK Buffers
struct
rte_mbuf
**
pkts
;
// Index of the first valid packet in the packets array
unsigned
int
index
;
// Number of valid packets awaiting to be sent after index
unsigned
int
nr_pending
;
// Timer to limit time a batch will take to be completed
Timer
timeout
;
}
__attribute__
((
aligned
(
64
)));
inline
void
set_flush_timer
(
TXInternalQueue
&
iqueue
);
void
flush_internal_tx_ring
(
TXInternalQueue
&
iqueue
);
TXInternalQueue
_iqueue
;
inline
void
set_flush_timer
(
DPDKDevice
::
TXInternalQueue
&
iqueue
);
void
flush_internal_tx_ring
(
DPDKDevice
::
TXInternalQueue
&
iqueue
);
DPDKDevice
::
TXInternalQueue
_iqueue
;
unsigned
int
_internal_tx_queue_size
;
...
...
include/click/dpdkdevice.hh
View file @
266d542a
...
...
@@ -32,6 +32,19 @@
#include <click/vector.hh>
#include <click/args.hh>
#include <click/etheraddress.hh>
#include <click/timer.hh>
/**
* Unified type for DPDK port IDs.
* Until DPDK v17.05 was uint8_t
* After DPDK v17.05 has been uint16_t
*/
#ifndef PORTID_T_DEFINED
#define PORTID_T_DEFINED
typedef
uint8_t
portid_t
;
#else
// Already defined in <testpmd.h>
#endif
CLICK_DECLS
class
DPDKDeviceArg
;
...
...
@@ -47,35 +60,71 @@ extern bool dpdk_enabled;
class
DPDKDevice
{
public:
unsigned
port_id
;
portid_t
port_id
;
DPDKDevice
()
CLICK_COLD
;
DPDKDevice
(
portid_t
port_id
)
CLICK_COLD
;
struct
DevInfo
{
inline
DevInfo
()
:
vendor_id
(
PCI_ANY_ID
),
vendor_name
(),
device_id
(
PCI_ANY_ID
),
driver
(
0
),
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
);
}
void
print_device_info
()
{
click_chatter
(
" Vendor ID: %d"
,
vendor_id
);
click_chatter
(
" Vendor Name: %s"
,
vendor_name
.
c_str
());
click_chatter
(
" Device ID: %d"
,
device_id
);
click_chatter
(
" Driver Name: %s"
,
driver
);
click_chatter
(
"Promisc Mode: %s"
,
promisc
?
"true"
:
"false"
);
click_chatter
(
" MAC Address: %s"
,
init_mac
.
unparse
().
c_str
());
click_chatter
(
"# of Rx Queues: %d"
,
rx_queues
.
size
());
click_chatter
(
"# of Tx Queues: %d"
,
tx_queues
.
size
());
click_chatter
(
"# of Rx Descs: %d"
,
n_rx_descs
);
click_chatter
(
"# of Tx Descs: %d"
,
n_tx_descs
);
}
DPDKDevice
();
DPDKDevice
(
unsigned
port_id
);
uint16_t
vendor_id
;
String
vendor_name
;
uint16_t
device_id
;
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
;
};
int
add_rx_queue
(
unsigned
&
queue_id
,
bool
promisc
,
unsigned
n_desc
,
ErrorHandler
*
errh
)
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
;
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
();
uint16_t
get_device_vendor_id
();
String
get_device_vendor_name
();
uint16_t
get_device_id
();
const
char
*
get_device_driver
();
static
struct
rte_mempool
*
get_mpool
(
unsigned
int
);
static
int
get_port_numa_node
(
unsigned
port_id
);
static
int
get_port_numa_node
(
portid_t
port_id
);
static
int
initialize
(
ErrorHandler
*
errh
);
...
...
@@ -97,7 +146,7 @@ public:
static
void
free_pkt
(
unsigned
char
*
,
size_t
,
void
*
pktmbuf
);
static
unsigned
int
get_nb_txdesc
(
unsigned
port_id
);
static
unsigned
int
get_nb_txdesc
(
const
portid_t
&
port_id
);
static
int
NB_MBUF
;
static
int
MBUF_DATA_SIZE
;
...
...
@@ -117,71 +166,62 @@ public:
static
unsigned
DEF_RING_NDESC
;
static
unsigned
DEF_BURST_SIZE
;
static
unsigned
RING_FLAGS
;
static
unsigned
RING_SIZE
;
static
unsigned
RING_POOL_CACHE_SIZE
;
static
unsigned
RING_PRIV_DATA_SIZE
;
static
struct
rte_mempool
**
_pktmbuf_pools
;
private:
enum
Dir
{
RX
,
TX
};
/*
* TXInternalQueue is a ring of DPDK buffers pointers (rte_mbuf *) awaiting
* to be sent. It is used as an internal buffer to be passed to DPDK ring
* queue.
* |-> index is the index of the first valid packet awaiting to be sent, while
* nr_pending is the number of packets.
* |-> index + nr_pending may be greater than
* _internal_tx_queue_size but index should be wrapped-around.
*/
class
TXInternalQueue
{
public:
TXInternalQueue
()
:
pkts
(
0
),
index
(
0
),
nr_pending
(
0
)
{
}
// Array of DPDK Buffers
struct
rte_mbuf
**
pkts
;
// Index of the first valid packet in the packets array
unsigned
int
index
;
// Number of valid packets awaiting to be sent after index
unsigned
int
nr_pending
;
// Timer to limit time a batch will take to be completed
Timer
timeout
;
}
__attribute__
((
aligned
(
64
)));
struct
DevInfo
{
inline
DevInfo
()
:
vendor_id
(
PCI_ANY_ID
),
vendor_name
(),
device_id
(
PCI_ANY_ID
),
driver
(
0
),
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
);
}
void
print_device_info
()
{
click_chatter
(
" Vendor ID: %d"
,
vendor_id
);
click_chatter
(
" Vendor Name: %s"
,
vendor_name
.
c_str
());
click_chatter
(
" Device ID: %d"
,
device_id
);
click_chatter
(
" Driver Name: %s"
,
driver
);
click_chatter
(
"Promisc Mode: %s"
,
promisc
?
"true"
:
"false"
);
click_chatter
(
" MAC Address: %s"
,
init_mac
.
unparse
().
c_str
());
click_chatter
(
"# of Rx Queues: %d"
,
rx_queues
.
size
());
click_chatter
(
"# of Tx Queues: %d"
,
tx_queues
.
size
());
click_chatter
(
"# of Rx Descs: %d"
,
n_rx_descs
);
click_chatter
(
"# of Tx Descs: %d"
,
n_tx_descs
);
}
private:
uint16_t
vendor_id
;
String
vendor_name
;
uint16_t
device_id
;
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
;
};
enum
Dir
{
RX
,
TX
};
struct
DevInfo
info
;
static
bool
_is_initialized
;
static
HashTable
<
unsigned
,
DPDKDevice
>
_devs
;
static
int
_nr_pktmbuf_pools
;
static
HashTable
<
portid_t
,
DPDKDevice
>
_devs
;
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
int
alloc_pktmbufs
()
CLICK_COLD
;
static
DPDKDevice
*
get_device
(
unsigned
port_id
)
{
return
&
(
_devs
.
find_insert
(
port_id
,
DPDKDevice
(
port_id
)).
value
());
static
DPDKDevice
*
get_device
(
const
portid_t
&
port_id
)
{
return
&
(
_devs
.
find_insert
(
port_id
,
DPDKDevice
(
port_id
)).
value
());
}
static
int
get_port_from_pci
(
uint
16
_t
domain
,
uint8_t
bus
,
uint8_t
dev_id
,
uint8_t
function
)
{
static
int
get_port_from_pci
(
uint
32
_t
domain
,
uint8_t
bus
,
uint8_t
dev_id
,
uint8_t
function
)
{
struct
rte_eth_dev_info
dev_info
;
for
(
uint8
_t
port_id
=
0
;
port_id
<
rte_eth_dev_count
();
++
port_id
)
{
for
(
portid
_t
port_id
=
0
;
port_id
<
rte_eth_dev_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
&&
...
...
lib/dpdkdevice.cc
View file @
266d542a
/*
* dpdkdevice.{cc,hh} -- library for interfacing with
Intel's
DPDK
* Cyril Soldani, Tom Barbette
* dpdkdevice.{cc,hh} -- library for interfacing with DPDK
* Cyril Soldani, Tom Barbette
, Georgios Katsikas
*
* Copyright (c) 2014-2016 University of Liege
* Copyright (c) 2016 Cisco Meraki
* Copyright (c) 2017 RISE SICS
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
...
...
@@ -17,8 +18,8 @@
*/
#include <click/config.h>
#include <click/dpdkdevice.hh>
#include <click/element.hh>
#include <click/dpdkdevice.hh>
#include <click/userutils.hh>
#include <rte_errno.h>
...
...
@@ -27,7 +28,7 @@ CLICK_DECLS
DPDKDevice
::
DPDKDevice
()
:
port_id
(
-
1
),
info
()
{
}
DPDKDevice
::
DPDKDevice
(
unsigned
port_id
)
:
port_id
(
port_id
)
{
DPDKDevice
::
DPDKDevice
(
portid_t
port_id
)
:
port_id
(
port_id
)
{
};
uint16_t
DPDKDevice
::
get_device_vendor_id
()
...
...
@@ -52,7 +53,7 @@ const char *DPDKDevice::get_device_driver()
/* Wraps rte_eth_dev_socket_id(), which may return -1 for valid ports when NUMA
* is not well supported. This function will return 0 instead in that case. */
int
DPDKDevice
::
get_port_numa_node
(
unsigned
port_id
)
int
DPDKDevice
::
get_port_numa_node
(
portid_t
port_id
)
{
if
(
port_id
>=
rte_eth_dev_count
())
return
-
1
;
...
...
@@ -66,16 +67,20 @@ unsigned int DPDKDevice::get_nb_txdesc()
}
/**
* This function is called by DPDK when Click run as a secondary process. It
* checks that the prefix match with the given config prefix and add it if it does so.
* This function is called by DPDK when Click runs as a secondary process.
* It checks that the prefix matches with the given config prefix and adds
* it if it does so.
*/
#if RTE_VERSION >= RTE_VERSION_NUM(16,07,0,0)
void
add_pool
(
struct
rte_mempool
*
rte
,
void
*
arg
){
void
add_pool
(
struct
rte_mempool
*
rte
,
void
*
arg
){
#else
void
add_pool
(
const
struct
rte_mempool
*
rte
,
void
*
arg
){
void
add_pool
(
const
struct
rte_mempool
*
rte
,
void
*
arg
){
#endif
int
*
i
=
(
int
*
)
arg
;
if
(
strncmp
(
DPDKDevice
::
MEMPOOL_PREFIX
.
c_str
(),
const_cast
<
struct
rte_mempool
*>
(
rte
)
->
name
,
DPDKDevice
::
MEMPOOL_PREFIX
.
length
())
!=
0
)
int
*
i
=
(
int
*
)
arg
;
if
(
strncmp
(
DPDKDevice
::
MEMPOOL_PREFIX
.
c_str
(),
const_cast
<
struct
rte_mempool
*>
(
rte
)
->
name
,
DPDKDevice
::
MEMPOOL_PREFIX
.
length
())
!=
0
)
return
;
DPDKDevice
::
_pktmbuf_pools
[
*
i
]
=
const_cast
<
struct
rte_mempool
*>
(
rte
);
click_chatter
(
"Found DPDK primary pool #%d %s"
,
*
i
,
DPDKDevice
::
_pktmbuf_pools
[
*
i
]
->
name
);
...
...
@@ -87,13 +92,13 @@ int core_to_numa_node(unsigned lcore_id) {
return
(
numa_node
<
0
)
?
0
:
numa_node
;
}
bool
DPDKDevice
::
alloc_pktmbufs
()
int
DPDKDevice
::
alloc_pktmbufs
()
{
/* Count NUMA sockets for each device and each node, we do not want to
* allocate a unused pool
*/
int
max_socket
=
-
1
;
for
(
HashTable
<
unsigned
,
DPDKDevice
>::
const_iterator
it
=
_devs
.
begin
();
for
(
HashTable
<
portid_t
,
DPDKDevice
>::
const_iterator
it
=
_devs
.
begin
();
it
!=
_devs
.
end
();
++
it
)
{
int
numa_node
=
DPDKDevice
::
get_port_numa_node
(
it
.
key
());
if
(
numa_node
>
max_socket
)
...
...
@@ -134,7 +139,8 @@ bool DPDKDevice::alloc_pktmbufs()
// Create a pktmbuf pool for each active socket
for
(
int
i
=
0
;
i
<
_nr_pktmbuf_pools
;
i
++
)
{
if
(
!
_pktmbuf_pools
[
i
])
{
const
char
*
name
=
(
DPDKDevice
::
MEMPOOL_PREFIX
+
String
(
i
)).
c_str
();
String
mempool_name
=
DPDKDevice
::
MEMPOOL_PREFIX
+
String
(
i
);
const
char
*
name
=
mempool_name
.
c_str
();
_pktmbuf_pools
[
i
]
=
#if RTE_VERSION >= RTE_VERSION_NUM(2,2,0,0)
rte_pktmbuf_pool_create
(
name
,
NB_MBUF
,
...
...
@@ -148,19 +154,19 @@ bool DPDKDevice::alloc_pktmbufs()
#endif
if
(
!
_pktmbuf_pools
[
i
])
return
false
;
return
rte_errno
;
}
}
}
else
{
int
i
=
0
;
rte_mempool_walk
(
add_pool
,(
void
*
)
&
i
);
int
i
=
0
;
rte_mempool_walk
(
add_pool
,(
void
*
)
&
i
);
if
(
i
==
0
)
{
click_chatter
(
"Could not get pools from the primary DPDK process"
);
return
false
;
click_chatter
(
"Could not get pools from the primary DPDK process"
);
return
-
1
;
}
}
return
true
;
return
0
;
}
struct
rte_mempool
*
DPDKDevice
::
get_mpool
(
unsigned
int
socket_id
)
{
...
...
@@ -272,11 +278,29 @@ int DPDKDevice::initialize_device(ErrorHandler *errh)
}
int
ret
;
if
((
ret
=
rte_eth_dev_configure
(
port_id
,
info
.
rx_queues
.
size
(),
info
.
tx_queues
.
size
(),
&
dev_conf
))
<
0
)
if
(
ret
=
rte_eth_dev_configure
(
port_id
,
info
.
rx_queues
.
size
(),
info
.
tx_queues
.
size
(),
&
dev_conf
)
<
0
)
return
errh
->
error
(
"Cannot initialize DPDK port %u with %u RX and %u TX queues.
\n
Error %d : %s"
,
port_id
,
info
.
rx_queues
.
size
(),
info
.
tx_queues
.
size
(),
ret
,
strerror
(
ret
));
"Cannot initialize DPDK port %u with %u RX and %u TX queues
\n
Error %d : %s"
,
port_id
,
info
.
rx_queues
.
size
(),
info
.
tx_queues
.
size
(),
ret
,
strerror
(
ret
));
rte_eth_dev_info_get
(
port_id
,
&
dev_info
);
#if RTE_VERSION >= RTE_VERSION_NUM(16,07,0,0)
if
(
dev_info
.
nb_rx_queues
!=
info
.
rx_queues
.
size
())
{
return
errh
->
error
(
"Device only initialized %d RX queues instead of %d. "
"Please check configuration."
,
dev_info
.
nb_rx_queues
,
info
.
rx_queues
.
size
());
}
if
(
dev_info
.
nb_tx_queues
!=
info
.
tx_queues
.
size
())
{
return
errh
->
error
(
"Device only initialized %d TX queues instead of %d. "
"Please check configuration."
,
dev_info
.
nb_tx_queues
,
info
.
tx_queues
.
size
());
}
#endif
struct
rte_eth_rxconf
rx_conf
;