📄 touserdevice.hh
字号:
#ifndef CLICK_TOUSERDEVICE_HH#define CLICK_TOUSERDEVICE_HH#include <click/element.hh>#include <click/etheraddress.hh>#include <click/timer.hh>#include <click/notifier.hh>#include <linux/fs.h>#include <asm/types.h>#include <click/cxxprotect.h>CLICK_CXX_PROTECT#include <linux/netdevice.h>#include <linux/route.h>CLICK_CXX_UNPROTECT#include <click/cxxunprotect.h>/*=cToUserDevice(DEV_MINOR, [<keywords> CAPACITY, BURST])=s netdevicesWrites packets from the click into a device's ring buffer, which can bethen read by a userlevel application.=dRequires --enable-experimental.Keyword arguments are:=over 8=item CAPACITYUnsigned integer. Sets the capacity of the internal ring buffer that storesthe packets.=item BURSTSets the maximum number of packets returned per multipacket read. Default is0, which means no limit.=backThe device must be first created in the /dev directoryvia mknod /dev/fromclickX c 241 X where X is the minor device number (i.e. 0, 1, 2)A user level application can then read directly from the device once it opens a file/dev/fromclickXThe user level application must know what sort of packets are written into the device. (i.e.Eth frames, IP packets, etc.)=n=e ... -> ToUserDevice(0, CAPACITY 200);Example how to read from the element in a userprogram when multimode is enabled. unsigned char buffer[BUFFERLEN]; ssize_t readlen = read(fd, buffer, BUFFERLEN); for (ssize_t pos = 0; pos < readlen; ) { int len = *(int*)(buffer + pos); pos += sizeof(int); int stored_len = (len <= readlen - pos ? len : readlen - pos); // At this point "buffer + pos" contains a packet that was "len" // bytes long. "stored_len" of those bytes are in the buffer. process_packet(buffer + pos, len, stored_len); // shift to next packet pos += stored_len; if (pos % sizeof(int)) pos += sizeof(int) - pos % sizeof(int); }=aToUserDevice */class ToUserDevice : public Element{public: ToUserDevice(); ~ToUserDevice(); static void static_initialize(); static void static_cleanup(); const char *class_name() const { return "ToUserDevice"; } const char *port_count() const { return PORTS_1_0; } const char *processing() const { return PUSH; } int configure(Vector<String> &, ErrorHandler *); bool process(Packet *); bool run_task(Task *); int initialize(ErrorHandler *); void cleanup(CleanupStage); void add_handlers(); void push(int, Packet *); static String read_handler(Element *e, void *thunk);private: enum { default_capacity = 64 }; Packet ** _q; uint32_t _size; uint32_t _r_slot; // where we read from uint32_t _w_slot; // where we write to uint32_t _capacity; spinlock_t _lock; ulong _read_count; ulong _pkt_read_count; ulong _pkt_count; ulong _drop_count; ulong _block_count; unsigned _max_burst; atomic_uint32_t _failed_count; Task _task; NotifierSignal _signal; volatile bool _exit; // related to device management String _devname; ulong _dev_major; ulong _dev_minor; wait_queue_head_t _proc_queue; ulong _sleep_proc; static struct file_operations *dev_fops; static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *ppos); static int dev_open(struct inode *inode, struct file *filp); static int dev_release(struct inode *inode, struct file *file); static uint dev_poll(struct file *, struct poll_table_struct *); static int dev_ioctl(struct inode *inode, struct file *filp, unsigned command, unsigned long address);};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -