22#ifndef CLICK_NETMAPDEVICE_HH
23#define CLICK_NETMAPDEVICE_HH
25#if HAVE_NETMAP && CLICK_USERLEVEL
27#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
31#include <net/netmap.h>
32#define NETMAP_WITH_LIBS 1
33#include <net/netmap_user.h>
39#include <click/ring.hh>
41#include <click/hashmap.hh>
43#include <click/args.hh>
49#define CLICK_NETMAP_POOL_DEBUG 0
51#define NETMAP_PACKET_POOL_SIZE 2048
52#define BUFFER_PTR(idx) reinterpret_cast<uint32_t *>(buf_start + idx * buf_size)
53#define BUFFER_NEXT_LIST(idx) *(((uint32_t*)BUFFER_PTR(idx)) + 1)
55#define CLICK_NETMAP_POOL_DEBUG_MAGIC(idx) (*(BUFFER_PTR(idx)+3))
56#define CLICK_NETMAP_POOL_DEBUG_MAGIC_VALUE 0b01011100010111000101110001011100
67 inline void insert(uint32_t idx);
68 inline void insert_p(
unsigned char *p);
69 inline void insert_all(uint32_t idx,
bool check_size);
71 inline uint32_t extract();
72 inline unsigned char * extract_p();
74 inline int count_buffers(uint32_t idx);
76 inline int count()
const {
81 static int static_initialize(
struct nm_desc* nmd);
82 static uint32_t static_cleanup();
84 static void global_insert_all(uint32_t idx,
int count);
86 inline static unsigned int buffer_size() {
90 static void buffer_destructor(
unsigned char *buf,
size_t,
void *) {
91 NetmapBufQ::local_pool()->insert_p(buf);
94 inline static bool is_netmap_packet(
Packet* p) {
95 return (p->buffer_destructor() == buffer_destructor ||
96 (p->
buffer() > NetmapBufQ::buf_start && p->
buffer() < NetmapBufQ::buf_end));
99 inline static bool is_valid_netmap_buffer(
void* data) {
100 return (data > NetmapBufQ::buf_start && data < NetmapBufQ::buf_end);
103 inline static bool is_valid_netmap_packet(
Packet* p) {
104 return (p->
buffer() > NetmapBufQ::buf_start && p->
buffer() < NetmapBufQ::buf_end);
107 inline static NetmapBufQ* local_pool() {
108 return NetmapBufQ::netmap_buf_pools[click_current_cpu_id()];
111 static inline bool initialized() {
112 return netmap_buf_pools != 0;
116 return find_count(_head) == _count;
119 static int find_count(uint32_t cur,
int limit = 65536) {
123 uint32_t* p = BUFFER_PTR(cur);
135 static unsigned char *buf_start;
136 static unsigned char *buf_end;
137 static unsigned int buf_size;
138 static uint32_t max_index;
143 static uint32_t global_buffer_list;
145 static int messagelimit;
146 static NetmapBufQ** netmap_buf_pools;
148} __attribute__((aligned(64)));
156 NetmapDevice(
String ifname) CLICK_COLD;
157 ~NetmapDevice() CLICK_COLD;
159 int initialize() CLICK_COLD;
160 void destroy() CLICK_COLD;
164 struct nm_desc* parent_nmd;
165 Vector<struct nm_desc*> nmds;
170#if HAVE_NETMAP_PACKET_POOL
171 static WritablePacket* make_netmap(
unsigned char* data,
struct netmap_ring* rxring,
struct netmap_slot* slot);
173 static PacketBatch* make_netmap_batch(
unsigned int n,
struct netmap_ring* rxring,
unsigned int &cur);
176 static NetmapDevice* open(
String ifname);
177 static void static_cleanup();
178 static struct nm_desc* some_nmd;
179 static int global_alloc;
184 int get_num_slots() {
185 return some_nmd->some_ring->num_slots;
189 static HashMap<String,NetmapDevice*> nics;
198inline void NetmapBufQ::expand() {
199 global_buffer_lock.acquire();
200 if (global_buffer_list != 0) {
202 _head = global_buffer_list;
203 global_buffer_list = BUFFER_NEXT_LIST(global_buffer_list);
204 _count = NETMAP_PACKET_POOL_SIZE;
207 click_chatter(
"Expanding buffer pool with %d new packets",NETMAP_PACKET_POOL_SIZE);
209 nbr.num = NETMAP_PACKET_POOL_SIZE;
211 if (ioctl(NetmapDevice::some_nmd->fd,NIOCALLOCBUF,&nbr) == 0) {
212 insert_all(nbr.head,
false);
216 if (messagelimit < 5)
217 click_chatter(
"No more netmap buffers !");
221 global_buffer_lock.release();
227inline void NetmapBufQ::insert_all(uint32_t idx,
bool check_size =
false) {
228 if (unlikely(idx >= max_index || idx == 0)) {
229 click_chatter(
"Error : cannot insert index %d",idx);
233 uint32_t firstidx = idx;
255int NetmapBufQ::count_buffers(uint32_t idx) {
259 idx = *BUFFER_PTR(idx);
264inline void NetmapBufQ::insert(uint32_t idx) {
265#if CLICK_NETMAP_POOL_DEBUG
266 assert(idx > 0 && idx < max_index);
267 assert(CLICK_NETMAP_POOL_DEBUG_MAGIC(idx) != CLICK_NETMAP_POOL_DEBUG_MAGIC_VALUE);
270 if (_count < NETMAP_PACKET_POOL_SIZE) {
271 *BUFFER_PTR(idx) = _head;
275#if CLICK_NETMAP_POOL_DEBUG
276 assert(_count == NETMAP_PACKET_POOL_SIZE);
277 assert(find_count(_head) == NETMAP_PACKET_POOL_SIZE);
279 global_buffer_lock.acquire();
280 BUFFER_NEXT_LIST(_head) = global_buffer_list;
281 global_buffer_list = _head;
282 global_buffer_lock.release();
284 *BUFFER_PTR(idx) = 0;
289inline void NetmapBufQ::insert_p(
unsigned char* buf) {
290 insert((buf - buf_start) / buf_size);
293inline uint32_t NetmapBufQ::extract() {
296 if (_count == 0)
return 0;
304 #if CLICK_NETMAP_POOL_DEBUG
305 CLICK_NETMAP_POOL_DEBUG_MAGIC(idx) = 0;
310inline unsigned char* NetmapBufQ::extract_p() {
311 uint32_t idx = extract();
312 return (idx == 0) ? 0 :
reinterpret_cast<unsigned char*
>(BUFFER_PTR(idx));
Definition packetbatch.hh:415
A network packet.
Definition packet.hh:68
const unsigned char * buffer() const
Return a pointer to the packet's data buffer.
Definition packet.hh:1243
A recursive spinlock for SMP Click threads.
Definition sync.hh:439
A string of characters.
Definition string.hh:22
Vector template.
Definition vector.hh:111
A network packet believed not to be shared.
Definition packet.hh:1004
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
Flexible error handling classes.
The Packet class models packets in Click.
Classes for synchronizing among multiple CPUs, particularly in the Linux kernel.
Click's vector container template.