// -*- c-basic-offset: 4 -*- #ifndef CLICK_LINKUNQUEUE_HH #define CLICK_LINKUNQUEUE_HH #include #include #include #include #include CLICK_DECLS /* =c LinkUnqueue(LATENCY, BANDWIDTH) =s shaping link emulator =d Pulls packets from the single input port, then delays them so as to emulate a serial link with latency LATENCY (microsecond precision) and bandwidth BANDWIDTH (such as "384kbps"). Thus, every packet is delayed at least by LATENCY, and additionally delayed by its packet size and BANDWIDTH, and by any packets ahead of it in the virtual link. Packets are pushed out the single output port when their time comes. LinkUnqueue listens for upstream notification, such as that available from Queue. LinkUnqueue stores packets that are in transit over the virtual link. It doesn't store any other packets, however; it doesn't pull from its input unless there is room on the link. To emulate a link fed by a packet queue, use a "Queue -> LinkUnqueue" combination. LinkUnqueue uses its input packets' "extra length" annotations, destroys their "next packet" annotations, and updates their timestamp annotations. =h latency read-only The LATENCY argument. =h bandwidth read-only The BANDWIDTH argument. =h size read-only The number of packets currently in, or partially in, the emulated link. =h reset write-only When written, drops all packets in, or partially in, the emulated link. =a DelayUnqueue, Queue, Unqueue, RatedUnqueue, BandwidthRatedUnqueue, DelayShaper, SetTimestamp */ class LinkUnqueue : public Element, public Storage { public: LinkUnqueue(); ~LinkUnqueue(); const char *class_name() const { return "LinkUnqueue"; } const char *port_count() const { return PORTS_1_1; } const char *processing() const { return PULL_TO_PUSH; } void *cast(const char *); int configure(Vector &, ErrorHandler *); int initialize(ErrorHandler *); void cleanup(CleanupStage); void add_handlers(); bool run_task(); private: Packet *_qhead; Packet *_qtail; Timestamp _latency; // enum { S_TASK, S_TIMER, S_ASLEEP } _state; bool _back_to_back; uint32_t _bandwidth; Task _task; Timer _timer; NotifierSignal _signal; void delay_by_bandwidth(Packet *, const Timestamp &) const; static String read_param(Element *, void *); static int write_handler(const String &, Element *, void *, ErrorHandler *); }; CLICK_ENDDECLS #endif