Click
Loading...
Searching...
No Matches
element.hh
Go to the documentation of this file.
1// -*- c-basic-offset: 4; related-file-name: "../../lib/element.cc" -*-
2#ifndef CLICK_ELEMENT_HH
3#define CLICK_ELEMENT_HH
4#include <click/glue.hh>
5#include <click/vector.hh>
6#include <click/string.hh>
7#include <click/packet.hh>
8#include <click/packetbatch.hh>
9#include <click/handler.hh>
10#include <click/sync.hh>
11#include <functional>
12
13#ifdef HAVE_RAND_ALIGN
14#include <random>
15#endif
16
17CLICK_DECLS
18class Router;
19class Master;
20class RouterThread;
21class Task;
22class IdleTask;
23class Timer;
24class NotifierSignal;
25class Element;
26class ErrorHandler;
27class Bitvector;
28class EtherAddress;
29
30class BatchElement;
31
32#define BATCH_MAX_PULL 256
33
38#ifndef CLICK_ELEMENT_DEPRECATED
39# define CLICK_ELEMENT_DEPRECATED CLICK_DEPRECATED
40#endif
41
42class Element { public:
43
44 Element();
45 virtual ~Element();
46 static int nelements_allocated;
47
48 // RUNTIME
49 virtual void push(int port, Packet *p);
50 virtual Packet *pull(int port) CLICK_WARN_UNUSED_RESULT;
51 virtual Packet *simple_action(Packet *p);
52#if HAVE_BATCH
53 virtual void push_batch(int port, PacketBatch *p);
54 virtual PacketBatch* pull_batch(int port,unsigned max) CLICK_WARN_UNUSED_RESULT;
55#endif
56
57 virtual bool run_task(Task *task); // return true iff did useful work
58 virtual void run_timer(Timer *timer);
59 virtual bool run_idle_task(IdleTask *task);
60#if CLICK_USERLEVEL
61 enum { SELECT_READ = 1, SELECT_WRITE = 2 };
62 virtual void selected(int fd, int mask);
63 virtual void selected(int fd);
64#endif
65
66#ifdef HAVE_RAND_ALIGN
67
68 static int nalloc;
69 static std::mt19937 generator;
70// Overloading CLass specific new operator
71 inline static void* operator new(size_t sz)
72 {
73 char * env = getenv("CLICK_ELEM_RAND_MAX");
74 int max = 0;
75 if (env)
76 max = atoi(env);
77 max = max / alignof(Element);
78 int of;
79 if (max > 0) {
80 int rand = generator() / (generator.max() / max);
81 of = (rand) * alignof(Element);
82 } else {
83 of = 0;
84 }
85 void* m = aligned_alloc(alignof(Element), sz + of);
86 //click_chatter("EALLOC %d OF %d AL %d", sz, of, alignof(Element) );
87
88 //click_chatter("RESULT-EL%d %d", nalloc++, of );
89
90 // Generate an interrupt
91// std::raise(SIGINT);
92 return ((unsigned char*)m) + of;
93 }
94 static void* operator new(size_t sz, void* p)
95 {
96 return p;
97 }
98 // Overloading CLass specific delete operator
99 static void operator delete(void* m)
100 {
101 //Let's leak
102 }
103#endif
104
105 inline bool is_fullpush() const;
106 enum batch_mode {BATCH_MODE_NO, BATCH_MODE_IFPOSSIBLE, BATCH_MODE_NEEDED, BATCH_MODE_YES};
107
108 inline void checked_output_push(int port, Packet *p) const;
109 inline Packet* checked_input_pull(int port) const;
110
111 // ELEMENT CHARACTERISTICS
112 virtual const char *class_name() const = 0;
113
114 virtual const char *port_count() const;
115 static const char PORTS_0_0[];
116 static const char PORTS_0_1[];
117 static const char PORTS_1_0[];
118 static const char PORTS_1_1[];
119 static const char PORTS_1_1X2[];
120
121 virtual const char *processing() const;
122 static const char AGNOSTIC[];
123 static const char PUSH[];
124 static const char PULL[];
125 static const char PUSH_TO_PULL[];
126 static const char PULL_TO_PUSH[];
127 static const char PROCESSING_A_AH[];
128
129 virtual const char *flow_code() const;
130 static const char COMPLETE_FLOW[];
131
132 virtual const char *flags() const;
133 int flag_value(int flag) const;
134
135 virtual void *cast(const char *name);
136 virtual void *port_cast(bool isoutput, int port, const char *name);
137
138 // CONFIGURATION, INITIALIZATION, AND CLEANUP
139 enum ConfigurePhase {
140 CONFIGURE_PHASE_FIRST = 0,
141 CONFIGURE_PHASE_INFO = 20,
142 CONFIGURE_PHASE_PRIVILEGED = 90,
143 CONFIGURE_PHASE_DEFAULT = 100,
144 CONFIGURE_PHASE_LAST = 2000
145 };
146 virtual int configure_phase() const;
147
148 virtual int configure(Vector<String> &conf, ErrorHandler *errh);
149
150 virtual void add_handlers();
151
152 virtual int initialize(ErrorHandler *errh);
153
154 virtual void take_state(Element *old_element, ErrorHandler *errh);
155 virtual Element *hotswap_element() const;
156
157 enum CleanupStage {
158 CLEANUP_NO_ROUTER,
159 CLEANUP_BEFORE_CONFIGURE = CLEANUP_NO_ROUTER,
160 CLEANUP_CONFIGURE_FAILED,
161 CLEANUP_CONFIGURED,
162 CLEANUP_INITIALIZE_FAILED,
163 CLEANUP_INITIALIZED,
164 CLEANUP_THREAD_INITIALZE_FAILED,
165 CLEANUP_THREAD_INITIALIZED,
166 CLEANUP_ROUTER_INITIALIZED,
167 CLEANUP_MANUAL
168 };
169 virtual void cleanup(CleanupStage stage);
170
171 static inline void static_initialize();
172 static inline void static_cleanup();
173
174 // ELEMENT ROUTER CONNECTIONS
175 String name() const;
176 virtual String declaration() const;
177
178 inline Router *router() const;
179 inline int eindex() const;
180 inline int eindex(Router *r) const;
181
183 inline Master *master() const;
184
185 inline void attach_router(Router *r, int eindex) {
186 assert(!_router);
187 _router = r;
188 _eindex = eindex;
189 }
190
191 // INPUTS AND OUTPUTS
192 inline int nports(bool isoutput) const;
193 inline int ninputs() const;
194 inline int noutputs() const;
195
196 class Port;
197 inline const Port &port(bool isoutput, int port) const;
198 inline const Port &input(int port) const;
199 inline const Port &output(int port) const;
200
201 inline bool port_active(bool isoutput, int port) const;
202 inline bool input_is_push(int port) const;
203 inline bool input_is_pull(int port) const;
204 inline bool output_is_push(int port) const;
205 inline bool output_is_pull(int port) const;
206 void port_flow(bool isoutput, int port, Bitvector*) const;
207
208 // LIVE RECONFIGURATION
209 String configuration() const;
210
211 virtual bool can_live_reconfigure() const;
213
214 RouterThread *home_thread() const;
215
216 virtual bool get_spawning_threads(Bitvector& b, bool isoutput, int port);
217
218 Bitvector get_pushing_threads();
219 Bitvector get_passing_threads(bool forward, int port, Element* origin, bool &_is_fullpush, int level = 0, bool touching = false);
220 Bitvector get_passing_threads(Element* origin, int level = 0, bool touching = false);
221 Bitvector get_passing_threads(bool touching = false);
222
224
225 int home_thread_id() const;
226 virtual bool is_mt_safe();
227 virtual bool do_mt_safe_check(ErrorHandler*);
228 void add_remote_element(Element* e);
229
230 // This feature should be re-designed. I'm not sure a new stage is a good idea. The beginning of future/promise patterns is more interesting.
231 enum ThreadReconfigurationStage {
232 THREAD_INITIALIZE,
233 THREAD_RECONFIGURE_UP_PRE,
234 THREAD_RECONFIGURE_UP_POST,
235 THREAD_RECONFIGURE_DOWN_PRE,
236 THREAD_RECONFIGURE_DOWN_POST,
237 };
238
239 virtual int thread_configure(ThreadReconfigurationStage stage, ErrorHandler* errh, Bitvector threads);
240 void trigger_thread_reconfiguration(bool is_up, std::function<void()> ready, Bitvector threads);
241
242 //Deprecated name, implement get_spawning_threads
243 virtual bool get_runnable_threads(Bitvector&) final = delete;
244 virtual bool get_spawning_threads(Bitvector&) final = delete;
245
246#if CLICK_USERLEVEL
247 // SELECT
248 int add_select(int fd, int mask);
249 int remove_select(int fd, int mask);
250#endif
251
252 // HANDLERS
253 void add_read_handler(const String &name, ReadHandlerCallback read_callback, const void *user_data = 0, uint32_t flags = 0);
254 void add_read_handler(const String &name, ReadHandlerCallback read_callback, int user_data, uint32_t flags = 0);
255 void add_read_handler(const char *name, ReadHandlerCallback read_callback, int user_data = 0, uint32_t flags = 0);
256 void add_write_handler(const String &name, WriteHandlerCallback write_callback, const void *user_data = 0, uint32_t flags = 0);
257 void add_write_handler(const String &name, WriteHandlerCallback write_callback, int user_data, uint32_t flags = 0);
258 void add_write_handler(const char *name, WriteHandlerCallback write_callback, int user_data = 0, uint32_t flags = 0);
259 void set_handler(const String &name, int flags, HandlerCallback callback, const void *read_user_data = 0, const void *write_user_data = 0);
260 void set_handler(const String &name, int flags, HandlerCallback callback, int read_user_data, int write_user_data = 0);
261 void set_handler(const char *name, int flags, HandlerCallback callback, int read_user_data = 0, int write_user_data = 0);
262 int set_handler_flags(const String &name, int set_flags, int clear_flags = 0);
263 enum { TASKHANDLER_WRITE_SCHEDULED = 1,
264 TASKHANDLER_WRITE_TICKETS = 2,
265 TASKHANDLER_WRITE_HOME_THREAD = 4,
266 TASKHANDLER_WRITE_ALL = 7,
267 TASKHANDLER_DEFAULT = 6 };
268 void add_task_handlers(Task *task, NotifierSignal *signal, int flags, const String &prefix = String());
269 inline void add_task_handlers(Task *task, NotifierSignal *signal, const String &prefix = String()) {
270 add_task_handlers(task, signal, TASKHANDLER_DEFAULT, prefix);
271 }
272 inline void add_task_handlers(Task *task, const String &prefix = String()) {
273 add_task_handlers(task, 0, TASKHANDLER_DEFAULT, prefix);
274 }
275
276 void add_data_handlers(const char *name, int flags, uint8_t *data);
277 void add_data_handlers(const char *name, int flags, bool *data);
278 void add_data_handlers(const char *name, int flags, uint16_t *data);
279 void add_data_handlers(const char *name, int flags, int *data);
280 void add_data_handlers(const char *name, int flags, unsigned *data);
281 void add_data_handlers(const char *name, int flags, atomic_uint32_t *data);
282 void add_data_handlers(const char *name, int flags, long *data);
283 void add_data_handlers(const char *name, int flags, unsigned long *data);
284#if HAVE_LONG_LONG
285 void add_data_handlers(const char *name, int flags, long long *data);
286 void add_data_handlers(const char *name, int flags, unsigned long long *data);
287#endif
288 void add_net_order_data_handlers(const char *name, int flags, uint16_t *data);
289 void add_net_order_data_handlers(const char *name, int flags, uint32_t *data);
290#if HAVE_FLOAT_TYPES
291 void add_data_handlers(const char *name, int flags, double *data);
292#endif
293 void add_data_handlers(const char *name, int flags, String *data);
294 void add_data_handlers(const char *name, int flags, IPAddress *data);
295 void add_data_handlers(const char *name, int flags, EtherAddress *data);
296 void add_data_handlers(const char *name, int flags, Timestamp *data, bool is_interval = false);
297
298 static String read_positional_handler(Element*, void*);
299 static String read_keyword_handler(Element*, void*);
300 static int reconfigure_positional_handler(const String&, Element*, void*, ErrorHandler*);
301 static int reconfigure_keyword_handler(const String&, Element*, void*, ErrorHandler*);
302
303 virtual int llrpc(unsigned command, void* arg);
304 int local_llrpc(unsigned command, void* arg);
305
306 class Port { public:
307
308 inline bool active() const;
309 inline Element* element() const;
310 inline int port() const;
311
312 inline void push(Packet* p) const;
313 inline Packet* pull() const;
314#if HAVE_BATCH
315 inline void push_batch(PacketBatch* p) const;
316 inline PacketBatch* pull_batch(unsigned max) const;
317
318 inline void start_batch();
319 inline void end_batch();
320#endif
321#if HAVE_FLOW_DYNAMIC
322 inline void set_unstack(bool unstack) {
323 _unstack = unstack;
324 }
325 inline bool unstack() const {
326 return _unstack;
327 }
328#endif
329
330#if CLICK_STATS >= 1
331 unsigned npackets() const { return _packets; }
332#endif
333
334 inline void assign_peer(bool isoutput, Element *e, int port, bool unstack=false);
335
336 private:
337
338 Element* _e;
339 int _port;
340 #ifdef HAVE_AUTO_BATCH
341 per_thread<PacketBatch*> current_batch;
342 #endif
343#if HAVE_FLOW_DYNAMIC
344 bool _unstack;
345#endif
346
347#if HAVE_BOUND_PORT_TRANSFER
348 union {
349 void (*push)(Element *e, int port, Packet *p);
350 Packet *(*pull)(Element *e, int port);
351 } _bound;
352 union {
353#if HAVE_BATCH
354 void (*push_batch)(Element *e, int port, PacketBatch *p);
355 PacketBatch* (*pull_batch)(Element *e, int port, unsigned max);
356#endif
357 } _bound_batch;
358#endif
359
360#if CLICK_STATS >= 1
361 mutable unsigned _packets; // How many packets have we moved?
362#endif
363#if CLICK_STATS >= 2
364 Element* _owner; // Whose input or output are we?
365#endif
366
367 inline Port();
368 inline void assign_owner(bool isoutput, Element *owner, Element *e, int port, bool unstack=false);
369
370 friend class Element;
371 friend class BatchElement;
372
373 };
374
375 // DEPRECATED
377 String id() const CLICK_DEPRECATED;
378 String landmark() const CLICK_DEPRECATED;
381 protected:
382 enum batch_mode in_batch_mode;
383 bool receives_batch;
384
385 private:
386
387 enum { INLINE_PORTS = 4 };
388
389 Port* _ports[2];
390 Port _inline_ports[INLINE_PORTS];
391
392 int _nports[2];
393
394 Router* _router;
395 int _eindex;
396
397 Vector<Element*> _remote_elements;
398#if HAVE_FULLPUSH_NONATOMIC
399 bool _is_fullpush;
400#endif
401
402#if CLICK_STATS >= 2
403 // STATISTICS
404 unsigned _xfer_calls; // Push and pull calls into this element.
405 click_cycles_t _xfer_own_cycles; // Cycles spent in self from push and pull.
406 click_cycles_t _child_cycles; // Cycles spent in children.
407
408 unsigned _task_calls; // Calls to tasks owned by this element.
409 click_cycles_t _task_own_cycles; // Cycles spent in self from tasks.
410
411 unsigned _timer_calls; // Calls to timers owned by this element.
412 click_cycles_t _timer_own_cycles; // Cycles spent in self from timers.
413
414 inline void reset_cycles() {
415 _xfer_calls = _task_calls = _timer_calls = 0;
416 _xfer_own_cycles = _task_own_cycles = _timer_own_cycles = _child_cycles = 0;
417 }
418 static String read_cycles_handler(Element *, void *);
419 static int write_cycles_handler(const String &, Element *, void *, ErrorHandler *);
420#endif
421
422 Element(const Element &);
423 Element &operator=(const Element &);
424
425 // METHODS USED BY ROUTER
426 int set_nports(int, int);
427 int notify_nports(int, int, ErrorHandler *);
428 enum Processing { VAGNOSTIC, VPUSH, VPULL };
429 static int next_processing_code(const char*& p, ErrorHandler* errh);
430 void processing_vector(int* input_codes, int* output_codes, ErrorHandler*) const;
431
432 void initialize_ports(const int* input_codes, const int* output_codes);
433 int connect_port(bool isoutput, int port, Element*, int);
434
435 static String read_handlers_handler(Element *e, void *user_data);
436 void add_default_handlers(bool writable_config);
437 inline void add_data_handlers(const char *name, int flags, HandlerCallback callback, void *data);
438
439 friend class BatchElement;
440 friend class Router;
441#if CLICK_STATS >= 2
442 friend class Task;
443 friend class Master;
444 friend class TimerSet;
445# if CLICK_USERLEVEL
446 friend class SelectSet;
447# endif
448#endif
449
450};
451
452
480inline void
484
508inline void
512
514inline Router*
516{
517 return _router;
518}
519
523inline int
525{
526 return _eindex;
527}
528
532inline int
534{
535 return (router() == r ? _eindex : -1);
536}
537
540inline int
541Element::nports(bool isoutput) const
542{
543 return _nports[isoutput];
544}
545
547inline int
549{
550 return _nports[0];
551}
552
554inline int
556{
557 return _nports[1];
558}
559
565inline const Element::Port&
566Element::port(bool isoutput, int port) const
567{
568 assert((unsigned) port < (unsigned) _nports[isoutput]);
569 return _ports[isoutput][port];
570}
571
578inline const Element::Port&
579Element::input(int port) const
580{
581 return Element::port(false, port);
582}
583
590inline const Element::Port&
591Element::output(int port) const
592{
593 return Element::port(true, port);
594}
595
604inline bool
605Element::port_active(bool isoutput, int port) const
606{
607 return (unsigned) port < (unsigned) nports(isoutput)
608 && _ports[isoutput][port].active();
609}
610
614inline bool
616{
617 return port_active(true, port);
618}
619
623inline bool
625{
626 return (unsigned) port < (unsigned) nports(true)
627 && !_ports[1][port].active();
628}
629
633inline bool
635{
636 return port_active(false, port);
637}
638
642inline bool
644{
645 return (unsigned) port < (unsigned) nports(false)
646 && !_ports[0][port].active();
647}
648
649#if CLICK_STATS >= 2
650# define PORT_ASSIGN(o) _packets = 0; _owner = (o)
651#elif CLICK_STATS >= 1
652# define PORT_ASSIGN(o) _packets = 0; (void) (o)
653#else
654# define PORT_ASSIGN(o) (void) (o)
655#endif
656
657inline
658Element::Port::Port()
659 : _e(0), _port(-2)
660#if HAVE_FLOW_DYNAMIC
661 , _unstack(false)
662#endif
663{
664 PORT_ASSIGN(0);
665}
666#ifndef __clang__
667#pragma GCC diagnostic push
668#pragma GCC diagnostic ignored "-Wpmf-conversions"
669#endif
670inline void
671Element::Port::assign_peer(bool isoutput, Element *e, int port, bool unstack)
672{
673 _e = e;
674 _port = port;
675#if HAVE_FLOW_DYNAMIC
676 _unstack = unstack;
677#else
678 (void)unstack;
679#endif
680#ifdef HAVE_AUTO_BATCH
681 for (unsigned i = 0; i < current_batch.weight() ; i++)
682 current_batch.set_value(i,0);
683#endif
684 (void) isoutput;
685#if HAVE_BOUND_PORT_TRANSFER
686 if (e) {
687 if (isoutput) {
688 void (Element::*pusher)(int, Packet *) = &Element::push;
689 _bound.push = (void (*)(Element *, int, Packet *)) (e->*pusher);
690# if HAVE_BATCH
691 void (Element::*pushbatcher)(int, PacketBatch *) = &Element::push_batch;
692 _bound_batch.push_batch = (void (*)(Element *, int, PacketBatch *)) (e->*pushbatcher);
693# endif
694 } else {
695 Packet *(Element::*puller)(int) = &Element::pull;
696 _bound.pull = (Packet *(*)(Element *, int)) (e->*puller);
697# if HAVE_BATCH
698 PacketBatch *(Element::*pullbatcher)(int,unsigned) = &Element::pull_batch;
699 _bound_batch.pull_batch = (PacketBatch *(*)(Element *, int, unsigned)) (e->*pullbatcher);
700# endif
701 }
702 }
703#endif
704}
705#ifndef __clang__
706#pragma GCC diagnostic pop
707#endif
708inline void
709Element::Port::assign_owner(bool isoutput, Element *owner, Element *e, int port, bool unstack)
710{
711 PORT_ASSIGN(owner);
712 assign_peer(isoutput, e, port, unstack);
713}
714
719inline bool
721{
722 return _port >= 0;
723}
724
728inline Element*
730{
731 return _e;
732}
733
737inline int
739{
740 return _port;
741}
742
764inline void
766{
767 assert(_e && p);
768#if HAVE_FLOW_DYNAMIC
769 FlowControlBlock* tmp_stack = 0;
770 if (_unstack) {
771 tmp_stack = fcb_stack;
772 fcb_stack->release(1);
773 fcb_stack = 0;
774 }
775#endif
776#ifdef HAVE_AUTO_BATCH
777 if (likely(_e->in_batch_mode == BATCH_MODE_YES)) {
778 if (*current_batch != 0) {
779 if (*current_batch == (PacketBatch*)-1) {
780 *current_batch = PacketBatch::make_from_packet(p);
781 } else {
782 (*current_batch)->append_packet(p);
783 }
784 } else {
785 push_batch(PacketBatch::make_from_packet(p));
786 }
787 } else {
788 assert(!_e->receives_batch);
789#else
790 {
791#endif
792#if CLICK_STATS >= 1
793 ++_packets;
794#endif
795#if CLICK_STATS >= 2
796 ++_e->input(_port)._packets;
797 click_cycles_t start_cycles = click_get_cycles(),
798 start_child_cycles = _e->_child_cycles;
799# if HAVE_BOUND_PORT_TRANSFER
800 _bound.push(_e, _port, p);
801# else
802 _e->push(_port, p);
803# endif
804 click_cycles_t all_delta = click_get_cycles() - start_cycles,
805 own_delta = all_delta - (_e->_child_cycles - start_child_cycles);
806 _e->_xfer_calls += 1;
807 _e->_xfer_own_cycles += own_delta;
808 _owner->_child_cycles += all_delta;
809#else
810# if HAVE_BOUND_PORT_TRANSFER
811 _bound.push(_e, _port, p);
812# else
813 _e->push(_port, p);
814# endif
815#endif
816 }
817#if HAVE_FLOW_DYNAMIC
818 if (_unstack) {
819 fcb_stack = tmp_stack;
820 }
821#endif
822}
823
840inline Packet*
842{
843 assert(_e);
844#if CLICK_STATS >= 2
845 click_cycles_t start_cycles = click_get_cycles(),
846 old_child_cycles = _e->_child_cycles;
847# if HAVE_BOUND_PORT_TRANSFER
848 Packet *p = _bound.pull(_e, _port);
849# else
850 Packet *p = _e->pull(_port);
851# endif
852 if (p)
853 _e->output(_port)._packets += 1;
854 click_cycles_t all_delta = click_get_cycles() - start_cycles,
855 own_delta = all_delta - (_e->_child_cycles - old_child_cycles);
856 _e->_xfer_calls += 1;
857 _e->_xfer_own_cycles += own_delta;
858 _owner->_child_cycles += all_delta;
859#else
860# if HAVE_BOUND_PORT_TRANSFER
861 Packet *p = _bound.pull(_e, _port);
862# else
863 Packet *p = _e->pull(_port);
864# endif
865#endif
866#if CLICK_STATS >= 1
867 if (p)
868 ++_packets;
869#endif
870 return p;
871}
872
873#if HAVE_BATCH
877void
878Element::Port::push_batch(PacketBatch* batch) const {
879#if HAVE_FLOW_DYNAMIC
880 FlowControlBlock* tmp_stack = 0;
881 if (unlikely(_unstack && fcb_stack)) {
882 tmp_stack = fcb_stack;
883 fcb_stack->release(batch->count());
884 fcb_stack = 0;
885 }
886#endif
887
888#if BATCH_DEBUG
889 click_chatter("Pushing batch of %d packets to %p{element}",batch->count(),_e);
890#endif
891#if HAVE_BOUND_PORT_TRANSFER
892 _bound_batch.push_batch(_e,_port,batch);
893#else
894 _e->push_batch(_port,batch);
895#endif
896#if HAVE_FLOW_DYNAMIC
897 if (unlikely(_unstack)) {
898 fcb_stack = tmp_stack;
899 }
900#endif
901}
902
903#ifdef HAVE_AUTO_BATCH
904inline void
905Element::Port::start_batch() {
911#if HAVE_AUTO_BATCH == AUTO_BATCH_JUMP
912# if BATCH_DEBUG
913 click_chatter("Passing start batch message in port to %p{element}",_e);
914# endif
915 if (_e->in_batch_mode == BATCH_MODE_YES) {
916 if (*current_batch == 0)
917 current_batch.set((PacketBatch*)-1);
918 } else {
919 for (int i = 0; i < _e->noutputs(); i++) {
920 if (_e->output_is_push(i))
921 _e->_ports[1][i].start_batch();
922 }
923 }
924#elif HAVE_AUTO_BATCH == AUTO_BATCH_PORT
925# if BATCH_DEBUG
926 click_chatter("Starting batch in port to %p{element}",_e);
927# endif
928 if (_e->in_batch_mode == BATCH_MODE_YES) { //Rebuild for the next element
929 if (*current_batch == 0)
930 current_batch.set((PacketBatch*)-1);
931 }
932#elif HAVE_AUTO_BATCH == AUTO_BATCH_LIST
933# if BATCH_DEBUG
934 click_chatter("Starting batch in port to %p{element}",_e);
935# endif
936 assert(*current_batch == 0);
937 current_batch.set((PacketBatch*)-1);
938#else
939 #error "Unknown batch auto mode"
940#endif
941}
942
943inline void
944Element::Port::end_batch() {
945 PacketBatch* cur = *current_batch;
946#if BATCH_DEBUG
947 click_chatter("Ending batch in port to %p{element}",_e);
948#endif
954#if HAVE_AUTO_BATCH == AUTO_BATCH_JUMP
955 if (_e->in_batch_mode == BATCH_MODE_YES)
956#endif
957 { //Send the buffered batch to the next element
958 if (cur != 0) {
959 current_batch.set((PacketBatch*)0);
960 if (cur != (PacketBatch*)-1)
961 {
962 #if BATCH_DEBUG
963 assert(cur->find_count() == cur->count());
964 #endif
965 _e->push_batch(_port,cur);
966 }
967 }
968
969 }
970#if HAVE_AUTO_BATCH == AUTO_BATCH_JUMP
971 else { //Pass the message
972 assert(cur == 0);
973 for (int i = 0; i < _e->noutputs(); i++) {
974 if (_e->output_is_push(i))
975 _e->_ports[1][i].end_batch();
976 }
977 }
978#endif
979};
980#endif
981
983Element::Port::pull_batch(unsigned max) const {
984 PacketBatch* batch = NULL;
985#if HAVE_BOUND_PORT_TRANSFER
986 batch = _bound_batch.pull_batch(_e,_port, max);
987#else
988 batch = _e->pull_batch(_port, max);
989#endif
990 return batch;
991}
992#endif
993
1009inline bool Element::is_fullpush() const {
1010#if HAVE_FULLPUSH_NONATOMIC
1011 return _is_fullpush;
1012#else
1013 return false;
1014#endif
1015}
1016
1017
1030inline void
1032{
1033 if ((unsigned) port < (unsigned) noutputs())
1034 _ports[1][port].push(p);
1035 else
1036 p->kill();
1037}
1038
1049inline Packet*
1051{
1052 if ((unsigned) port < (unsigned) ninputs())
1053 return _ports[0][port].pull();
1054 else
1055 return 0;
1056}
1057
1058#undef PORT_ASSIGN
1059CLICK_ENDDECLS
1060#endif
Vector of bits.
Definition bitvector.hh:21
An Element's ports.
Definition element.hh:306
Packet * pull() const
Pull a packet over this port and return it.
Definition element.hh:841
int port() const
Returns the port number of the port connected to this active port.
Definition element.hh:738
bool active() const
Returns whether this port is active (a push output or a pull input).
Definition element.hh:720
Element * element() const
Returns the element connected to this active port.
Definition element.hh:729
void push(Packet *p) const
Push packet p over this port.
Definition element.hh:765
Base class for Click elements.
Definition element.hh:42
bool output_is_push(int port) const
Check whether output port is push.
Definition element.hh:615
const Port & port(bool isoutput, int port) const
Return one of the element's ports.
Definition element.hh:566
String name() const
Return the element's name.
Definition element.cc:555
virtual int llrpc(unsigned command, void *arg)
Handle a low-level remote procedure call.
Definition element.cc:3095
void add_read_handler(const String &name, ReadHandlerCallback read_callback, const void *user_data=0, uint32_t flags=0)
Register a read handler named name.
Definition element.cc:2020
bool is_fullpush() const
Tell if the path up to this element is a full push path, always served by the same thread.
Definition element.hh:1009
static int reconfigure_positional_handler(const String &, Element *, void *, ErrorHandler *)
Standard write handler for reconfiguring an element by changing one of its positional arguments.
Definition element.cc:3022
void port_flow(bool isoutput, int port, Bitvector *) const
Analyze internal packet flow with respect to port p.
Definition element.cc:1041
void set_handler(const String &name, int flags, HandlerCallback callback, const void *read_user_data=0, const void *write_user_data=0)
Register a comprehensive handler named name.
Definition element.cc:2147
void add_write_handler(const String &name, WriteHandlerCallback write_callback, const void *user_data=0, uint32_t flags=0)
Register a write handler named name.
Definition element.cc:2079
virtual Element * hotswap_element() const
Return a compatible element in the hotswap router.
Definition element.cc:1537
bool input_is_push(int port) const
Check whether input port is push.
Definition element.hh:643
virtual int configure_phase() const
Return the element's configure phase, which determines the order in which elements are configured and...
Definition element.cc:1308
static void static_initialize()
Initialize static data for this element class.
Definition element.hh:481
virtual const char * processing() const
Return the element's processing specifier.
Definition element.cc:1139
virtual const char * port_count() const
Return the element's port count specifier.
Definition element.cc:710
RouterThread * home_thread() const
Return the element's home thread.
Definition element.cc:1675
bool port_active(bool isoutput, int port) const
Check whether a port is active.
Definition element.hh:605
virtual int live_reconfigure(Vector< String > &, ErrorHandler *)
Reconfigure the element while the router is running.
Definition element.cc:1649
enum batch_mode in_batch_mode
Definition element.hh:382
virtual void add_handlers()
Install the element's handlers.
Definition element.cc:1401
const Port & output(int port) const
Return one of the element's output ports.
Definition element.hh:591
virtual const char * flags() const
Return the element's flags.
Definition element.cc:1234
int noutputs() const
Return the number of output ports.
Definition element.hh:555
int eindex() const
Return the element's index within its router.
Definition element.hh:524
int remove_select(int fd, int mask)
Remove interest in mask events on file descriptor fd.
Definition element.cc:1981
int add_select(int fd, int mask)
Register interest in mask events on file descriptor fd.
Definition element.cc:1962
static int reconfigure_keyword_handler(const String &, Element *, void *, ErrorHandler *)
Standard write handler for reconfiguring an element by changing one of its keyword arguments.
Definition element.cc:3062
void add_data_handlers(const char *name, int flags, uint8_t *data)
Register read and/or write handlers accessing data.
Definition element.cc:2727
bool output_is_pull(int port) const
Check whether output port is pull.
Definition element.hh:624
int ninputs() const
Return the number of input ports.
Definition element.hh:548
virtual bool can_live_reconfigure() const
Return whether an element supports live reconfiguration.
Definition element.cc:1618
virtual Packet * simple_action(Packet *p)
Process a packet for a simple packet filter.
Definition element.cc:3252
virtual void * port_cast(bool isoutput, int port, const char *name)
Attempt to cast an element's port to a named type.
Definition element.cc:544
int set_handler_flags(const String &name, int set_flags, int clear_flags=0)
Set flags for the handler named name.
Definition element.cc:2188
int nports(bool isoutput) const
Return the number of input or output ports.
Definition element.hh:541
virtual void cleanup(CleanupStage stage)
Clean up the element's state.
Definition element.cc:1601
void add_net_order_data_handlers(const char *name, int flags, uint16_t *data)
Register read and/or write handlers accessing data in network byte order.
Definition element.cc:2864
virtual void selected(int fd, int mask)
Handle a file descriptor event.
Definition element.cc:1913
virtual const char * flow_code() const
Return the element's internal packet flow specifier (its flow code).
Definition element.cc:946
Element()
Construct an Element.
Definition element.cc:422
bool input_is_pull(int port) const
Check whether input port is pull.
Definition element.hh:634
virtual int configure(Vector< String > &conf, ErrorHandler *errh)
Parse the element's configuration arguments.
Definition element.cc:1372
virtual bool run_task(Task *task)
Run the element's task.
Definition element.cc:3267
Master * master() const
Return the element's master.
Definition master.hh:222
virtual String declaration() const
Return a string giving the element's name and class name.
Definition element.cc:595
const Port & input(int port) const
Return one of the element's input ports.
Definition element.hh:579
virtual void take_state(Element *old_element, ErrorHandler *errh)
Initialize the element for hotswap, where the element should take old_element's state,...
Definition element.cc:1511
static String read_keyword_handler(Element *, void *)
Standard read handler returning a keyword argument.
Definition element.cc:2985
int home_thread_id() const
Return the element's home thread id.
Definition element.cc:1682
virtual int initialize(ErrorHandler *errh)
Initialize the element.
Definition element.cc:1460
static void static_cleanup()
Clean up static data for this element class.
Definition element.hh:509
int flag_value(int flag) const
Return the flag value for flag in flags().
Definition element.cc:1246
virtual Packet * pull(int port)
Pull a packet from pull output port.
Definition element.cc:3162
static String read_positional_handler(Element *, void *)
Standard read handler returning a positional argument.
Definition element.cc:2949
virtual const char * class_name() const =0
Return the element's class name.
virtual bool get_spawning_threads(Bitvector &b, bool isoutput, int port)
Definition element.cc:1727
virtual void run_timer(Timer *timer)
Run the element's timer.
Definition element.cc:3290
virtual void * cast(const char *name)
Attempt to cast the element to a named type.
Definition element.cc:515
String configuration() const
Return the element's current configuration string.
Definition element.cc:1664
Packet * checked_input_pull(int port) const
Pull a packet from input port, or return 0 if port is out of range.
Definition element.hh:1050
void checked_output_push(int port, Packet *p) const
Push packet p to output port, or kill it if port is out of range.
Definition element.hh:1031
void add_task_handlers(Task *task, NotifierSignal *signal, int flags, const String &prefix=String())
Register handlers for a task.
Definition element.cc:2493
Router * router() const
Return the element's router.
Definition element.hh:515
int local_llrpc(unsigned command, void *arg)
Execute an LLRPC from within the configuration.
Definition element.cc:3111
virtual void push(int port, Packet *p)
Push packet p onto push input port.
Definition element.cc:3142
void trigger_thread_reconfiguration(bool is_up, std::function< void()> ready, Bitvector threads)
Definition element.cc:1877
Error reporting class.
Definition error.hh:90
An Ethernet address.
Definition etheraddress.hh:9
An IPv4 address.
Definition ipaddress.hh:16
An activity signal.
Definition notifier.hh:12
Definition packetbatch.hh:415
unsigned count()
Definition packetbatch.hh:475
static PacketBatch * make_from_packet(Packet *p)
Definition packetbatch.hh:664
A network packet.
Definition packet.hh:68
void kill()
Delete this packet.
Definition packet.hh:1804
void pull(uint32_t len)
Remove a header from the front of the packet.
Definition packet.hh:2122
A router configuration.
Definition router.hh:28
A set of Tasks scheduled on the same CPU.
Definition routerthread.hh:32
A string of characters.
Definition string.hh:22
Represents a frequently-scheduled computational task.
Definition task.hh:49
Triggers execution at a given time.
Definition timer.hh:14
Represents a moment or interval in time.
Definition timestamp.hh:125
Vector template.
Definition vector.hh:111
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
Definition sync.hh:57
The Handler class for router handlers.
The Packet class models packets in Click.
Click's String class.
Classes for synchronizing among multiple CPUs, particularly in the Linux kernel.
Click's vector container template.