📄 element.hh
字号:
// -*- c-basic-offset: 4; related-file-name: "../../lib/element.cc" -*-#ifndef CLICK_ELEMENT_HH#define CLICK_ELEMENT_HH#include <click/glue.hh>#include <click/vector.hh>#include <click/string.hh>#include <click/packet.hh>CLICK_DECLSclass Router;class Master;class Task;class Element;class ErrorHandler;class Bitvector;class Handler;// #define CLICK_STATS 5typedef int (*HandlerHook)(int operation, String&, Element*, const Handler*, ErrorHandler*);typedef String (*ReadHandler)(Element*, void*);typedef int (*WriteHandler)(const String&, Element*, void*, ErrorHandler*);class Element { public: Element(); Element(int ninputs, int noutputs); virtual ~Element(); static int nelements_allocated; static void static_initialize() { } static void static_cleanup() { } // RUNTIME virtual void push(int port, Packet*); virtual Packet* pull(int port); virtual Packet* simple_action(Packet*); virtual bool run_task(); // return true iff did useful work virtual void run_timer();#if CLICK_USERLEVEL virtual void selected(int fd);#endif virtual void run_scheduled(); // deprecated, use run_{task,timer}() // CHARACTERISTICS virtual const char* class_name() const = 0; virtual void* cast(const char*); String id() const; String declaration() const; String landmark() const; Router* router() const { return _router; } Master* master() const; int eindex() const { return _eindex; } inline int eindex(Router*) const; // INPUTS AND OUTPUTS inline int nports(bool isoutput) const { return _nports[isoutput]; } int ninputs() const { return _nports[0]; } int noutputs() const { return _nports[1]; } void set_ninputs(int); void set_noutputs(int); void add_input() { set_ninputs(ninputs()+1); } void add_output() { set_noutputs(noutputs()+1); } bool ports_frozen() const; class Port; inline const Port& port(bool isoutput, int) const; inline const Port& input(int) const; inline const Port& output(int) const; inline bool port_allowed(bool isoutput, int) const; inline bool input_is_push(int) const; inline bool input_is_pull(int) const; inline bool output_is_push(int) const; inline bool output_is_pull(int) const; inline void checked_output_push(int, Packet*) const; // PROCESSING, FLOW, AND FLAGS virtual const char* processing() const; static const char AGNOSTIC[]; static const char PUSH[]; static const char PULL[]; static const char PUSH_TO_PULL[]; static const char PULL_TO_PUSH[]; virtual const char* flow_code() const; static const char COMPLETE_FLOW[]; virtual const char* flags() const; // CONFIGURATION AND INITIALIZATION virtual void notify_ninputs(int); virtual void notify_noutputs(int); enum ConfigurePhase { CONFIGURE_PHASE_FIRST = 0, CONFIGURE_PHASE_INFO = 20, CONFIGURE_PHASE_PRIVILEGED = 90, CONFIGURE_PHASE_DEFAULT = 100, CONFIGURE_PHASE_LAST = 2000 }; virtual int configure_phase() const; virtual int configure(Vector<String>&, ErrorHandler*); virtual int initialize(ErrorHandler*); // CLEANUP enum CleanupStage { CLEANUP_NO_ROUTER, CLEANUP_CONFIGURE_FAILED, CLEANUP_CONFIGURED, CLEANUP_INITIALIZE_FAILED, CLEANUP_INITIALIZED, CLEANUP_ROUTER_INITIALIZED, CLEANUP_MANUAL }; virtual void cleanup(CleanupStage); // LIVE RECONFIGURATION, HOTSWAP virtual void configuration(Vector<String>&) const; String configuration() const; virtual bool can_live_reconfigure() const; virtual int live_reconfigure(Vector<String>&, ErrorHandler*); virtual Element* hotswap_element() const; virtual void take_state(Element*, ErrorHandler*); // HANDLERS virtual void add_handlers(); void add_read_handler(const String&, ReadHandler, void*); void add_write_handler(const String&, WriteHandler, void*); void set_handler(const String&, int flags, HandlerHook, void* = 0, void* = 0); void add_task_handlers(Task*, const String& prefix = String()); static String read_positional_handler(Element*, void*); static String read_keyword_handler(Element*, void*); static int reconfigure_positional_handler(const String&, Element*, void*, ErrorHandler*); static int reconfigure_keyword_handler(const String&, Element*, void*, ErrorHandler*); virtual int llrpc(unsigned command, void* arg); int local_llrpc(unsigned command, void* arg); #if CLICK_USERLEVEL // SELECT enum { SELECT_READ = 1, SELECT_WRITE = 2 }; int add_select(int fd, int mask); int remove_select(int fd, int mask);#endif // METHODS USED BY ROUTER void attach_router(Router* r, int n) { _router = r; _eindex = n; } enum Processing { VAGNOSTIC, VPUSH, VPULL }; void processing_vector(int* input_codes, int* output_codes, ErrorHandler*) const; void port_flow(bool isoutput, int, Bitvector*) const; void initialize_ports(const int* input_codes, const int* output_codes); int connect_port(bool isoutput, int port, Element*, int); void add_default_handlers(bool writable_config);#if CLICK_STATS >= 2 // STATISTICS int _calls; // Push and pull calls into this element. uint64_t _self_cycles; // Cycles spent in self and children. uint64_t _child_cycles; // Cycles spent in children.#endif class Port { public: inline Port(); inline Port(Element*, Element*, int); operator bool() const { return _e != 0; } bool allowed() const { return _port >= 0; } bool initialized() const { return _port >= -1; } Element* element() const { return _e; } int port() const { return _port; } inline void push(Packet* p) const; inline Packet* pull() const;#if CLICK_STATS >= 1 unsigned npackets() const { return _packets; }#endif private: Element* _e; int _port; #if CLICK_STATS >= 1 mutable unsigned _packets; // How many packets have we moved?#endif#if CLICK_STATS >= 2 Element* _owner; // Whose input or output are we?#endif }; private: enum { INLINE_PORTS = 4 }; Port* _ports[2]; Port _inline_ports[INLINE_PORTS]; int _nports[2]; Router* _router; int _eindex; Element(const Element &); Element &operator=(const Element &); void set_nports(int, int); };inline intElement::eindex(Router* r) const{ return (router() == r ? eindex() : -1);}inline const Element::Port&Element::port(bool isoutput, int p) const{ assert((unsigned) p < (unsigned) _nports[isoutput]); return _ports[isoutput][p];}inline const Element::Port&Element::input(int p) const{ return port(false, p);}inline const Element::Port&Element::output(int p) const{ return port(true, p);}inline boolElement::port_allowed(bool isoutput, int p) const{ return (unsigned) p < (unsigned) nports(isoutput) && _ports[isoutput][p].allowed();}inline boolElement::output_is_push(int p) const{ return port_allowed(true, p);}inline boolElement::output_is_pull(int p) const{ return (unsigned) p < (unsigned) nports(true) && !_ports[1][p].allowed();}inline boolElement::input_is_pull(int p) const{ return port_allowed(false, p);}inline boolElement::input_is_push(int p) const{ return (unsigned) p < (unsigned) nports(false) && !_ports[0][p].allowed();}#if CLICK_STATS >= 2# define PORT_CTOR_INIT(o) , _packets(0), _owner(o)#else# if CLICK_STATS >= 1# define PORT_CTOR_INIT(o) , _packets(0)# else# define PORT_CTOR_INIT(o)# endif#endifinlineElement::Port::Port() : _e(0), _port(-2) PORT_CTOR_INIT(0){}inlineElement::Port::Port(Element* owner, Element* e, int p) : _e(e), _port(p) PORT_CTOR_INIT(owner){ (void) owner;}inline voidElement::Port::push(Packet* p) const{ assert(_e);#if CLICK_STATS >= 1 _packets++;#endif#if CLICK_STATS >= 2 _e->input(_port)._packets++; uint64_t c0 = click_get_cycles(); _e->push(_port, p); uint64_t c1 = click_get_cycles(); uint64_t x = c1 - c0; _e->_calls += 1; _e->_self_cycles += x; _owner->_child_cycles += x;#else _e->push(_port, p);#endif}inline Packet*Element::Port::pull() const{ assert(_e);#if CLICK_STATS >= 2 _e->output(_port)._packets++; uint64_t c0 = click_get_cycles(); Packet *p = _e->pull(_port); uint64_t c1 = click_get_cycles(); uint64_t x = c1 - c0; _e->_calls += 1; _e->_self_cycles += x; _owner->_child_cycles += x;#else Packet* p = _e->pull(_port);#endif#if CLICK_STATS >= 1 if (p) _packets++;#endif return p;}inline voidElement::checked_output_push(int port, Packet* p) const{ if ((unsigned) port < (unsigned) noutputs()) _ports[1][port].push(p); else p->kill();}#undef CONNECTION_CTOR_INITCLICK_ENDDECLS#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -