+diff -Nurb click-1.6.0/include/click/packet.hh.orig click-1.6.0-27/include/click/packet.hh.orig
+--- click-1.6.0/include/click/packet.hh.orig 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/include/click/packet.hh.orig 2007-09-07 16:11:26.000000000 -0400
+@@ -0,0 +1,1171 @@
++// -*- related-file-name: "../../lib/packet.cc" -*-
++#ifndef CLICK_PACKET_HH
++#define CLICK_PACKET_HH
++#include <click/ipaddress.hh>
++#include <click/ip6address.hh>
++#include <click/glue.hh>
++#include <click/timestamp.hh>
++#if CLICK_LINUXMODULE
++# include <click/skbmgr.hh>
++#else
++# include <click/atomic.hh>
++#endif
++struct click_ether;
++struct click_ip;
++struct click_icmp;
++struct click_ip6;
++struct click_tcp;
++struct click_udp;
++
++#if CLICK_NS
++# include <click/simclick.h>
++#endif
++
++
++CLICK_DECLS
++
++class IP6Address;
++class WritablePacket;
++
++class Packet { public:
++
++ // PACKET CREATION
++ enum { DEFAULT_HEADROOM = 28, MIN_BUFFER_LENGTH = 64 };
++
++ static WritablePacket *make(uint32_t);
++ static WritablePacket *make(const char *, uint32_t);
++ static WritablePacket *make(const unsigned char *, uint32_t);
++ static WritablePacket *make(uint32_t, const unsigned char *, uint32_t, uint32_t);
++
++#if CLICK_LINUXMODULE
++ // Packet::make(sk_buff *) wraps a Packet around an existing sk_buff.
++ // Packet now owns the sk_buff (ie we don't increment skb->users).
++ static Packet *make(struct sk_buff *);
++ struct sk_buff *skb() { return (struct sk_buff *)this; }
++ const struct sk_buff *skb() const { return (const struct sk_buff*)this; }
++#elif CLICK_BSDMODULE
++ // Packet::make(mbuf *) wraps a Packet around an existing mbuf.
++ // Packet now owns the mbuf.
++ static Packet *make(struct mbuf *);
++ struct mbuf *m() { return _m; }
++ const struct mbuf *m() const { return (const struct mbuf *)_m; }
++ struct mbuf *steal_m();
++#else /* User-space */
++ static WritablePacket *make(unsigned char *, uint32_t, void (*destructor)(unsigned char *, size_t));
++#endif
++
++ inline void kill();
++
++ inline bool shared() const;
++ Packet *clone();
++ WritablePacket *uniqueify();
++
++ inline const unsigned char *data() const;
++ inline const unsigned char *end_data() const;
++ inline uint32_t length() const;
++ inline uint32_t headroom() const;
++ inline uint32_t tailroom() const;
++ inline const unsigned char *buffer() const;
++ inline const unsigned char *end_buffer() const;
++ inline uint32_t buffer_length() const;
++
++ WritablePacket *push(uint32_t nb); // Add more space before packet.
++ WritablePacket *push_mac_header(uint32_t nb);
++ Packet *nonunique_push(uint32_t nb);
++ void pull(uint32_t nb); // Get rid of initial bytes.
++ WritablePacket *put(uint32_t nb); // Add bytes to end of pkt.
++ Packet *nonunique_put(uint32_t nb);
++ void take(uint32_t nb); // Delete bytes from end of pkt.
++
++ Packet *shift_data(int offset, bool free_on_failure = true);
++#if CLICK_USERLEVEL
++ inline void shrink_data(const unsigned char *, uint32_t length);
++ inline void change_headroom_and_length(uint32_t headroom, uint32_t length);
++#endif
++
++ // HEADER ANNOTATIONS
++ inline const unsigned char *mac_header() const;
++ inline void set_mac_header(const unsigned char *);
++ inline void set_mac_header(const unsigned char *, uint32_t);
++ inline int mac_header_offset() const;
++ inline uint32_t mac_header_length() const;
++ inline int mac_length() const;
++
++ inline const unsigned char *network_header() const;
++ inline void set_network_header(const unsigned char *, uint32_t);
++ inline void set_network_header_length(uint32_t);
++ inline int network_header_offset() const;
++ inline uint32_t network_header_length() const;
++ inline int network_length() const;
++
++ inline const unsigned char *transport_header() const;
++ inline int transport_header_offset() const;
++ inline int transport_length() const;
++
++ // CONVENIENCE HEADER ANNOTATIONS
++ inline const click_ether *ether_header() const;
++ inline void set_ether_header(const click_ether *);
++
++ inline const click_ip *ip_header() const;
++ inline void set_ip_header(const click_ip *, uint32_t);
++ inline int ip_header_offset() const;
++ inline uint32_t ip_header_length() const;
++
++ inline const click_ip6 *ip6_header() const;
++ inline void set_ip6_header(const click_ip6 *);
++ inline void set_ip6_header(const click_ip6 *, uint32_t);
++ inline int ip6_header_offset() const;
++ inline uint32_t ip6_header_length() const;
++
++ inline const click_icmp *icmp_header() const;
++ inline const click_tcp *tcp_header() const;
++ inline const click_udp *udp_header() const;
++
++ // LINKS
++ inline Packet *next() const;
++ inline Packet *&next();
++ inline void set_next(Packet *p);
++
++ // ANNOTATIONS
++
++ private:
++ struct Anno;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ const Anno *anno() const { return (const Anno *)skb()->cb; }
++ Anno *anno() { return (Anno *)skb()->cb; }
++#else /* User-space and BSD kernel module */
++ const Anno *anno() const { return (const Anno *)_cb; }
++ Anno *anno() { return (Anno *)_cb; }
++#endif
++ public:
++
++ enum PacketType { // must agree with if_packet.h
++ HOST = 0, BROADCAST = 1, MULTICAST = 2, OTHERHOST = 3, OUTGOING = 4,
++ LOOPBACK = 5, FASTROUTE = 6
++ };
++
++ enum { ADDR_ANNO_SIZE = 16 };
++
++ uint8_t *addr_anno() { return anno()->addr.c; }
++ const uint8_t *addr_anno() const { return anno()->addr.c; }
++ IPAddress dst_ip_anno() const;
++ void set_dst_ip_anno(IPAddress);
++ const IP6Address &dst_ip6_anno() const;
++ void set_dst_ip6_anno(const IP6Address &);
++
++ inline const Timestamp ×tamp_anno() const;
++ inline Timestamp ×tamp_anno();
++ inline void set_timestamp_anno(const Timestamp &);
++
++ inline net_device *device_anno() const;
++ inline void set_device_anno(net_device *);
++
++ inline PacketType packet_type_anno() const;
++ inline void set_packet_type_anno(PacketType);
++
++#if CLICK_LINUXMODULE
++# ifdef HAVE_INT64_TYPES
++ uint64_t perfctr_anno() const { return anno()->perfctr; }
++ void set_perfctr_anno(uint64_t pc) { anno()->perfctr = pc; }
++# endif
++
++#else /* User-space and BSD kernel module */
++
++#if CLICK_NS
++ class SimPacketinfoWrapper {
++ public:
++ simclick_simpacketinfo _pinfo;
++ SimPacketinfoWrapper() {
++ // The uninitialized value for the simulator packet data can't be
++ // all zeros (0 is a valid packet id) or random junk out of memory
++ // since the simulator will look at this info to see if the packet
++ // was originally generated by it. Accidental collisions with other
++ // packet IDs or bogus packet IDs can cause weird things to happen. So we
++ // set it to all -1 here to keep the simulator from getting confused.
++ memset(&_pinfo,-1,sizeof(_pinfo));
++ }
++ };
++ simclick_simpacketinfo* get_sim_packetinfo() {
++ return &(_sim_packetinfo._pinfo);
++ }
++ void set_sim_packetinfo(simclick_simpacketinfo* pinfo) {
++ _sim_packetinfo._pinfo = *pinfo;
++ }
++#endif
++#endif
++
++ enum { USER_ANNO_SIZE = 24,
++ USER_ANNO_US_SIZE = 12,
++ USER_ANNO_S_SIZE = 12,
++ USER_ANNO_U_SIZE = 6,
++ USER_ANNO_I_SIZE = 6 };
++
++ uint8_t user_anno_c(int i) const { return anno()->user.c[i]; }
++ void set_user_anno_c(int i, uint8_t v) { anno()->user.c[i] = v; }
++ uint16_t user_anno_us(int i) const { return anno()->user.us[i]; }
++ void set_user_anno_us(int i, uint16_t v) { anno()->user.us[i] = v; }
++ int16_t user_anno_s(int i) const { return anno()->user.us[i]; }
++ void set_user_anno_s(int i, int16_t v) { anno()->user.s[i] = v; }
++ uint32_t user_anno_u(int i) const { return anno()->user.u[i]; }
++ void set_user_anno_u(int i, uint32_t v) { anno()->user.u[i] = v; }
++ int32_t user_anno_i(int i) const { return anno()->user.i[i]; }
++ void set_user_anno_i(int i, int32_t v) { anno()->user.i[i] = v; }
++
++ const uint8_t *all_user_anno() const { return &anno()->user.c[0]; }
++ uint8_t *all_user_anno() { return &anno()->user.c[0]; }
++ const uint32_t *all_user_anno_u() const { return &anno()->user.u[0]; }
++ uint32_t *all_user_anno_u() { return &anno()->user.u[0]; }
++
++ void clear_annotations();
++ void copy_annotations(const Packet *);
++
++ inline const unsigned char *buffer_data() const CLICK_DEPRECATED;
++
++ private:
++
++ // Anno must fit in sk_buff's char cb[48].
++ struct Anno {
++ union {
++ char ch[ADDR_ANNO_SIZE];
++ uint8_t c[ADDR_ANNO_SIZE];
++ uint32_t ip4;
++ } addr;
++
++ union {
++ uint8_t c[USER_ANNO_SIZE];
++ uint16_t us[USER_ANNO_US_SIZE];
++ int16_t s[USER_ANNO_S_SIZE];
++ uint32_t u[USER_ANNO_U_SIZE];
++ int32_t i[USER_ANNO_I_SIZE];
++ } user;
++ // flag allocations: see packet_anno.hh
++
++#if (CLICK_LINUXMODULE || CLICK_BSDMODULE) && defined(HAVE_INT64_TYPES)
++ uint64_t perfctr;
++#endif
++ };
++
++#if !CLICK_LINUXMODULE
++ // User-space and BSD kernel module implementations.
++ atomic_uint32_t _use_count;
++ Packet *_data_packet;
++ /* mimic Linux sk_buff */
++ unsigned char *_head; /* start of allocated buffer */
++ unsigned char *_data; /* where the packet starts */
++ unsigned char *_tail; /* one beyond end of packet */
++ unsigned char *_end; /* one beyond end of allocated buffer */
++# if CLICK_USERLEVEL
++ void (*_destructor)(unsigned char *, size_t);
++# endif
++ unsigned char _cb[48];
++ unsigned char *_mac;
++ unsigned char *_nh;
++ unsigned char *_h;
++ PacketType _pkt_type;
++ Timestamp _timestamp;
++# if CLICK_BSDMODULE
++ struct mbuf *_m;
++# endif
++ Packet *_next;
++# if CLICK_NS
++ SimPacketinfoWrapper _sim_packetinfo;
++# endif
++#endif
++
++ Packet();
++ Packet(const Packet &);
++ ~Packet();
++ Packet &operator=(const Packet &);
++
++#if !CLICK_LINUXMODULE
++ Packet(int, int, int) { }
++ static WritablePacket *make(int, int, int);
++ bool alloc_data(uint32_t, uint32_t, uint32_t);
++#endif
++#if CLICK_BSDMODULE
++ static void assimilate_mbuf(Packet *p);
++ void assimilate_mbuf();
++#endif
++
++ inline void shift_header_annotations(int32_t shift);
++ WritablePacket *expensive_uniqueify(int32_t extra_headroom, int32_t extra_tailroom, bool free_on_failure);
++ WritablePacket *expensive_push(uint32_t nbytes);
++ WritablePacket *expensive_put(uint32_t nbytes);
++
++ friend class WritablePacket;
++
++};
++
++
++class WritablePacket : public Packet { public:
++
++ inline unsigned char *data() const;
++ inline unsigned char *end_data() const;
++ inline unsigned char *buffer() const;
++ inline unsigned char *end_buffer() const;
++ inline unsigned char *mac_header() const;
++ inline click_ether *ether_header() const;
++ inline unsigned char *network_header() const;
++ inline click_ip *ip_header() const;
++ inline click_ip6 *ip6_header() const;
++ inline unsigned char *transport_header() const;
++ inline click_icmp *icmp_header() const;
++ inline click_tcp *tcp_header() const;
++ inline click_udp *udp_header() const;
++
++ inline unsigned char *buffer_data() const CLICK_DEPRECATED;
++
++ private:
++
++ WritablePacket() { }
++ WritablePacket(const Packet &) { }
++ ~WritablePacket() { }
++
++ friend class Packet;
++
++};
++
++
++
++inline const unsigned char *
++Packet::data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->data;
++#else
++ return _data;
++#endif
++}
++
++inline const unsigned char *
++Packet::end_data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->tail;
++#else
++ return _tail;
++#endif
++}
++
++inline uint32_t
++Packet::length() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->len;
++#else
++ return _tail - _data;
++#endif
++}
++
++inline uint32_t
++Packet::headroom() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->data - skb()->head;
++#else
++ return _data - _head;
++#endif
++}
++
++inline uint32_t
++Packet::tailroom() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end - skb()->tail;
++#else
++ return _end - _tail;
++#endif
++}
++
++inline const unsigned char *
++Packet::buffer() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->head;
++#else
++ return _head;
++#endif
++}
++
++inline const unsigned char *
++Packet::end_buffer() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end;
++#else
++ return _end;
++#endif
++}
++
++inline uint32_t
++Packet::buffer_length() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end - skb()->head;
++#else
++ return _end - _head;
++#endif
++}
++
++inline const unsigned char *
++Packet::buffer_data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->head;
++#else
++ return _head;
++#endif
++}
++
++
++inline Packet *
++Packet::next() const
++{
++#if CLICK_LINUXMODULE
++ return (Packet *)(skb()->next);
++#else
++ return _next;
++#endif
++}
++
++inline Packet *&
++Packet::next()
++{
++#if CLICK_LINUXMODULE
++ return (Packet *&)(skb()->next);
++#else
++ return _next;
++#endif
++}
++
++inline void
++Packet::set_next(Packet *p)
++{
++#if CLICK_LINUXMODULE
++ skb()->next = p->skb();
++#else
++ _next = p;
++#endif
++}
++
++inline const unsigned char *
++Packet::mac_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->mac.raw;
++#else
++ return _mac;
++#endif
++}
++
++inline const unsigned char *
++Packet::network_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->nh.raw;
++#else
++ return _nh;
++#endif
++}
++
++inline const unsigned char *
++Packet::transport_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->h.raw;
++#else
++ return _h;
++#endif
++}
++
++inline const click_ether *
++Packet::ether_header() const
++{
++ return reinterpret_cast<const click_ether *>(mac_header());
++}
++
++inline const click_ip *
++Packet::ip_header() const
++{
++ return reinterpret_cast<const click_ip *>(network_header());
++}
++
++inline const click_ip6 *
++Packet::ip6_header() const
++{
++ return reinterpret_cast<const click_ip6 *>(network_header());
++}
++
++inline const click_icmp *
++Packet::icmp_header() const
++{
++ return reinterpret_cast<const click_icmp *>(transport_header());
++}
++
++inline const click_tcp *
++Packet::tcp_header() const
++{
++ return reinterpret_cast<const click_tcp *>(transport_header());
++}
++
++inline const click_udp *
++Packet::udp_header() const
++{
++ return reinterpret_cast<const click_udp *>(transport_header());
++}
++
++inline int
++Packet::mac_length() const
++{
++ return end_data() - mac_header();
++}
++
++inline int
++Packet::network_length() const
++{
++ return end_data() - network_header();
++}
++
++inline int
++Packet::transport_length() const
++{
++ return end_data() - transport_header();
++}
++
++inline const Timestamp &
++Packet::timestamp_anno() const
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ return *(const Timestamp *) &skb()->stamp;
++# else
++ return *(const Timestamp *) &skb()->tstamp;
++# endif
++#else
++ return _timestamp;
++#endif
++}
++
++inline Timestamp &
++Packet::timestamp_anno()
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ return *(Timestamp *) &skb()->stamp;
++# else
++ return *(Timestamp *) &skb()->tstamp;
++# endif
++#else
++ return _timestamp;
++#endif
++}
++
++inline void
++Packet::set_timestamp_anno(const Timestamp ×tamp)
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ memcpy(&skb()->stamp, ×tamp, 8);
++# else
++ skb_set_timestamp(skb(), ×tamp.timeval());
++# endif
++#else
++ _timestamp = timestamp;
++#endif
++}
++
++inline net_device *
++Packet::device_anno() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->dev;
++#elif CLICK_BSDMODULE
++ if (m())
++ return m()->m_pkthdr.rcvif;
++ else
++ return 0;
++#else
++ return 0;
++#endif
++}
++
++inline void
++Packet::set_device_anno(net_device *dev)
++{
++#if CLICK_LINUXMODULE
++ skb()->dev = dev;
++#elif CLICK_BSDMODULE
++ if (m())
++ m()->m_pkthdr.rcvif = dev;
++#else
++ (void) dev;
++#endif
++}
++
++inline Packet::PacketType
++Packet::packet_type_anno() const
++{
++#if CLICK_LINUXMODULE
++ return (PacketType)(skb()->pkt_type & PACKET_TYPE_MASK);
++#else
++ return _pkt_type;
++#endif
++}
++
++inline void
++Packet::set_packet_type_anno(PacketType p)
++{
++#if CLICK_LINUXMODULE
++ skb()->pkt_type = (skb()->pkt_type & PACKET_CLEAN) | p;
++#else
++ _pkt_type = p;
++#endif
++}
++
++inline WritablePacket *
++Packet::make(uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)0, len, 0);
++}
++
++inline WritablePacket *
++Packet::make(const char *s, uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)s, len, 0);
++}
++
++inline WritablePacket *
++Packet::make(const unsigned char *s, uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)s, len, 0);
++}
++
++#if CLICK_LINUXMODULE
++inline Packet *
++Packet::make(struct sk_buff *skb)
++{
++ if (atomic_read(&skb->users) == 1) {
++ skb_orphan(skb);
++ return reinterpret_cast<Packet *>(skb);
++ } else {
++ Packet *p = reinterpret_cast<Packet *>(skb_clone(skb, GFP_ATOMIC));
++ atomic_dec(&skb->users);
++ return p;
++ }
++}
++#endif
++
++
++inline void
++Packet::kill()
++{
++#if CLICK_LINUXMODULE
++ struct sk_buff *b = skb();
++ b->next = b->prev = 0;
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
++ b->list = 0;
++# endif
++ skbmgr_recycle_skbs(b);
++#else
++ if (_use_count.dec_and_test())
++ delete this;
++#endif
++}
++
++
++#if CLICK_BSDMODULE /* BSD kernel module */
++inline void
++Packet::assimilate_mbuf(Packet *p)
++{
++ struct mbuf *m = p->m();
++
++ if (!m) return;
++
++ p->_head = (unsigned char *)
++ (m->m_flags & M_EXT ? m->m_ext.ext_buf :
++ m->m_flags & M_PKTHDR ? m->m_pktdat :
++ m->m_dat);
++ p->_data = (unsigned char *)m->m_data;
++ p->_tail = (unsigned char *)(m->m_data + m->m_len);
++ p->_end = p->_head + (
++ m->m_flags & M_EXT ? MCLBYTES :
++ m->m_flags & M_PKTHDR ? MHLEN :
++ MLEN);
++}
++
++inline void
++Packet::assimilate_mbuf()
++{
++ assimilate_mbuf(this);
++}
++
++inline Packet *
++Packet::make(struct mbuf *m)
++{
++ if (!(m->m_flags & M_PKTHDR))
++ panic("trying to construct Packet from a non-packet mbuf");
++
++ Packet *p = new Packet;
++ if (m->m_pkthdr.len != m->m_len) {
++ /* click needs contiguous data */
++ // click_chatter("m_pulldown, Click needs contiguous data");
++
++ if (m_pulldown(m, 0, m->m_pkthdr.len, NULL) == NULL)
++ panic("m_pulldown failed");
++ }
++ p->_m = m;
++ assimilate_mbuf(p);
++
++ return p;
++}
++#endif
++
++inline bool
++Packet::shared() const
++{
++#if CLICK_LINUXMODULE
++ return skb_cloned(const_cast<struct sk_buff *>(skb()));
++#else
++ return (_data_packet || _use_count > 1);
++#endif
++}
++
++inline WritablePacket *
++Packet::uniqueify()
++{
++ if (!shared())
++ return static_cast<WritablePacket *>(this);
++ else
++ return expensive_uniqueify(0, 0, true);
++}
++
++inline WritablePacket *
++Packet::push(uint32_t nbytes)
++{
++ if (headroom() >= nbytes && !shared()) {
++ WritablePacket *q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_data -= nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_data -= nbytes;
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return q;
++ } else
++ return expensive_push(nbytes);
++}
++
++inline Packet *
++Packet::nonunique_push(uint32_t nbytes)
++{
++ if (headroom() >= nbytes) {
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _data -= nbytes;
++# if CLICK_BSDMODULE
++ m()->m_data -= nbytes;
++ m()->m_len += nbytes;
++ m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return this;
++ } else
++ return expensive_push(nbytes);
++}
++
++/* Get rid of some bytes at the start of a packet */
++inline void
++Packet::pull(uint32_t nbytes)
++{
++ if (nbytes > length()) {
++ click_chatter("Packet::pull %d > length %d\n", nbytes, length());
++ nbytes = length();
++ }
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_pull(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _data += nbytes;
++# if CLICK_BSDMODULE
++ m()->m_data += nbytes;
++ m()->m_len -= nbytes;
++ m()->m_pkthdr.len -= nbytes;
++# endif
++#endif
++}
++
++inline WritablePacket *
++Packet::put(uint32_t nbytes)
++{
++ if (tailroom() >= nbytes && !shared()) {
++ WritablePacket *q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_put(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_tail += nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return q;
++ } else
++ return expensive_put(nbytes);
++}
++
++inline Packet *
++Packet::nonunique_put(uint32_t nbytes)
++{
++ if (tailroom() >= nbytes) {
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_put(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _tail += nbytes;
++# if CLICK_BSDMODULE
++ m()->m_len += nbytes;
++ m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return this;
++ } else
++ return expensive_put(nbytes);
++}
++
++/* Get rid of some bytes at the end of a packet */
++inline void
++Packet::take(uint32_t nbytes)
++{
++ if (nbytes > length()) {
++ click_chatter("Packet::take %d > length %d\n", nbytes, length());
++ nbytes = length();
++ }
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->tail -= nbytes;
++ skb()->len -= nbytes;
++#else /* User-space and BSD kernel module */
++ _tail -= nbytes;
++# if CLICK_BSDMODULE
++ m()->m_len -= nbytes;
++ m()->m_pkthdr.len -= nbytes;
++# endif
++#endif
++}
++
++#if CLICK_USERLEVEL
++inline void
++Packet::shrink_data(const unsigned char *d, uint32_t length)
++{
++ assert(_data_packet);
++ if (d >= _head && d + length >= d && d + length <= _end) {
++ _head = _data = const_cast<unsigned char *>(d);
++ _tail = _end = const_cast<unsigned char *>(d + length);
++ }
++}
++
++inline void
++Packet::change_headroom_and_length(uint32_t headroom, uint32_t length)
++{
++ if (headroom + length <= buffer_length()) {
++ _data = _head + headroom;
++ _tail = _data + length;
++ }
++}
++#endif
++
++inline const IP6Address &
++Packet::dst_ip6_anno() const
++{
++ return *reinterpret_cast<const IP6Address *>(anno()->addr.ch);
++}
++
++inline void
++Packet::set_dst_ip6_anno(const IP6Address &a)
++{
++ memcpy(anno()->addr.ch, &a, 16);
++}
++
++inline IPAddress
++Packet::dst_ip_anno() const
++{
++ return IPAddress(anno()->addr.ip4);
++}
++
++inline void
++Packet::set_dst_ip_anno(IPAddress a)
++{
++ anno()->addr.ip4 = a.addr();
++}
++
++inline void
++Packet::set_mac_header(const unsigned char *h)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->mac.raw = const_cast<unsigned char *>(h);
++#else /* User-space and BSD kernel module */
++ _mac = const_cast<unsigned char *>(h);
++#endif
++}
++
++inline void
++Packet::set_mac_header(const unsigned char *h, uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->mac.raw = const_cast<unsigned char *>(h);
++ skb()->nh.raw = const_cast<unsigned char *>(h) + len;
++#else /* User-space and BSD kernel module */
++ _mac = const_cast<unsigned char *>(h);
++ _nh = const_cast<unsigned char *>(h) + len;
++#endif
++}
++
++inline void
++Packet::set_ether_header(const click_ether *h)
++{
++ set_mac_header(reinterpret_cast<const unsigned char *>(h), 14);
++}
++
++inline WritablePacket *
++Packet::push_mac_header(uint32_t nbytes)
++{
++ WritablePacket *q;
++ if (headroom() >= nbytes && !shared()) {
++ q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_data -= nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_data -= nbytes;
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ } else if ((q = expensive_push(nbytes)))
++ /* nada */;
++ else
++ return 0;
++ q->set_mac_header(q->data(), nbytes);
++ return q;
++}
++
++inline void
++Packet::set_network_header(const unsigned char *h, uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->nh.raw = const_cast<unsigned char *>(h);
++ skb()->h.raw = const_cast<unsigned char *>(h) + len;
++#else /* User-space and BSD kernel module */
++ _nh = const_cast<unsigned char *>(h);
++ _h = const_cast<unsigned char *>(h) + len;
++#endif
++}
++
++inline void
++Packet::set_network_header_length(uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->h.raw = skb()->nh.raw + len;
++#else /* User-space and BSD kernel module */
++ _h = _nh + len;
++#endif
++}
++
++inline void
++Packet::set_ip_header(const click_ip *iph, uint32_t len)
++{
++ set_network_header(reinterpret_cast<const unsigned char *>(iph), len);
++}
++
++inline void
++Packet::set_ip6_header(const click_ip6 *ip6h, uint32_t len)
++{
++ set_network_header(reinterpret_cast<const unsigned char *>(ip6h), len);
++}
++
++inline void
++Packet::set_ip6_header(const click_ip6 *ip6h)
++{
++ set_ip6_header(ip6h, 40);
++}
++
++inline int
++Packet::mac_header_offset() const
++{
++ return mac_header() - data();
++}
++
++inline uint32_t
++Packet::mac_header_length() const
++{
++ return network_header() - mac_header();
++}
++
++inline int
++Packet::network_header_offset() const
++{
++ return network_header() - data();
++}
++
++inline uint32_t
++Packet::network_header_length() const
++{
++ return transport_header() - network_header();
++}
++
++inline int
++Packet::ip_header_offset() const
++{
++ return network_header_offset();
++}
++
++inline uint32_t
++Packet::ip_header_length() const
++{
++ return network_header_length();
++}
++
++inline int
++Packet::ip6_header_offset() const
++{
++ return network_header_offset();
++}
++
++inline uint32_t
++Packet::ip6_header_length() const
++{
++ return network_header_length();
++}
++
++inline int
++Packet::transport_header_offset() const
++{
++ return transport_header() - data();
++}
++
++inline void
++Packet::clear_annotations()
++{
++ memset(anno(), '\0', sizeof(Anno));
++ set_packet_type_anno(HOST);
++ set_device_anno(0);
++ set_timestamp_anno(Timestamp());
++ set_mac_header(0);
++ set_network_header(0, 0);
++ set_next(0);
++}
++
++inline void
++Packet::copy_annotations(const Packet *p)
++{
++ *anno() = *p->anno();
++ set_packet_type_anno(p->packet_type_anno());
++ set_device_anno(p->device_anno());
++ set_timestamp_anno(p->timestamp_anno());
++}
++
++inline void
++Packet::shift_header_annotations(int32_t shift)
++{
++#if CLICK_USERLEVEL || CLICK_BSDMODULE
++ _mac += (_mac ? shift : 0);
++ _nh += (_nh ? shift : 0);
++ _h += (_h ? shift : 0);
++#else
++ struct sk_buff *mskb = skb();
++ mskb->mac.raw += (mskb->mac.raw ? shift : 0);
++ mskb->nh.raw += (mskb->nh.raw ? shift : 0);
++ mskb->h.raw += (mskb->h.raw ? shift : 0);
++#endif
++}
++
++
++inline unsigned char *
++WritablePacket::data() const
++{
++ return const_cast<unsigned char *>(Packet::data());
++}
++
++inline unsigned char *
++WritablePacket::end_data() const
++{
++ return const_cast<unsigned char *>(Packet::end_data());
++}
++
++inline unsigned char *
++WritablePacket::buffer() const
++{
++ return const_cast<unsigned char *>(Packet::buffer());
++}
++
++inline unsigned char *
++WritablePacket::end_buffer() const
++{
++ return const_cast<unsigned char *>(Packet::end_buffer());
++}
++
++inline unsigned char *
++WritablePacket::buffer_data() const
++{
++ return const_cast<unsigned char *>(Packet::buffer());
++}
++
++inline unsigned char *
++WritablePacket::mac_header() const
++{
++ return const_cast<unsigned char *>(Packet::mac_header());
++}
++
++inline unsigned char *
++WritablePacket::network_header() const
++{
++ return const_cast<unsigned char *>(Packet::network_header());
++}
++
++inline unsigned char *
++WritablePacket::transport_header() const
++{
++ return const_cast<unsigned char *>(Packet::transport_header());
++}
++
++inline click_ether *
++WritablePacket::ether_header() const
++{
++ return const_cast<click_ether *>(Packet::ether_header());
++}
++
++inline click_ip *
++WritablePacket::ip_header() const
++{
++ return const_cast<click_ip *>(Packet::ip_header());
++}
++
++inline click_ip6 *
++WritablePacket::ip6_header() const
++{
++ return const_cast<click_ip6 *>(Packet::ip6_header());
++}
++
++inline click_icmp *
++WritablePacket::icmp_header() const
++{
++ return const_cast<click_icmp *>(Packet::icmp_header());
++}
++
++inline click_tcp *
++WritablePacket::tcp_header() const
++{
++ return const_cast<click_tcp *>(Packet::tcp_header());
++}
++
++inline click_udp *
++WritablePacket::udp_header() const
++{
++ return const_cast<click_udp *>(Packet::udp_header());
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/include/click/pathvars.h click-1.6.0-27/include/click/pathvars.h
+--- click-1.6.0/include/click/pathvars.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/include/click/pathvars.h 2009-01-28 16:15:43.000000000 -0500
+@@ -0,0 +1,39 @@
++/* include/click/pathvars.h. Generated from pathvars.h.in by configure. */
++/* Process this file with configure to produce pathvars.h. -*- mode: c -*- */
++#ifndef CLICK_PATHVARS_H
++#define CLICK_PATHVARS_H
++
++/* Directory for binaries. */
++#define CLICK_BINDIR "/d/click/click-1.6.0-27/inst/bin"
++
++/* Directory for packages and kernel module. */
++#define CLICK_LIBDIR "/d/click/click-1.6.0-27/inst/lib"
++
++/* Directory for shared files. */
++#define CLICK_DATADIR "/d/click/click-1.6.0-27/inst/share/click"
++
++/* FreeBSD kernel include directory. */
++#define FREEBSD_INCLUDEDIR "/usr/include"
++
++/* Define if the BSD kernel module driver was compiled. */
++/* #undef HAVE_BSDMODULE_DRIVER */
++
++/* Define if the Click kernel module should provide clickfs. */
++#define HAVE_CLICKFS 1
++
++/* Define if the expat library is available. */
++#define HAVE_EXPAT 1
++
++/* Define if the Click linuxmodule is compiled for a 2.6 kernel. */
++#define HAVE_LINUXMODULE_2_6 1
++
++/* Define if the Linux kernel module driver was compiled. */
++#define HAVE_LINUXMODULE_DRIVER 1
++
++/* Define if the user-level driver was compiled. */
++#define HAVE_USERLEVEL_DRIVER 1
++
++/* Directory containing Linux sources. */
++#define LINUX_SRCDIR "/d/kernels/linux-2.6.27.10-clickport"
++
++#endif
+diff -Nurb click-1.6.0/include/clicknet/ip.h click-1.6.0-27/include/clicknet/ip.h
+--- click-1.6.0/include/clicknet/ip.h 2007-07-16 19:47:50.000000000 -0400
++++ click-1.6.0-27/include/clicknet/ip.h 2009-01-19 16:01:43.000000000 -0500
+@@ -5,6 +5,7 @@
+ #include <click/cxxprotect.h>
+ CLICK_CXX_PROTECT
+ #if CLICK_LINUXMODULE
++#include <linux/autoconf.h>
+ # include <net/checksum.h>
+ # include <linux/in.h>
+ #else
+diff -Nurb click-1.6.0/include/clicknet/ip.h.orig click-1.6.0-27/include/clicknet/ip.h.orig
+--- click-1.6.0/include/clicknet/ip.h.orig 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/include/clicknet/ip.h.orig 2007-07-16 19:47:50.000000000 -0400
+@@ -0,0 +1,156 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_IP_H
++#define CLICKNET_IP_H
++/* get struct in_addr */
++#include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++#if CLICK_LINUXMODULE
++# include <net/checksum.h>
++# include <linux/in.h>
++#else
++# include <sys/types.h>
++# include <netinet/in.h>
++#endif
++
++/*
++ * <clicknet/ip.h> -- IP header definitions, based on one of the BSDs.
++ *
++ * Relevant RFCs include:
++ * RFC791 Internet Protocol
++ * RFC3168 The Addition of Explicit Congestion Notification (ECN) to IP
++ */
++
++struct click_ip {
++#if CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
++ unsigned ip_v : 4; /* 0 version == 4 */
++ unsigned ip_hl : 4; /* header length */
++#elif CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++ unsigned ip_hl : 4; /* 0 header length */
++ unsigned ip_v : 4; /* version == 4 */
++#else
++# error "unknown byte order"
++#endif
++ uint8_t ip_tos; /* 1 type of service */
++#define IP_DSCPMASK 0xFC /* diffserv code point */
++#define IP_ECNMASK 0x03 /* ECN code point */
++#define IP_ECN_NOT_ECT 0x00 /* not ECN capable transport */
++#define IP_ECN_ECT1 0x01 /* ECN capable transport */
++#define IP_ECN_ECT2 0x02 /* ECN capable transport */
++#define IP_ECN_CE 0x03 /* ECN congestion exp'd */
++ uint16_t ip_len; /* 2-3 total length */
++ uint16_t ip_id; /* 4-5 identification */
++ uint16_t ip_off; /* 6-7 fragment offset field */
++#define IP_RF 0x8000 /* reserved fragment flag */
++#define IP_DF 0x4000 /* don't fragment flag */
++#define IP_MF 0x2000 /* more fragments flag */
++#define IP_OFFMASK 0X1FFF /* mask for fragmenting bits */
++ uint8_t ip_ttl; /* 8 time to live */
++ uint8_t ip_p; /* 9 protocol */
++ uint16_t ip_sum; /* 10-11 checksum */
++ struct in_addr ip_src; /* 12-15 source address */
++ struct in_addr ip_dst; /* 16-19 destination address */
++};
++
++/* ip_protocol */
++#define IP_PROTO_ICMP 1
++#define IP_PROTO_IGMP 2
++#define IP_PROTO_GGP 3
++#define IP_PROTO_IPIP 4
++#define IP_PROTO_ST 5
++#define IP_PROTO_TCP 6
++#define IP_PROTO_UCL 7
++#define IP_PROTO_EGP 8
++#define IP_PROTO_IGP 9
++#define IP_PROTO_BBN 10
++#define IP_PROTO_NVPII 11
++#define IP_PROTO_PUP 12
++#define IP_PROTO_ARGUS 13
++#define IP_PROTO_EMCON 14
++#define IP_PROTO_XNET 15
++#define IP_PROTO_CHAOS 16
++#define IP_PROTO_UDP 17
++#define IP_PROTO_MUX 18
++#define IP_PROTO_DCN 19
++#define IP_PROTO_HMP 20
++#define IP_PROTO_PRM 21
++#define IP_PROTO_XNS 22
++#define IP_PROTO_TRUNK1 23
++#define IP_PROTO_TRUNK2 24
++#define IP_PROTO_LEAF1 25
++#define IP_PROTO_LEAF2 26
++#define IP_PROTO_RDP 27
++#define IP_PROTO_IRTP 28
++#define IP_PROTO_ISOTP4 29
++#define IP_PROTO_NETBLT 30
++#define IP_PROTO_MFENSP 31
++#define IP_PROTO_MERIT 32
++#define IP_PROTO_DCCP 33
++#define IP_PROTO_ICMP6 58
++#define IP_PROTO_CFTP 62
++#define IP_PROTO_SATNET 64
++#define IP_PROTO_MITSUBNET 65
++#define IP_PROTO_RVD 66
++#define IP_PROTO_IPPC 67
++#define IP_PROTO_SATMON 69
++#define IP_PROTO_IPCV 71
++#define IP_PROTO_BRSATMON 76
++#define IP_PROTO_WBMON 78
++#define IP_PROTO_WBEXPAK 79
++#define IP_PROTO_SCTP 132
++
++#define IP_PROTO_NONE 257
++#define IP_PROTO_TRANSP 258
++#define IP_PROTO_TCP_OR_UDP 256
++#define IP_PROTO_PAYLOAD 259
++
++#define IPOPT_EOL 0 /* end of option list */
++#define IPOPT_NOP 1 /* no operation */
++#define IPOPT_RR 7 /* record packet route */
++#define IPOPT_TS 68 /* timestamp */
++#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
++#define IPOPT_LSRR 131 /* loose source route */
++#define IPOPT_SATID 136 /* satnet id */
++#define IPOPT_SSRR 137 /* strict source route */
++#define IPOPT_RA 148 /* router alert */
++
++#define IP_ISFRAG(iph) (((iph)->ip_off & htons(IP_MF | IP_OFFMASK)) != 0)
++#define IP_FIRSTFRAG(iph) (((iph)->ip_off & htons(IP_OFFMASK)) == 0)
++
++
++/* checksum functions */
++
++#if !CLICK_LINUXMODULE
++uint16_t click_in_cksum(const unsigned char *addr, int len);
++uint16_t click_in_cksum_pseudohdr_raw(uint32_t csum, uint32_t src, uint32_t dst, int proto, int packet_len);
++#else
++# define click_in_cksum(addr, len) \
++ ip_compute_csum((unsigned char *)(addr), (len))
++# define click_in_cksum_pseudohdr_raw(csum, src, dst, proto, transport_len) \
++ csum_tcpudp_magic((src), (dst), (transport_len), (proto), ~(csum) & 0xFFFF)
++#endif
++uint16_t click_in_cksum_pseudohdr_hard(uint32_t csum, const struct click_ip *iph, int packet_len);
++
++/* use if you're not sure whether there are source routing options */
++static inline uint16_t
++click_in_cksum_pseudohdr(uint32_t csum, const struct click_ip *iph,
++ int transport_len)
++{
++ if (iph->ip_hl == 5)
++ return click_in_cksum_pseudohdr_raw(csum, iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p, transport_len);
++ else
++ return click_in_cksum_pseudohdr_hard(csum, iph, transport_len);
++}
++
++static inline void
++click_update_in_cksum(uint16_t *csum, uint16_t old_hw, uint16_t new_hw)
++{
++ /* incrementally update IP checksum according to RFC1624:
++ new_sum = ~(~old_sum + ~old_halfword + new_halfword) */
++ uint32_t sum = (~*csum & 0xFFFF) + (~old_hw & 0xFFFF) + new_hw;
++ sum = (sum & 0xFFFF) + (sum >> 16);
++ *csum = ~(sum + (sum >> 16));
++}
++
++CLICK_CXX_UNPROTECT
++#include <click/cxxunprotect.h>
++#endif
+Files click-1.6.0/inst/bin/click and click-1.6.0-27/inst/bin/click differ
+Files click-1.6.0/inst/bin/click-align and click-1.6.0-27/inst/bin/click-align differ
+diff -Nurb click-1.6.0/inst/bin/click-buildtool click-1.6.0-27/inst/bin/click-buildtool
+--- click-1.6.0/inst/bin/click-buildtool 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/bin/click-buildtool 2009-02-05 10:20:40.000000000 -0500
+@@ -0,0 +1,1326 @@
++#! /bin/sh
++
++# click-buildtool -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2000-2001 Massachusetts Institute of Technology
++# Copyright (c) 2000-2006 Mazu Networks, Inc.
++# Copyright (c) 2001-2003 International Computer Science Institute
++# Copyright (c) 2004-2007 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++prefix=/d/click/click-1.6.0-27/inst
++exec_prefix=/d/click/click-1.6.0-27/inst
++bindir=/d/click/click-1.6.0-27/inst/bin
++datarootdir=/d/click/click-1.6.0-27/inst/share
++datadir=/d/click/click-1.6.0-27/inst/share
++clickdatadir=/d/click/click-1.6.0-27/inst/share/click
++LINUXMODULE_2_6=1
++gmake=make
++
++verbose=""
++elem2=""
++default_provisions="i686 i386 i586 int64 linux linux_2_6 pcap"
++driver_provisions=" userlevel linuxmodule"
++
++trap "exit 1" HUP
++
++# find a good version of awk
++if test -x /usr/bin/gawk; then
++ awk=gawk
++elif test -x /usr/bin/nawk; then
++ awk=nawk
++else
++ awk=awk
++fi
++
++echo_n () {
++ # suns can't echo -n, and Mac OS X can't echo "x\c"
++ echo "$@" | tr -d '
++'
++}
++
++
++############
++# FINDELEM #
++############
++
++findelem_usage () {
++ echo "Usage: click-buildtool findelem [-a] [-V] [-p PREFIX] < [FILES AND DIRECTORIES]
++Try 'click-buildtool findelem --help' for more information." 1>&2
++ exit 1
++}
++
++elementmap_provisions () {
++ elementmap="$1"
++ grep "^<elementmap \|^<entry " <"$elementmap" | $awk '/ name="([^"]*)"/ {
++ sub(/.* name="/, "", $0);
++ sub(/".*/, "", $0);
++ prov[$0] = 1;
++}
++/ provides="([^"]*)"/ {
++ sub(/.* provides="/, "", $0);
++ sub(/".*/, "", $0);
++ split($0, d, / +/);
++ for (j in d) prov[d[j]] = 1;
++}
++END {
++ # delete references to drivers
++ delete prov["userlevel"]; delete prov["linuxmodule"];
++ delete prov["bsdmodule"]; delete prov["ns"];
++ for (j in prov) print j;
++}'
++}
++
++findelem () {
++ pfx=
++ all=
++ provisions=
++ filenames=
++ standards=
++ unprovisions='false 0'
++ while [ x"$1" != x ]; do
++ case $1 in
++ -S|--s|--st|--sta|--stan|--stand|--standa|--standar|--standard|--standards)
++ standards=1; shift 1;;
++ -p|--pre|--pref|--prefi|--prefix)
++ if test $# -lt 2; then findelem_usage; fi
++ shift 1; pfx="$1/"; shift 1;;
++ -p*)
++ pfx="`echo "$1" | sed 's/^-p//'`"/; shift 1;;
++ --pre=*|--pref=*|--prefi=*|--prefix=*)
++ pfx="`echo "$1" | sed 's/^[^=]*=//'`"/; shift 1;;
++ -f|--filenames)
++ filenames=f; shift 1;;
++ -F|--filename-|--filename-p|--filename-pa|--filename-pai|--filename-pair|--filename-pairs)
++ filenames=F; shift 1;;
++ -V|--verb|--verbo|--verbos|--verbose)
++ verbose=1; shift 1;;
++ -a|--a|--al|--all)
++ all=1; shift 1;;
++ -r|--pro|--prov|--provi|--provid|--provide)
++ if test $# -lt 2; then findelem_usage; fi
++ shift 1; provisions="$1
++$provisions"; shift 1;;
++ -r*)
++ provisions="`echo "$1" | sed 's/^-r//'`
++$provisions"; shift 1;;
++ --pro=*|--prov=*|--provi=*|--provid=*|--provide=*)
++ provisions="`echo "$1" | sed 's/^[^=]*=//'`
++$provisions"; shift 1;;
++ -x|--u|--un|--unp|--unpr|--unpro|--unprov|--unprovi|--unprovid|--unprovide)
++ if test $# -lt 2; then findelem_usage; fi
++ shift 1; unprovisions="$1
++$unprovisions"; shift 1;;
++ -x*)
++ unprovisions="`echo "$1" | sed 's/^-x//'`
++$unprovisions"; shift 1;;
++ --u=*|--un=*|--unp=*|--unpr=*|--unpro=*|--unprov=*|--unprovi=*|--unprovid=*|--unprovide=*)
++ unprovisions="`echo "$1" | sed 's/^[^=]*=//'`
++$unprovisions"; shift 1;;
++ -e|--e|--el|--ele|--elem|--eleme|--elemen|--element|--elementm|--elementma|--elementmap)
++ if test $# -lt 2; then findelem_usage; fi
++ shift 1; provisions="`elementmap_provisions "$1"`
++$provisions"; shift 1;;
++ -e*)
++ emap="`echo "$1" | sed 's/^-e//'`"
++ provisions="`elementmap_provisions "$emap"`
++$provisions"; shift 1;;
++ --e=*|--el=*|--ele=*|--elem=*|--eleme=*|--elemen=*|--element=*|--elementm=*|--elementma=*|--elementmap=*)
++ emap="`echo '$1' | sed 's/^[^=]*=//'`"
++ provisions="`elementmap_provisions "$emap"`
++$provisions"; shift 1;;
++ -P|--pa|--pac|--pack|--packa|--packag|--package)
++ provisions="`elementmap_provisions "${clickdatadir}/elementmap.xml"`
++$provisions"; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool findelem' locates valid Click element source code. It starts
++with a collection of source code, then eliminates files whose requirements
++are not available until reaching a stable set of sources. It expects a list of
++files and directories on standard input. Directories are searched for .cc/.c
++source files. Only files containing EXPORT_ELEMENT() or ELEMENT_PROVIDES() are
++considered. The initial list of available requirements is the list of
++requirements specified with '-r', plus the list of EXPORT_ELEMENT() and
++ELEMENT_PROVIDES() keywords.
++
++Usage: click-buildtool findelem [OPTIONS] < [FILES AND DIRECTORIES]
++
++Options:
++ -a, --all Include all subdirectories of 'elements' rather
++ than reading standard input, and pretend all
++ requirements are available (except for '-x').
++ -V, --verbose Print more information about dependency checking.
++ -p, --prefix PREFIX Prepend PREFIX to every file and/or directory.
++ -r, --provide REQ Provide requirement(s) in REQ.
++ -e, --elementmap EMAP Provide requirement(s) from EMAP.
++ -P, --package Provide requirement(s) from default elementmap.
++ -S, --standards Mark standard elements as available.
++ -x, --unprovide REQ Mark requirement(s) REQ as unavailable.
++ -f, --filenames Output filenames only.
++ -F, --filename-pairs Output "sourcefile:headerfile" pairs for elements.
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ findelem_usage;;
++ esac
++ done
++
++ if test -n "$verbose" -a -n "$pfx"; then
++ echo "Prefix: $pfx" 1>&2
++ fi
++
++ # add defaults to provisions
++ provisions="$provisions $default_provisions"
++
++ # add standards to provisions if necessary
++ if test "x$standards" != x; then
++ provisions="$provisions AddressInfo AlignmentInfo ErrorElement PortInfo ScheduleInfo Storage"
++ fi
++
++ # expand provisions and unprovisions: require one per line
++ provisions=`echo "$provisions" | tr -s ' \011\015\014\013' '\012'`
++ unprovisions=`echo "$unprovisions" | tr -s ' \011\015\014\013' '\012'`
++ if test -n "$verbose" -a -n "$provisions"; then
++ echo 1>&2
++ echo "Provisions: $provisions" 1>&2
++ fi
++ if test -n "$verbose" -a -n "$unprovisions"; then
++ echo 1>&2
++ echo "Unprovisions: $unprovisions" 1>&2
++ fi
++
++ # expand list of files
++ if test -n "$all"; then
++ fdir=${pfx}
++ test -d ${pfx}elements && fdir=${pfx}elements
++ first_files=`cd $fdir >/dev/null && ls`
++ bad_first_files=`echo "$first_files
++$unprovisions" | sort | uniq -d`
++ first_files=`echo "$first_files
++$bad_first_files" | sort | uniq -u`
++ else
++ first_files=`cat`
++ fi
++
++ files=""
++ for i in $first_files; do
++ ppfx="$pfx"
++ if test -d "${pfx}elements/$i" && echo "$i" | grep -v '^\.' >/dev/null; then
++ ppfx="${pfx}elements/"
++ fi
++ if test -d "${ppfx}$i"; then
++ files="$files
++"`find ${ppfx}$i -follow \( -name \*.cc -o -name \*.c \) -print | grep -v '/[.,][^/]*$'`
++ elif test -r "${ppfx}$i"; then
++ files="$files
++${ppfx}$i"
++ fi
++ done
++ files=`echo "$files" | sort | uniq | grep .`
++
++ # die if no files
++ if test -z "$files"; then
++ echo "no files found" 1>&2
++ exit 1
++ fi
++
++ # if '$all', then accept all dependencies except the unprovisions
++ dep_test='<='
++ if test -n "$all"; then
++ dep_test='<'
++ fi
++
++ # check dependencies: generate a list of bad files, then remove those files
++ # from the list of good files
++
++ # first remove files that provide an unprovision
++ awk_exports=`echo "$unprovisions" | sed 's/\(..*\)/dep["\1"]=-1;/'`
++ bad_files=`egrep '^EXPORT_ELEMENT|^ELEMENT_PROVIDES' $files | sed 's/EXPORT_ELEMENT[ ]*(\(.*\)).*/\1/
++s/ELEMENT_PROVIDES[ ]*(\(.*\)).*/\1/' | $awk -F: 'BEGIN {OFS="";'"$awk_exports"'}
++{
++ split($2, deps, / +/);
++ for (j in deps) {
++ if (dep[deps[j]] < 0) {
++ print $1;
++ break;
++ }
++ }
++}' | sort | uniq`
++ if test -n "$verbose" -a -n "$bad_files"; then
++ echo 1>&2
++ echo "Files: $files" 1>&2
++ echo 1>&2
++ echo "Bad files: $bad_files" 1>&2
++ fi
++ if test -n "$bad_files"; then
++ files=`echo "$files
++$bad_files" | sort | uniq -u`
++ fi
++
++ # then cycle, removing files that require something not provided
++ while true; do
++ provides=`egrep '^EXPORT_ELEMENT|^ELEMENT_PROVIDES' $files | sed 's/.*(\(.*\)).*/\1/' | tr ' \011' '\012'`
++ awk_exports=`echo "$provides"'
++'"$provisions" | sed 's/\(..*\)/dep["\1"]=1;/'`"
++"`echo "$unprovisions" | sed 's/\(..*\)/dep["\1"]=-1;/'`
++ new_bad_files=`grep '^ELEMENT_REQUIRES' $files | sed 's/ELEMENT_REQUIRES[ ]*(\(.*\)).*/\1/' | $awk -F: 'BEGIN {OFS="";'"$awk_exports"'dep["true"]=1; dep["1"]=1;}
++{
++ split($2, deps, / +/);
++ for (j in deps) {
++ i = deps[j]
++ if (dep[i] <= 0) {
++ bad = 1;
++ split(i, or_deps, /\|+/);
++ for (k in or_deps) {
++ if (!(dep[or_deps[k]] '"$dep_test"' 0))
++ bad = 0;
++ }
++ if (bad) {
++ print $1;
++ break;
++ }
++ }
++ }
++}' | sort | uniq`
++ if test -n "$verbose"; then
++ echo 1>&2
++ echo "Files: $files" 1>&2
++ echo 1>&2
++ echo "Bad files: $new_bad_files" 1>&2
++ fi
++ if test -z "$new_bad_files"; then
++ break
++ else
++ files=`echo "$files
++$new_bad_files" | sort | uniq -u`
++ bad_files="$new_bad_files
++$bad_files"
++ fi
++ done
++
++ header_files=`echo "$files" | sed 's/\.cc/\.hh/'`
++
++ # generate output
++ if test "$filenames" = f; then
++ outscriptlet=i
++ elif test "$filenames" = F; then
++ outscriptlet='i, ":", header[i]'
++ else
++ echo "# Generated by 'click-buildtool findelem' on" `date`
++ outscriptlet='i, "\t", header[i], "\t", ex'
++ fi
++
++ egrep '^ELEMENT_PROVIDES|^EXPORT_ELEMENT|^ELEMENT_HEADER|^ELEMENT_LIBS|^class|^[ ]*const *char *\* *class_name|^[ ]*static *void *static_[ic]|^}' $files $header_files /dev/null 2>/dev/null | $awk -F: 'BEGIN {
++ OFS = ""; cur_class = ""; line_warned = 0; nexports = 0
++}
++/:class[ ]/ {
++ sub(/^class[ ]*/, "", $2);
++ sub(/[ ]*$/, "", $2);
++ cur_class = $2;
++ next
++}
++/:}/ {
++ cur_class = "";
++ next
++}
++/:EXPORT_ELEMENT/ {
++ sub(/.*EXPORT_ELEMENT[ ]*\([ ]*/, "", $2);
++ sub(/[ ]*\).*/, "", $2);
++ if (exports[$1] != "") {
++ exports[$1] = exports[$1] " " $2
++ } else {
++ exports[$1] = $2; nexports++
++ }
++ next
++}
++/:ELEMENT_PROVIDES/ {
++ if (!($1 in exports)) {
++ exports[$1] = ""; nexports++
++ }
++ next
++}
++/:ELEMENT_HEADER/ {
++ sub(/.*ELEMENT_HEADER[ ]*\(/, "", $2)
++ sub(/\).*/, "", $2)
++ header[$1] = $2
++ next
++}
++/:ELEMENT_LIBS/ {
++ sub(/.*ELEMENT_LIBS[ ]*\(\(?/, "", $2)
++ sub(/\)?\).*/, "", $2)
++ gsub(/[ ][ ]*/, ";", $2)
++ gsub(/-L;/, "-L", $2)
++ libs[$1] = $2
++ next
++}
++/class_name.*return[ ]"/ {
++ sub(/.*return[ ]*"/, "", $0);
++ sub(/".*/, "", $0);
++ class_name[cur_class] = $0
++ next
++}
++/class_name/ {
++ print $1, ": ", cur_class, "::class_name method malformed" | "cat 1>&2"
++ if (++line_warned == 1)
++ print " (class_name methods must be written on a single line.)" | "cat 1>&2"
++}
++/static_initialize/ {
++ static_initialize[cur_class] = 1
++ next
++}
++/static_cleanup/ {
++ static_cleanup[cur_class] = 1
++ next
++}
++END {
++ if (nexports == 0)
++ print "click-buildtool: No elements found" | "cat 1>&2"
++ if (line_warned || nexports == 0)
++ system("kill -HUP '$$'")
++ for (i in exports) {
++ ex = exports[i]
++ if (ex == "") {
++ print i
++ } else {
++ if (header[i] == "") {
++ header[i] = "\"" i "\""; sub(/\.cc/, ".hh", header[i])
++ }
++ split(ex, exes, / /); ex = ""
++ for (j in exes) {
++ dash = index(exes[j], "-")
++ if (dash == 0) {
++ dash = length(exes[j]);
++ if (class_name[exes[j]] == "")
++ exes[j] = exes[j] "-" exes[j];
++ else
++ exes[j] = exes[j] "-" class_name[exes[j]];
++ }
++ ex = ex exes[j] " ";
++ klass = substr(exes[j], 1, dash)
++ if (static_initialize[klass]) {
++ ex = ex klass "-!si ";
++ static_initialize[klass] = 0
++ }
++ if (static_cleanup[klass]) {
++ ex = ex klass "-!sc ";
++ static_cleanup[klass] = 0
++ }
++ }
++ if (libs[i])
++ ex = ex "-!lib" libs[i] " ";
++ print '"$outscriptlet"'
++ }
++ }
++}' | sort
++
++ exit $?
++}
++
++
++
++##########################
++# ELEM2MAKE/ELEM2PACKAGE #
++##########################
++
++elem2xxx_usage () {
++ echo_n "Usage: click-buildtool elem2$elem2 [-p PREFIX] [-V]" 1>&2
++ if test "$elem2" = package; then echo_n " PKGNAME" 1>&2; fi
++ echo " < elements.conf
++Try 'click-buildtool elem2$elem2 --help' for more information." 1>&2
++ exit 1
++}
++
++elem2make () {
++ driver=""
++ makevar=""
++ date=`date`
++ linux26=x
++ while [ x"$1" != x ]; do
++ case $1 in
++ -t|--d|--dr|--dri|--driv|--drive|--driver)
++ if test $# -lt 2; then elem2xxx_usage; fi
++ shift 1; driver="$1"; shift 1;;
++ -t*)
++ driver=`echo "$1" | sed 's/^-D//'`; shift 1;;
++ --d=*|--dr=*|--dri=*|--driv=*|--drive=*|--driver=*)
++ driver=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ --t|--ta|--tar|--targ|--targe|--target)
++ if test $# -lt 2; then elem2xxx_usage; fi
++ shift 1; driver="$1"; shift 1;;
++ --t=*|--ta=*|--tar=*|--targ=*|--targe=*|--target=*)
++ driver=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ -v|--m|--ma|--mak|--make|--make-|--make-v|--make-va|--make-var|--make-vari|--make-varia|--make-variab|--make-variabl|--make-variable)
++ if test $# -lt 2; then elem2xxx_usage; fi
++ shift 1; makevar="$1"; shift 1;;
++ -v*)
++ makevar=`echo "$1" | sed 's/^-v//'`; shift 1;;
++ --m=*|--ma=*|--mak=*|--make=*|--make-=*|--make-v=*|--make-va=*|--make-var=*|--make-vari=*|--make-varia=*|--make-variab=*|--make-variabl=*|--make-variable=*)
++ makevar=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ -x|--e|--ex|--exc|--excl|--exclu|--exclud|--exclude)
++ if test $# -lt 2; then elem2xxx_usage; fi
++ shift 1
++ for i in $1; do excludes=";/^$i"' \\$'"/d$excludes"; done
++ shift 1;;
++ -x*)
++ this_exclude=`echo "$1" | sed 's/^-p//'`
++ for i in $this_exclude; do excludes=";/^$i"' \\$'"/d$excludes"; done
++ shift 1;;
++ --e=*|--ex=*|--exc=*|--excl=*|--exclu=*|--exclud=*|--exclude=*)
++ this_exclude=`echo "$1" | sed 's/^[^=]*=//'`
++ for i in $this_exclude; do excludes=";/^$i"' \\$'"/d$excludes"; done
++ shift 1;;
++ --l|--li|--lin|--linu|--linux|--linux2|--linux26)
++ linux26=1; shift 1;;
++ --no-l|--no-li|--no-lin|--no-linu|--no-linux|--no-linux2|--no-linux26)
++ linux26=0; shift 1;;
++ -V|--verb|--verbo|--verbos|--verbose)
++ verbose=1; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool elem2make' reads an 'elements.conf' file generated by
++'click-buildtool findelem' on the standard input, and writes a Makefile
++fragment defining the ELEMENT_OBJS variable to the standard output.
++
++Usage: click-buildtool elem2make [-t DRIVER] [-V] < elements.conf
++
++Options:
++ -t, --driver DRIVER Set target driver to DRIVER ('userlevel',
++ 'linuxmodule', 'bsdmodule', 'ns', or 'tool').
++ -v, --make-variable N Use make variable N.
++ --linux26 Generate Linux 2.6-style makefile fragment.
++ -x, --exclude FILE Do not include FILE.
++ -V, --verbose Print more information.
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ elem2xxx_usage;;
++ esac
++ done
++
++ L=
++ defmakevar="ELEMENT_OBJS"
++ if test -n "$driver"; then
++ if test "$driver" = 'user' -o "$driver" = 'userlevel'; then
++ L=u
++ elif test "$driver" = 'kernel' -o "$driver" = 'linuxmodule'; then
++ L=k
++ test "$linux26" = x && linux26="$LINUXMODULE_2_6"
++ elif test "$driver" = 'bsdmodule'; then
++ L=b
++ elif test "$driver" = 'ns' -o "$driver" = 'nsmodule'; then
++ L=n
++ elif test "$driver" = 'tool'; then
++ L=t
++ else
++ echo "Unknown driver $driver" 1>&2
++ exit 1
++ fi
++ fi
++ osuffix=".${L}o"
++ if test -z "$makevar"; then
++ makevar=$defmakevar
++ fi
++
++ # expand list of files
++ elemconf=`cat`
++ files=`echo "$elemconf" | grep -v '^#' | sed 's/[ ].*//'`
++
++ # find libraries
++ libs=`echo "$elemconf" | sed '/-!lib/!d;s/^.*-!lib//g;s/;/ /g' | grep .`
++ if test -n "$libs"; then
++ libs=`echo "$libs" | sed 's/^\([^ ][^ ]*\) *$/\1 \1/'`
++ while echo "$libs" | grep ' [^ ].* [^ ]' >/dev/null; do
++ libs=`echo "$libs" | sed '/ [^ ].* [^ ]/s/^\([^ ][^ ]*\) *\([^ ][^ ]*\) /\1 \2\\
++\2 /'`
++ done
++ fi
++ test -n "$libs" && libs=`echo "$libs" | tsort`
++
++ # massage awk script based on Linux 2.6 or not
++ if test "$linux26" = 1; then
++ set_subdir_scriptlet='
++ if (dir != "" && substr(dir, 1, 1) == "/")
++ subdirs[dirid] = dir;
++ else
++ subdirs[dirid] = "$(obj)/" dir;
++ '
++ pattern_scriptlet='$(addprefix $(obj)/,$('"$makevar"'__", i, ")): $(obj)/%'"$osuffix"
++ ccaction=' $(call if_changed_dep,cxxcompile)'
++ caction=' $(call if_changed_dep,ccompile)'
++ else
++ set_subdir_scriptlet='subdirs[dirid] = dir;'
++ pattern_scriptlet='$('"$makevar"'__", i, "): %'"$osuffix"
++ ccaction=' $(call cxxcompile,-c $< -o $@,CXX)'
++ caction=' $(call ccompile,-c $< -o $@,CC)'
++ if test -n "$L"; then
++ ccaction="$ccaction"'\n $(FIXDEP)'
++ caction="$caction"'\n $(FIXDEP)'
++ fi
++ fi
++
++ # output
++ echo "# Generated by 'click-buildtool elem2make' on" `date`
++ echo "$files" | $awk '
++BEGIN { OFS = ""
++ action["c"] = "'"$caction"'";
++ action["cc"] = "'"$ccaction"'";
++}
++{ filetype = ($0 ~ /\.c$/ ? "c" : "cc");
++ sub(/\.cc*$/, "'"$osuffix"'");
++ i = match($0, /\/[^\/]*$/);
++ if (i == 0) {
++ dir = "";
++ file = $0;
++ } else {
++ dir = substr($0, 1, RSTART);
++ file = substr($0, RSTART + 1);
++ }
++ decdir = filetype dir;
++ if (decdir in subdirid)
++ dirid = subdirid[decdir];
++ else {
++ dirid = nsubdirs++;
++ subdirid[decdir] = dirid;
++ subdirtype[dirid] = filetype;
++ '"$set_subdir_scriptlet"'
++ }
++ elements[dirid] = elements[dirid] file " \\\n";
++}
++END {
++ for (i = 0; i < nsubdirs; i++) {
++ print "'"$makevar"'__", i, " = \\\n", elements[i];
++ allsubdirs = allsubdirs "$('"$makevar"'__" i ") \\\n";
++ }
++ print "'"$makevar"' = \\\n", allsubdirs;
++ for (i = 0; i < nsubdirs; i++) {
++ print "'"$pattern_scriptlet"': ", subdirs[i], "%.", subdirtype[i];
++ print action[subdirtype[i]];
++ }
++}' | sed "$excludes"
++ echo
++
++ if test -n "$libs"; then
++ libvar=`echo $makevar | sed 's/OBJS$/LIBS/'`
++ echo $libvar = $libs
++ fi
++}
++
++elem2xxx () {
++ package=""
++ date=`date`
++ standards=''
++ includes=''
++ while [ x"$1" != x ]; do
++ case $1 in
++ -S|--s|--st|--sta|--stan|--stand|--standa|--standar|--standard|--standards)
++ standards=1; shift 1;;
++ -V|--verb|--verbo|--verbos|--verbose)
++ verbose=1; shift 1;;
++ -i|--i|--in|--inc|--incl|--inclu|--includ|--include)
++ if test $# -lt 2; then elem2xxx_usage; fi
++ includes="$includes print '#include $2';"; shift 2;;
++ -i*)
++ this_include=`echo "$1" | sed 's/^-i//'`
++ includes="$includes print '#include $this_include';"; shift 1;;
++ --i=*|--in=*|--inc=*|--incl=*|--inclu=*|--includ=*|--include=*)
++ this_include=`echo "$1" | sed 's/^[^=]*=//'`
++ includes="$includes print '#include $this_include';"; shift 1;;
++ -h|--h|--he|--hel|--help)
++ if test "$elem2" = export; then
++ cat <<'EOF' 1>&2
++'Click-buildtool elem2export' reads an 'elements.conf' file generated by
++'click-buildtool findelem' on the standard input, examines those files for
++exported elements, and writes a C++ source file defining the
++click_export_elements() function to the standard output.
++
++Usage: click-buildtool elem2export [-V] < elements.conf
++EOF
++ elif test "$elem2" = package; then
++ cat <<'EOF' 1>&2
++'Click-buildtool elem2package' reads an 'elements.conf' file generated by
++'click-buildtool findelem' on the standard input, examines those files for
++exported elements, and writes a C++ source file suitable for creating a
++dynamically linked package with those elements to the standard output. PKGNAME
++is the name of the package.
++
++Usage: click-buildtool elem2package [-p PREFIX] [-V] PKGNAME < elements.conf
++EOF
++ fi
++ cat <<'EOF' 1>&2
++
++Options:
++ -S, --standards Export standard required elements as well.
++ -i, --include HDR Emit "#include HDR" at top of file.
++ -V, --verbose Print more information.
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ -*)
++ elem2xxx_usage;;
++ *)
++ if test -z "$package" -a "$elem2" = package; then package="$1"; shift 1; else elem2xxx_usage; fi;;
++ esac
++ done
++
++ # set up awk program
++ if test -n "$package"; then
++ includes=" $includes "'print "#define WANT_MOD_USE_COUNT 1\n#include <click/config.h>\n#include <click/package.hh>\n#include <click/glue.hh>";
++ for (file in INCLUDES) {
++ if (file != "-") print "#include ", file;
++ }'
++ awk_program='BEGIN {
++ OFS = ""; nrebecca = 0; packname="'"$package"'";
++}
++/^#/ { next; }
++{
++ if (NF == 1)
++ next;
++ INCLUDES[$2] = 1;
++ for (i = 3; i <= NF; i++) {
++ split($i, ans, /-/);
++ if (ans[2] == "!si")
++ B = B " " ans[1] "::static_initialize();\n";
++ else if (ans[2] == "!sc")
++ C = C " " ans[1] "::static_cleanup();\n";
++ else if (ans[2] !~ /^!/) {
++ B = B " hatred_of_rebecca[" nrebecca "] = click_add_element_type(\"" ans[2] "\", beetlemonkey, " nrebecca ");\n"
++ C = C " click_remove_element_type(hatred_of_rebecca[" nrebecca "]);\n";
++ D = D " case " nrebecca ": return new " ans[1] ";\n";
++ nrebecca++;
++ }
++ }
++}
++END {
++ print "/* Generated by \"click-buildtool elem2package\" on '"$date"' */";
++ print "/* Package name: ", packname, " */\n";
++'"$includes"'
++ print "\nCLICK_USING_DECLS";
++ print "static int hatred_of_rebecca[", nrebecca, "];";
++ print "static Element *\nbeetlemonkey(uintptr_t heywood)\n{\n switch (heywood) {\n", D, " default: return 0;\n }\n}\n";
++ print "#ifdef CLICK_LINUXMODULE\n#define click_add_element_type(n, f, t) click_add_element_type((n), (f), (t), THIS_MODULE)\n#endif";
++ print "#ifdef CLICK_BSDMODULE\nstatic int\nmodevent(module_t, int t, void *)\n{\n if (t == MOD_LOAD) {\n#else\nextern \"C\" int\ninit_module()\n{\n#endif";
++ print " click_provide(\"", packname, "\");\n", B, " CLICK_DMALLOC_REG(\"nXXX\");\n return 0;";
++ print "#ifdef CLICK_BSDMODULE\n } else if (t == MOD_UNLOAD) {\n#else\n}\nextern \"C\" void\ncleanup_module()\n{\n#endif";
++ print C, " click_unprovide(\"", packname, "\");";
++ print "#ifdef CLICK_BSDMODULE\n return 0;\n } else\n return 0;\n}\nstatic moduledata_t modinfo = {\n \"", packname, "\", modevent, 0\n};\nDECLARE_MODULE(", packname, ", modinfo, SI_SUB_PSEUDO, SI_ORDER_ANY);\n#else\n}\n#endif";
++}
++'
++
++ else
++ includes="$includes"' print "#include <click/config.h>\n#include <click/package.hh>";
++ for (file in INCLUDES) {
++ if (file != "-") print "#include ", file;
++ }'
++ awk_program='BEGIN {
++ OFS = ""; nrebecca = 0;
++}
++/^#/ { next; }
++{
++ if (NF == 1)
++ next;
++ INCLUDES[$2] = 1;
++ for (i = 3; i <= NF; i++) {
++ split($i, ans, /-/);
++ if (ans[2] == "!si")
++ B = B " " ans[1] "::static_initialize();\n";
++ else if (ans[2] == "!sc")
++ C = C " " ans[1] "::static_cleanup();\n";
++ else if (ans[2] !~ /^!/) {
++ B = B " (void) click_add_element_type(\"" ans[2] "\", beetlemonkey, " nrebecca ");\n";
++ D = D " case " nrebecca ": return new " ans[1] ";\n";
++ }
++ nrebecca++;
++ }
++}
++END {
++ print "/* Generated by \"click-buildtool elem2export\" on '"$date"' */\n";
++'"$includes"'
++ print "CLICK_USING_DECLS";
++ print "static Element *\nbeetlemonkey(uintptr_t heywood)\n{\n switch (heywood) {\n", D, " default: return 0;\n }\n}\n";
++ print "#ifdef CLICK_LINUXMODULE\n#define click_add_element_type(n, f, t) click_add_element_type((n), (f), (t), 0)\n#endif";
++ print "void\nclick_export_elements()\n{\n", B, " CLICK_DMALLOC_REG(\"nXXX\");\n}\n";
++ print "void\nclick_unexport_elements()\n{\n", C, "}";
++}
++'
++ fi
++
++ # Actually generate the command!
++ if test -z "$standards"; then
++ $awk "$awk_program"
++ else
++ cat <<EOF >/tmp/click-buildtool-standards.$$
++- <click/standard/addressinfo.hh> AddressInfo-AddressInfo
++- <click/standard/alignmentinfo.hh> AlignmentInfo-AlignmentInfo
++- <click/standard/errorelement.hh> ErrorElement-ErrorElement
++- <click/standard/portinfo.hh> PortInfo-PortInfo
++- <click/standard/scheduleinfo.hh> ScheduleInfo-ScheduleInfo
++EOF
++ cat - /tmp/click-buildtool-standards.$$ | $awk "$awk_program"
++ /bin/rm -f /tmp/click-buildtool-standards.$$
++ fi
++}
++
++
++
++############
++# PROVIDES #
++############
++
++provides_usage () {
++ echo "Usage: click-buildtool provides [REQS]" 1>&2
++ echo "Try 'click-buildtool provides --help' for more information." 1>&2
++ exit 1
++}
++
++provides () {
++ provisions="$default_provisions
++$driver_provisions
++"`elementmap_provisions ${clickdatadir}/elementmap.xml`
++ requirements=""
++ stdin=n; query=n; print=n
++ while [ x"$1" != x ]; do
++ case $1 in
++ -q|--q|--qu|--que|--quer|--query)
++ query=y; shift 1;;
++ -l|--pri|--prin|--print)
++ print=y; shift 1;;
++ -r|--pro|--prov|--provi|--provid|--provide)
++ if test $# -lt 2; then provides_usage; fi
++ shift 1; provisions="$1
++$provisions"; shift 1;;
++ -r*)
++ provisions=`echo "$1" | sed 's/^-r//'`"
++$provisions"; shift 1;;
++ --p=*|--pr=*|--pro=*|--prov=*|--provi=*|--provid=*|--provide=*)
++ provisions=`echo "$1" | sed 's/^[^=]*=//'`"
++$provisions"; shift 1;;
++ -e|--e|--el|--ele|--elem|--eleme|--elemen|--element|--elementm|--elementma|--elementmap)
++ if test $# -lt 2; then provides_usage; fi
++ shift 1; provisions=`elementmap_provisions $1`"
++$provisions"; shift 1;;
++ -e*)
++ emap=`echo "$1" | sed 's/^-e//'`
++ provisions=`elementmap_provisions $emap`"
++$provisions"; shift 1;;
++ --e=*|--el=*|--ele=*|--elem=*|--eleme=*|--elemen=*|--element=*|--elementm=*|--elementma=*|--elementmap=*)
++ emap=`echo "$1" | sed 's/^[^=]*=//'`
++ provisions=`elementmap_provisions $emap`"
++$provisions"; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool provides' exits with status 0 if the Click installation
++provides all requirement(s) in REQ arguments, and status 1 otherwise.
++
++Usage: click-buildtool provides [OPTIONS] [REQ...]
++
++Options:
++ -q, --query Print provisions to standard output.
++ -r, --provide REQ Provide requirement(s) in REQ.
++ -e, --elementmap EMAP Provide requirement(s) from EMAP.
++ -l, --print Print 0 (REQs not provided) or 1 (REQs provided).
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ -)
++ stdin=y; shift 1;;
++ -*)
++ provides_usage;;
++ *)
++ requirements="$1
++$requirements"; shift 1;;
++ esac
++ done
++
++ [ $stdin = y ] && requirements="`cat` $requirements"
++ provisions="`echo "$provisions" | tr -s ' \011\015\014\013' '\012' | grep . | sort | uniq`"
++ [ $query = y ] && echo "$provisions"
++ requirements="`echo "$requirements" | tr -s ' \011\015\014\013' '\012' | grep . | sort | uniq`"
++ awk_provisions="`echo "$provisions" | sed 's/\(..*\)/dep["\1"]=1;/'`"
++ echo "$requirements" | $awk -F: 'BEGIN {
++'"$awk_provisions"'
++}
++/./ { if (!dep[$1]) exit 1; }' >/dev/null 2>&1
++ status=$?
++ [ $print = y ] && expr 1 - $status
++ exit $status
++}
++
++
++#############
++# QUIETLINK #
++#############
++
++quietlink_usage () {
++ echo "Usage: click-buildtool quietlink" 1>&2
++ echo "Try 'click-buildtool quietlink --help' for more information." 1>&2
++ exit 1
++}
++
++quietlink () {
++ while [ x"$1" != x ]; do
++ case $1 in
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool quietlink' quiets the GNU linker when linking an element
++package. Specifically, it removes undefined reference complaints.
++
++Usage: ld ... 2>&1 | click-buildtool quietlink
++
++Options:
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ quietlink_usage;;
++ esac
++ done
++
++ $awk -F: 'BEGIN {
++ context = ""
++}
++/: In function/ {
++ context = $0
++ next
++}
++/: undefined reference to/ {
++ next
++}
++/: more undefined references to/ {
++ next
++}
++{
++ if (context != "") {
++ print context
++ context = ""
++ }
++ print $0
++}' 1>&2
++}
++
++
++
++##########
++# PREFIX #
++##########
++
++prefix_usage () {
++ echo "Usage: click-buildtool prefix" 1>&2
++ echo "Try 'click-buildtool prefix --help' for more information." 1>&2
++ exit 1
++}
++
++prefix () {
++ while [ x"$1" != x ]; do
++ case $1 in
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool prefix' prints the Click prefix directory.
++
++Usage: click-buildtool prefix
++
++Options:
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ prefix_usage;;
++ esac
++ done
++ echo $prefix
++}
++
++
++
++############
++# KVERSION #
++############
++
++kversion_usage () {
++ echo_n "Usage: click-buildtool kversion [--gpl] > kversion.c" 1>&2
++ echo "Try 'click-buildtool kversion --help' for more information." 1>&2
++ exit 1
++}
++
++kversion () {
++ gpl=0
++ linux26=$LINUXMODULE_2_6
++ while [ x"$1" != x ]; do
++ case $1 in
++ --g|--gp|--gpl)
++ gpl=1; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool kversion' writes a kversion.c file, to be used for building
++a Click kernel package, on the standard output.
++
++Usage: click-buildtool kversion [--gpl] > kversion.c
++
++Options:
++ --gpl The package is dual-licensed BSD/GPL (otherwise
++ no license).
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ kversion_usage;;
++ esac
++ done
++
++ cat <<EOF
++#include <click/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++
++/* a new version of EXPORT_NO_SYMBOLS that works */
++const int __ksymtab_nothing[0] __attribute__((section("__ksymtab"))) = { };
++EOF
++ test $gpl = 1 && cat <<EOF
++
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++EOF
++}
++
++
++
++##########
++# KBUILD #
++##########
++
++kbuild_usage () {
++ echo_n "Usage: click-buildtool kbuild > Kbuild" 1>&2
++ echo "Try 'click-buildtool kbuild --help' for more information." 1>&2
++ exit 1
++}
++
++kbuild () {
++ while [ x"$1" != x ]; do
++ case $1 in
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool kbuild' writes a Kbuild file, to be used for building
++a Click kernel package for Linux 2.6 kernels, on the standard output.
++
++Usage: click-buildtool kbuild > Kbuild
++
++Options:
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ kversion_usage;;
++ esac
++ done
++
++ echo "include ${clickdatadir}/pkg-linuxmodule-26.mk"
++}
++
++
++
++###############
++# MAKEPACKAGE #
++###############
++
++makepackage_usage () {
++ echo "Usage: click-buildtool makepackage [-t DRIVER] PACKAGENAME SRCFILES..." 1>&2
++ echo "Try 'click-buildtool makepackage for more information." 1>&2
++ exit 1
++}
++
++makepackage () {
++ driver=""
++ date=`date`
++ dir=
++ pkg=
++ srcs=
++ quiet=
++ cflags=
++ while [ x"$1" != x ]; do
++ case $1 in
++ -t|--d|--dr|--dri|--driv|--drive|--driver)
++ test $# -lt 2 && makepackage_usage
++ shift 1; driver="$1"; shift 1;;
++ -t*)
++ driver=`echo "$1" | sed 's/^-D//'`; shift 1;;
++ --dr=*|--dri=*|--driv=*|--drive=*|--driver=*)
++ driver=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ --t|--ta|--tar|--targ|--targe|--target)
++ test $# -lt 2 && makepackage_usage
++ shift 1; driver="$1"; shift 1;;
++ --t=*|--ta=*|--tar=*|--targ=*|--targe=*|--target=*)
++ driver=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ -C|--di|--dir|--dire|--direc|--direct|--directo|--director|--directory)
++ test $# -lt 2 && makepackage_usage
++ shift 1; dir="$1"; shift 1;;
++ -C*)
++ dir="`echo "$1" | sed 's/^-C//'`"/; shift 1;;
++ --di=*|--dir=*|--dire=*|--direc=*|--direct=*|--directo=*|--director=*|--directory=*)
++ dir="`echo "$1" | sed 's/^[^=]*=//'`"/; shift 1;;
++ -q|--q|--qu|--qui|--quie|--quiet)
++ quiet="-s"; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool makepackage' builds a Click package for the specified
++driver from sources listed on the command line.
++
++Usage: click-buildtool makepackage [-t DRIVER] PACKAGENAME SRCFILES...
++
++Options:
++ -t, --driver DRIVER Set target driver to DRIVER ('userlevel',
++ 'linuxmodule', 'bsdmodule', 'ns', or 'tool').
++ -q, --quiet Build quietly (may be ignored).
++ -C, --directory DIR Switch to DIR directory before building.
++ -h, --help Print this message and exit.
++ -[other options] Passed to the C/C++ compiler.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ -*)
++ cflags="$cflags $1"; shift 1;;
++ *)
++ if test -z "$pkg"; then
++ pkg="$1"; shift 1
++ else
++ srcs="$srcs
++$1"; shift 1
++ fi;;
++ esac
++ done
++
++ test -z "$srcs" && makepackage_usage
++
++ objs=
++ objsvar=OBJS
++ if test -z "$driver" -o "$driver" = 'user' -o "$driver" = 'userlevel'; then
++ L=u
++ elif test "$driver" = 'kernel' -o "$driver" = 'linuxmodule'; then
++ L=k
++ elif test "$driver" = 'bsdmodule'; then
++ L=b
++ elif test "$driver" = 'ns' -o "$driver" = 'nsmodule'; then
++ L=n
++ elif test "$driver" = 'tool'; then
++ L=t
++ else
++ echo "Unknown driver $driver" 1>&2
++ exit 1
++ fi
++ osuffix=".${L}o"
++
++ if test -n "$dir"; then cd "$dir"; fi
++ echo > ${L}elements.conf
++ echo "$srcs" | grep . | elem2make -t $driver > ${L}elements.mk
++ echo "PACKAGE_OBJS :=" >> ${L}elements.mk
++
++ echo "package = $pkg
++
++srcdir = .
++top_srcdir = .
++builddir = .
++top_builddir = .
++PACKAGE_CFLAGS = $cflags
++PACKAGE_CXXFLAGS = $cflags
++
++include ${clickdatadir}/config.mk
++include ${clickdatadir}/pkg-Makefile" > Makefile
++
++ test -z "$quiet" && echo "+" $gmake $pkg$osuffix
++ $gmake $quiet $pkg$osuffix
++}
++
++
++
++#########
++# KSYMS #
++#########
++
++ksyms_usage () {
++ echo "Usage: click-buildtool ksyms OBJ... > KSYMS" 1>&2
++ echo "Try 'click-buildtool ksyms --help' for more information." 1>&2
++ exit 1
++}
++
++ksyms () {
++ driver=""
++ date=`date`
++ dir=
++ objs=
++ exclude=
++ while [ x"$1" != x ]; do
++ case $1 in
++ -C|--di|--dir|--dire|--direc|--direct|--directo|--director|--directory)
++ test $# -lt 2 && ksyms_usage
++ shift 1; dir="$1"; shift 1;;
++ -C*)
++ dir="`echo "$1" | sed 's/^-C//'`"/; shift 1;;
++ --di=*|--dir=*|--dire=*|--direc=*|--direct=*|--directo=*|--director=*|--directory=*)
++ dir="`echo "$1" | sed 's/^[^=]*=//'`"/; shift 1;;
++ -x|--e|--ex|--exc|--excl|--exclu|--exclud|--exclude)
++ test $# -lt 2 && ksyms_usage
++ shift 1; exclude="$exclude
++$1"; shift 1;;
++ -x*)
++ exclude="$exclude
++`echo "$1" | sed 's/^-x//'`"; shift 1;;
++ --e=*|--ex=*|--exc=*|--excl=*|--exclu=*|--exclud=*|--exclude=*)
++ exclude="$exclude
++`echo "$1" | sed 's/^[^=]*=//'`"; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool ksyms' creates a C file that exports all symbols for the
++Click objects listed on the command line.
++
++Usage: click-buildtool ksyms OBJ... > KSYMS
++
++Options:
++ -x, --exclude=FILE Ignore OBJ even if it is supplied as an argument.
++ -C, --directory DIR Switch to DIR directory before running.
++ -h, --help Print this message and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ *)
++ objs="$objs
++$1"; shift 1;;
++ esac
++ done
++
++ test -z "$objs" && ksyms_usage
++ objs=`echo "$objs" | sort | uniq`
++ test -n "$exclude" && objs=`echo "$objs
++$exclude" | sort | uniq -u`
++
++ if test -n "$dir"; then cd "$dir"; fi
++ echo "// Created by 'click-buildtool ksyms' on $date"
++ echo "#include <click/config.h>"
++ echo "#include <linux/version.h>"
++ echo "#include <linux/module.h>"
++ nm -g $objs | $awk '
++BEGIN {
++ printed["init_module"] = printed["cleanup_module"] = 1;
++}
++/^[ ]/ {
++ next
++}
++/........[ ][ABCDGRSTVW]/ {
++ x = $3;
++ if (x ~ /^[_A-Za-z][_A-Za-z0-9]*$/ && !printed[x]) {
++ printed[x] = 1;
++ if (x != "click_assert_failed")
++ print "extern char " x "[];";
++ print "EXPORT_SYMBOL(" x ");";
++ }
++}'
++}
++
++
++
++################
++# MAIN PROGRAM #
++################
++
++if test $# = 0; then
++ # force usage message
++ set crapfunc
++fi
++
++while [ x"$1" != x ]; do
++case $1 in
++ --vers|--versi|--versio|--version)
++ cat <<'EOF'
++click-buildtool (Click) 1.6.0
++Copyright (c) 2000-2001 Massachusetts Institute of Technology
++Copyright (c) 2000-2004 Mazu Networks, Inc.
++Copyright (c) 2001-2003 International Computer Science Institute
++Copyright (c) 2004-2007 Regents of the University of California
++This is free software; see the source for copying conditions.
++There is NO warranty, not even for merchantability or fitness for a
++particular purpose.
++EOF
++ exit 0;;
++ -V|--verb|--verbo|--verbos|--verbose)
++ verbose=1; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF' 1>&2
++'Click-buildtool' is a set of tools used when building Click. For information
++on a particular tool, run 'click-buildtool TOOLNAME --help'.
++
++Usage: click-buildtool elem2make [-V] [-p PREFIX] < [ELEMENTS]
++ or: click-buildtool elem2export [-V] [-p PREFIX] < [ELEMENTS]
++ or: click-buildtool elem2package [-V] [-p PREFIX] PACKAGENAME < [ELEMENTS]
++ or: click-buildtool findelem [-a] [-V] [-p PREFIX] < [FILES AND DIRECTORIES]
++ or: click-buildtool makepackage [-t DRIVER] PACKAGENAME SRCFILES...
++ or: click-buildtool prefix
++ or: click-buildtool provides [REQS]
++ or: click-buildtool quietlink
++ or: click-buildtool kbuild
++ or: click-buildtool kversion [--gpl]
++ or: click-buildtool ksyms OBJS > KSYMSFILE
++
++Options:
++ -V, --verbose Print more information.
++ -h, --help Print this message and exit.
++ --version Print version number and exit.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ findelem)
++ shift 1; findelem "$@"; exit 0;;
++ elem2make)
++ elem2="make"; shift 1; elem2make "$@"; exit 0;;
++ elem2export)
++ elem2="export"; shift 1; elem2xxx "$@"; exit 0;;
++ elem2package)
++ elem2="package"; shift 1; elem2xxx "$@"; exit 0;;
++ makepackage)
++ shift 1; makepackage "$@"; exit 0;;
++ prefix)
++ shift 1; prefix "$@"; exit 0;;
++ provides)
++ shift 1; provides "$@"; exit 0;;
++ quietlink)
++ shift 1; quietlink "$@"; exit 0;;
++ kversion)
++ shift 1; kversion "$@"; exit 0;;
++ kbuild)
++ shift 1; kbuild "$@"; exit 0;;
++ ksyms)
++ shift 1; ksyms "$@"; exit 0;;
++ *)
++ echo "Usage: click-buildtool TOOLNAME [ARGUMENTS]
++Try 'click-buildtool --help' for more information." 1>&2
++ exit 1;;
++esac
++done
+Files click-1.6.0/inst/bin/click-check and click-1.6.0-27/inst/bin/click-check differ
+Files click-1.6.0/inst/bin/click-combine and click-1.6.0-27/inst/bin/click-combine differ
+diff -Nurb click-1.6.0/inst/bin/click-compile click-1.6.0-27/inst/bin/click-compile
+--- click-1.6.0/inst/bin/click-compile 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/bin/click-compile 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,302 @@
++#! /bin/sh
++
++# click-compile.in -- script compiles Click elements
++# Eddie Kohler
++#
++# Copyright (c) 1999 Massachusetts Institute of Technology
++# Copyright (c) 2001 International Computer Science Institute
++# Copyright (c) 2005 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++prefix=/d/click/click-1.6.0-27/inst
++exec_prefix=/d/click/click-1.6.0-27/inst
++includedir=/d/click/click-1.6.0-27/inst/include
++libdir=/d/click/click-1.6.0-27/inst/lib
++datarootdir=/d/click/click-1.6.0-27/inst/share
++datadir=/d/click/click-1.6.0-27/inst/share
++srcdir=${datadir}/click/src
++linuxdir=/d/kernels/linux-2.6.27.10-clickport
++freebsd_includedir=/usr/include
++CLICK_VERSION=1.6.0
++
++# determine mode
++directory=.
++driver=
++package=NONE
++cflags=
++compileflag=-c
++quiet=
++gpl=y
++while true; do
++ bad=x
++ case $1 in
++ -t|--dr|--dri|--driv|--drive|--driver)
++ driver=$2; shift 2;;
++ -t*)
++ driver=`echo "$1" | sed 's/^-t//'`; shift 1;;
++ --dr=*|--dri=*|--driv=*|--drive=*|--driver=*)
++ driver=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
++ --c|--cf|--cfl|--cfla|--cflag|--cflags|--de|--def|--defs)
++ echo -I$includedir
++ exit 0;;
++ --l|--li|--lib|--libs)
++ echo -L$libdir -lclick -lpcap -ldl
++ exit 0;;
++ --toolc|--toolcf|--toolcfl|--toolcfla|--toolcflag|--toolcflags)
++ echo -DCLICK_TOOL -I$includedir
++ exit 0;;
++ --tooll|--toolli|--toollib|--toollibs)
++ echo -L$libdir -lclicktool -ldl
++ exit 0;;
++ --o|--ot|--oth|--othe|--other|--otherl|--otherli|--otherlib|--otherlibs)
++ echo -lpcap -ldl
++ exit 0;;
++ -d|--di|--dir|--dire|--direc|--direct|--directo|--director|--directory)
++ directory=$2; shift 2;;
++ -d*)
++ directory=`echo "$1" | sed 's/^-d//'`; shift 1;;
++ --di=*|--dir=*|--dire=*|--direc=*|--direct=*|--directo=*|--director=*|--directory=*)
++ directory=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
++ --t|--ta|--tar|--targ|--targe|--target)
++ echo "click-compile: '--target' is obsolete; change your script to use '--driver'" 1>&2
++ driver=$2; shift 2;;
++ --t=*|--ta=*|--tar=*|--targ=*|--targe=*|--target=*)
++ echo "click-compile: '--target' is obsolete; change your script to use '--driver'" 1>&2
++ driver=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
++ -p|--p|--pa|--pac|--pack|--packa|--packag|--package)
++ package=$2; shift 2;;
++ -p*)
++ package=`echo "$1" | sed 's/^-p//'`; shift 1;;
++ --p=*|--pa=*|--pac=*|--pack=*|--packa=*|--packag=*|--package=*)
++ package=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
++ -q|--q|--qu|--qui|--quie|--quiet)
++ quiet=y; shift 1;;
++ --no-g|--no-gp|--no-gpl)
++ gpl=n; shift 1;;
++ -h|--h|--he|--hel|--help)
++ cat <<'EOF'
++'Click-compile' compiles a Click source file, or outputs any compiler options
++relevant for userlevel Click drivers.
++
++Usage: click-compile -t DRIVER [OPTIONS] SOURCEFILE...
++
++Options:
++ --defs Outputs preprocessor options for userlevel drivers.
++ --libs Outputs link options for userlevel drivers.
++ --otherlibs Like '--libs' minus the Click library.
++ --toolcflags Outputs C/C++ flags options for tools.
++ --toollibs Outputs link options for tools.
++ -t, --driver DRIVER Sets target driver to 'bsdmodule', 'linuxmodule',
++ 'userlevel', 'ns', or 'tool'.
++ -p, --package PACKAGE Build a dynamically loadable package named PACKAGE.
++ -d, --directory DIR Change to directory DIR.
++ -q, --quiet Be quiet (don't echo commands or print warnings).
++ --no-gpl Omit "BSD/GPL" declaration from kernel package.
++ -h, --help Print this message and exit.
++ -v, --version Print version number and exit.
++ Other options are passed to the compiler unchanged.
++
++Report bugs to <click@pdos.lcs.mit.edu>.
++EOF
++ exit 0;;
++ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
++ echo click-compile '(Click)' $CLICK_VERSION
++ cat <<"EOF"
++Copyright (C) 1999-2001 Massachusetts Institute of Technology
++Copyright (C) 2002 International Computer Science Institute
++Copyright (C) 2004 Regents of the University of California
++This is free software; see the source for copying conditions.
++There is NO warranty, not even for merchantability or fitness for any
++particular purpose.
++EOF
++ exit 0;;
++ -*)
++ if test "$1" = -E -o "$1" = -c -o "$1" = -S; then
++ compileflag=$1
++ else
++ cflags="$cflags '$1'"
++ fi
++ shift 1;;
++ *)
++ bad=;;
++ esac
++ if test -z "$bad"; then break; fi
++done
++
++cd $directory
++
++# test directory function
++test_dir () {
++ test -d "$1" -a -d "$1/elements" -a -d "$1/lib"
++}
++
++# analyze CLICKPATH to find sources
++path=${CLICKPATH-:}
++tried_defaults=
++include_source=
++while true; do
++ case $path in
++ :*)
++ if test -z "$tried_defaults" && test_dir "$srcdir"; then
++ include_source="-I$srcdir"
++ else
++ tried_defaults=y
++ fi
++ path=`echo "$path" | sed 's/://'`
++ ;;
++ *:*)
++ dir=`echo "$path" | sed 's/:.*//'`
++ if test_dir "$dir"; then include_source="-I$dir"; fi
++ path=`echo "$path" | sed 's/[^:]*://'`
++ ;;
++ *:)
++ dir=`echo "$path" | sed 's/:.*//'`
++ if test_dir "$dir"; then include_source="-I$dir"; fi
++ path=":"
++ ;;
++ *)
++ if test_dir "$path"; then include_source="-I$path"; fi
++ path=""
++ ;;
++ esac
++ if test -z "$path" -o -n "$include_source"; then break; fi
++done
++
++if test ! -d "$includedir"; then
++ echo "click-compile: Cannot find Click include directory!" 1>&2
++ echo " (Have you installed Click yet?)" 1>&2
++ exit 1
++elif test -z "$include_source"; then
++ if test -z "$quiet"; then
++ echo "click-compile: warning: cannot find full Click source" 1>&2
++ fi
++fi
++
++
++case $driver in
++ u|us|use|user|userl|userle|userlev|userleve|userlevel)
++ idefs="-DHAVE_CONFIG_H -DCLICK_USERLEVEL"
++ iincludes="${include_source} -I${includedir}"
++ icppflags=""
++ icxxflags="-fPIC -g -O2 -MD"
++ icflags="-fPIC -g -O2 -MD"
++ command="${CXX-g++ -W -Wall } ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
++ c_command="${CC-gcc -W -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CFLAGS-$icflags} $cflags $compileflag"
++ driver=userlevel;;
++ k|ke|ker|kern|kerne|kernel|l|li|lin|linu|linux|linuxm|linuxmo|linuxmod|linuxmodu|linuxmodul|linuxmodule)
++ idefs="-DHAVE_CONFIG_H -DCLICK_LINUXMODULE"
++ iincludes="${include_source} -I${includedir} -I${linuxdir}/include"
++ icppflags=""
++ icxxflags=" -O2 -MD"
++ icflags=" -O2 -MD"
++ command="${CXX-g++ -w -W -Wall -fno-exceptions -fno-rtti -D__SMP__} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
++ c_command="${CC-gcc -W -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CFLAGS-$icflags} $cflags $compileflag"
++ driver=linuxmodule;;
++ b|bs|bsd|bsdm|bsdmo|bsdmod|bsdmodu|bsdmodul|bsdmodule)
++ idefs="-DHAVE_CONFIG_H -DCLICK_BSDMODULE"
++ iincludes="-nostdinc ${include_source} -I${includedir}"
++ icppflags=""
++ icxxflags=" -O2 -MD"
++ icflags=" -O2 -MD"
++ command="${CXX-g++ -w -W -Wall -fno-exceptions -fno-rtti -D__SMP__} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
++ c_command="${CC-gcc -W -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CFLAGS-$icflags} $cflags $compileflag"
++ driver=bsdmodule;;
++ ns|nsm|nsmo|nsmod|nsmodu|nsmodul|nsmodule)
++ idefs="-DHAVE_CONFIG_H -DCLICK_NS"
++ iincludes="${include_source} -I${includedir}"
++ icppflags=""
++ icxxflags="-fPIC -g -O2 -MD"
++ icflags="-fPIC -g -O2 -MD"
++ command="${CXX-g++ -W -Wall } ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
++ c_command="${CC-gcc -W -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CFLAGS-$icflags} $cflags $compileflag"
++ driver=ns;;
++ t|to|too|tool)
++ idefs="-DHAVE_CONFIG_H -DCLICK_TOOL"
++ iincludes="${include_source} -I${includedir}"
++ icppflags=""
++ icxxflags="-fPIC -g -O2 -MD"
++ icflags="-fPIC -g -O2 -MD"
++ command="${CXX-g++ -W -Wall } ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
++ c_command="${CC-gcc -W -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-$icppflags} ${CFLAGS-$icflags} $cflags $compileflag"
++ driver=tool;;
++ "")
++ echo "click-compile: you must specify a driver" 1>&2; exit 1;;
++ *)
++ echo "click-compile: acceptable drivers are 'userlevel', 'linuxmodule'," 1>&2
++ echo "click-compile: 'bsdmodule', and 'tool'" 1>&2; exit 1;;
++esac
++
++exec_command () {
++ if test -z "$quiet"; then
++ echo "$@" 1>&2
++ fi
++ eval "$@" || exit 1
++}
++
++compile_file () {
++ option=
++ source="$1"; shift
++ if test -r "$source"; then
++ option=`head -n 5 $source | grep '^/\*\* click-compile:' | sed -e 's/\/\*\* click-compile://g' -e 's/\*\///g'`
++ fi
++ exec_command $command $option $source "$@"
++}
++
++# do stuff
++if test "x$package" != "xNONE"; then
++ command="$command -DCLICK_PACKAGE"
++ files=; rmfiles=
++ trap 'rm -f $rmfiles' 0
++ trap 'rm -f $rmfiles; exit 1' 1 2 15
++ for file; do
++ if echo "$file" | grep '\.cc*$' >/dev/null 2>&1; then
++ objfile=`echo "$file" | sed 's/\.c*$/'"$$"'\.o/;s/^.*\///'`
++ compile_file $file -o $objfile
++ rmfiles="$rmfiles $objfile "`echo $objfile | sed 's/\.o/\.d/'`
++ else
++ objfile="$file"
++ fi
++ files="$files $objfile"
++ done
++ if test $driver = linuxmodule; then
++ vfile=kernelversion$$
++ test -f $vfile.c && echo "click-compile: A file '$vfile.c' already exists in this directory!" 1>&2 && echo "click-compile: You must remove it, or run me somewhere else." 1>&2 && exit 1
++ files="$files $vfile.o"
++ rmfiles="$rmfiles $vfile.o $vfile.c $vfile.d"
++ cat > $vfile.c <<EOF
++#include <click/config.h>
++#include <linux/module.h>
++/* a new version of EXPORT_NO_SYMBOLS that works */
++const int __ksymtab_nothing[0] __attribute__((section("__ksymtab"))) = { };
++EOF
++ if test $gpl = y; then
++ cat >> $vfile.c <<EOF
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("Dual BSD/GPL");
++#endif
++EOF
++ fi
++ c_command_nowarn=`echo $c_command | sed 's/-W[-a-z]*//g'`
++ exec_command $c_command_nowarn $vfile.c
++ exec_command "ld -r -o $package $cflags $files"
++ exit 0
++ elif test $driver = userlevel -o $driver = tool -o $driver = ns; then
++ exec_command "${CXX-g++ -W -Wall } ${CXXFLAGS-$icxxflags} -shared -o $package $cflags $files"
++ exit 0
++ elif test $driver = bsdmodule; then
++ exec_command "ld -Bshareable -o $package $cflags $files"
++ exit 0
++ fi
++else
++ exec_command "$command $@"
++ exit 0
++fi
+Files click-1.6.0/inst/bin/click-devirtualize and click-1.6.0-27/inst/bin/click-devirtualize differ
+diff -Nurb click-1.6.0/inst/bin/click-elem2man click-1.6.0-27/inst/bin/click-elem2man
+--- click-1.6.0/inst/bin/click-elem2man 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/bin/click-elem2man 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,1484 @@
++#! /usr/bin/perl -w
++
++# click-elem2man -- creates man pages from structured comments in element
++# source code
++# Eddie Kohler
++# Robert Morris - original make-faction-html script
++#
++# Copyright (c) 1999-2001 Massachusetts Institute of Technology
++# Copyright (c) 2001-2003 International Computer Science Institute
++# Copyright (c) 2006 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++my($verbose) = 0;
++
++# information stored about each Click element, indexed by C++ class name
++my(%processing, %deprecated, %portcount, %docrequires, %requires, $PREFIX);
++
++my(%section_break) =
++ ( 'head1' => 1, 'c' => 1, 's' => 1,
++ 'io' => 1, 'processing' => 1, 'drivers' => 1,
++ 'd' => 1, 'n' => 1, 'e' => 1, 'h' => 1, 'a' => 1, 'title' => 1,
++ 'deprecated' => 1, 'package' => 1 );
++my(%section_takes_args) =
++ ( 'head1' => 1, 'c' => 0, 's' => 2,
++ 'io' => 2, 'processing' => 2, 'drivers' => 2,
++ 'd' => 0, 'n' => 0, 'e' => 0, 'h' => 1, 'a' => 2, 'title' => 1,
++ 'deprecated' => 1, 'package' => 2 );
++my(%section_takes_text) =
++ ( 'head1' => 2, 'c' => 1, 's' => 1,
++ 'io' => 2, 'processing' => 2, 'drivers' => 2,
++ 'd' => 1, 'n' => 1, 'e' => 1, 'h' => 1, 'a' => 2, 'title' => 0,
++ 'deprecated' => 0, 'package' => 1 );
++my(%xsection_takes_args) =
++ ( 'head1' => 1, 'head2' => 1, 'item' => 1, 'over' => 1, 'back' => 0,
++ 'for' => 1, 'begin' => 1, 'end' => 1, 'start!' => 1, 'name!' => 1,
++ 'end!' => 0, 'text' => 0 );
++my(%infosection_name) =
++ ( 'package' => 'Package', 'io' => 'Ports', 'processing' => 'Processing',
++ 'drivers' => 'Drivers' );
++
++my $section = 'n';
++my $package;
++my $uninstall = 0;
++my(@all_outnames, %all_outsections, %summaries_by_section, %all_roff_summaries);
++
++my(%processing_constants) =
++ ( 'AGNOSTIC' => 'a/a', 'PUSH' => 'h/h', 'PULL' => 'l/l',
++ 'PUSH_TO_PULL' => 'h/l', 'PULL_TO_PUSH' => 'l/h' );
++my(%processing_text) =
++ ( 'a/a' => 'agnostic', 'h/h' => 'push', 'l/l' => 'pull',
++ 'h/l' => 'push inputs, pull outputs',
++ 'l/h' => 'pull inputs, push outputs',
++ 'a/ah' => 'agnostic, but output 1 is push' );
++
++my(@section_headers) =
++ ( 'basicsources' => 'Basic Sources and Sinks',
++ 'classification' => 'Basic Classification and Selection',
++ 'basictransfer' => 'Basic Packet Transfer',
++ 'counters' => 'Counters',
++ 'timestamps' => 'Timestamps',
++ 'basicmod' => 'Basic Packet Modification',
++ 'storage' => 'Packet Storage',
++ 'aqm' => 'Active Queue Management',
++ 'scheduling' => 'Packet Scheduling',
++ 'shaping' => 'Traffic Shaping',
++ 'information' => 'Information Elements',
++ 'netdevices' => 'Network Devices',
++ 'comm' => 'Host and Socket Communication',
++ 'ethernet' => 'Ethernet',
++ 'arp' => 'ARP',
++ 'ip' => 'IPv4',
++ 'iproute' => 'IPv4 Routing',
++ 'icmp' => 'ICMP',
++ 'nat' => 'Network Address Translation',
++ 'tcp' => 'TCP',
++ 'udp' => 'UDP',
++ 'app' => 'Applications',
++ 'traces' => 'Trace Manipulation',
++ 'ipmeasure' => 'TCP/IP Measurement',
++ 'aggregates' => 'Aggregates',
++ 'ip6' => 'IPv6',
++ 'ipsec' => 'IPsec',
++ 'crc' => 'CRCs',
++ 'paint' => 'Paint Annotations',
++ 'annotations' => 'Annotations',
++ 'debugging' => 'Debugging',
++ 'control' => 'Control',
++ 'smpclick' => 'Multithreaded Click',
++ 'test' => 'Regression Tests'
++ );
++my(%section_headers);
++for (my $i = 0; $i < @section_headers; $i += 2) {
++ $section_headers{$section_headers[$i]} = $section_headers[$i+1];
++}
++
++my(%default_packages) =
++ ( 'analysis' => 'analysis (core)',
++ 'app' => 'app (core)',
++ 'aqm' => 'aqm (core)',
++ 'bsdmodule' => 'bsdmodule (core)',
++ 'ethernet' => 'ethernet (core)',
++ 'etherswitch' => 'etherswitch (core)',
++ 'grid' => 'grid (core)',
++ 'icmp' => 'icmp (core)',
++ 'ip' => 'ip (core)',
++ 'ip6' => 'ip6 (core)',
++ 'ipsec' => 'ipsec (core)',
++ 'linuxmodule' => 'linuxmodule (core)',
++ 'local' => 'local (core)',
++ 'ns' => 'ns (core)',
++ 'radio' => 'radio (core)',
++ 'simple' => 'simple (core)',
++ 'standard' => 'standard (core)',
++ 'tcpudp' => 'tcpudp (core)',
++ 'test' => 'test (core)',
++ 'userlevel' => 'userlevel (core)',
++ 'wifi' => 'wifi (core)'
++ );
++
++# find date
++my($today) = '';
++if (localtime =~ /\w*\s+(\w*)\s+(\d*)\s+\S*\s+(\d*)/) {
++ $today = "$2/$1/$3";
++}
++
++# Unrolling [^A-Z>]|[A-Z](?!<) gives: // MRE pp 165.
++my $nonest = '(?:[^A-Z>]*(?:[A-Z](?!<)[^A-Z>]*)*)';
++
++
++# XXX one paragraph at a time
++
++my($Filename, $PrimaryElement, @Related, %RelatedSource, @Over, $Begun);
++
++
++############
++## shared ##
++
++sub textize_add_links ($$) {
++ my($t, $selfref) = @_;
++ my($pos);
++
++ # embolden & manpageize
++ foreach my $r (@Related) {
++ my $l = length($r);
++ my $result = ($r eq $PrimaryElement ? "$selfref<$r>" : "L<$r>");
++ for ($pos = index($t, $r); $pos >= 0; $pos = index($t, $r, $pos + 1)) {
++ if (($pos == 0 || substr($t, $pos - 1, 1) =~ /^[^\w@\/<]$/s)
++ && (substr($t, $pos + $l, 1) =~ /^[^\w@\/]$/s)) {
++ substr($t, $pos, $l) = $result;
++ $pos += 2 + $l;
++ }
++ }
++ }
++ $t;
++}
++
++sub quote_unquoted_gt ($) {
++ my($t) = @_;
++ my($tt, $nest, $pos) = ('', 0);
++ for ($pos = index($t, ">"); $pos >= 0; $pos = index($t, ">")) {
++ my($w) = substr($t, 0, $pos);
++ $nest++ while $w =~ m|[A-Z]<|g;
++ if ($nest) {
++ $tt .= $w . ">";
++ $nest--;
++ } else {
++ $tt .= $w . "E<gt>";
++ }
++ $t = substr($t, $pos + 1);
++ }
++ $tt . $t;
++}
++
++
++###########
++## nroff ##
++
++my $nroff_prologue = <<'EOD;';
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++EOD;
++chomp $nroff_prologue;
++
++my(%nroff_podentities) =
++ ( 'lt' => '<', 'gt' => '>', 'amp' => '&', 'solid' => '/',
++ 'verbar' => '|', 'eq' => '=', 'star' => '*', 'lparen' => '(',
++ 'rparen' => ')', 'lbrack' => '[', 'rbrack' => ']', 'lbrace' => '{',
++ 'rbrace' => '}' );
++
++sub nroff_quote ($) {
++ my($x) = @_;
++ $x =~ tr/\000-\177/\200-\377/;
++ $x;
++}
++
++sub nroff_unentity ($) {
++ my($x) = @_;
++ $x =~ tr/\200-\377/\000-\177/;
++ if ($x =~ /^\d+$/) {
++ chr($x);
++ } elsif ($nroff_podentities{$x}) {
++ $nroff_podentities{$x};
++ } else {
++ print STDERR "click-elem2man: $Filename: unknown entity E<$x>\n";
++ "";
++ }
++}
++
++sub nroff_fixfP ($$) {
++ my($x, $f) = @_;
++ $x =~ s/\\fP/\\f$f/g;
++ $x;
++}
++
++sub nroffize_text ($) {
++ my($t) = @_;
++ my($s);
++
++ # embolden & manpageize
++ $t = textize_add_links($t, 'L');
++
++ $t =~ s/\\/\\\\/g;
++ $t =~ s/^\./\\&./gm;
++ $t =~ s/^'/\\&'/gm;
++ $t =~ s/^\s*$/.PP\n/gm;
++ $t =~ s/^\.PP\n(?:\.PP\n)+/.PP\n/gm;
++ $t =~ s{\A\s*(?:\.PP\n)?}{}s;
++ if (@Over > 0) {
++ $t =~ s/^\.PP$/.IP \"\" $Over[-1]/gm;
++ }
++
++ # get rid of entities
++ $t =~ s{[\200-\377]}{"E<" . ord($1) . ">"}ge;
++ $t =~ s{(E<[^>]*>)}{nroff_quote($1)}ge;
++
++ my $maxnest = 10;
++ while ($maxnest-- && $t =~ /[A-Z]</) {
++
++ # can't do C font here
++ $t =~ s/([BI])<($nonest)>/"\\f$1" . nroff_fixfP($2, $1) . "\\fP"/eg;
++ $t =~ s/[PU]<($nonest)>/$1/g;
++
++ # files and filelike refs in italics
++ $t =~ s/F<($nonest)>/I<$1>/g;
++
++ # LREF: man page references
++ $t =~ s{L<($nonest)\(([\dln])\)>(\S*)(\s*)}{\n.M $1 $2 $3\n}g;
++
++ $t =~ s/V<($nonest)>//g;
++
++ # LREF: a la HREF L<show this text|man/section>
++ $t =~ s{L<($nonest)>(\S*)(\s*)}{
++ if (($s = $RelatedSource{$1})) {
++ "\n.M $1 \"$s\" $2\n";
++ } else {
++ my $i = index($1, "|");
++ ($i >= 0 ? substr($1, 0, $i) . $2 . $3 : "\\fB$1\\fP$2$3");
++ }
++ }eg;
++
++ $t =~ s/Z<>/\\&/g;
++ $t =~ s/N<>(\n?)/\n.br\n/g;
++
++ # comes last because not subject to reprocessing
++ $t =~ s/C<($nonest)>/"\\f(CW" . nroff_fixfP($1, 'R') . "\\fP"/eg;
++ }
++
++ # replace entities
++ $t =~ s/\305\274([^\276]*)\276/nroff_unentity($1)/ge;
++
++ # fix fonts
++ $t =~ s/\\fP/\\fR/g;
++
++ # fix manual
++ $t =~ s/\n\.M (\S+) \"(\S+)\" (\(\2\))/\n.M $1 \"$2\" /sg;
++
++ $t =~ s/\n+/\n/sg;
++ $t =~ s/^\n+//;
++ $t =~ s/\n+$//;
++
++ $t;
++}
++
++sub nroffize ($) {
++ my($t) = @_;
++ # $t cannot contain \t, as all \ts have been expanded to spaces below
++
++ #$t =~ s{\n[ \r]+$}{\n}gm;
++
++ if ($t =~ /^ /m) {
++ # worry about verbatims
++ $t =~ s/^( .*)\n(\n+)(?= )/$1 . "\n" . (" \n" x length($2))/mge;
++ my(@x) = split(/(^ .*$)/m, $t);
++ my($o, $i) = '';
++ for ($i = 0; $i < @x; $i += 2) {
++ if ($x[$i]) {
++ $o .= nroffize_text($x[$i]) . "\n";
++ }
++ if ($x[$i+1]) {
++ $x[$i+1] =~ s/\\/\\e/g;
++ $o .= ".nf\n\\&" . $x[$i+1] . "\n.fi\n.PP\n";
++ }
++ }
++ $o =~ s/\n\.fi\n\.PP\n\n\.nf\n/\n/g;
++ if (@Over > 0) {
++ $o =~ s/^\.PP$/.IP \"\" $Over[-1]/gm;
++ }
++ $o;
++ } else {
++ nroffize_text($t);
++ }
++}
++
++sub nroff_do_section ($$$) {
++ my($name, $args, $text) = @_;
++ if (!exists($xsection_takes_args{$name})) {
++ print STDERR "click-elem2man: $Filename: unknown section '=$name' ignored\n";
++ return;
++ }
++ print STDERR "click-elem2man: $Filename: section '=$name' requires arguments\n"
++ if ($xsection_takes_args{$name} && !$args);
++
++ # handle '=begin' .. '=end'
++ if ($name eq 'end') {
++ undef $Begun;
++ } elsif ($Begun && ($Begun eq 'man' || $Begun eq 'roff')) {
++ print OUT '=', $name, ($args ? ' ' . $args : ''), "\n", $text;
++ return;
++ } elsif ($Begun) {
++ return;
++ }
++
++ if ($name eq 'head1') {
++ print OUT ".SH \"", nroffize($args), "\"\n";
++ } elsif ($name eq 'head2') {
++ print OUT ".SS \"", nroffize($args), "\"\n";
++ } elsif ($name eq 'over') {
++ if ($args =~ /^\s*(\d+)\s*$/s) {
++ print OUT ".RS $Over[-1]\n" if @Over;
++ push @Over, $1;
++ } else {
++ print STDERR "click-elem2man: $Filename: bad arguments to '=over'\n";
++ }
++ } elsif ($name eq 'item') {
++ if (@Over == 0) {
++ print STDERR "click-elem2man: $Filename: '=item' outside any '=over' section\n";
++ } else {
++ print OUT ".IP \"", nroffize($args), "\" $Over[-1]\n";
++ }
++ } elsif ($name eq 'back') {
++ my($overarg);
++ if ($args =~ /^\s*(\d+)\s*$/s) {
++ $overarg = $1;
++ } elsif ($args !~ /^\s*$/s) {
++ print STDERR "click-elem2man: $Filename: bad arguments to '=back'\n";
++ }
++ if (@Over == 0) {
++ print STDERR "click-elem2man: $Filename: too many '=back's\n";
++ } else {
++ my($over) = pop @Over;
++ print OUT ".RE\n" if @Over;
++ print OUT (@Over ? ".IP \"\" $Over[-1]\n" : ".PP\n");
++ print STDERR "click-elem2man: $Filename: '=back $overarg' paired with '=over $over'\n"
++ if defined($overarg) && $over != $overarg;
++ }
++ } elsif ($name eq 'for') {
++ my($fortext);
++ if ($text =~ /^(.*)\n\s*\n(.*)$/s) {
++ ($fortext, $text) = ($1, $2);
++ } else {
++ ($fortext, $text) = ($text, '');
++ }
++ if ($args =~ /^\s*(man|roff)\s*(.*)/) {
++ print OUT $2, $fortext;
++ }
++ } elsif ($name eq 'begin') {
++ $Begun = $args;
++ $Begun =~ s/^\s*(\S+).*/$1/;
++ if ($Begun eq 'man' || $Begun eq 'roff') {
++ print OUT $text;
++ }
++ return;
++ } elsif ($name eq 'start!') {
++ print OUT <<"EOD;";
++.\\" -*- mode: nroff -*-
++.\\" Generated by 'click-elem2man' from '$Filename'
++$nroff_prologue
++.TH "\U$text\E" $args "$today" "Click"
++EOD;
++ return;
++ } elsif ($name eq 'name!') {
++ print OUT <<"EOD;";
++.SH "NAME"
++$args \\- $text
++EOD;
++ return;
++ } elsif ($name eq 'end!') {
++ return;
++ }
++
++ print OUT nroffize($text), "\n";
++ print OUT "\n" if $name eq 'head1';
++}
++
++
++##############
++## dokuwiki ##
++
++my($dokuwiki_dl);
++
++my(%dokuwiki_podentities) =
++ ( 'lt' => '<', 'gt' => "\xFF\xFF", 'amp' => '&', 'solid' => '/',
++ 'verbar' => '|', 'eq' => '=', 'star' => '*', 'lparen' => '(',
++ 'rparen' => ')', 'lbrack' => '[', 'rbrack' => ']', 'lbrace' => '{',
++ 'rbrace' => '}' );
++my($dokuwiki_sensitive_char) = "[!%'\\(\\)\\*\\+/?\\[\\\\\\]_\\{\\}]";
++
++sub dokuwiki_unentity ($) {
++ my($x) = @_;
++ if ($x =~ /^\d+$/) {
++ $x = pack 'U', $x;
++ if ($x =~ /\A$dokuwiki_sensitive_char\Z/) {
++ "%%$x%%";
++ } else {
++ $x;
++ }
++ } elsif ($dokuwiki_podentities{$x}) {
++ $dokuwiki_podentities{$x};
++ } else {
++ print STDERR "click-elem2man: $Filename: unknown entity E<$x>\n";
++ "";
++ }
++}
++
++sub dokuwiki_quotedbl ($) {
++ my($x) = @_;
++ $x =~ s/^(.)/\%\%$1\%\%/;
++ $x;
++}
++
++sub dokuwiki_surround ($$) {
++ my($text, $chr) = @_;
++ my($re) = "\\$chr\\$chr";
++ $text =~ s{$re}{}g;
++ "$chr$chr$text$chr$chr";
++}
++
++sub dokuwikiize_text ($) {
++ my($t) = @_;
++
++ # embolden & manpageize
++ $t = textize_add_links($t, 'P');
++
++ # get rid of entities
++ $t =~ s{E<([^>]*)>}{dokuwiki_unentity($1)}ge;
++ $t =~ s{($dokuwiki_sensitive_char)}{^$1^}g;
++
++ my $maxnest = 10;
++ while ($maxnest-- && $t =~ /[A-Z]</) {
++
++ # can't do C font here
++ $t =~ s/B<($nonest)>/dokuwiki_surround($1, "*")/eg;
++ $t =~ s.I<($nonest)>.dokuwiki_surround($1, "/").eg;
++ $t =~ s.U<($nonest)>.dokuwiki_surround($1, "_").eg;
++ $t =~ s/P<($nonest)>/$1/g;
++ $t =~ s/C<($nonest)>/dokuwiki_surround($1, "'")/eg;
++
++ # files and filelike refs in italics
++ $t =~ s/F<($nonest)>/I<$1>/g;
++
++ # LREF: man page references
++ $t =~ s{L<($nonest)\^\(\^[\dln]\^\)\^>}{[[$1]]}g;
++ $t =~ s{L<($nonest)>\^\(\^[\dln]\^\)\^}{[[$1]]}g;
++
++ # LREF: a la HREF L<show this text|man/section>
++ $t =~ s{L<($nonest)\|($nonest)>}{[[$2|$1]]}g;
++ $t =~ s{L<($nonest)>}{[[$1]]}g;
++
++ $t =~ s/V<($nonest)>//g;
++ $t =~ s/Z<>//g;
++ $t =~ s/N<>(\n?)/\\\\ /g;
++ }
++
++ $t =~ s/\n+/\n/sg;
++ $t =~ s/^\n+//;
++ $t =~ s/\n+$//;
++ $t =~ s/\xFF\xFF/>/g;
++
++ $t =~ s{^(\s*)\^([?!])\^}{$1 . dokuwiki_quotedbl($2)}egm;
++ $t =~ s{($dokuwiki_sensitive_char)\^\1\^}{$1 . dokuwiki_quotedbl($1)}eg;
++ $t =~ s{\^($dokuwiki_sensitive_char)\^\1}{dokuwiki_quotedbl($1) . $1}eg;
++ $t =~ s{\^($dokuwiki_sensitive_char)\^}{$1}g;
++
++ # remove self references
++ $t =~ s{\[\[$PrimaryElement\]\]}{$PrimaryElement}g;
++
++ $t;
++}
++
++sub dokuwikiize ($) {
++ my($t) = @_;
++ # $t cannot contain \t, as all \ts have been expanded to spaces below
++
++ if ($t =~ /^ /m) {
++ # worry about verbatims
++ $t =~ s/^( .*)\n(\n+)(?= )/$1 . "\n" . (" \n" x length($2))/mge;
++ my(@x) = split(/(^ .*$)/m, $t);
++ my($o, $i) = '';
++ for ($i = 0; $i < @x; $i += 2) {
++ if ($x[$i]) {
++ $o .= dokuwikiize_text($x[$i]);
++ $o .= "\n" if $o !~ /\n\Z/;
++ }
++ if ($x[$i+1]) {
++ $o .= " " . $x[$i+1] . "\n";
++ }
++ }
++ $o;
++ } else {
++ dokuwikiize_text($t);
++ }
++}
++
++sub dokuwiki_do_section ($$$) {
++ my($name, $args, $text) = @_;
++ if (!exists($xsection_takes_args{$name})) {
++ print STDERR "click-elem2man: $Filename: unknown section '=$name' ignored\n";
++ return;
++ }
++ print STDERR "click-elem2man: $Filename: section '=$name' requires arguments\n"
++ if ($xsection_takes_args{$name} && !$args);
++
++ # handle '=begin' .. '=end'
++ if ($name eq 'end') {
++ undef $Begun;
++ } elsif ($Begun && $Begun eq 'dokuwiki') {
++ print OUT '=', $name, ($args ? ' ' . $args : ''), "\n", $text;
++ return;
++ } elsif ($Begun) {
++ return;
++ }
++
++ if ($name eq 'head1') {
++ print OUT "\n===== ", dokuwikiize($args), " =====\n\n";
++ } elsif ($name eq 'head2') {
++ print OUT "\n==== ", dokuwikiize($args), " ====\n\n";
++ } elsif ($name eq 'over') {
++ if ($args =~ /^\s*(\d+)\s*$/s) {
++ push @Over, $1;
++ } else {
++ print STDERR "click-elem2man: $Filename: bad arguments to '=over'\n";
++ }
++ } elsif ($name eq 'item') {
++ if (@Over == 0) {
++ print STDERR "click-elem2man: $Filename: '=item' outside any '=over' section\n";
++ } else {
++ print OUT "\n", ' ' x @Over, "? " if $dokuwiki_dl;
++ print OUT dokuwikiize("B<" . quote_unquoted_gt($args) . ">");
++ print OUT ($dokuwiki_dl ? "\n" : "\n\n");
++ }
++ } elsif ($name eq 'back') {
++ my($overarg);
++ if ($args =~ /^\s*(\d+)\s*$/s) {
++ $overarg = $1;
++ } elsif ($args !~ /^\s*$/s) {
++ print STDERR "click-elem2man: $Filename: bad arguments to '=back'\n";
++ }
++ if (@Over == 0) {
++ print STDERR "click-elem2man: $Filename: too many '=back's\n";
++ } else {
++ my($over) = pop @Over;
++ print STDERR "click-elem2man: $Filename: '=back $overarg' paired with '=over $over'\n"
++ if defined($overarg) && $over != $overarg;
++ }
++ } elsif ($name eq 'for') {
++ my($fortext);
++ if ($text =~ /^(.*)\n\s*\n(.*)$/s) {
++ ($fortext, $text) = ($1, $2);
++ } else {
++ ($fortext, $text) = ($text, '');
++ }
++ if ($args =~ /^\s*dokuwiki\s*(.*)/) {
++ print OUT $2, $fortext;
++ }
++ } elsif ($name eq 'begin') {
++ $Begun = $args;
++ $Begun =~ s/^\s*(\S+).*/$1/;
++ if ($Begun eq 'dokuwiki') {
++ print OUT $text;
++ }
++ return;
++ } elsif ($name eq 'start!') {
++ return;
++ } elsif ($name eq 'name!') {
++ print OUT <<"EOD;";
++====== $args Element Documentation ======
++
++===== NAME =====
++
++**$args** -- $text
++EOD;
++ return;
++ } elsif ($name eq 'end!') {
++ print OUT "\n\nGenerated by 'click-elem2man' from '$Filename' on $today.\n";
++ return;
++ }
++
++ print OUT ' ' x @Over, "! " if $text =~ /\S/ && @Over && $dokuwiki_dl;
++ print OUT dokuwikiize($text), "\n";
++ print OUT "\n" if $name eq 'head1';
++}
++
++
++###########
++## main ##
++
++my $do_section_func = \&nroff_do_section;
++my $do_text_func = \&nroffize;
++my $filename_func;
++
++sub do_section ($$$) {
++ my($name, $args, $text) = @_;
++ my(@text) = split(/^(=\w.*)$/m, $text);
++ push @text, '' if !@text;
++ my($i);
++ @Over = ();
++ undef $Begun;
++ for ($i = 0; $i < @text; ) {
++ &$do_section_func($name, $args, $text[$i]);
++ ($name, $args) = ($text[$i+1] =~ /=(\w+)\s*(.*)/)
++ if ($i < @text - 1);
++ $i += 2;
++ }
++ &$do_section_func('back', '', '') while @Over;
++ print STDERR "click-elem2man: $Filename: '=begin' not closed by end of section\n"
++ if $Begun;
++}
++
++sub process_processing ($) {
++ my($t) = @_;
++ return undef if !defined($t);
++ if (exists($processing_constants{$t})) {
++ $t = $processing_constants{$t};
++ }
++ $t =~ tr/\" \t//d;
++ $t =~ s{\A([^/]*)\Z}{$1/$1};
++ $processing_text{$t};
++}
++
++sub process_one_portcount ($$) {
++ my($t, $type) = @_;
++ if ($t eq '0') {
++ "no ${type}s";
++ } elsif ($t eq '-') {
++ "any number of ${type}s";
++ } elsif ($t eq '1') {
++ "1 $type";
++ } elsif ($t eq '=') {
++ "the same number of ${type}s";
++ } elsif ($t =~ /^=(\++)$/) {
++ length($1) . " more $type";
++ } elsif ($t =~ /^0?-1$/) {
++ "at most 1 $type";
++ } elsif ($t =~ /^0?-(.*)/) {
++ "at most $1 ${type}s";
++ } elsif ($t =~ /^(\d+)-$/) {
++ "$1 or more ${type}s";
++ } else {
++ "$t ${type}s";
++ }
++}
++
++sub process_portcount ($) {
++ my($t) = @_;
++ $t = "$t/$t" if $t !~ /\//;
++ return 'none' if $t eq '0/0';
++ my($i, $o) = split(/\//, $t);
++ process_one_portcount($i, "input") . ", " . process_one_portcount($o, "output");
++}
++
++sub process_summary_section ($$) {
++ my($summary, $file) = @_;
++ my($i);
++ foreach $i (split(/,/, $summary)) {
++ $i =~ s/^\s*//;
++ $i =~ s/\s*$//;
++ $i = $section_headers{$i} if exists $section_headers{$i};
++ next if !$i;
++ push @{$summaries_by_section{$i}}, $file;
++ }
++}
++
++sub process_drivers ($) {
++ my($driv) = @_;
++ my(@d, $d);
++ foreach $d ('userlevel', 'linuxmodule', 'bsdmodule', 'ns') {
++ push @d, $d if $driv =~ /\b$d\b/;
++ }
++ join(', ', @d);
++}
++
++sub insert_section (\@\@\@$$$$) {
++ my($sn, $sa, $st, $i, $n, $a, $t) = @_;
++ splice @$sn, $i, 0, $n;
++ splice @$sa, $i, 0, $a;
++ splice @$st, $i, 0, $t;
++}
++
++sub insert_section2 (\@\@\@$$$\%@) {
++ my($sn, $sa, $st, $n, $a, $t, $fis, @x) = @_;
++ my($pos);
++ foreach $pos (@x) {
++ if (exists $fis->{$pos}) {
++ insert_section(@$sn, @$sa, @$st, $fis->{$pos} + 1, $n, $a, $t);
++ $fis->{$n} = $fis->{$pos} + 1;
++ return;
++ }
++ }
++}
++
++sub process_comment ($$) {
++ my($t, $filename) = @_;
++ my($i);
++ $Filename = $filename;
++
++ # split document into sections
++ my(@section_text, @section_args, @section_name, $bad_section, $ref);
++ $ref = \$bad_section;
++ while ($t =~ m{^=(\w+)( *)(.*)([\0-\377]*?)(?=^=\w|\Z)}mg) {
++ if ($section_break{$1}) {
++ insert_section(@section_name, @section_args, @section_text,
++ @section_name, $1, $3, $4);
++ $ref = \$section_text[-1];
++ } else {
++ $$ref .= '=' . $1 . $2 . $3 . $4;
++ }
++ }
++
++ # check document for sectioning errors
++ print STDERR "click-elem2man: $Filename: warning: comment does not start with section\n"
++ if $bad_section;
++ my(%num_sections, %first_in_section);
++ foreach $i (0..$#section_name) {
++ my($n) = $section_name[$i];
++ print STDERR "click-elem2man: $Filename: warning: section '=$n' requires arguments\n"
++ if $section_takes_args{$n} == 1 && !$section_args[$i];
++ print STDERR "click-elem2man: $Filename: warning: section '=$n' arguments ignored\n"
++ if $section_takes_args{$n} == 0 && $section_args[$i];
++ print STDERR "click-elem2man: $Filename: warning: empty section '=$n'\n"
++ if $section_takes_text{$n} == 1 && !$section_text[$i];
++ print STDERR "click-elem2man: $Filename: warning: section '=$n' text ignored\n"
++ if $section_takes_text{$n} == 0 && $section_text[$i] =~ /\S/;
++ $num_sections{$n}++;
++ $first_in_section{$n} = $i if $num_sections{$n} == 1;
++ }
++ foreach $i ('a', 'c', 'd', 'n', 'e', 'title', 'io', 'processing', 'drivers') {
++ print STDERR "click-elem2man: $Filename: warning: multiple '=$i' sections; some may be ignored\n"
++ if $num_sections{$i} && $num_sections{$i} > 1;
++ }
++
++ # read class names from configuration arguments section
++ $i = $first_in_section{'c'};
++ if (!defined($i)) {
++ print STDERR "click-elem2man: $Filename: section '=c' missing; cannot continue\n";
++ return;
++ }
++ my(@classes, %classes);
++ while ($section_text[$i] =~ /^\s*(\w+)\(/mg) {
++ push @classes, $1 if !exists $classes{$1};
++ $classes{$1} = 1;
++ }
++ if (!@classes && $section_text[$i] =~ /^\s*([\w@]+)\s*$/) {
++ push @classes, $1;
++ $classes{$1} = 1;
++ }
++ if (!@classes) {
++ print STDERR "click-elem2man: $Filename: no class definitions\n (did you forget '()' in the =c section?)\n";
++ return;
++ }
++ my($Title) = $classes[0];
++
++ # output filenames might be specified in 'title' section
++ my(@outfiles, @outsections, $title);
++ if (defined($first_in_section{'title'})) {
++ $title = $section_args[ $first_in_section{'title'} ];
++ if (!$title) {
++ print STDERR "click-elem2man: $Filename: '=title' section present, but empty\n";
++ return;
++ }
++ if ($title =~ /[^-.\w@+,]/) {
++ print STDERR "click-elem2man: $Filename: strange characters in '=title', aborting\n";
++ return;
++ }
++ foreach $i (split(/\s+/, $title)) {
++ if ($i =~ /^(.*)\((.*)\)$/) {
++ push @outfiles, $1;
++ push @outsections, $2;
++ $Title = $1;
++ } else {
++ push @outfiles, $i;
++ push @outsections, $section;
++ $Title = $i;
++ }
++ }
++ } else {
++ $title = join(', ', @classes);
++ @outfiles = @classes;
++ @outsections = ($section) x @classes;
++ }
++
++ # open new output file if necessary
++ my($main_outname);
++ if ($filename_func) {
++ $main_outname = &$filename_func($outfiles[0], $outsections[0]);
++ if ($uninstall) {
++ print STDERR "Uninstalled $main_outname\n" if $verbose;
++ unlink($main_outname);
++ open(OUT, ">/dev/null");
++ } elsif (open(OUT, ">$main_outname")) {
++ print STDERR "Writing to $main_outname\n" if $verbose;
++ } else {
++ print STDERR "$main_outname: $!\n";
++ return;
++ }
++ }
++ push @all_outfiles, $outfiles[0];
++ $all_outsections{$outfiles[0]} = $outsections[0];
++ $PrimaryElement = $outfiles[0];
++
++ # prepare related
++ %RelatedSource = ();
++ $i = $first_in_section{'a'};
++ if (defined($i)) {
++ $section_text[$i] = $section_args[$i] . $section_text[$i]
++ if $section_args[$i];
++ if ($section_text[$i] =~ /\A\s*(.*?)(\n\s*\n.*\Z|\Z)/s) {
++ my($bit, $last) = ($1, $2);
++ while ($bit =~ m{(\b[A-Z][-\w@.+=]+)([,\s]|\Z)}g) {
++ $RelatedSource{$1} = 'n';
++ }
++ $bit =~ s{([-\w@.+=]+)([,\s]|\Z)}{$1(n)$2}g;
++ while ($bit =~ m{([-\w@.+=]+\(([0-9ln])\))}g) {
++ $RelatedSource{$1} = $2;
++ }
++ $section_text[$i] = $bit . $last;
++ }
++ }
++ map(delete $RelatedSource{$_}, @outfiles);
++ @Related = sort { length($b) <=> length($a) } (keys %RelatedSource, @classes);
++
++ # front matter
++ my($oneliner) = (@classes == 1 ? "Click element" : "Click elements");
++ $i = $first_in_section{'s'};
++ my($summary_section) = '';
++ if (defined($i)) {
++ $summary_section = $section_args[$i];
++ process_summary_section($summary_section, $outfiles[0]);
++ $section_text[$i] =~ s/\n\s*\n/\n/g;
++ my($t) = &$do_text_func($section_text[$i]);
++ $oneliner .= ";\n" . $t;
++ $oneliner =~ s/\n(^\.)/ /g;
++ $all_roff_summaries{$outfiles[0]} = $t . "\n";
++ } else {
++ # avoid uninitialized value warns
++ $all_roff_summaries{$outfiles[0]} = '';
++ }
++
++ # deprecation
++ if (defined($first_in_section{'deprecated'})) {
++ $deprecated{$outfiles[0]} = $section_text[$first_in_section{'deprecated'}];
++ }
++
++ # package
++ if (!defined($first_in_section{'package'}) && defined($package)) { PACKAGE: {
++ my($pkg) = $package;
++ if ($pkg eq 'DEFAULT') {
++ $pkg = $1 if $Filename =~ m|\belements/(\w+)/|;
++ $pkg = 'standard' if $Filename =~ m|\binclude/click/standard/|;
++ last PACKAGE if $pkg eq 'DEFAULT';
++ $pkg = exists($default_packages{$pkg}) ? $default_packages{$pkg} : $pkg;
++ }
++ insert_section2(@section_name, @section_args, @section_text,
++ 'package', '', $pkg,
++ %first_in_section, 'drivers', 'processing', 'io', 'c');
++ }}
++
++ # drivers
++ my($drivers);
++ if ($docrequires{$Title}
++ && ($drivers = process_drivers($docrequires{$Title}))
++ && !defined($first_in_section{'drivers'})) {
++ insert_section2(@section_name, @section_args, @section_text,
++ 'drivers', '', $drivers,
++ %first_in_section, 'processing', 'io', 'c');
++ }
++
++ # processing
++ if (!defined($first_in_section{'processing'})) { PROCESSING: {
++ # can we figure out the processing type?
++ last PROCESSING
++ if (defined($first_in_section{'io'}) && $section_text[$first_in_section{'io'}] =~ /None/i) || (defined($portcount{$Title}) && ($portcount{$Title} eq '0' || $portcount{$Title} eq '0/0'));
++ my($ptype) = process_processing($processing{$Title});
++ insert_section2(@section_name, @section_args, @section_text,
++ 'processing', '', $ptype,
++ %first_in_section, 'io', 'c') if $ptype;
++ }}
++
++ # input/output
++ if (!defined($first_in_section{'io'})) { PORTCOUNT: {
++ last PORTCOUNT if !defined($portcount{$Title});
++ insert_section2(@section_name, @section_args, @section_text,
++ 'io', '', process_portcount($portcount{$Title}),
++ %first_in_section, 'c');
++ }}
++
++ # initial sections
++ insert_section(@section_name, @section_args, @section_text,
++ 0, 'start!', $outsections[0], $title);
++ insert_section(@section_name, @section_args, @section_text,
++ 1, 'name!', $title, $oneliner);
++ insert_section(@section_name, @section_args, @section_text,
++ @section_name, 'end!', $outsections[0], $title);
++
++ # output
++ my($special_section) = 0;
++ for ($i = 0; $i < @section_text; $i++) {
++ my($s) = $section_name[$i];
++ my($x) = $section_text[$i];
++ my($was_special_section) = $special_section;
++ $special_section = 0;
++
++ if ($s eq 'c') {
++ $x =~ s{(\S\s*)\n}{$1N<>\n}g;
++ $x =~ s{N<>\n*\z}{};
++ do_section('head1', 'SYNOPSIS', $x);
++ } elsif ($s eq 'package' || $s eq 'io' || $s eq 'processing'
++ || $s eq 'drivers') {
++ $x =~ s/\A\s+//;
++ $x =~ s/\s+\Z//;
++ do_section('text', '', 'B<' . $infosection_name{$s} . '>: ' . $x . 'N<>');
++ } elsif ($s eq 'io') {
++ do_section('head1', 'INPUTS AND OUTPUTS', $x);
++ } elsif ($s eq 'processing') {
++ do_section('head1', 'PROCESSING TYPE', $x);
++ } elsif ($s eq 'd') {
++ do_section('head1', 'DESCRIPTION', $x);
++ } elsif ($s eq 'n') {
++ do_section('head1', 'NOTES', $x);
++ } elsif ($s eq 'e') {
++ do_section('head1', 'EXAMPLES', $x);
++ } elsif ($s eq 'h') {
++ my($t) = "=over 5\n";
++ while ($i < @section_text && $section_name[$i] eq 'h') {
++ if ($section_args[$i] =~ /\A\s*(.*?)\s*"(.*?)"\s*\Z/
++ || $section_args[$i] =~ /\A\s*(.*?)\s*(\S+)\s*\Z/) {
++ $t .= "=item B<$1> ($2)\n";
++ } else {
++ print STDERR "click-elem2man: $Filename: bad handler section arguments ('=h $section_args[$i]')\n";
++ $t .= "=item B<$section_args[$i]>\n";
++ }
++ $t .= $section_text[$i] . "\n";
++ $i++;
++ }
++ $i--;
++ do_section('head1', 'ELEMENT HANDLERS', $t);
++ } elsif ($s eq 'a') {
++ do_section('head1', 'SEE ALSO', $x);
++ } elsif ($s eq 'title' || $s eq 's' || $s eq 'deprecated') {
++ # nada
++ } else {
++ do_section($s, $section_args[$i], $x);
++ }
++ }
++
++ # close output file & make links if appropriate
++ if ($filename_func) {
++ close OUT;
++ for ($i = 1; $i < @outfiles; $i++) {
++ my($outname) = &$filename_func($outfiles[$i], $outsections[$i]);
++ print STDERR "Unlinking $outname\n" if $verbose;
++ unlink($outname);
++ if ($uninstall) {
++ # do nothing
++ } elsif (link $main_outname, $outname) {
++ print STDERR "Linked $outname\n" if $verbose;
++ push @all_outfiles, $outfiles[$i];
++ $all_outsections{$outfiles[$i]} = $outsections[$i];
++ process_summary_section($summary_section, $outfiles[$i]);
++ $all_roff_summaries{$outfiles[$i]} = $all_roff_summaries{$outfiles[0]};
++ } else {
++ print STDERR "click-elem2man: $outname: $!\n";
++ }
++ }
++ }
++}
++
++sub process_file ($;$) {
++ my($filename, $text) = @_;
++
++ print STDERR "Attempting $filename...\n" if $verbose;
++ $filename = "include/$1" if !-e $filename && $filename =~ /^<(.*)>$/s;
++ $filename = "$PREFIX/$filename" if !-e $filename && defined($PREFIX);
++ return if !-e $filename;
++ print STDERR "Found $filename\n" if $verbose;
++ if (!defined($text)) {
++ if (!open(IN, $filename)) {
++ print STDERR "click-elem2man: $filename: $!\n";
++ return;
++ }
++ $text = <IN>;
++ close IN;
++ }
++
++ print "$filename??\n" if !defined $text;
++ foreach $_ (split(m{(/\*.*?\*/)}s, $text)) {
++ if (/^\/\*/m && /^[\/*\s]+=/m) {
++ s/^(.*?)\t/$1 . (' ' x (8 - (length($1) % 8)))/egm while /\t/;
++ s/^\/\*\s*//g;
++ s/\s*\*\/$//g;
++ s/^ ?\* ?//gm;
++ process_comment($_, $filename);
++ }
++ }
++}
++
++sub xmlunquote ($) {
++ my($x) = @_;
++ if ($x =~ /&/) {
++ $x =~ s/</</g;
++ $x =~ s/>/>/g;
++ $x =~ s/&/&/g;
++ $x =~ s/&#([0-9]+);/chr($1)/eg;
++ $x =~ s/&#x([0-9a-zA-Z]+);/chr(oct("0x$1"))/eg;
++ }
++ $x;
++}
++
++sub read_elementmap_text ($;$) {
++ my($text, $headerhash) = @_;
++ $headerhash = {} if !defined($headerhash);
++ local($_);
++ foreach $_ (split(/\n+/, $text)) {
++ next if !/^<entry\b/;
++ my($n) = (/\bname="(.*?)"/);
++ my($dn) = (/\bdocname="(.*?)"/);
++ my($p) = (/\bprocessing="(.*?)"/);
++ my($hf) = (/\bheaderfile="(.*?)"/);
++ my($pc) = (/\bportcount="(.*?)"/);
++ my($req) = (/\brequires="(.*?)"/);
++ if (defined($n) || defined($dn)) {
++ $dn = xmlunquote(defined($dn) ? $dn : $n);
++ $processing{$dn} = xmlunquote($p) if defined($p);
++ $portcount{$dn} = xmlunquote($pc) if defined($pc);
++ $req = defined($req) ? xmlunquote($req) : undef;
++ $docrequires{$dn} = $req if defined($req);
++
++ $n = $1 if defined($req) && !defined($n) && /\bprovides="(.*?)"/;
++ if (defined($n) && defined($req)) {
++ $n = xmlunquote($n);
++ $requires{$n} = [] if !defined $requires{$n};
++ push @{$requires{$n}}, $req;
++ }
++
++ $headerhash->{xmlunquote($hf)} = 1 if defined($hf);
++ }
++ }
++}
++
++sub read_elementmap ($;$) {
++ my($fn, $headerhash) = @_;
++ open(E, $fn) || die "$fn: $!\n";
++ local($/) = undef;
++ read_elementmap_text(<E>, $headerhash);
++ close E;
++}
++
++sub process_file_set ($$) {
++ my($fn, $fnhash) = @_;
++ if (open(IN, ($fn eq '-' ? "<&STDIN" : $fn))) {
++ my(@a, @b, $t, $x);
++ $t = <IN>;
++ close IN;
++
++ # Parse file; click-buildtool gets special treatment
++ if ($t =~ /\A#.*click-buildtool findelem/) {
++ $t =~ s/^#.*//mg;
++ foreach $_ (split(/\n+/, $t)) {
++ if (/^\S+\s+<(\S+?)>/) {
++ $fnhash->{"include/$1"} = 1;
++ } elsif (/^\S+\s+"(\S+?)"/) {
++ $fnhash->{$1} = 1;
++ } else {
++ s/.cc$/.hh/;
++ $fnhash->{$_} = 1;
++ }
++ }
++ } elsif ($t =~ /\A<\?xml/) {
++ read_elementmap_text($t, $fnhash);
++ } elsif ($t =~ /[\(\)]/) {
++ die if $fn eq '-';
++ $fnhash->{$fn} = 1;
++ } else {
++ $t =~ s/^#.*//mg;
++ foreach $_ (split(/\s+/, $t)) {
++ if ($t =~ /[*?\[]/) {
++ foreach my $x (glob($t)) {
++ $fnhash->{$x} = 1;
++ }
++ } else {
++ $fnhash->{$_} = 1;
++ }
++ }
++ }
++ } else {
++ print STDERR "click-elem2man: $fn: $!\n";
++ }
++}
++
++sub uniq (@) {
++ my(@a, $x);
++ foreach $x (@_) {
++ push @a, $x if !@a || $a[-1] ne $x;
++ }
++ @a;
++}
++
++
++sub driver_requirement ($) {
++ my($req) = @_;
++ my($d) = 0;
++ $d |= 1 if $req =~ /\buserlevel\b/;
++ $d |= 2 if $req =~ /\blinuxmodule\b/;
++ $d |= 4 if $req =~ /\bbsdmodule\b/;
++ $d |= 8 if $req =~ /\bns\b/;
++ $d ? $d : 15;
++}
++
++my(%requires_fixed);
++sub fix_one_requires ($) {
++ my($req) = @_;
++ my($driver) = driver_requirement($req);
++
++ my($t, $i);
++ my($changes) = '';
++ foreach $t (split(/\s+/, $req)) {
++ if (defined($requires{$t})) {
++ my($treq) = $requires{$t};
++ if (!$requires_fixed{$t}) {
++ $requires_fixed{$t} = 1;
++ for ($i = 0; $i < @$treq; $i++) {
++ $treq->[$i] = &fix_one_requires($treq->[$i]);
++ }
++ }
++ for ($i = 0; $i < @$treq; $i++) {
++ if ($driver & driver_requirement($treq->[$i])) {
++ $changes .= " " . $treq->[$i];
++ }
++ }
++ }
++ }
++
++ if ($changes) {
++ join(' ', uniq(sort {$a cmp $b} split(/\s+/, $req . $changes)));
++ } else {
++ $req;
++ }
++}
++
++sub fix_requires () {
++ my($k);
++ foreach $k (keys %docrequires) {
++ $docrequires{$k} = fix_one_requires($docrequires{$k});
++ }
++}
++
++
++# main program: parse options
++
++sub usage () {
++ print STDERR "Usage: click-elem2man [OPTIONS] FILES...
++Try 'click-elem2man --help' for more information.\n";
++ exit 1;
++}
++
++sub help () {
++ print STDERR <<"EOD;";
++'Click-elem2man' translates Click element documentation into manual pages.
++
++Usage: click-elem2man [-l | -L] [-d DIRECTORY] FILE...
++
++Each FILE is a Click header file, a list of Click header files, or the
++output of click-mkelemmap. '-' means standard input.
++
++Options:
++ -f, --files FILE Read header filenames from FILE.
++ -e, --elementmap EMAP Read information about other elements from EMAP.
++ -d, --directory DIR Place generated manual pages in directory DIR.
++ -P, --package PKG Elements are in PKG package, or say 'DEFAULT'.
++ -l, --list Generate the elements(n) manual page as well.
++ -L, --extend-list Extend an existing elements(n) manual page.
++ -p, --prefix PFX Look for header files in PFX after looking in '.'.
++ --dokuwiki Generate dokuwiki source instead of manual pages.
++ --dokuwiki-dl Generate dokuwiki source using dl plugin.
++ -u, --uninstall Remove existing manual pages.
++ -h, --help Print this message and exit.
++
++Report bugs to <click\@pdos.lcs.mit.edu>.
++EOD;
++ exit 0;
++}
++
++undef $/;
++my(@files, $fn, $elementlist, $any_files, $directory, $output_type);
++$output_type = 'nroff';
++
++while (@ARGV) {
++ $_ = shift @ARGV;
++ if (/^-d$/ || /^--directory$/) {
++ usage() if !@ARGV;
++ $directory = shift @ARGV;
++ } elsif (/^--directory=(.*)$/) {
++ $directory = $1;
++ } elsif (/^-P$/ || /^--package$/) {
++ usage() if !@ARGV;
++ $package = shift @ARGV;
++ } elsif (/^-V$/ || /^--verbose$/) {
++ $verbose = 1;
++ } elsif (/^--package=(.*)$/) {
++ $package = $1;
++ } elsif (/^-f$/ || /^--files$/) {
++ usage() if !@ARGV;
++ push @files, shift @ARGV;
++ $any_files = 1;
++ } elsif (/^--files=(.*)$/) {
++ push @files, $1;
++ $any_files = 1;
++ } elsif (/^-l$/ || /^--list$/) {
++ $elementlist = 1;
++ } elsif (/^-L$/ || /^--extend-list$/) {
++ $elementlist = 2;
++ } elsif (/^-e$/ || /^--elementmap$/) {
++ usage() if !@ARGV;
++ read_elementmap(shift @ARGV);
++ } elsif (/^--elementmap=(.*)$/) {
++ read_elementmap($1);
++ } elsif (/^-p$/ || /^--prefix$/) {
++ usage() if !@ARGV;
++ $PREFIX = shift @ARGV;
++ } elsif (/^--prefix=(.*)$/) {
++ $PREFIX = $1;
++ } elsif (/^-u$/ || /^--uninstall$/) {
++ $uninstall = 1;
++ } elsif (/^-h$/ || /^--help$/) {
++ help();
++ } elsif (/^--dokuwiki$/ || /^--doku$/) {
++ $do_section_func = \&dokuwiki_do_section;
++ $do_text_func = \&dokuwikiize;
++ $output_type = 'dokuwiki';
++ } elsif (/^--dokuwiki-dl$/) {
++ $do_section_func = \&dokuwiki_do_section;
++ $do_text_func = \&dokuwikiize;
++ $output_type = 'dokuwiki';
++ $dokuwiki_dl = 1;
++ } elsif (/^-./) {
++ usage();
++ } elsif (/^-$/) {
++ push @files, "-";
++ $any_files = 1;
++ } else {
++ push @files, glob($_);
++ $any_files = 1;
++ }
++}
++push @files, "-" if !$any_files;
++
++sub nroff_filename_func ($$) {
++ my($name, $sec) = @_;
++ "$directory/$name.$sec";
++}
++
++sub dokuwiki_filename_func ($$) {
++ my($name, $sec) = @_;
++ if ($sec eq 'n') {
++ "$directory/" . lc($name) . ".txt";
++ } else {
++ "$directory/" . lc($name) . "-$sec.txt";
++ }
++}
++
++if ($directory) {
++ $filename_func = ($output_type eq 'dokuwiki' ? \&dokuwiki_filename_func : \&nroff_filename_func);
++}
++
++umask(022);
++if ($uninstall) {
++ open(OUT, ">/dev/null");
++} elsif (!$directory) {
++ open(OUT, ">&STDOUT");
++}
++
++# read file sets
++my(%fnhash);
++foreach $fn (@files) {
++ process_file_set($fn, \%fnhash);
++}
++fix_requires();
++
++# process files
++foreach $fn (keys(%fnhash)) {
++ process_file($fn);
++}
++
++if ($uninstall || !$directory) {
++ close OUT;
++}
++
++
++# printing element list
++#
++
++sub read_elementlist ($) {
++ my($fn) = @_;
++
++ local($/) = "\n";
++ if (!open(IN, $fn)) {
++ print STDERR "click-elem2man: $fn: $!\n";
++ return;
++ }
++
++ my($section, $active, $cur_name, $cur_section, %new_summary);
++ $active = 0;
++ while (<IN>) {
++ if (/^\.SS \"(.*)\"/) {
++ $section = $1;
++ } elsif (/^\.TP 20/) {
++ $active = 1;
++ } elsif ($active == 1 && /^\.M (\S+) (\S+)/) {
++ if (!exists $all_outsections{$1}) {
++ $active = 2;
++ $cur_name = $1;
++ $new_summary{$1} = 1;
++ $all_outsections{$1} = $2;
++ $all_roff_summaries{$1} = '';
++ push @{$summaries_by_section{$section}}, $1;
++ push @all_outfiles, $1;
++ } elsif ($new_summary{$1}) {
++ push @{$summaries_by_section{$section}}, $1;
++ $active = 3;
++ } else {
++ $active = 3;
++ }
++ } elsif (/^\.PD/) {
++ $active = 0;
++ } elsif (/^\.SH \"ALPHABETICAL/) {
++ last;
++ } elsif ($active == 2) {
++ $all_roff_summaries{$cur_name} .= $_;
++ }
++ }
++}
++
++my(%el_generated);
++sub one_elementlist (@) {
++ my($t);
++ $t .= ".PP\n.PD 0\n";
++ foreach $_ (sort { lc($a) cmp lc($b) } @_) {
++ $t .= ".TP 20\n.M " . $_ . " " . $all_outsections{$_};
++ $t .= " \" (deprecated)\"" if $deprecated{$_};
++ $t .= "\n";
++ $t .= $all_roff_summaries{$_} if $all_roff_summaries{$_};
++ $el_generated{$_} = 1;
++ }
++ $t . ".PD\n";
++}
++
++my(@Links, $Text);
++
++sub one_summary ($@) {
++ my($name, @elts) = @_;
++ print STDERR "click-elem2man: warning: category '", $name, "' begins with a lowercase letter (used in @elts)\n" if $name =~ /^[a-z]/;
++ my($a) = $name;
++ $a =~ s{([+\&\#\"\000-\037\177-\377])}{sprintf("%%%02X", $1)}eg;
++ $a =~ tr/ /+/;
++ my($x) = $name;
++ $x =~ s{ }{ }g;
++ if (@elts) {
++ push @Links, "<a href=\"#$a\">$x</a>";
++ $Text .= ".SS \"$name\"\n";
++ $Text .= one_elementlist(@elts);
++ }
++}
++
++sub write_elementlist ($$) {
++ my($enamebase, $l_uninstall) = @_;
++ if ($filename_func) {
++ my($fn) = &$filename_func($enamebase, $section);
++ if ($l_uninstall) {
++ print STDERR "Removing $fn\n" if $verbose;
++ unlink($fn);
++ return;
++ }
++ if (!open(OUT, ">$fn")) {
++ print STDERR "click-elem2man: $fn: $!\n";
++ return;
++ }
++ } elsif ($uninstall) {
++ return;
++ }
++
++ print OUT <<"EOD;";
++.\\" -*- mode: nroff -*-
++.\\" Generated by 'click-elem2man'
++$nroff_prologue
++.TH "\U$enamebase\E" $section "$today" "Click"
++.SH "NAME"
++$enamebase \- documented Click element classes
++.SH "DESCRIPTION"
++This page lists all Click element classes that have manual page documentation.
++EOD;
++
++ $Text = "";
++ my(%did_section, $sec);
++ # erase 'Miscellaneous' section, if any
++ delete $summaries_by_section{'Miscellaneous'};
++ my($i) = 0;
++ foreach $sec ((map { $i++ % 2 ? ($_) : () } @section_headers),
++ (sort { lc($a) cmp lc($b) } keys(%summaries_by_section))) {
++ next if $did_section{$sec};
++ one_summary($sec, @{$summaries_by_section{$sec}});
++ $did_section{$sec} = 1;
++ }
++ one_summary('Miscellaneous', grep { !$el_generated{$_} } @all_outfiles);
++
++ my($links) = join(" - ", @Links);
++ print OUT <<"EOD;";
++.\\"html <p><a href="#BY+FUNCTION"><b>By Function</b></a>:
++.\\"html $links<br>
++.\\"html <a href="#ALPHABETICAL+LIST"><b>Alphabetical List</b></a></p>
++EOD;
++
++ print OUT ".SH \"BY FUNCTION\"\n";
++ print OUT $Text;
++ print OUT ".SH \"ALPHABETICAL LIST\"\n";
++ print OUT one_elementlist(@all_outfiles);
++
++ close OUT if $filename_func;
++}
++
++sub read_main_elementlist () {
++ if ($filename_func) {
++ my($fn) = &$filename_func('elements', $section);
++ $fn = &$filename_func('elements-click', $section) if !-r $fn;
++ read_elementlist($fn) if -r $fn && $elementlist > 1;
++ }
++}
++
++if ($elementlist && @all_outfiles) {
++ # erase record of elements added on uninstall
++ if ($elementlist > 1 && $uninstall) {
++ %summaries_by_section = ();
++ @all_outfiles = ();
++ }
++
++ # package-specific elementlist
++ if (defined($package)) {
++ my($fename) = ($package eq "DEFAULT" ? "elements-click" : "elements-$package");
++ write_elementlist($fename, $uninstall);
++ }
++ read_main_elementlist();
++ write_elementlist("elements", 0);
++}
+Files click-1.6.0/inst/bin/click-fastclassifier and click-1.6.0-27/inst/bin/click-fastclassifier differ
+Files click-1.6.0/inst/bin/click-flatten and click-1.6.0-27/inst/bin/click-flatten differ
+diff -Nurb click-1.6.0/inst/bin/click-mkelemmap click-1.6.0-27/inst/bin/click-mkelemmap
+--- click-1.6.0/inst/bin/click-mkelemmap 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/bin/click-mkelemmap 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,535 @@
++#! /usr/bin/perl -w
++
++# click-mkelemmap -- make map of element name to C++ class and file
++# Eddie Kohler
++#
++# Copyright (c) 1999-2001 Massachusetts Institute of Technology
++# Copyright (c) 2004-2006 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++my(%port_count_constants) =
++ ('PORTS_0_0' => '0/0', 'PORTS_0_1' => '0/1', 'PORTS_1_0' => '1/0',
++ 'PORTS_1_1' => '1/1');
++my(%processing_constants) =
++ ('AGNOSTIC' => 'a/a', 'PUSH' => 'h/h', 'PULL' => 'l/l',
++ 'PUSH_TO_PULL' => 'h/l', 'PULL_TO_PUSH' => 'l/h');
++my(%flow_code_constants) =
++ ('COMPLETE_FLOW' => 'x/x');
++my(@source_file, @header_file, @click_name, @cxx_name, @doc_name,
++ @parents, @port_count, @processing, @flow_code, @flags, @requirements,
++ @element_methods, @element_libs, @provisions,
++ %click_name_to_id, %cxx_name_to_id);
++my(@includes) = ( );
++
++sub driver_mask ($) {
++ my($m) = 0;
++ # XXX "|" syntax?
++ $m |= 1 if $_[0] =~ /\buserlevel\b/;
++ $m |= 2 if $_[0] =~ /\blinuxmodule\b/;
++ $m |= 4 if $_[0] =~ /\bbsdmodule\b/;
++ $m |= 8 if $_[0] =~ /\bns\b/;
++ ($m ? $m : 15);
++}
++
++sub filecontents ($) {
++ my $text = "";
++ if (open(IN, $_[0])) {
++ $text = <IN>;
++ close IN;
++ }
++ $text;
++}
++
++sub process_file ($) {
++ my($filename) = @_;
++ my($headername, $headerfile, $i, $comment);
++
++ if ($filename =~ /^(.*):"(.*)"$/) {
++ ($filename, $headername) = ($1, $2);
++ $headerfile = $headername;
++ } elsif ($filename =~ /^(.*):<(.*)>$/) {
++ ($filename, $headername) = ($1, "<$2>");
++ $headerfile = $2;
++ } else {
++ $headername = $filename;
++ $headername =~ s/\.cc$/.hh/;
++ $headerfile = $headername;
++ }
++
++ my($text) = "";
++ if ($headerfile =~ m|^/|) {
++ $text = filecontents($headerfile);
++ } else {
++ for ($i = 0; $i < @includes && $text eq ""; $i++) {
++ $text = filecontents($includes[$i] . "/" . $headerfile);
++ }
++ }
++ $headername = "" if $text eq "";
++
++ my $first;
++ $first = @cxx_name;
++ foreach $_ (split(m{^class(?=.*[\n\s]*\{)}m, $text)) {
++ my($cxx_class) = (/^\s*(\w+)(\s|:\s).*[\n\s]*\{/);
++ my($click_name) = (/class_name.*return\s*\"([^\"]+)\"/);
++ next if !$click_name;
++ push @cxx_name, $cxx_class;
++ push @source_file, $filename;
++ push @header_file, $headername;
++ $cxx_name_to_id{$cxx_class} = @cxx_name - 1 if $cxx_class;
++ if (/\A\s*\w*\s*:\s*([\w\s,]+)/) {
++ my $p = $1;
++ $p =~ s/\bpublic\b//g;
++ push @parents, [ split(/[\s,]+/, $p) ];
++ } else {
++ push @parents, [];
++ }
++ if (/class_name.*return\s*\"([^\"]+)\"/) {
++ push @click_name, $1;
++ } else {
++ push @click_name, "";
++ }
++ if (/port_count.*return\s*(.*?);/) {
++ my $p = $1;
++ $p = $port_count_constants{$p} if exists($port_count_constants{$p});
++ $p =~ tr/\" \t\r\n//d;
++ push @port_count, $p;
++ } else {
++ push @port_count, "";
++ }
++ if (/processing.*return\s*(.*?);/) {
++ my $p = $1;
++ $p = $processing_constants{$p} if exists($processing_constants{$p});
++ $p =~ tr/\" \t\r\n//d;
++ push @processing, $p;
++ } else {
++ push @processing, "";
++ }
++ if (/flow_code.*return\s*(.*?);/) {
++ my $p = $1;
++ $p = $flow_code_constants{$p} if exists($flow_code_constants{$p});
++ $p =~ tr/\" \t\r\n//d;
++ push @flow_code, $p;
++ } else {
++ push @flow_code, "";
++ }
++ if (/\bflags\(\).*return\s*"(.*?)";/) {
++ push @flags, $1;
++ } else {
++ push @flags, undef;
++ }
++ my($methods) = '';
++ $methods .= "static_initialize " if /\n\s*static\s+void\s+static_initialize/;
++ $methods .= "static_cleanup " if /\n\s*static\s+void\s+static_cleanup/;
++ $methods =~ s/\s+\Z//;
++ push @element_methods, $methods;
++ }
++
++ # process element documentation
++ my(%doc_titles);
++ foreach $comment (split(m{(/\*.*?\*/)}s, $text)) {
++ if ($comment =~ /^\/\*/ && $comment =~ /^[\/*\s]+=/) {
++ $comment =~ s/^\/\*\s*//g;
++ $comment =~ s/\s*\*\/$//g;
++ $comment =~ s/^ ?\* ?//gm;
++ my($title, $count);
++ while ($comment =~ m{^=(\w+)( *)(.*)([\0-\377]*?)(?=^=\w|\Z)}mg) {
++ if ($1 eq 'title') {
++ $title = $3;
++ } elsif ($1 eq 'c') {
++ $_ = $4;
++ while (/^\s*(\w+)\(/mg) {
++ $doc_titles{$1} = ($title ? $title : $1);
++ }
++ if (!%doc_titles && /^\s*([\w@]+)\s*$/) {
++ $doc_titles{$1} = ($title ? $title : $1);
++ }
++ last;
++ }
++ }
++ }
++ }
++
++ # apply element documentation to element names
++ for ($i = $first; $i < @processing; $i++) {
++ push @doc_name, $doc_titles{$click_name[$i]};
++ }
++
++ # check titles
++ if (@processing == 0 && keys(%doc_titles) > 1) {
++ print STDERR "$filename: more than 1 documentation class for requirement\n";
++ }
++
++ # process ELEMENT_REQUIRES, ELEMENT_PROVIDES, and EXPORT_ELEMENT
++ if (!open(IN, $filename)) {
++ print STDERR "$filename: $!\n";
++ return;
++ }
++ $text = <IN>;
++ close IN;
++
++ my($req, $prov, $exp, $libs) = ('', '', '', '');
++ $req .= " " . $1 while $text =~ /^ELEMENT_REQUIRES\s*\((.*)\)/mg;
++ $prov .= " " . $1 while $text =~ /^ELEMENT_PROVIDES\s*\((.*)\)/mg;
++ $exp .= " " . $1 while $text =~ /^EXPORT_ELEMENT\s*\((.*)\)/mg;
++ $libs .= " " . $1 while $text =~ /^ELEMENT_LIBS\s*\((.*)\)/mg;
++ $req =~ s/^\s+//;
++ $prov =~ s/^\s+//;
++ $libs =~ s/^\s+//;
++
++ # make copies of classes as required
++ while ($exp =~ /(\S+)-(\S+)/g) {
++ my($cxx, $click) = ($1, $2);
++ for ($i = $first; $i < @processing; $i++) {
++ if ($cxx_name[$i] eq $cxx) {
++ push @click_name, $click;
++ push @cxx_name, $cxx;
++ push @doc_name, $doc_name[$i];
++ push @source_file, $source_file[$i];
++ push @header_file, $header_file[$i];
++ push @parents, $parents[$i];
++ push @port_count, $port_count[$i];
++ push @processing, $processing[$i];
++ push @flow_code, $flow_code[$i];
++ push @flags, $flags[$i];
++ push @element_methods, $element_methods[$i];
++ last;
++ }
++ }
++ }
++
++ # add a fake class if there were no classes
++ if (@cxx_name == $first && $prov) {
++ push @click_name, "";
++ push @cxx_name, "";
++ push @doc_name, (%doc_titles ? keys(%doc_titles) : (""));
++ push @source_file, $filename;
++ push @header_file, $headername;
++ push @parents, [];
++ push @port_count, "";
++ push @processing, "";
++ push @flow_code, "";
++ push @flags, undef;
++ push @element_methods, "";
++ }
++
++ # apply requirements and provisions
++ for ($i = $first; $i < @processing; $i++) {
++ push @requirements, $req;
++ push @provisions, $prov;
++ push @element_libs, $libs;
++
++ # check to see if overloading is valid
++ if ($click_name[$i] && exists($click_name_to_id{$click_name[$i]})) {
++ my($j) = $click_name_to_id{$click_name[$i]};
++ my($dm_a) = driver_mask($requirements[$i]);
++ my($dm_b) = driver_mask($requirements[$j]);
++ if (($dm_a & $dm_b) == 0) {
++ # ok
++ } else {
++ print STDERR "invalid multiple definition of element class '$click_name[$i]'\n";
++ print STDERR $header_file[$j], ": first definition here\n";
++ print STDERR $header_file[$i], ": second definition here\n";
++ print STDERR "(Two classes may share a name only if they work in disjoint drivers.\nAdd explicit ELEMENT_REQUIRES() statements.)\n";
++ }
++ }
++ $click_name_to_id{$click_name[$i]} = $i;
++ }
++}
++
++sub parents_port_count ($) {
++ my($classid) = @_;
++ return undef if !defined $classid;
++ if (!$port_count[$classid]) {
++ my($parent);
++ foreach $parent (@{$parents[$classid]}) {
++ if ($parent eq 'Element') {
++ $port_count[$classid] = '0/0';
++ last;
++ } elsif ($parent ne '') {
++ $port_count[$classid] = &parents_port_count($cxx_name_to_id{$parent});
++ last if $port_count[$classid];
++ }
++ }
++ }
++ return $port_count[$classid];
++}
++
++sub parents_processing ($) {
++ my($classid) = @_;
++ return undef if !defined $classid;
++ if (!$processing[$classid]) {
++ my($parent);
++ foreach $parent (@{$parents[$classid]}) {
++ if ($parent eq 'Element') {
++ $processing[$classid] = 'a/a';
++ last;
++ } elsif ($parent ne '') {
++ $processing[$classid] = &parents_processing($cxx_name_to_id{$parent});
++ last if $processing[$classid];
++ }
++ }
++ }
++ return $processing[$classid];
++}
++
++sub parents_flow_code ($) {
++ my($classid) = @_;
++ return undef if !defined $classid;
++ if (!$flow_code[$classid]) {
++ my($parent);
++ foreach $parent (@{$parents[$classid]}) {
++ if ($parent eq 'Element') {
++ $flow_code[$classid] = 'x/x';
++ last;
++ } elsif ($parent ne '') {
++ $flow_code[$classid] = &parents_flow_code($cxx_name_to_id{$parent});
++ last if $flow_code[$classid];
++ }
++ }
++ }
++ return $flow_code[$classid];
++}
++
++sub parents_flags ($) {
++ my($classid) = @_;
++ return undef if !defined $classid;
++ if (!defined $flags[$classid]) {
++ my($parent);
++ foreach $parent (@{$parents[$classid]}) {
++ if ($parent eq 'Element') {
++ last;
++ } elsif ($parent ne '') {
++ $flags[$classid] = &parents_flags($cxx_name_to_id{$parent});
++ last if defined $flags[$classid];
++ }
++ }
++ }
++ return $flags[$classid];
++}
++
++sub xml_quote ($) {
++ my($x) = @_;
++ $x =~ s/&/&/g;
++ $x =~ s/</</g;
++ $x;
++}
++
++# main program: parse options
++sub read_files_from ($) {
++ my($fn) = @_;
++ if (open(IN, ($fn eq '-' ? "<&STDIN" : $fn))) {
++ my(@a, @b, $t);
++ $t = <IN>;
++ close IN;
++
++ # Parse file; click-buildtool gets special treatment
++ if ($t =~ /\A#.*click-(buildtool findelem|mkmindriver)/) {
++ $t =~ s/^#.*//mg;
++ @a = map {
++ if (/^(\S+)\s+(\S+)/) {
++ "$1:$2";
++ } else {
++ $_;
++ }
++ } split(/\n+/, $t);
++ } else {
++ $t =~ s/^#.*//mg;
++ @a = split(/\s+/, $t);
++ }
++
++ foreach $t (@a) {
++ next if $t eq '';
++ if ($t =~ /[*?\[]/) {
++ push @b, glob($t);
++ } else {
++ push @b, $t;
++ }
++ }
++
++ @b;
++ } else {
++ print STDERR "$fn: $!\n";
++ ();
++ }
++}
++
++sub long_option_match ($$$) {
++ my($have, $want, $len) = @_;
++ $have = $1 if $have =~ /^(--[^=]*)=/;
++ my($hl) = length($have);
++ ($hl <= length($want) && $hl >= $len && $have eq substr($want, 0, $hl));
++}
++
++sub help () {
++ print STDERR <<"EOD;";
++'Click-mkelemmap' creates an elementmap file from a collection of Click
++elements.
++
++Usage: click-mkelemmap [OPTIONS] [-f FILE | SRCFILE]...
++
++Each SRCFILE is a Click header file. '-' means standard input. Default is
++'-f -' if no '-f' or 'SRCFILE' options are supplied.
++
++Options:
++ -f, --files FILE Read header filenames, or an 'elements.conf' file,
++ from FILE.
++ -r, --provide PROV Record provisions PROV in output.
++ -t, --drivers DRIVERS Record drivers DRIVERS in output.
++ --dochref DOCSTR Record documentation URL pattern DOCSTR in output.
++ -p, --prefix PFX Remove PFX from filenames in output.
++ -I, --include DIR Look for header files in DIR.
++ -s, --sourcedir DIR Record DIR as source directory in output.
++ -h, --help Print this message and exit.
++
++Report bugs to <click\@pdos.lcs.mit.edu>.
++EOD;
++ exit 0;
++}
++
++undef $/;
++my(@files, @provides, @drivers, $fn, $prefix, $any_files, $dochref, $sourcedir);
++$prefix = "";
++
++while (@ARGV) {
++ $_ = shift @ARGV;
++ if (long_option_match($_, '--files', 3) && /^[^=]*=(.*)$/) {
++ push @files, read_files_from($1);
++ $any_files = 1;
++ } elsif (/^-f$/ || long_option_match($_, '--files', 3)) {
++ die "not enough arguments" if !@ARGV;
++ push @files, read_files_from(shift @ARGV);
++ $any_files = 1;
++ } elsif (long_option_match($_, '--prefix', 5) && /^[^=]*=(.*)$/) {
++ $prefix = $1;
++ $prefix .= "/" if $prefix !~ m|/\Z|;
++ } elsif (/^-p$/ || long_option_match($_, '--prefix', 5)) {
++ die "not enough arguments" if !@ARGV;
++ $prefix = shift @ARGV;
++ $prefix .= "/" if $prefix !~ m|/\Z|;
++ } elsif (long_option_match($_, '--provide', 5) && /^[^=]*=(.*)$/) {
++ push @provides, split(/\s+/, $1);
++ } elsif (/^-r$/ || long_option_match($_, '--provide', 5)) {
++ die "not enough arguments" if !@ARGV;
++ push @provides, split(/\s+/, shift @ARGV);
++ } elsif (long_option_match($_, '--drivers', 4) && /^[^=]*=(.*)$/) {
++ push @drivers, split(/\s+/, $1);
++ } elsif (/^-t$/ || long_option_match($_, '--drivers', 4)) {
++ die "not enough arguments" if !@ARGV;
++ push @drivers, split(/\s+/, shift @ARGV);
++ } elsif (long_option_match($_, '--include', 3) && /^[^=]*=(.*)$/) {
++ push @includes, $prefix . $1;
++ } elsif (/^-I$/ || long_option_match($_, '--include', 3)) {
++ die "not enough arguments" if !@ARGV;
++ push @includes, $prefix . shift @ARGV;
++ } elsif (/^-I(.+)$/) {
++ push @includes, $prefix . $1;
++ } elsif (long_option_match($_, '--sourcedir', 3) && /^[^=]*=(.*)$/) {
++ $sourcedir = xml_quote($1);
++ } elsif (/^-s$/ || long_option_match($_, '--sourcedir', 3)) {
++ die "not enough arguments" if !@ARGV;
++ $sourcedir = xml_quote(shift @ARGV);
++ } elsif (/^-s(.+)$/) {
++ $sourcedir = xml_quote($1);
++ } elsif ((long_option_match($_, '--dochref', 4) || long_option_match($_, '--webdoc', 3))
++ && /^[^=]*=(.*)$/) {
++ die "repeated --dochref" if defined($dochref);
++ $dochref = $1;
++ } elsif (long_option_match($_, '--dochref', 4) || long_option_match($_, '--webdoc', 3)) {
++ die "not enough arguments" if !@ARGV;
++ die "repeated --dochref" if defined($dochref);
++ $dochref = shift @ARGV;
++ } elsif (/^-h$/ || long_option_match($_, '--help', 3)) {
++ help();
++ } elsif (/^-./) {
++ die "unknown option '$_'\n";
++ } elsif (/^-$/) {
++ push @files, "-";
++ $any_files = 1;
++ } else {
++ push @files, glob($_);
++ $any_files = 1;
++ }
++}
++push @files, read_files_from("-") if !$any_files;
++push @includes, ($prefix eq '' ? "." : $prefix);
++
++foreach $fn (@files) {
++ process_file($fn);
++}
++
++umask(022);
++open(OUT, ">&STDOUT");
++
++print OUT "<?xml version=\"1.0\" standalone=\"yes\"?>
++<?xml-stylesheet type=\"application/xml\" href=\"http://www.lcdf.org/click/xml/elementmap.xsl\"?>\n";
++print OUT "<?xml-stylesheet type=\"application/xml\" href=\"file://$sourcedir/etc/elementmap.xsl\"?>\n" if defined($sourcedir) && $sourcedir =~ m|^/|;
++print OUT "<elementmap xmlns=\"http://www.lcdf.org/click/xml/\"";
++print OUT " sourcedir=\"$sourcedir\"" if defined($sourcedir);
++print OUT " src=\"file://$sourcedir\"" if defined($sourcedir) && $sourcedir =~ m|^/|;
++print OUT " provides=\"", join(' ', @provides), "\"";
++print OUT " drivers=\"", join(' ', @drivers), "\"" if @drivers;
++print OUT " dochref=\"$dochref\"" if defined($dochref);
++print OUT ">\n";
++
++sub sorter {
++ my($xa, $xb) = ($click_name[$a], $click_name[$b]);
++ if ($xa && $xb) {
++ $xa cmp $xb;
++ } elsif ($xa || $xb) {
++ ($xa ? -1 : 1);
++ } else {
++ $provisions[$a] cmp $provisions[$b];
++ }
++}
++
++foreach $id (sort sorter 0..$#click_name) {
++ print OUT "<entry";
++
++ print OUT " name=\"", $click_name[$id], "\"" if $click_name[$id];
++ print OUT " cxxclass=\"", $cxx_name[$id], "\"" if $cxx_name[$id];
++ print OUT " docname=\"", $doc_name[$id], "\"" if $doc_name[$id];
++
++ my($hf) = $header_file[$id];
++ $hf =~ s/^$prefix\/*// if $prefix;
++ print OUT " headerfile=\"", xml_quote($hf), "\"" if $hf;
++
++ my($sf) = $source_file[$id];
++ $sf =~ s/^$prefix\/*// if $prefix;
++ print OUT " sourcefile=\"", xml_quote($sf), "\"" if $sf;
++
++ my($pc) = $port_count[$id];
++ $pc = parents_port_count($id) if !$pc;
++ print OUT " portcount=\"", $pc, "\"" if $pc;
++
++ my($p) = $processing[$id];
++ $p = parents_processing($id) if !$p;
++ print OUT " processing=\"", $p, "\"" if $p;
++
++ my($flow) = $flow_code[$id];
++ $flow = parents_flow_code($id) if !$flow;
++ print OUT " flowcode=\"", $flow, "\"" if $flow;
++
++ my($flags) = $flags[$id];
++ $flags = parents_flags($id) if !defined($flags);
++ print OUT " flags=\"", $flags, "\"" if defined($flags);
++
++ print OUT " methods=\"", $element_methods[$id], "\"" if $element_methods[$id];
++
++ print OUT " requires=\"", $requirements[$id], "\"" if $requirements[$id];
++ print OUT " provides=\"", $provisions[$id], "\"" if $provisions[$id];
++ print OUT " libs=\"", xml_quote($element_libs[$id]), "\"" if $element_libs[$id];
++
++ print OUT " />\n";
++}
++
++print OUT "</elementmap>\n";
++close OUT;
+Files click-1.6.0/inst/bin/click-mkmindriver and click-1.6.0-27/inst/bin/click-mkmindriver differ
+Files click-1.6.0/inst/bin/click-pretty and click-1.6.0-27/inst/bin/click-pretty differ
+Files click-1.6.0/inst/bin/click-uncombine and click-1.6.0-27/inst/bin/click-uncombine differ
+Files click-1.6.0/inst/bin/click-undead and click-1.6.0-27/inst/bin/click-undead differ
+Files click-1.6.0/inst/bin/click-xform and click-1.6.0-27/inst/bin/click-xform differ
+Files click-1.6.0/inst/bin/click2xml and click-1.6.0-27/inst/bin/click2xml differ
+diff -Nurb click-1.6.0/inst/bin/testie click-1.6.0-27/inst/bin/testie
+--- click-1.6.0/inst/bin/testie 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/bin/testie 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,1206 @@
++#! /usr/bin/perl -w
++use Symbol 'qualify_to_ref';
++no locale;
++use bytes;
++require 5.006;
++
++($attempts, $internal_errors, $errors, $require_errors) = (0, 0, 0, 0);
++($preserve_temporaries, $expand_mode) = (0, 0);
++
++## utilities
++
++sub index2 ($$;$) {
++ my($result) = (defined($_[2]) ? index($_[0], $_[1], $_[2]) : index($_[0], $_[1]));
++ $result = length $_[0] if $result < 0;
++ $result;
++}
++
++sub shquote ($) {
++ my($t) = @_;
++ $t =~ s/\'/\'\"\'\"\'/g;
++ "'$t'";
++}
++
++sub min (@) {
++ my($m) = pop @_;
++ foreach my $mm (@_) {
++ $m = $mm if $mm < $m;
++ }
++ $m;
++}
++
++
++## read file
++
++package Testie;
++
++my %_special_filerefs = ('stdin' => 1, 'stdout' => 2, 'stderr' => 2);
++%_variables = ();
++
++# return filename
++sub filename ($) {
++ $_[0]->{'filename'};
++}
++
++# return line number text
++sub lineno ($$) {
++ my($tt, $lineno) = @_;
++ my($fn) = $tt->{'filename'};
++ $fn = 'line ' if !defined($fn);
++ $fn .= ':' if $fn !~ /[ :]$/;
++ "$fn$lineno";
++}
++
++# return a command at a given line number
++sub command_at ($$;$) {
++ my($tt, $lineno, $script_type) = @_;
++ return undef if !defined($lineno);
++ $lineno =~ s/^\s*|\s*$//g;
++ if ($lineno =~ /^(.*):(.*)$/) {
++ return undef if $1 ne $tt->{'filename'};
++ $lineno = $2;
++ } elsif ($lineno =~ /^line (.*)$/) {
++ $lineno = $2;
++ }
++
++ $script_type = 'script' if !defined($script_type);
++ my($lineno_arr) = $tt->{$script_type . '_lineno'};
++ for ($i = 0; $i < @$lineno_arr; $i++) {
++ return $tt->{$script_type}->[$i] if $lineno_arr->[$i] == $lineno;
++ }
++ undef;
++}
++
++# report an error
++sub file_err ($$) {
++ my($tt, $text) = @_;
++ $text .= "\n" if $text !~ /\n$/s;
++ print STDERR $tt->lineno($.), ': ', $text;
++ $tt->{'err'}++;
++}
++
++sub _shell_split (\@\@$$;$) {
++ my($arr, $lineno_arr, $text, $lineno, $rewrite_sub) = @_;
++ $rewrite_sub = sub { $_[0] } if !defined($rewrite_sub);
++ my($qf, $qb, $func, $out) = (0, 0, 0, '');
++ my($sq, $dq, $bq, $nl, $hh, $lb, $rb) = (-2, -2, -2, -2, -2, -2, -2);
++ my($first, $pos) = (0, 0);
++ $lineno -= ($text =~ tr/\n//);
++
++ while ($pos < length $text) {
++ $sq = ::index2($text, "\'", $pos) if $sq < $pos;
++ $dq = ::index2($text, "\"", $pos) if $dq < $pos;
++ $bq = ::index2($text, "\`", $pos) if $bq < $pos;
++ $nl = ::index2($text, "\n", $pos) if $nl < $pos;
++ $hh = ::index2($text, "#", $pos) if $hh < $pos;
++ $lb = ::index2($text, "{", $pos) if $lb < $pos;
++ $rb = ::index2($text, "}", $pos) if $rb < $pos;
++
++ if ($qf == 1) {
++ $qf = 0 if $sq < length $text;
++ $out .= substr($text, $pos, $sq + 1 - $pos);
++ $pos = $sq + 1;
++ next;
++ } elsif ($qf == 2) {
++ $qf = 0 if $dq < length $text;
++ $out .= $rewrite_sub->(substr($text, $pos, $dq - $pos), 2) . '"';
++ $pos = $dq + 1;
++ next;
++ }
++
++ # find minimum
++ my($min) = ::min($sq, $dq, $bq, $nl, $hh, $lb, $rb);
++ $out .= $rewrite_sub->(substr($text, $pos, $min - $pos), 0) . substr($text, $min, 1);
++
++ if ($sq == $min) {
++ $qf = 1;
++ $pos = $sq + 1;
++ } elsif ($dq == $min) {
++ $qf = 2;
++ $pos = $dq + 1;
++ } elsif ($bq == $min) {
++ $qb = !$qb;
++ $pos = $bq + 1;
++ } elsif ($lb == $min) {
++ $func++;
++ $pos = $lb + 1;
++ } elsif ($rb == $min) {
++ $func--;
++ $pos = $rb + 1;
++ } elsif ($hh == $min) {
++ $out .= substr($text, $min + 1, $nl - $min);
++ $lineno++;
++ $pos = $nl + 1;
++ } elsif (!$qb && !$func && ($nl == $pos || substr($text, $nl - 1, 1) ne "\\")) {
++ push @$arr, $out;
++ push @$lineno_arr, $lineno;
++ $out = '';
++ $lineno += (substr($text, $first, $nl - $first + 1) =~ tr/\n//);
++ $first = $pos = $nl + 1;
++ } else {
++ $pos = $nl + 1;
++ }
++ }
++
++ if ($first < length $text) {
++ push @$arr, $out;
++ push @$lineno_arr, $lineno;
++ }
++
++ if ($qf == 1) {
++ "unmatched single quote";
++ } elsif ($qf == 2) {
++ "unmatched double quote";
++ } elsif ($qb) {
++ "unmatched backquote";
++ } else {
++ "";
++ }
++}
++
++sub _read_text ($) {
++ my($fh) = @_;
++ my($r, $t) = ('');
++ while (defined($t = <$fh>)) {
++ last if $t =~ /^\%/;
++ $t =~ s/^\\\%/\%/;
++ $r .= $t;
++ }
++ ($r, $t);
++}
++
++sub _read_text_into ($$$) {
++ my($fh, $tt, $section) = @_;
++ my($r, $t) = _read_text($fh);
++ $tt->{$section} = '' if !defined($tt->{$section});
++ $tt->{$section} .= $r;
++ $t;
++}
++
++sub _read_script_section ($$$$) {
++ my($fh, $tt, $args, $script_type) = @_;
++
++ my($lineno_type, $quiet_type) = ($script_type . '_lineno', $script_type . '_quietline');
++ $tt->{$lineno_type} = [] if !exists $tt->{$lineno_type};
++ $tt->{$quiet_type} = {} if !exists $tt->{$quiet_type};
++
++ my($quiet);
++ if ($script_type eq 'require' & $args eq '-q') {
++ $quiet = 1;
++ } elsif ($args ne '') {
++ $tt->file_err("arguments to '\%$script_type' ignored");
++ }
++ #$tt->file_err("multiple '\%$script_type' sections defined") if $tt->{$script_type};
++ my($r, $t) = _read_text($fh);
++ my $count = @{$tt->{$lineno_type}};
++ my($what) = _shell_split(@{$tt->{$script_type}}, @{$tt->{$lineno_type}}, $r, $.);
++ $tt->file_err("$what in '\%$script_type'") if $what ne '';
++ while ($quiet && $count < @{$tt->{$lineno_type}}) {
++ my($line) = $tt->{$lineno_type}->[$count++];
++ $tt->{$quiet_type}->{$line} = 1;
++ }
++ $t;
++}
++
++sub braces_to_regex ($) {
++ my($x) = @_;
++ my(@a) = split(/(\{\{.*?\}\})/, $x);
++ my($d, $i) = '';
++ for ($i = 0; $i < @a; $i++) {
++ $d .= ($i % 2 ? substr($a[$i], 2, -2) : quotemeta($a[$i]));
++ }
++ $d;
++}
++
++sub _read_file_section ($$$$$) {
++ my($fh, $tt, $args, $secname, $prefix) = @_;
++ $args =~ s/\s+$//;
++
++ # split arguments to get fileref
++ my(@args) = split(/\s+/, $args);
++
++ # assert that we understand $secname
++ die if $secname ne 'file' && $secname ne 'expect' && $secname ne 'expectv' && $secname ne 'expectx' && $secname ne 'ignore' && $secname ne 'ignorex' && $secname ne 'ignorev';
++
++ # check for alternates and length
++ my($alternate, $delfirst, $regex_opts, $length) = (0, 0, '', undef);
++ while (@args) {
++ if ($args[0] eq '-a') {
++ $alternate = 1;
++ } elsif ($args[0] eq '-d') {
++ $delfirst = 1;
++ } elsif ($args[0] eq '-i') {
++ $regex_opts .= "(?i)";
++ } elsif ($args[0] =~ /^\+(\d+)$/) {
++ $length = $1;
++ } else {
++ last;
++ }
++ shift @args;
++ }
++
++ # make sure there are filerefs
++ if (!@args) {
++ push @args, "stdin" if $secname eq 'file';
++ push @args, "stdout" if $secname eq 'expect' || $secname eq 'expectv' || $secname eq 'expectx';
++ push @args, "all" if $secname eq 'ignore' || $secname eq 'ignorev' || $secname eq 'ignorex';
++ }
++
++ # complain about '%file -a'
++ if (($secname eq 'file' || $secname eq 'ignore' || $secname eq 'ignorev' || $secname eq 'ignorex') && $alternate) {
++ $tt->file_err("'\%file -a' is illegal");
++ } elsif (($secname eq 'file' || $secname eq 'expectv') && $regex_opts) {
++ $tt->file_err("'\%file -i' is illegal");
++ }
++
++ # read contents
++ my($t, $file_data);
++ if (defined($length)) {
++ read $fh, $file_data, $length;
++ $tt->file_err("file too short") if length($file_data) != $length;
++ $t = <$fh>;
++ } else {
++ ($file_data, $t) = _read_text($fh);
++ }
++
++ # modify contents based on flags
++ $alternate = 1 if $secname eq 'ignore' || $secname eq 'ignorex' || $secname eq 'ignorev'; # 'ignore' always behaves like -a
++ if ($delfirst) {
++ $file_data =~ s{^.}{}mg;
++ }
++ if ($secname eq 'ignorev') {
++ $file_data =~ s{^(.+)}{quotemeta($1)}meg;
++ } elsif ($secname eq 'ignore') {
++ $file_data =~ s{^(.+)}{braces_to_regex($1)}meg;
++ }
++ if ($regex_opts && $secname eq 'expect') {
++ $file_data =~ s{\{\{}{\{\{$regex_opts}g;
++ } elsif ($regex_opts) {
++ $file_data =~ s{^(?=.)}{$regex_opts}mg;
++ }
++
++ # stick contents where appropriate
++ my($fn);
++ foreach $fn (@args) {
++ if (($fn eq 'stdin' && $secname ne 'file')
++ || (($fn eq 'stdout' || $fn eq 'stderr') && $secname eq 'file')
++ || ($fn eq 'all' && ($secname ne 'ignore' && $secname ne 'ignorev' && $secname ne 'ignorex'))) {
++ $tt->file_err("'$fn' not meaningful for '\%$secname'");
++ }
++
++ my($hashkey) = $prefix . ":" . $fn;
++ if ($fn !~ m/^[A-Za-z_.0-9]+$/) {
++ $tt->file_err("fileref error: '$fn' contains illegal characters");
++ } elsif (!exists($tt->{$hashkey})) {
++ push @{$tt->{$secname}}, $fn;
++ $tt->{$hashkey} = [];
++ } elsif (!$alternate) {
++ $tt->file_err("'\%$secname $fn' already defined");
++ }
++
++ push @{$tt->{$hashkey}}, $file_data;
++ $tt->{"F:$fn"} = 1;
++ }
++
++ # return next line
++ $t;
++}
++
++sub _skip_section ($$) {
++ my($fh, $tt) = @_;
++ my($t);
++ while (defined($t = <$fh>)) {
++ last if $t =~ /^%/;
++ }
++ $t;
++}
++
++sub read (*;$) {
++ my($fh, $fn) = @_;
++ $fh = ::qualify_to_ref($fh, caller);
++
++ my($tt) = bless { 'filename' => $fn, 'err' => 0, 'errprefix' => $fn . ": " }, Testie;
++
++ my($t, $read_command) = (undef, 0);
++ $t = <$fh>;
++ while (defined($t)) {
++ if ($t =~ /^%\s*(\w+)\s*(.*?)\s*$/) {
++ my($command) = lc($1);
++ my($args) = $2;
++ if ($command eq 'script' || $command eq 'test') {
++ $t = _read_script_section($fh, $tt, $args, 'script');
++ } elsif ($command eq 'require') {
++ $t = _read_script_section($fh, $tt, $args, 'require');
++ } elsif ($command eq 'info') {
++ $tt->file_err("arguments to '\%info' ignored") if $args ne '';
++ $t = _read_text_into($fh, $tt, 'info');
++ } elsif ($command eq 'desc') {
++ $tt->file_err("arguments to '\%desc' ignored") if $args ne '';
++ $t = _read_text_into($fh, $tt, 'desc');
++ } elsif ($command eq 'cut') {
++ $t = _read_text_into($fh, $tt, 'cut');
++ } elsif ($command eq 'stdin' || $command eq 'input') {
++ $t = _read_file_section($fh, $tt, $args, 'file', 'f');
++ } elsif ($command eq 'file') {
++ $t = _read_file_section($fh, $tt, $args, 'file', 'f');
++ } elsif ($command eq 'stdout' || $command eq 'output') {
++ $t = _read_file_section($fh, $tt, $args, 'expect', 'e');
++ } elsif ($command eq 'stderr') {
++ $t = _read_file_section($fh, $tt, $args, 'expect', 'e');
++ } elsif ($command eq 'expect') {
++ $t = _read_file_section($fh, $tt, $args, 'expect', 'e');
++ } elsif ($command eq 'expectx') {
++ $t = _read_file_section($fh, $tt, $args, 'expectx', 'x');
++ } elsif ($command eq 'expectv' || $command eq 'expect_verbatim'
++ || $command eq 'verbatim') {
++ $t = _read_file_section($fh, $tt, $args, 'expectv', 'v');
++ } elsif ($command eq 'ignore') {
++ $t = _read_file_section($fh, $tt, $args, 'ignore', 'i');
++ } elsif ($command eq 'ignorex') {
++ $t = _read_file_section($fh, $tt, $args, 'ignorex', 'i');
++ } elsif ($command eq 'ignorev') {
++ $t = _read_file_section($fh, $tt, $args, 'ignorev', 'i');
++ } elsif ($command eq 'eot') {
++ $tt->{'continue'} = 1;
++ last;
++ } elsif ($command eq 'eof') {
++ last;
++ } else {
++ $tt->file_err("unrecognized command '$command'");
++ $t = _skip_section($fh, $tt);
++ }
++ $read_command = 1;
++ } else {
++ if ($t =~ /^%/) {
++ $tt->file_err("bad '\%' command");
++ } elsif ($t !~ /^[\#!]/ && $t =~ /\S/) {
++ $tt->file_err("warning: garbage ignored") if $read_command;
++ $read_command = 0;
++ }
++ $t = <$fh>;
++ }
++ }
++
++ $tt;
++}
++
++sub have_file ($$) {
++ my($tt, $fileref) = @_;
++ exists($tt->{"F:$fileref"});
++}
++
++sub empty ($) {
++ my($tt) = @_;
++ !exists($tt->{'script'});
++}
++
++sub save_files ($&) {
++ my($tt, $fileref_subr) = @_;
++ foreach my $fn (@{$tt->{'file'}}) {
++ my($actual) = $fileref_subr->($fn);
++ next if !defined($actual);
++ open OUT, ">$actual" || die "$actual: $!\n";
++ print OUT $tt->{"f:$fn"}->[0];
++ close OUT;
++ }
++}
++
++sub script_text ($&$) {
++ my($tt, $fileref_subr, $script_type) = @_;
++ my($subbody, $var, $val) = '';
++
++ # add variables
++ while (($var, $val) = each %_variables) {
++ $var = quotemeta($var);
++ $val = quotemeta($val);
++ $subbody .= "\$t =~ s/(^|[^\\\\])\\\$$var\\b/\${1}$val/g;\n";
++ $subbody .= "\$t =~ s/(^|[^\\\\])\\\${$var}\\b/\${1}$val/g;\n";
++ }
++
++ my($code) = eval("sub { my(\$t) = \@_; $subbody\$t; }");
++
++ my($t) = '';
++ if (!$::expand_mode) {
++ $t .= <<'EOD;';
++testie_failed () {
++ exitval=$?
++ test $exitval = 0 || (echo; echo testie_failure:$exitval) >&2
++ exit $exitval
++}
++trap testie_failed EXIT
++EOD;
++ }
++
++ my($scriptarr, $linenoarr) = ($tt->{$script_type}, $tt->{$script_type . "_lineno"});
++ foreach my $i (0..$#{$tt->{$script_type}}) {
++ my($ln, $text) = ($linenoarr->[$i], $scriptarr->[$i]);
++ $t .= "echo >&2; echo testie_lineno:$ln >&2\n" if !$::expand_mode;
++ my(@c, @d);
++ _shell_split(@c, @d, $text, 0, $code);
++ die if @c != 1;
++ chomp $c[0];
++ next if $c[0] =~ /^\s*$/s;
++ $c[0] =~ s,^(\s*)\./,$1../, if !$::expand_mode;
++ $t .= $c[0] . "\n";
++ }
++
++ $t;
++}
++
++sub output_error ($$$$) {
++ my($tt, $fileref_subr, $script_type, $verbose) = @_;
++ my($fp) = $tt->{'errprefix'};
++
++ if (!open(ERR, $fileref_subr->('stderr'))) {
++ print STDERR $fp, $!, "\n";
++ $::internal_errors++;
++ return;
++ }
++
++ my($errortext, $t, $lineno, $failure) = ('');
++ while ($t = <ERR>) {
++ if ($t =~ /^testie_lineno:(.*)$/) {
++ $lineno = $1;
++ $errortext = '';
++ } elsif ($t =~ /^testie_failure:(.*)$/) {
++ $failure = $1;
++ } else {
++ $errortext .= $t;
++ }
++ }
++ close ERR;
++
++ my($failure_text);
++ if (!defined($failure)) {
++ $failure_text = "undefined error";
++ } elsif ($failure == 1) {
++ $failure_text = "failure";
++ } else {
++ $failure_text = "error $failure";
++ }
++ if (defined($script_type) && $script_type eq 'require') {
++ $failure_text = "requirement $failure_text";
++ $::require_errors++;
++ } else {
++ $::errors++;
++ }
++
++ $errortext =~ s/\s*\Z//;
++
++ my($cmd) = $tt->command_at($lineno, $script_type);
++ if ($fp =~ /: $/) {
++ chop $fp;
++ } else {
++ $lineno = "line $lineno";
++ }
++ $lineno = $tt->filename if !defined($cmd);
++
++ #Â exit early if quiet
++ return 1 if $tt->{$script_type . '_quietline'}->{$lineno} && !$verbose;
++
++ if ($errortext =~ /^testie_error:/) {
++ while ($errortext =~ /^testie_error:([^\n]*)/g) {
++ print STDERR $fp, $lineno, ": ", $1, "\n";
++ }
++ $errortext =~ s/^testie_error:([^\n]*)//g;
++ $errortext =~ s/\s*//;
++ print STDERR $fp, $lineno, ": (There were other errors as well.)\n"
++ if $errortext ne '';
++ } elsif (!defined($cmd)) {
++ print STDERR $fp, $lineno, ": $failure_text at undefined point in script\n";
++ } else {
++ $cmd =~ s/^\s*|\s*$//g;
++ $cmd =~ s/([\000-\037])/'^' . chr(ord($1) + ord('@'))/eg;
++ $cmd =~ s/([\177-\377])/"\\" . sprintf("%03o", ord($1))/eg;
++ if (length($cmd) > 40) {
++ $cmd = substr($cmd, 0, 40) . "...";
++ }
++ print STDERR $fp, $lineno, ": $failure_text at '$cmd'\n";
++ while ($errortext =~ /([^\n]*)/g) {
++ print STDERR $fp, $lineno, ": $1\n" if $1 ne '';
++ }
++ }
++
++ 1;
++}
++
++sub _output_expectation_error ($$$$$) {
++ my($fp, $efn, $lineno, $wanted, $got) = @_;
++
++ # output message
++ if ($efn eq 'stdout') {
++ print STDERR $fp, "standard output has unexpected value starting at line $lineno\n";
++ } elsif ($efn eq 'stderr') {
++ print STDERR $fp, "standard error has unexpected value starting at line $lineno\n";
++ } else {
++ print STDERR $fp, "file $efn has unexpected value starting at line $lineno\n";
++ }
++
++ # output '$wanted' and '$got' if possible
++ $wanted = "<end of file>" if $wanted eq "\376";
++ $wanted =~ s/\r?\n?\Z//;
++ $got = "<end of file>" if $got eq "\376";
++ $got =~ s/\r?\n?\Z//;
++ if ($wanted =~ /\A[\t\040-\176]*\Z/ && $got =~ /\A[\t\040-\176]*\Z/) {
++ print STDERR $fp, "$efn:$lineno: expected '$wanted'\n", $fp, "$efn:$lineno: but got '$got'\n";
++ }
++
++ # maintain error count
++ $::errors++;
++}
++
++sub _check_one_expect ($$$) {
++ my($tt, $fileref_subr, $efn) = @_;
++ my($fp) = $tt->{'errprefix'};
++ my($xtp, $xtl, $xel);
++
++ # read file text
++ if (!open(IN, $fileref_subr->($efn))) {
++ print STDERR $fp, $efn, ": ", $!, "\n";
++ $::errors++;
++ return 0;
++ }
++ my($raw_text) = <IN>;
++ $raw_text = '' if !defined($raw_text);
++ close IN;
++
++ # prepare $ignores
++ my($ignores) = '';
++ $ignores .= join("\n", @{$tt->{"i:$efn"}}) . "\n" if exists($tt->{"i:$efn"});
++ $ignores .= join("\n", @{$tt->{"i:all"}}) . "\n" if exists($tt->{"i:all"});
++ # ignore testie messages
++ $ignores .= "testie_lineno:.*\ntestie_error:.*\n" if $efn eq 'stderr';
++ if ($ignores ne '') {
++ $ignores =~ s/([!\#<>])/\\$1/g;
++ $ignores =~ s{^([ \t]*\S[^\n]*)}{\$text =~ s<^$1\[ \\t\]*\$><\\377>mg;\n}mg;
++ }
++
++ # now compare alternates
++ my($mode, $expect_marker) = (0, {});
++ foreach my $exp (@{$tt->{"v:$efn"}}, $expect_marker, @{$tt->{"e:$efn"}}, $expect_marker, @{$tt->{"x:$efn"}}) {
++ # check for change of mode
++ if (ref($exp)) {
++ $mode++;
++ next;
++ }
++ my($text) = $raw_text;
++
++ # escape in common case
++ return 0 if $text eq $exp;
++
++ # check that files really disagree (in later modes)
++ if ($mode > 0) {
++ # ignore differences in amounts of whitespace
++ $text =~ s/\s+\n/\n/g;
++ $text =~ s/\n\n+\Z/\n/;
++ $text =~ s/\A\n//;
++ $exp =~ s/\s+\n/\n/g;
++ $exp =~ s/\n\n\n+/\n\n/g;
++ $exp =~ s/\n\n+\Z/\n/;
++ return 0 if $text eq $exp;
++
++ # ignore explicitly ignored text
++ eval($ignores) if $ignores ne '';
++ }
++
++ # line-by-line comparison
++ my(@tl) = (split(/\n/, $text), "\376");
++ my(@el) = (split(/\n/, $exp), "\376");
++ my($tp, $ep) = (0, 0);
++ while ($tp < @tl && $ep < @el) {
++
++ # a single blank line in $exp matches multiple blank lines
++ # in $text
++ if ($el[$ep] eq '' && $tl[$tp] eq '' && $mode > 0) {
++ $tp++ while $tl[$tp] eq '' || $tl[$tp] eq "\377";
++ $tp--;
++ }
++
++ # skip ignored lines
++ $tp++ while $tl[$tp] eq "\377";
++
++ # compare lines
++ if ($mode == 2) {
++ last if $tl[$tp] !~ m/\A$el[$ep]\Z/;
++ } elsif ($mode == 1 && $el[$ep] =~ /\{\{/) {
++ my($t, $re) = ($el[$ep], '');
++ while ($t =~ /\A(.*?)\{\{(.*?)\}\}(.*)\Z/) {
++ $re .= quotemeta($1) . $2;
++ $t = $3;
++ }
++ $re .= quotemeta($t);
++ last if $tl[$tp] !~ m/\A$re\Z/;
++ } elsif ($tl[$tp] ne $el[$ep]) {
++ last;
++ }
++
++ $tp++, $ep++;
++ }
++ return 0 if $tp >= @tl || $ep >= @el;
++
++ ($xtp, $xel, $xtl) = ($tp + 1, $el[$ep], $tl[$tp])
++ if !defined($xtp) || $tp + 1 > $xtp;
++ }
++
++ # if we get here, none of the attempts matched
++ _output_expectation_error($fp, $efn, $xtp, $xel, $xtl);
++}
++
++
++sub check_expects ($$) {
++ my($tt, $fileref_subr) = @_;
++ my($fp) = $tt->{'errprefix'};
++ local($/) = undef;
++ my($expectx) = 0;
++ my($tp, @tl, $ep, @el);
++
++ # check expected files
++ my(%done);
++ foreach my $efn (@{$tt->{'expect'}}, @{$tt->{'expectx'}}, @{$tt->{'expectv'}}) {
++ next if $done{$efn};
++ _check_one_expect($tt, $fileref_subr, $efn);
++ $done{$efn} = 1;
++ }
++
++ 0;
++}
++
++
++package main;
++
++my($dir, @show, $show_stdout, $show_stderr, $any_tests_done, $can_setpgrp);
++my($SHELL) = "/bin/sh";
++
++sub script_fn_to_fn ($) {
++ my($fn) = @_;
++ $fn;
++}
++
++sub out_script_fn_to_fn ($) {
++ my($fn) = @_;
++ "$dir/$fn";
++}
++
++sub _shell ($$$$$) {
++ my($dir, $scriptfn, $stdin, $stdout, $stderr) = @_;
++ $scriptfn = "./$scriptfn" if $scriptfn !~ m|^/|;
++
++ # Create a new process group so we can (likely) kill any children
++ # processes the script carelessly left behind. Thanks, Chuck Blake!
++ my($child_pid) = fork();
++ if (!defined($child_pid)) {
++ die "cannot fork: $!\n";
++ } elsif ($child_pid == 0) {
++ eval { setpgrp() };
++ chdir($dir);
++ open(STDIN, "<", $stdin) || die "$stdin: $!\n";
++ open(STDOUT, ">", $stdout) || die "$stdout: $!\n";
++ open(STDERR, ">", $stderr) || die "$stderr: $!\n";
++ exec $SHELL, "-e", $scriptfn;
++ } else {
++ waitpid($child_pid, 0); # assume it succeeds
++ my($result) = $?;
++ kill('HUP', -$child_pid); # kill any processes left behind
++ $result;
++ }
++}
++
++sub execute_test ($$$) {
++ my($tt, $fn, $verbose) = @_;
++ my($f);
++
++ # count attempt
++ $::attempts++;
++
++ # print description in superverbose mode
++ if ($verbose > 1) {
++ return 0 if $tt->empty;
++ print STDERR "\n" if $any_tests_done;
++ if ($tt->{'desc'}) {
++ my($desc) = $tt->{'desc'};
++ $desc =~ s/^(.*?)\t/$1 . (' ' x (8 - (length($1) % 8)))/egm
++ while $desc =~ /\t/;
++ $desc =~ s/^/ /;
++ print STDERR $fn, " Description:\n", $desc;
++ }
++ print STDERR $fn, " Results:\n";
++ $tt->{'errprefix'} = " ";
++ }
++
++ # note that we're running the test in verbose mode
++ if ($verbose == 1) {
++ print STDERR $tt->{'errprefix'}, "Running...\n";
++ }
++
++ # check requirements
++ if (exists $tt->{'require'}) {
++ open(SCR, ">$dir/+require+") || die "$dir/+require+: $!\n";
++ print SCR $tt->script_text(\&script_fn_to_fn, 'require');
++ close SCR;
++
++ if (!$expand_mode) {
++ my($exitval) = _shell($dir, '+require+', '/dev/null', '/dev/null', script_fn_to_fn('stderr'));
++
++ # if it exited with a bad value, quit
++ if ($exitval) {
++ return $tt->output_error(\&out_script_fn_to_fn, 'require', $verbose);
++ } elsif ($verbose) {
++ print STDERR $tt->{'errprefix'}, "Requirements OK\n";
++ }
++ }
++ }
++
++ # save the files it names
++ $tt->save_files(\&out_script_fn_to_fn);
++
++ # save the script
++ open(SCR, ">$dir/+script+") || die "$dir/+script+: $!\n";
++ print SCR $tt->script_text(\&script_fn_to_fn, 'script');
++ close SCR;
++
++ # exit if expand mode
++ return 0 if ($expand_mode);
++
++ # run the script
++ my($actual_stdin) = ($tt->have_file('stdin') ? script_fn_to_fn('stdin') : "/dev/null");
++ my($actual_stdout) = ($show_stdout || $tt->have_file('stdout') ? script_fn_to_fn('stdout') : "/dev/null");
++ my($actual_stderr) = script_fn_to_fn('stderr');
++ my($exitval) = _shell($dir, '+script+', $actual_stdin, $actual_stdout, $actual_stderr);
++ $any_tests_done = 1;
++
++ # echo files
++ foreach $f (@show) {
++ if (-r out_script_fn_to_fn($f)) {
++ print "$fn: $f\n", "=" x 79, "\n";
++ local($/) = undef;
++ open(X, out_script_fn_to_fn($f));
++ $_ = <X>;
++ close(X);
++ print $_, "=" x 79, "\n";
++ } else {
++ print "$fn: $f does not exist\n";
++ }
++ }
++
++ # if it exited with a bad value, quit
++ if ($exitval) {
++ return $tt->output_error(\&out_script_fn_to_fn, 'script', $verbose);
++ }
++
++ # check files
++ my $old_errors = $::errors;
++ if ($exitval = $tt->check_expects(\&out_script_fn_to_fn)) {
++ return $exitval;
++ }
++
++ if ($verbose && !$tt->empty && $old_errors == $::errors) {
++ print STDERR $tt->{'errprefix'}, "Success!\n";
++ }
++
++ 0;
++}
++
++sub run_test (;$$) {
++ my($fn, $verbose) = @_;
++
++ # read the testie
++ my($tt, $display_fn, $close_in);
++ if (!defined($fn) || $fn eq '-') {
++ if (!open(IN, "<&=STDIN")) {
++ print STDERR "<stdin>: $!\n";
++ return -1;
++ }
++ $display_fn = "<stdin>";
++ } elsif (-d $fn) {
++ print STDERR "$fn: is a directory\n";
++ return -1;
++ } else {
++ if (!open(IN, "<", $fn)) {
++ print STDERR "$fn: $!\n";
++ return -1;
++ }
++ $display_fn = $fn;
++ $close_in = 1;
++ }
++
++ my($result, $suffix) = (0, '');
++
++ while (1) {
++ $tt = Testie::read(IN, $display_fn . $suffix);
++ my($this_result) = execute_test($tt, $display_fn . $suffix, $verbose);
++ $result = $this_result if $this_result;
++ last if !$tt->{'continue'};
++ if (!($suffix =~ s/^<(\d+)>$/"<" . ($1+1) . ">"/e)) {
++ $suffix = "<2>";
++ }
++ }
++
++ close IN if $close_in;
++ $result;
++}
++
++$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = $SIG{'__DIE__'} = sub {
++ system("/bin/rm -rf $dir 2>/dev/null") if !$preserve_temporaries;
++ exit(1);
++};
++
++
++
++sub help () {
++ print <<'EOD;';
++'Testie' is a simple test harness.
++
++Usage: testie [OPTIONS] [FILE]...
++
++Options:
++ VARIABLE=VALUE Variable settings for test script.
++ -V, --verbose Print information for successful tests.
++ -VV, --superverbose Print %desc information for all tests.
++ -s, --show TESTIEFILE Show contents of TESTIEFILE on completion.
++ --preserve-temporaries Preserve temporary files.
++ -e, --expand Expand test files into current directory.
++ -v, --version Print version information and exit.
++ --help Print this message and exit.
++
++Report bugs and suggestions to <kohler@icir.org>.
++EOD;
++ exit(0);
++}
++
++sub usage () {
++ print STDERR <<'EOD;';
++Usage: testie [-V] [--preserve-temporaries] [FILE]...
++Try 'testie --help' for more information.
++EOD;
++ exit(1);
++}
++
++sub print_version () {
++ print <<'EOD;';
++Testie 1.1
++Copyright (c) 2002-2003 International Computer Science Institute
++This is free software; see the source for copying conditions.
++There is NO warranty, not even for merchantability or fitness for a
++particular purpose.
++EOD;
++ exit(0);
++}
++
++sub argcmp ($$$;\$) {
++ my($arg, $opt, $min_match, $store) = @_;
++ $$store = undef if defined($store);
++ return 0 if substr($arg, 0, 2 + $min_match) ne substr($opt, 0, 2 + $min_match);
++ my($eq) = index($arg, '=');
++ my($last) = ($eq >= 0 ? $eq : length($arg));
++ return 0 if $last > length($opt) || substr($arg, 0, $last) ne substr($opt, 0, $last);
++ return 0 if !defined($store) && $eq >= 0;
++ $$store = substr($arg, $eq + 1) if defined($store) && $eq >= 0;
++ 1;
++}
++
++
++# directory searching
++
++sub search_dir ($$) {
++ my($dir, $aref) = @_;
++ $dir =~ s/\/+$//;
++ if (!opendir(DIR, $dir)) {
++ print STDERR "$dir: $!\n";
++ return;
++ }
++ my(@f) = grep { !/^\.\.?$/ } readdir(DIR);
++ closedir(DIR);
++ foreach my $f (@f) {
++ if (-d "$dir/$f") {
++ &search_dir("$dir/$f", $aref);
++ } elsif ($f =~ /\.testie$/) {
++ push @$aref, "$dir/$f";
++ }
++ }
++}
++
++
++# argument processing
++
++$dir = "testie$$";
++
++my(@tests, $verbose, $arg);
++$verbose = 0;
++
++while (@ARGV) {
++ $_ = shift @ARGV;
++ if (/^([A-Za-z_]\w*)=(.*)$/s) {
++ $Testie::_variables{$1} = $2;
++ } elsif (/^-$/) {
++ push @tests, $_;
++ } elsif (!/^-/) {
++ if (-d $_) {
++ search_dir($_, \@tests);
++ } else {
++ push @tests, $_;
++ }
++ } elsif (/^-v$/ || argcmp($_, '--version', 4)) {
++ print_version;
++ } elsif (/^-V$/ || argcmp($_, '--verbose', 4)) {
++ $verbose = 1;
++ } elsif (/^-VV$/ || argcmp($_, '--superverbose', 2)) {
++ $verbose = 2;
++ } elsif (/^-e$/ || argcmp($_, '--expand', 1)) {
++ $expand_mode = 1;
++ $preserve_temporaries = 1;
++ $dir = ".";
++ } elsif (argcmp($_, '--help', 1)) {
++ help;
++ } elsif (argcmp($_, '--preserve-temporaries', 1)) {
++ $preserve_temporaries = 1;
++ } elsif (/^-s$/ || argcmp($_, '--show', 2)) {
++ usage if @ARGV == 0;
++ push @show, (shift @ARGV);
++ } elsif (/^-s(.+)$/) {
++ push @show, $1;
++ } elsif (argcmp($_, '--show', 2, $arg)) {
++ push @show, $arg;
++ } else {
++ usage;
++ }
++}
++
++if (-d $dir && !$expand_mode) {
++ print STDERR "warning: $dir directory exists; removing it\n";
++ system("/bin/rm -rf $dir");
++ -d $dir && die "cannot remove $dir directory: $!\n";
++}
++mkdir $dir || die "cannot create $dir directory: $!\n";
++
++# check @show for stdout/stderr
++foreach my $s (@show) {
++ $show_stdout = 1 if $s eq 'stdout';
++ $show_stderr = 1 if $s eq 'stderr';
++}
++
++push @tests, '-' if !@tests;
++foreach my $test (@tests) {
++ run_test($test, $verbose);
++}
++
++system("/bin/rm -rf $dir") if !$preserve_temporaries;
++if ($internal_errors > 0) {
++ exit(2);
++} elsif ($attempts == 0
++ || ($errors == 0 && $require_errors < $attempts)) {
++ exit(0);
++} else {
++ exit(1);
++}
++
++
++=pod
++
++=head1 NAME
++
++testie - simple test harness
++
++=head1 SYNOPSIS
++
++ testie [OPTIONS] [FILE]...
++
++=head1 DESCRIPTION
++
++Testie is a simple test harness. Each testie test file incorporates a shell
++script to be run and, optionally, input and expected output files for that
++script. Testie runs the script; the test fails if any of the script
++commands fail, or if the script generates unexpected output.
++
++To run testie, pass it one or more test filenames. It will print useful
++error messages for failed tests. Alternatively, give it directory names;
++the directories are recursively searched for 'F<*.testie>' files.
++
++Return status is 0 if all tests succeed, 1 if any test fails, and 2 if a
++test fails due to an internal error. Tests whose %require prerequisites
++fail do not affect the return status, except that if all tests'
++prerequisites fail, the return status is 1 instead of 0.
++
++=head1 OPTIONS
++
++=over 8
++
++=item I<VARIABLE>=I<VALUE>
++
++Provide a setting for I<VARIABLE>. Occurrences in the script of
++'C<$VARIABLE>' or 'C<${VARIABLE}>' will be replaced by I<VALUE>. Note that
++this is not an environment variable setting. Variable references to unset
++variables are left unchanged.
++
++=item -V, --verbose
++
++Print information to standard error about successful tests as well as
++unsuccessful tests.
++
++=item -VV, --superverbose
++
++Like --verbose, but use a slightly different format, and additionally print
++every test's %desc section before the test results.
++
++=item -v, --version
++
++Print version number information and exit.
++
++=item --help
++
++Print help information and exit.
++
++=item --preserve-temporaries
++
++Preserve the temporary directory created for the test.
++
++=item -s, --show FILE
++
++Echo the contents of FILE on completion. FILE should be one of the
++filenames specified by %file or %expect*, or 'stdout' or 'stderr'.
++
++=item -e, --expand
++
++Don't run the given test; instead, expand its files into the current
++directory. The script is stored in a file called '+script+'.
++
++=back
++
++=head1 FILE FORMAT
++
++Testie test files consist of several sections, each introduced by a line
++starting with %. There must be, at least, a %script section.
++
++The %file and %expect* sections define input and/or output files by
++name. Testie runs its script in a private directory in F</tmp>; any files
++mentioned in %file or %expect* are placed in that directory.
++
++=over 8
++
++=item %script
++
++The shell script (in sh syntax) that controls the test. Testie will run
++each command in sequence. Every command in the script must succeed, with
++exit status 0, or the test will fail. The script's inputs and outputs are
++defined with the %file and %expect* sections.
++
++=item %require [-q]
++
++A shell script (in sh syntax) defining prerequisites that must be satisfied
++before the test can run. Every command in the script must succeed, with
++exit status 0, for the test to run. %require's output is not checked,
++however. The C<-q> flag tells testie not to print an error message if a
++requirement fails.
++
++=item %desc
++
++A short description of the test. In --superverbose mode, its contents are
++printed before the test results.
++
++=item %info
++
++This section is ignored. It is intended for information about the test.
++
++=item %cut
++
++This section is ignored. It is intended to comment out obsolete parts of
++the test.
++
++=item %file [-d] [+LENGTH] FILENAME...
++
++Create an input file for the script. FILENAME can be 'stdin', which sets
++the script's standard input. If LENGTH is provided, the file data consists
++of the LENGTH bytes following this line. Otherwise, it consists of the data
++up to the next section. The C<-d> flag tells testie to delete the
++first character of each line in the section; this makes it possible to
++include files that have lines that start with %. FILENAME cannot contain
++slashes.
++
++=item %expectv [-a] [-d] [+LENGTH] FILENAME...
++
++An expected output file for the script. FILENAME can be 'stdout', for
++standard output. If LENGTH is provided, the file data consists of the
++LENGTH bytes following this line; otherwise, it consists of the data up to
++the next section.
++
++Testie will run the script, then compare the script's output file with the
++provided data. They must match exactly or the test fails.
++
++The C<-a> flag marks this expected output as an alternate. Testie will
++compare the script's output file with each provided alternate; the test
++succeeds if any of the alternates match. The C<-d> flag behaves as in
++%file.
++
++=item %expect [-a] [-d] [-i] [+LENGTH] FILENAME...
++
++An expected output file for the script. Arguments are as for %expectv.
++
++Testie will run the script, then compare the file generated by script
++with the provided data. The files are compared line-by-line. Testie
++ignores trailing whitespace on each line and in the files at large. It also
++ignores lines in the script output that match %ignore patterns (see below).
++Blank lines in the %expect data match one or more blank lines in the
++output. %expect lines can contain Perl regular expressions, enclosed by two
++sets of braces; so the %expect line
++
++ foo{{(bar)?}}
++
++matches either 'foo' or 'foobar'. The C<-i> flag makes any regular
++expressions case-insensitive.
++
++=item %expectx [-a] [-d] [-i] [+LENGTH] FILENAME...
++
++%expectx is just like %expect, except that every line is treated as a
++regular expression (so there is no need for the "{{ }}" escapes).
++
++=item %stdin [+LENGTH]
++
++Same as '%file stdin [ARGS]'.
++
++=item %stdout [-a] [-d] [-i] [+LENGTH]
++
++Same as '%expect stdout'.
++
++=item %stderr [-a] [-d] [-i] [+LENGTH]
++
++Same as '%expect stderr'.
++
++=item %ignorex [-d] [-i] [+LENGTH] [FILENAME]
++
++Each line in the %ignorex section is a Perl regular expression. Lines in
++the supplied FILENAME that match any of those regular expressions will not
++be considered when comparing files with %expect[x] data. The regular
++expression must match the whole line. FILENAME may be 'all', in which case
++the regular expressions will apply to all %expect[x] files.
++
++=item %ignore, %ignorev
++
++Like '%ignorex', but '%ignore' parses regular expressions only inside
++double braces ("{{ }}"), and '%ignorev' lines must match exactly.
++
++=item %eot
++
++Marks the end of the current test. The rest of the file will be parsed for
++additional tests.
++
++=item %eof
++
++The rest of the file is ignored.
++
++=back
++
++=head1 EXAMPLE
++
++This simple testie script checks that 'grep -c' works for a simple output
++file.
++
++ %script
++ grep -c B.
++ %stdin
++ Bfoo
++ B
++ %stdout
++ 1
++
++=head1 AUTHOR
++
++Eddie Kohler, <kohler@cs.ucla.edu>
+Files click-1.6.0/inst/bin/xml2click and click-1.6.0-27/inst/bin/xml2click differ
+diff -Nurb click-1.6.0/inst/include/click/algorithm.hh click-1.6.0-27/inst/include/click/algorithm.hh
+--- click-1.6.0/inst/include/click/algorithm.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/algorithm.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,24 @@
++#ifndef CLICK_ALGORITHM_HH
++#define CLICK_ALGORITHM_HH
++CLICK_DECLS
++
++template <class T>
++inline T *
++find(T *begin, T *end, const T &val)
++{
++ while (begin < end && *begin != val)
++ begin++;
++ return begin;
++}
++
++template <class T>
++inline const T *
++find(const T *begin, const T *end, const T &val)
++{
++ while (begin < end && *begin != val)
++ begin++;
++ return begin;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/archive.hh click-1.6.0-27/inst/include/click/archive.hh
+--- click-1.6.0/inst/include/click/archive.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/archive.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,29 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/archive.cc" -*-
++#ifndef CLICK_ARCHIVE_HH
++#define CLICK_ARCHIVE_HH
++#include <click/string.hh>
++#include <click/vector.hh>
++CLICK_DECLS
++class ErrorHandler;
++
++struct ArchiveElement {
++
++ String name;
++ int date;
++ int uid;
++ int gid;
++ int mode;
++ String data;
++
++ bool live() const { return name; }
++ bool dead() const { return !name; }
++ void kill() { name = String(); }
++
++};
++
++int separate_ar_string(const String &, Vector<ArchiveElement> &,
++ ErrorHandler * = 0);
++String create_ar_string(const Vector<ArchiveElement> &, ErrorHandler * = 0);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/atomic.hh click-1.6.0-27/inst/include/click/atomic.hh
+--- click-1.6.0/inst/include/click/atomic.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/atomic.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,433 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ATOMIC_HH
++#define CLICK_ATOMIC_HH
++#if CLICK_LINUXMODULE
++# include <click/glue.hh>
++#endif
++CLICK_DECLS
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++# define CLICK_ATOMIC_VAL _val.counter
++# else
++# define CLICK_ATOMIC_VAL __atomic_fool_gcc(&_val)
++# endif
++# ifdef __SMP__
++# define CLICK_ATOMIC_LOCK "lock ; "
++# else
++# define CLICK_ATOMIC_LOCK /* nothing */
++# endif
++#else
++# define CLICK_ATOMIC_VAL _val
++# if HAVE_MULTITHREAD && defined(__i386__)
++# define CLICK_ATOMIC_X86 1
++# define CLICK_ATOMIC_LOCK "lock ; "
++# else
++# define CLICK_ATOMIC_LOCK /* nothing */
++# endif
++#endif
++
++/** @file <click/atomic.hh>
++ * @brief An atomic 32-bit integer.
++ */
++
++/** @class atomic_uint32_t
++ * @brief A 32-bit integer with support for atomic operations.
++ *
++ * The atomic_uint32_t class represents a 32-bit integer, with support for
++ * atomic operations. The +=, -=, &=, |=, ++, and -- operations are
++ * implemented using atomic instructions. There are also atomic swap(),
++ * fetch_and_add(), dec_and_test(), and compare_and_swap() operations.
++ *
++ * Because of some issues with compiler implementations, atomic_uint32_t has
++ * no explicit constructor; to set an atomic_uint32_t to a value, use
++ * operator=.
++ *
++ * The atomic_uint32_t only provides true atomic semantics when that has been
++ * implemented. It has been implemented in the Linux kernel, and at userlevel
++ * (when --enable-multithread has been defined) for x86 machines. In other
++ * situations, it's not truly atomic (because it doesn't need to be).
++ */
++class atomic_uint32_t { public:
++
++ // No constructors because, unfortunately, GCC generates worse code. Use
++ // operator= instead.
++
++ inline uint32_t value() const;
++ inline operator uint32_t() const;
++
++ inline atomic_uint32_t &operator=(uint32_t v);
++
++ inline atomic_uint32_t &operator+=(int32_t delta);
++ inline atomic_uint32_t &operator-=(int32_t delta);
++ inline atomic_uint32_t &operator|=(uint32_t mask);
++ inline atomic_uint32_t &operator&=(uint32_t mask);
++
++ inline void operator++();
++ inline void operator++(int);
++ inline void operator--();
++ inline void operator--(int);
++
++ inline uint32_t swap(uint32_t v);
++ inline uint32_t fetch_and_add(uint32_t delta);
++ inline bool dec_and_test();
++ inline bool compare_and_swap(uint32_t test_value, uint32_t new_value);
++
++ private:
++
++#if CLICK_LINUXMODULE
++ atomic_t _val;
++#elif HAVE_MULTITHREAD
++ volatile uint32_t _val;
++#else
++ uint32_t _val;
++#endif
++
++};
++
++/** @brief Return the value. */
++inline uint32_t
++atomic_uint32_t::value() const
++{
++#if CLICK_LINUXMODULE
++ return atomic_read(&_val);
++#else
++ return CLICK_ATOMIC_VAL;
++#endif
++}
++
++/** @brief Return the value. */
++inline
++atomic_uint32_t::operator uint32_t() const
++{
++ return value();
++}
++
++/** @brief Set the value to @a v. */
++inline atomic_uint32_t &
++atomic_uint32_t::operator=(uint32_t v)
++{
++#if CLICK_LINUXMODULE
++ atomic_set(&_val, v);
++#else
++ CLICK_ATOMIC_VAL = v;
++#endif
++ return *this;
++}
++
++/** @brief Atomically add @a delta to the value. */
++inline atomic_uint32_t &
++atomic_uint32_t::operator+=(int32_t delta)
++{
++#if CLICK_LINUXMODULE
++ atomic_add(delta, &_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "addl %1,%0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "r" (delta), "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL += delta;
++#endif
++ return *this;
++}
++
++/** @brief Atomically subtract @a delta from the value. */
++inline atomic_uint32_t &
++atomic_uint32_t::operator-=(int32_t delta)
++{
++#if CLICK_LINUXMODULE
++ atomic_sub(delta, &_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "subl %1,%0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "r" (delta), "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL -= delta;
++#endif
++ return *this;
++}
++
++/** @brief Atomically bitwise-or the value with @a mask. */
++inline atomic_uint32_t &
++atomic_uint32_t::operator|=(uint32_t mask)
++{
++#if CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_SET_MASK
++ atomic_set_mask(mask, &_val);
++#elif CLICK_LINUXMODULE
++ unsigned long flags;
++ local_irq_save(flags);
++ CLICK_ATOMIC_VAL |= mask;
++ local_irq_restore(flags);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "orl %1,%0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "r" (mask), "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL |= mask;
++#endif
++ return *this;
++}
++
++/** @brief Atomically bitwise-and the value with @a mask. */
++inline atomic_uint32_t &
++atomic_uint32_t::operator&=(uint32_t mask)
++{
++#if CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_SET_MASK
++ atomic_clear_mask(~mask, &_val);
++#elif CLICK_LINUXMODULE
++ unsigned long flags;
++ local_irq_save(flags);
++ CLICK_ATOMIC_VAL &= mask;
++ local_irq_restore(flags);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "andl %1,%0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "r" (mask), "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL &= mask;
++#endif
++ return *this;
++}
++
++/** @brief Atomically increment the value. */
++inline void
++atomic_uint32_t::operator++()
++{
++#if CLICK_LINUXMODULE
++ atomic_inc(&_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "incl %0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL++;
++#endif
++}
++
++/** @brief Atomically increment the value. */
++inline void
++atomic_uint32_t::operator++(int)
++{
++#if CLICK_LINUXMODULE
++ atomic_inc(&_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "incl %0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL++;
++#endif
++}
++
++/** @brief Atomically decrement the value. */
++inline void
++atomic_uint32_t::operator--()
++{
++#if CLICK_LINUXMODULE
++ atomic_dec(&_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "decl %0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL--;
++#endif
++}
++
++/** @brief Atomically decrement the value. */
++inline void
++atomic_uint32_t::operator--(int)
++{
++#if CLICK_LINUXMODULE
++ atomic_dec(&_val);
++#elif CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "decl %0"
++ : "=m" (CLICK_ATOMIC_VAL)
++ : "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++#else
++ CLICK_ATOMIC_VAL--;
++#endif
++}
++
++/** @brief Atomically assign the value to @a v, returning the old value.
++ *
++ * Behaves like this, but in one atomic step:
++ * @code
++ * uint32_t old_value = value();
++ * *this = v;
++ * return old_value;
++ * @endcode*/
++inline uint32_t
++atomic_uint32_t::swap(uint32_t v)
++{
++#if (CLICK_LINUXMODULE && (defined(__i386__) || defined(__arch_um__) || defined(__x86_64__))) || CLICK_ATOMIC_X86
++ asm ("xchgl %0,%1"
++ : "=r" (v), "=m" (CLICK_ATOMIC_VAL));
++ return v;
++#elif CLICK_LINUXMODULE
++ unsigned long flags;
++ local_irq_save(flags);
++ uint32_t old_value = value();
++ CLICK_ATOMIC_VAL = v;
++ local_irq_restore(flags);
++ return old_value;
++#else
++ uint32_t old_value = value();
++ CLICK_ATOMIC_VAL = v;
++ return old_value;
++#endif
++}
++
++/** @brief Atomically add @a delta to the value, returning the old value.
++ *
++ * Behaves like this, but in one atomic step:
++ * @code
++ * uint32_t old_value = value();
++ * *this += delta;
++ * return old_value;
++ * @endcode */
++inline uint32_t
++atomic_uint32_t::fetch_and_add(uint32_t delta)
++{
++#if (CLICK_LINUXMODULE && (defined(__i386__) || defined(__arch_um__) || defined(__x86_64__))) || CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "xaddl %0,%1"
++ : "=r" (delta), "=m" (CLICK_ATOMIC_VAL)
++ : "0" (delta), "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++ return delta;
++#elif CLICK_LINUXMODULE
++ unsigned long flags;
++ local_irq_save(flags);
++ uint32_t old_value = value();
++ CLICK_ATOMIC_VAL += delta;
++ local_irq_restore(flags);
++ return old_value;
++#else
++ uint32_t old_value = value();
++ CLICK_ATOMIC_VAL += delta;
++ return old_value;
++#endif
++}
++
++/** @brief Atomically decrement the value, returning true if the new value
++ * is 0.
++ *
++ * Behaves like this, but in one atomic step:
++ * @code
++ * --*this;
++ * return value() == 0;
++ * @endcode */
++inline bool
++atomic_uint32_t::dec_and_test()
++{
++#if CLICK_LINUXMODULE
++ return atomic_dec_and_test(&_val);
++#elif CLICK_ATOMIC_X86
++ uint8_t result;
++ asm volatile (CLICK_ATOMIC_LOCK "decl %0 ; sete %1"
++ : "=m" (CLICK_ATOMIC_VAL), "=qm" (result)
++ : "m" (CLICK_ATOMIC_VAL)
++ : "cc");
++ return result;
++#else
++ return (--CLICK_ATOMIC_VAL == 0);
++#endif
++}
++
++/** @brief Perform a compare-and-swap operation.
++ * @param test_value test value
++ * @param new_value new value
++ * @return True if the old value equaled @a test_value (in which case the
++ * value was set to @a new_value), false otherwise.
++ *
++ * Behaves like this, but in one atomic step:
++ * @code
++ * uint32_t old_value = value();
++ * if (old_value == test_value)
++ * *this = new_value;
++ * return old_value == test_value;
++ * @endcode */
++inline bool
++atomic_uint32_t::compare_and_swap(uint32_t test_value, uint32_t new_value)
++{
++#if (CLICK_LINUXMODULE && (defined(__i386__) || defined(__arch_um__) || defined(__x86_64__))) || CLICK_ATOMIC_X86
++ asm volatile (CLICK_ATOMIC_LOCK "cmpxchgl %2,%0 ; sete %%al"
++ : "=m" (CLICK_ATOMIC_VAL), "=a" (test_value)
++ : "r" (new_value), "m" (CLICK_ATOMIC_VAL), "a" (test_value)
++ : "cc");
++ return (uint8_t) test_value;
++#elif CLICK_LINUXMODULE
++ unsigned long flags;
++ local_irq_save(flags);
++ uint32_t old_value = value();
++ if (old_value == test_value)
++ CLICK_ATOMIC_VAL = new_value;
++ local_irq_restore(flags);
++ return old_value == test_value;
++#else
++ uint32_t old_value = value();
++ if (old_value == test_value)
++ CLICK_ATOMIC_VAL = new_value;
++ return old_value == test_value;
++#endif
++}
++
++inline uint32_t
++operator+(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() + b.value();
++}
++
++inline uint32_t
++operator-(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() - b.value();
++}
++
++inline bool
++operator==(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() == b.value();
++}
++
++inline bool
++operator!=(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() != b.value();
++}
++
++inline bool
++operator>(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() > b.value();
++}
++
++inline bool
++operator<(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() < b.value();
++}
++
++inline bool
++operator>=(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() >= b.value();
++}
++
++inline bool
++operator<=(const atomic_uint32_t &a, const atomic_uint32_t &b)
++{
++ return a.value() <= b.value();
++}
++
++typedef atomic_uint32_t uatomic32_t;
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/bighashmap.cc click-1.6.0-27/inst/include/click/bighashmap.cc
+--- click-1.6.0/inst/include/click/bighashmap.cc 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/bighashmap.cc 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,719 @@
++/*
++ * bighashmap.{cc,hh} -- a hash table template that supports removal
++ * Eddie Kohler
++ *
++ * Copyright (c) 2000 Mazu Networks, Inc.
++ * Copyright (c) 2003 International Computer Science Institute
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file. These conditions include: you must
++ * preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding.
++ */
++
++#ifndef CLICK_BIGHASHMAP_CC
++#define CLICK_BIGHASHMAP_CC
++
++CLICK_ENDDECLS
++#include <click/bighashmap.hh>
++#include <click/bighashmap_arena.hh>
++CLICK_DECLS
++
++#define BIGHASHMAP_REARRANGE_ON_FIND 1
++
++template <class K, class V>
++void
++HashMap<K, V>::initialize(HashMap_ArenaFactory *factory, size_t initial_nbuckets)
++{
++ _nbuckets = initial_nbuckets;
++ _buckets = new Elt *[_nbuckets];
++ for (size_t i = 0; i < _nbuckets; i++)
++ _buckets[i] = 0;
++ set_dynamic_resizing(true);
++
++ _n = 0;
++
++ set_arena(factory);
++}
++
++template <class K, class V>
++HashMap<K, V>::HashMap()
++ : _default_value(), _arena(0)
++{
++ initialize(0, DEFAULT_INITIAL_NBUCKETS);
++}
++
++template <class K, class V>
++HashMap<K, V>::HashMap(const V &def, HashMap_ArenaFactory *factory)
++ : _default_value(def), _arena(0)
++{
++ initialize(factory, DEFAULT_INITIAL_NBUCKETS);
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::copy_from(const HashMap<K, V> &o)
++ // requires that 'this' is empty and has the same number of buckets as 'o'
++ // and the same resize policy
++{
++ for (size_t i = 0; i < _nbuckets; i++) {
++ Elt **pprev = &_buckets[i];
++ *pprev = 0;
++ for (const Elt *e = o._buckets[i]; e; e = e->next) {
++ Elt *ee = reinterpret_cast<Elt *>(_arena->alloc());
++ new(reinterpret_cast<void *>(&ee->key)) K(e->key);
++ new(reinterpret_cast<void *>(&ee->value)) V(e->value);
++ ee->next = 0;
++ *pprev = ee;
++ pprev = &ee->next;
++ }
++ }
++ _n = o._n;
++}
++
++template <class K, class V>
++HashMap<K, V>::HashMap(const HashMap<K, V> &o)
++ : _buckets(new Elt *[o._nbuckets]), _nbuckets(o._nbuckets),
++ _default_value(o._default_value), _capacity(o._capacity), _arena(o._arena)
++{
++ _arena->use();
++ copy_from(o);
++}
++
++template <class K, class V>
++HashMap<K, V> &
++HashMap<K, V>::operator=(const HashMap<K, V> &o)
++{
++ if (&o != this) {
++ clear();
++ _default_value = o._default_value;
++ if (_nbuckets < o._nbuckets)
++ resize0(o._nbuckets);
++ _nbuckets = o._nbuckets;
++ _capacity = o._capacity;
++ copy_from(o);
++ }
++ return *this;
++}
++
++template <class K, class V>
++HashMap<K, V>::~HashMap()
++{
++ for (size_t i = 0; i < _nbuckets; i++)
++ for (Elt *e = _buckets[i]; e; ) {
++ Elt *next = e->next;
++ e->key.~K();
++ e->value.~V();
++ _arena->free(e);
++ e = next;
++ }
++ delete[] _buckets;
++ _arena->unuse();
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::set_dynamic_resizing(bool on)
++{
++ if (!on)
++ _capacity = 0x7FFFFFFF;
++ else if (_nbuckets >= MAX_NBUCKETS)
++ _capacity = 0x7FFFFFFE;
++ else
++ _capacity = DEFAULT_RESIZE_THRESHOLD * _nbuckets;
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::set_arena(HashMap_ArenaFactory *factory)
++{
++ assert(empty());
++ if (_arena)
++ _arena->unuse();
++ _arena = HashMap_ArenaFactory::get_arena(sizeof(Elt), factory);
++ _arena->use();
++}
++
++template <class K, class V>
++inline size_t
++HashMap<K, V>::bucket(const K &key) const
++{
++ return ((size_t) hashcode(key)) % _nbuckets;
++}
++
++template <class K, class V>
++typename HashMap<K, V>::Pair *
++HashMap<K, V>::find_pair(const K &key) const
++{
++#if BIGHASHMAP_REARRANGE_ON_FIND
++ Elt *prev = 0;
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; prev = e, e = e->next)
++ if (e->key == key) {
++ if (prev) {
++ // move to front
++ prev->next = e->next;
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ }
++ return e;
++ }
++ return 0;
++#else
++ for (Elt *e = _buckets[bucket(key)]; e; e = e->next)
++ if (e->key == key)
++ return e;
++ return 0;
++#endif
++}
++
++
++template <class K, class V>
++void
++HashMap<K, V>::resize0(size_t new_nbuckets)
++{
++ Elt **new_buckets = new Elt *[new_nbuckets];
++ for (size_t i = 0; i < new_nbuckets; i++)
++ new_buckets[i] = 0;
++
++ size_t old_nbuckets = _nbuckets;
++ Elt **old_buckets = _buckets;
++ _nbuckets = new_nbuckets;
++ _buckets = new_buckets;
++ if (dynamic_resizing())
++ set_dynamic_resizing(true); // reset threshold
++
++ for (size_t i = 0; i < old_nbuckets; i++)
++ for (Elt *e = old_buckets[i]; e; ) {
++ Elt *n = e->next;
++ size_t b = bucket(e->key);
++ e->next = new_buckets[b];
++ new_buckets[b] = e;
++ e = n;
++ }
++
++ delete[] old_buckets;
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::resize(size_t want_nbuckets)
++{
++ size_t new_nbuckets = 1;
++ while (new_nbuckets < want_nbuckets && new_nbuckets < MAX_NBUCKETS)
++ new_nbuckets = ((new_nbuckets + 1) << 1) - 1;
++ assert(new_nbuckets > 0 && new_nbuckets <= MAX_NBUCKETS);
++ if (_nbuckets != new_nbuckets)
++ resize0(new_nbuckets);
++}
++
++template <class K, class V>
++bool
++HashMap<K, V>::insert(const K &key, const V &value)
++{
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; e = e->next)
++ if (e->key == key) {
++ e->value = value;
++ return false;
++ }
++
++ if (_n >= _capacity) {
++ resize(_nbuckets + 1);
++ b = bucket(key);
++ }
++
++ if (Elt *e = reinterpret_cast<Elt *>(_arena->alloc())) {
++ new(reinterpret_cast<void *>(&e->key)) K(key);
++ new(reinterpret_cast<void *>(&e->value)) V(value);
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ _n++;
++ }
++ return true;
++}
++
++template <class K, class V>
++bool
++HashMap<K, V>::remove(const K &key)
++{
++ size_t b = bucket(key);
++ Elt *prev = 0;
++ Elt *e = _buckets[b];
++ while (e && !(e->key == key)) {
++ prev = e;
++ e = e->next;
++ }
++ if (e) {
++ if (prev)
++ prev->next = e->next;
++ else
++ _buckets[b] = e->next;
++ e->key.~K();
++ e->value.~V();
++ _arena->free(e);
++ _n--;
++ return true;
++ } else
++ return false;
++}
++
++template <class K, class V>
++typename HashMap<K, V>::Pair *
++HashMap<K, V>::find_pair_force(const K &key, const V &default_value)
++{
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; e = e->next)
++ if (e->key == key)
++ return e;
++ if (_n >= _capacity) {
++ resize(_nbuckets + 1);
++ b = bucket(key);
++ }
++ if (Elt *e = reinterpret_cast<Elt *>(_arena->alloc())) {
++ new(reinterpret_cast<void *>(&e->key)) K(key);
++ new(reinterpret_cast<void *>(&e->value)) V(default_value);
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ _n++;
++ return e;
++ } else
++ return 0;
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::clear()
++{
++ for (size_t i = 0; i < _nbuckets; i++) {
++ for (Elt *e = _buckets[i]; e; ) {
++ Elt *next = e->next;
++ e->key.~K();
++ e->value.~V();
++ _arena->free(e);
++ e = next;
++ }
++ _buckets[i] = 0;
++ }
++ _n = 0;
++}
++
++template <class K, class V>
++void
++HashMap<K, V>::swap(HashMap<K, V> &o)
++{
++ Elt **t_elts;
++ V t_v;
++ size_t t_size;
++ HashMap_Arena *t_arena;
++
++ t_elts = _buckets; _buckets = o._buckets; o._buckets = t_elts;
++ t_size = _nbuckets; _nbuckets = o._nbuckets; o._nbuckets = t_size;
++ t_v = _default_value; _default_value = o._default_value; o._default_value = t_v;
++
++ t_size = _n; _n = o._n; o._n = t_size;
++ t_size = _capacity; _capacity = o._capacity; o._capacity = t_size;
++
++ t_arena = _arena; _arena = o._arena; o._arena = t_arena;
++}
++
++template <class K, class V>
++_HashMap_const_iterator<K, V>::_HashMap_const_iterator(const HashMap<K, V> *hm, bool begin)
++ : _hm(hm)
++{
++ size_t nb = _hm->_nbuckets;
++ typename HashMap<K, V>::Elt **b = _hm->_buckets;
++ for (_bucket = 0; _bucket < nb && begin; _bucket++)
++ if (b[_bucket]) {
++ _elt = b[_bucket];
++ return;
++ }
++ _elt = 0;
++}
++
++template <class K, class V>
++void
++_HashMap_const_iterator<K, V>::operator++(int)
++{
++ if (_elt->next)
++ _elt = _elt->next;
++ else {
++ size_t nb = _hm->_nbuckets;
++ typename HashMap<K, V>::Elt **b = _hm->_buckets;
++ for (_bucket++; _bucket < nb; _bucket++)
++ if (b[_bucket]) {
++ _elt = b[_bucket];
++ return;
++ }
++ _elt = 0;
++ }
++}
++
++#if 0
++static size_t
++HashMap_partition_elts(void **elts, size_t left, size_t right)
++{
++ void *pivot = elts[(left + right) / 2];
++
++ // loop invariant:
++ // elts[i] < pivot for all left_init <= i < left
++ // elts[i] > pivot for all right < i <= right_init
++ while (left < right) {
++ if (elts[left] < pivot)
++ left++;
++ else if (elts[right] > pivot)
++ right--;
++ else {
++ void *x = elts[left];
++ elts[left] = elts[right];
++ elts[right] = x;
++ }
++ }
++
++ return left;
++}
++
++void
++HashMap_qsort_elts(void **elts, size_t left, size_t right)
++{
++ if (left < right) {
++ size_t split = HashMap_partition_elts(elts, left, right);
++ HashMap_qsort_elts(elts, left, split);
++ HashMap_qsort_elts(elts, split, right);
++ }
++}
++#endif
++
++
++// void * partial specialization
++
++template <class K>
++void
++HashMap<K, void *>::initialize(HashMap_ArenaFactory *factory, size_t initial_nbuckets)
++{
++ _nbuckets = initial_nbuckets;
++ _buckets = new Elt *[_nbuckets];
++ for (size_t i = 0; i < _nbuckets; i++)
++ _buckets[i] = 0;
++ set_dynamic_resizing(true);
++
++ _n = 0;
++
++ set_arena(factory);
++}
++
++template <class K>
++HashMap<K, void *>::HashMap()
++ : _default_value(0), _arena(0)
++{
++ initialize(0, DEFAULT_INITIAL_NBUCKETS);
++}
++
++template <class K>
++HashMap<K, void *>::HashMap(void *def, HashMap_ArenaFactory *factory)
++ : _default_value(def), _arena(0)
++{
++ initialize(factory, DEFAULT_INITIAL_NBUCKETS);
++}
++
++template <class K>
++void
++HashMap<K, void *>::copy_from(const HashMap<K, void *> &o)
++{
++ for (size_t i = 0; i < _nbuckets; i++) {
++ Elt **pprev = &_buckets[i];
++ *pprev = 0;
++ for (const Elt *e = o._buckets[i]; e; e = e->next) {
++ Elt *ee = reinterpret_cast<Elt *>(_arena->alloc());
++ new(reinterpret_cast<void *>(&ee->key)) K(e->key);
++ ee->value = e->value;
++ ee->next = 0;
++ *pprev = ee;
++ pprev = &ee->next;
++ }
++ }
++ _n = o._n;
++}
++
++template <class K>
++HashMap<K, void *>::HashMap(const HashMap<K, void *> &o)
++ : _buckets(new Elt *[o._nbuckets]), _nbuckets(o._nbuckets),
++ _default_value(o._default_value), _capacity(o._capacity), _arena(o._arena)
++{
++ _arena->use();
++ copy_from(o);
++}
++
++template <class K>
++HashMap<K, void *> &
++HashMap<K, void *>::operator=(const HashMap<K, void *> &o)
++{
++ if (&o != this) {
++ clear();
++ _default_value = o._default_value;
++ if (_nbuckets < o._nbuckets)
++ resize0(o._nbuckets);
++ _nbuckets = o._nbuckets;
++ _capacity = o._capacity;
++ copy_from(o);
++ }
++ return *this;
++}
++
++template <class K>
++HashMap<K, void *>::~HashMap()
++{
++ for (size_t i = 0; i < _nbuckets; i++)
++ for (Elt *e = _buckets[i]; e; ) {
++ Elt *next = e->next;
++ e->key.~K();
++ _arena->free(e);
++ e = next;
++ }
++ delete[] _buckets;
++ _arena->unuse();
++}
++
++template <class K>
++void
++HashMap<K, void *>::set_dynamic_resizing(bool on)
++{
++ if (!on)
++ _capacity = 0x7FFFFFFF;
++ else if (_nbuckets >= MAX_NBUCKETS)
++ _capacity = 0x7FFFFFFE;
++ else
++ _capacity = DEFAULT_RESIZE_THRESHOLD * _nbuckets;
++}
++
++template <class K>
++void
++HashMap<K, void *>::set_arena(HashMap_ArenaFactory *factory)
++{
++ assert(empty());
++ if (_arena)
++ _arena->unuse();
++ _arena = HashMap_ArenaFactory::get_arena(sizeof(Elt), factory);
++ _arena->use();
++}
++
++template <class K>
++inline size_t
++HashMap<K, void *>::bucket(const K &key) const
++{
++ return ((size_t) hashcode(key)) % _nbuckets;
++}
++
++template <class K>
++typename HashMap<K, void *>::Pair *
++HashMap<K, void *>::find_pair(const K &key) const
++{
++#if BIGHASHMAP_REARRANGE_ON_FIND
++ Elt *prev = 0;
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; prev = e, e = e->next)
++ if (e->key == key) {
++ if (prev) {
++ // move to front
++ prev->next = e->next;
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ }
++ return e;
++ }
++ return 0;
++#else
++ for (Elt *e = _buckets[bucket(key)]; e; e = e->next)
++ if (e->key == key)
++ return e;
++ return 0;
++#endif
++}
++
++
++template <class K>
++void
++HashMap<K, void *>::resize0(size_t new_nbuckets)
++{
++ Elt **new_buckets = new Elt *[new_nbuckets];
++ for (size_t i = 0; i < new_nbuckets; i++)
++ new_buckets[i] = 0;
++
++ size_t old_nbuckets = _nbuckets;
++ Elt **old_buckets = _buckets;
++ _nbuckets = new_nbuckets;
++ _buckets = new_buckets;
++ if (dynamic_resizing())
++ set_dynamic_resizing(true); // reset threshold
++
++ for (size_t i = 0; i < old_nbuckets; i++)
++ for (Elt *e = old_buckets[i]; e; ) {
++ Elt *n = e->next;
++ size_t b = bucket(e->key);
++ e->next = new_buckets[b];
++ new_buckets[b] = e;
++ e = n;
++ }
++
++ delete[] old_buckets;
++}
++
++template <class K>
++void
++HashMap<K, void *>::resize(size_t want_nbuckets)
++{
++ size_t new_nbuckets = 1;
++ while (new_nbuckets < want_nbuckets && new_nbuckets < MAX_NBUCKETS)
++ new_nbuckets = ((new_nbuckets + 1) << 1) - 1;
++ assert(new_nbuckets > 0 && new_nbuckets <= MAX_NBUCKETS);
++ if (_nbuckets != new_nbuckets)
++ resize0(new_nbuckets);
++}
++
++template <class K>
++bool
++HashMap<K, void *>::insert(const K &key, void *value)
++{
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; e = e->next)
++ if (e->key == key) {
++ e->value = value;
++ return false;
++ }
++
++ if (_n >= _capacity) {
++ resize(_nbuckets + 1);
++ b = bucket(key);
++ }
++
++ if (Elt *e = reinterpret_cast<Elt *>(_arena->alloc())) {
++ new(reinterpret_cast<void *>(&e->key)) K(key);
++ e->value = value;
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ _n++;
++ }
++ return true;
++}
++
++template <class K>
++bool
++HashMap<K, void *>::remove(const K &key)
++{
++ size_t b = bucket(key);
++ Elt *prev = 0;
++ Elt *e = _buckets[b];
++ while (e && !(e->key == key)) {
++ prev = e;
++ e = e->next;
++ }
++ if (e) {
++ if (prev)
++ prev->next = e->next;
++ else
++ _buckets[b] = e->next;
++ e->key.~K();
++ _arena->free(e);
++ _n--;
++ return true;
++ } else
++ return false;
++}
++
++template <class K>
++typename HashMap<K, void *>::Pair *
++HashMap<K, void *>::find_pair_force(const K &key, void *default_value)
++{
++ size_t b = bucket(key);
++ for (Elt *e = _buckets[b]; e; e = e->next)
++ if (e->key == key)
++ return e;
++ if (_n >= _capacity) {
++ resize(_nbuckets + 1);
++ b = bucket(key);
++ }
++ if (Elt *e = reinterpret_cast<Elt *>(_arena->alloc())) {
++ new(reinterpret_cast<void *>(&e->key)) K(key);
++ e->value = default_value;
++ e->next = _buckets[b];
++ _buckets[b] = e;
++ _n++;
++ return e;
++ } else
++ return 0;
++}
++
++template <class K>
++void
++HashMap<K, void *>::clear()
++{
++ for (size_t i = 0; i < _nbuckets; i++) {
++ for (Elt *e = _buckets[i]; e; ) {
++ Elt *next = e->next;
++ e->key.~K();
++ _arena->free(e);
++ e = next;
++ }
++ _buckets[i] = 0;
++ }
++ _n = 0;
++}
++
++template <class K>
++void
++HashMap<K, void *>::swap(HashMap<K, void *> &o)
++{
++ Elt **t_elts;
++ void *t_v;
++ size_t t_size;
++ HashMap_Arena *t_arena;
++
++ t_elts = _buckets; _buckets = o._buckets; o._buckets = t_elts;
++ t_size = _nbuckets; _nbuckets = o._nbuckets; o._nbuckets = t_size;
++ t_v = _default_value; _default_value = o._default_value; o._default_value = t_v;
++
++ t_size = _n; _n = o._n; o._n = t_size;
++ t_size = _capacity; _capacity = o._capacity; o._capacity = t_size;
++
++ t_arena = _arena; _arena = o._arena; o._arena = t_arena;
++}
++
++
++template <class K>
++_HashMap_const_iterator<K, void *>::_HashMap_const_iterator(const HashMap<K, void *> *hm, bool begin)
++ : _hm(hm)
++{
++ size_t nb = _hm->_nbuckets;
++ typename HashMap<K, void *>::Elt **b = _hm->_buckets;
++ for (_bucket = 0; _bucket < nb && begin; _bucket++)
++ if (b[_bucket]) {
++ _elt = b[_bucket];
++ return;
++ }
++ _elt = 0;
++}
++
++template <class K>
++void
++_HashMap_const_iterator<K, void *>::operator++(int)
++{
++ if (_elt->next)
++ _elt = _elt->next;
++ else {
++ size_t nb = _hm->_nbuckets;
++ typename HashMap<K, void *>::Elt **b = _hm->_buckets;
++ for (_bucket++; _bucket < nb; _bucket++)
++ if (b[_bucket]) {
++ _elt = b[_bucket];
++ return;
++ }
++ _elt = 0;
++ }
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/bighashmap.hh click-1.6.0-27/inst/include/click/bighashmap.hh
+--- click-1.6.0/inst/include/click/bighashmap.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/bighashmap.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,567 @@
++#ifndef CLICK_BIGHASHMAP_HH
++#define CLICK_BIGHASHMAP_HH
++#include <click/hashcode.hh>
++CLICK_DECLS
++class HashMap_Arena;
++class HashMap_ArenaFactory;
++
++// K AND V REQUIREMENTS:
++//
++// K::K(const K &)
++// k1 == k2
++// unsigned hashcode(const K &)
++// If hashcode(k1) != hashcode(k2), then k1 != k2.
++//
++// V::V() -- only used for default value
++// V::V(const V &)
++// V & V::operator=(const V &)
++
++template <class K, class V> class _HashMap_const_iterator;
++template <class K, class V> class _HashMap_iterator;
++
++template <class K, class V>
++class HashMap { public:
++
++ struct Pair;
++
++ HashMap();
++ explicit HashMap(const V &, HashMap_ArenaFactory * = 0);
++ HashMap(const HashMap<K, V> &);
++ ~HashMap();
++
++ void set_arena(HashMap_ArenaFactory *);
++
++ size_t size() const { return _n; }
++ bool empty() const { return _n == 0; }
++ size_t nbuckets() const { return _nbuckets; }
++
++ Pair *find_pair(const K &) const;
++ inline V *findp(const K &) const;
++ inline const V &find(const K &, const V &) const;
++ inline const V &find(const K &) const;
++ inline const V &operator[](const K &) const;
++
++ Pair *find_pair_force(const K &, const V &);
++ Pair *find_pair_force(const K &k) { return find_pair_force(k, _default_value); }
++ V *findp_force(const K &k, const V &v) { if (Pair *p = find_pair_force(k, v)) return &p->value; else return 0; }
++ V &find_force(const K &k, const V &v) { return *findp_force(k, v); }
++ V *findp_force(const K &k) { return findp_force(k, _default_value); }
++ V &find_force(const K &k) { return *findp_force(k, _default_value); }
++
++ bool insert(const K &, const V &);
++ bool remove(const K &);
++ void clear();
++
++ void swap(HashMap<K, V> &);
++
++ // iteration
++ typedef _HashMap_const_iterator<K, V> const_iterator;
++ typedef _HashMap_iterator<K, V> iterator;
++ inline const_iterator begin() const;
++ inline iterator begin();
++ inline const_iterator end() const;
++ inline iterator end();
++
++ // dynamic resizing
++ void resize(size_t);
++ bool dynamic_resizing() const { return _capacity < 0x7FFFFFFF; }
++ void set_dynamic_resizing(bool);
++
++ HashMap<K, V> &operator=(const HashMap<K, V> &);
++
++ struct Pair {
++ K key;
++ V value;
++ };
++
++ enum { MAX_NBUCKETS = 32767,
++ DEFAULT_INITIAL_NBUCKETS = 127,
++ DEFAULT_RESIZE_THRESHOLD = 2 };
++
++ private:
++
++ struct Elt : public Pair {
++ Elt *next;
++#if defined(__GNUC__) && __GNUC__ < 4
++ /* Shut up compiler about Pair lacking default constructor */
++ Elt(const Pair &p) : Pair(p) { }
++#endif
++ };
++
++ Elt **_buckets;
++ size_t _nbuckets;
++ V _default_value;
++
++ size_t _n;
++ size_t _capacity;
++
++ HashMap_Arena *_arena;
++
++ void initialize(HashMap_ArenaFactory *, size_t);
++ void copy_from(const HashMap<K, V> &);
++ void resize0(size_t);
++ size_t bucket(const K &) const;
++
++ friend class _HashMap_iterator<K, V>;
++ friend class _HashMap_const_iterator<K, V>;
++
++};
++
++template <class K, class V>
++class _HashMap_const_iterator { public:
++
++ bool live() const { return _elt; }
++ typedef bool (_HashMap_const_iterator::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const CLICK_DEPRECATED;
++ void operator++(int);
++ void operator++() { (*this)++; }
++
++ typedef typename HashMap<K, V>::Pair Pair;
++ const Pair *pair() const { return _elt; }
++
++ const K &key() const { return _elt->key; }
++ const V &value() const { return _elt->value; }
++
++ private:
++
++ const HashMap<K, V> *_hm;
++ typename HashMap<K, V>::Elt *_elt;
++ size_t _bucket;
++
++ _HashMap_const_iterator(const HashMap<K, V> *m, bool begin);
++ friend class HashMap<K, V>;
++ friend class _HashMap_iterator<K, V>;
++
++};
++
++template <class K, class V>
++class _HashMap_iterator : public _HashMap_const_iterator<K, V> { public:
++
++ typedef _HashMap_const_iterator<K, V> inherited;
++
++ typedef typename HashMap<K, V>::Pair Pair;
++ Pair *pair() const { return const_cast<Pair *>(inherited::pair()); }
++ V &value() const { return const_cast<V &>(inherited::value()); }
++
++ private:
++
++ _HashMap_iterator(HashMap<K, V> *m, bool begin) : inherited(m, begin) { }
++ friend class HashMap<K, V>;
++
++};
++
++template <class K, class V>
++inline typename HashMap<K, V>::const_iterator
++HashMap<K, V>::begin() const
++{
++ return const_iterator(this, true);
++}
++
++template <class K, class V>
++inline typename HashMap<K, V>::iterator
++HashMap<K, V>::begin()
++{
++ return iterator(this, true);
++}
++
++template <class K, class V>
++inline typename HashMap<K, V>::const_iterator
++HashMap<K, V>::end() const
++{
++ return const_iterator(this, false);
++}
++
++template <class K, class V>
++inline typename HashMap<K, V>::iterator
++HashMap<K, V>::end()
++{
++ return iterator(this, false);
++}
++
++template <class K, class V>
++inline V *
++HashMap<K, V>::findp(const K &key) const
++{
++ Pair *p = find_pair(key);
++ return (p ? &p->value : 0);
++}
++
++template <class K, class V>
++inline const V &
++HashMap<K, V>::find(const K &key, const V &default_value) const
++{
++ Pair *p = find_pair(key);
++ const V *v = (p ? &p->value : &default_value);
++ return *v;
++}
++
++template <class K, class V>
++inline const V &
++HashMap<K, V>::find(const K &key) const
++{
++ return find(key, _default_value);
++}
++
++template <class K, class V>
++inline const V &
++HashMap<K, V>::operator[](const K &key) const
++{
++ return find(key);
++}
++
++template <class K, class V>
++inline
++_HashMap_const_iterator<K, V>::operator unspecified_bool_type() const
++{
++ return live() ? &_HashMap_const_iterator::live : 0;
++}
++
++
++template <class K>
++class HashMap<K, void *> { public:
++
++ struct Pair;
++
++ HashMap();
++ explicit HashMap(void *, HashMap_ArenaFactory * = 0);
++ HashMap(const HashMap<K, void *> &);
++ ~HashMap();
++
++ void set_arena(HashMap_ArenaFactory *);
++
++ size_t size() const { return _n; }
++ bool empty() const { return _n == 0; }
++ size_t nbuckets() const { return _nbuckets; }
++
++ Pair *find_pair(const K &) const;
++ inline void **findp(const K &) const;
++ inline void *find(const K &, void *) const;
++ inline void *find(const K &) const;
++ inline void *operator[](const K &) const;
++
++ Pair *find_pair_force(const K &, void *);
++ Pair *find_pair_force(const K &k) { return find_pair_force(k, _default_value); }
++ void **findp_force(const K &k, void *v) { if (Pair *p = find_pair_force(k, v)) return &p->value; else return 0; }
++ void *&find_force(const K &k, void *v) { return *findp_force(k, v); }
++ void **findp_force(const K &k) { return findp_force(k, _default_value); }
++ void *&find_force(const K &k) { return *findp_force(k, _default_value); }
++
++ bool insert(const K &, void *);
++ bool remove(const K &);
++ void clear();
++
++ void swap(HashMap<K, void *> &);
++
++ // iterators
++ typedef _HashMap_const_iterator<K, void *> const_iterator;
++ typedef _HashMap_iterator<K, void *> iterator;
++ inline const_iterator begin() const;
++ inline iterator begin();
++ inline const_iterator end() const;
++ inline iterator end();
++
++ // dynamic resizing
++ void resize(size_t);
++ bool dynamic_resizing() const { return _capacity < 0x7FFFFFFF; }
++ void set_dynamic_resizing(bool);
++
++ HashMap<K, void *> &operator=(const HashMap<K, void *> &);
++
++ struct Pair {
++ K key;
++ void *value;
++ };
++
++ enum { MAX_NBUCKETS = 32767,
++ DEFAULT_INITIAL_NBUCKETS = 127,
++ DEFAULT_RESIZE_THRESHOLD = 2 };
++
++ private:
++
++ struct Elt : public Pair {
++ Elt *next;
++#if defined(__GNUC__) && __GNUC__ < 4
++ /* Shut up compiler about Pair lacking default constructor */
++ Elt(const Pair &p) : Pair(p) { }
++#endif
++ };
++
++ Elt **_buckets;
++ size_t _nbuckets;
++ void *_default_value;
++
++ size_t _n;
++ size_t _capacity;
++
++ HashMap_Arena *_arena;
++
++ void initialize(HashMap_ArenaFactory *, size_t);
++ void copy_from(const HashMap<K, void *> &);
++ void resize0(size_t);
++ size_t bucket(const K &) const;
++
++ friend class _HashMap_iterator<K, void *>;
++ friend class _HashMap_const_iterator<K, void *>;
++
++};
++
++template <class K>
++class _HashMap_const_iterator<K, void *> { public:
++
++ bool live() const { return _elt; }
++ typedef bool (_HashMap_const_iterator::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const CLICK_DEPRECATED;
++ void operator++(int);
++ void operator++() { (*this)++; }
++
++ typedef typename HashMap<K, void *>::Pair Pair;
++ const Pair *pair() const { return _elt; }
++
++ const K &key() const { return _elt->key; }
++ void *value() const { return _elt->value; }
++
++ private:
++
++ const HashMap<K, void *> *_hm;
++ typename HashMap<K, void *>::Elt *_elt;
++ size_t _bucket;
++
++ _HashMap_const_iterator(const HashMap<K, void *> *, bool begin);
++ template <class, class> friend class _HashMap_const_iterator;
++ template <class, class> friend class _HashMap_iterator;
++ template <class, class> friend class HashMap;
++
++};
++
++template <class K>
++class _HashMap_iterator<K, void *> : public _HashMap_const_iterator<K, void *> { public:
++
++ typedef _HashMap_const_iterator<K, void *> inherited;
++
++ typedef typename HashMap<K, void *>::Pair Pair;
++ Pair *pair() const { return const_cast<Pair *>(inherited::pair()); }
++ void *&value() const { return this->_elt->value; }
++
++ private:
++
++ _HashMap_iterator(HashMap<K, void *> *m, bool begin) : inherited(m, begin) { }
++ template <class, class> friend class HashMap;
++
++};
++
++template <class K>
++inline typename HashMap<K, void *>::const_iterator
++HashMap<K, void *>::begin() const
++{
++ return const_iterator(this, true);
++}
++
++template <class K>
++inline typename HashMap<K, void *>::iterator
++HashMap<K, void *>::begin()
++{
++ return iterator(this, true);
++}
++
++template <class K>
++inline typename HashMap<K, void *>::const_iterator
++HashMap<K, void *>::end() const
++{
++ return const_iterator(this, false);
++}
++
++template <class K>
++inline typename HashMap<K, void *>::iterator
++HashMap<K, void *>::end()
++{
++ return iterator(this, false);
++}
++
++template <class K>
++inline void **
++HashMap<K, void *>::findp(const K &key) const
++{
++ Pair *p = find_pair(key);
++ return (p ? &p->value : 0);
++}
++
++template <class K>
++inline void *
++HashMap<K, void *>::find(const K &key, void *default_value) const
++{
++ Pair *p = find_pair(key);
++ return (p ? p->value : default_value);
++}
++
++template <class K>
++inline void *
++HashMap<K, void *>::find(const K &key) const
++{
++ return find(key, _default_value);
++}
++
++template <class K>
++inline void *
++HashMap<K, void *>::operator[](const K &key) const
++{
++ return find(key);
++}
++
++template <class K>
++inline
++_HashMap_const_iterator<K, void *>::operator unspecified_bool_type() const
++{
++ return live() ? &_HashMap_const_iterator::live : 0;
++}
++
++
++template <class K, class T>
++class HashMap<K, T *> : public HashMap<K, void *> { public:
++
++ typedef HashMap<K, void *> inherited;
++ struct Pair;
++
++ HashMap() : inherited() { }
++ explicit HashMap(T *def, HashMap_ArenaFactory *factory = 0)
++ : inherited(def, factory) { }
++ HashMap(const HashMap<K, T *> &o) : inherited(o) { }
++ ~HashMap() { }
++
++ void set_arena(HashMap_ArenaFactory *af) { inherited::set_arena(af); }
++
++ // size_t size() const inherited
++ // bool empty() const inherited
++ // size_t nbuckets() const inherited
++
++ Pair *find_pair(const K &k) const { return reinterpret_cast<Pair *>(inherited::find_pair(k)); }
++ T **findp(const K &k) const { return reinterpret_cast<T **>(inherited::findp(k)); }
++ T *find(const K &k, T *v) const { return reinterpret_cast<T *>(inherited::find(k, v)); }
++ T *find(const K &k) const { return reinterpret_cast<T *>(inherited::find(k)); }
++ T *operator[](const K &k) const { return reinterpret_cast<T *>(inherited::operator[](k)); }
++
++ Pair *find_pair_force(const K &k, T *v) { return reinterpret_cast<Pair *>(inherited::find_pair_force(k, v)); }
++ Pair *find_pair_force(const K &k) { return reinterpret_cast<Pair *>(inherited::find_pair_force(k)); }
++ T **findp_force(const K &k, T *v) { return reinterpret_cast<T **>(inherited::findp_force(k, v)); }
++ T *&find_force(const K &k, T *v) { return *reinterpret_cast<T **>(inherited::findp_force(k, v)); }
++ T **findp_force(const K &k) { return reinterpret_cast<T **>(inherited::findp_force(k)); }
++ T *&find_force(const K &k) { return *reinterpret_cast<T **>(inherited::findp_force(k)); }
++
++ bool insert(const K &k, T *v) { return inherited::insert(k, v); }
++ // bool remove(const K &) inherited
++ // void clear() inherited
++
++ void swap(HashMap<K, T *> &o) { inherited::swap(o); }
++
++ // iteration
++ typedef _HashMap_const_iterator<K, T *> const_iterator;
++ typedef _HashMap_iterator<K, T *> iterator;
++ inline const_iterator begin() const;
++ inline iterator begin();
++ inline const_iterator end() const;
++ inline iterator end();
++
++ // dynamic resizing methods inherited
++
++ HashMap<K, T *> &operator=(const HashMap<K, T *> &o) { return static_cast<HashMap<K, T *> &>(inherited::operator=(o)); }
++
++ struct Pair {
++ K key;
++ T *value;
++ };
++
++};
++
++template <class K, class T>
++class _HashMap_const_iterator<K, T *> { public:
++
++ typedef _HashMap_const_iterator<K, void *> inherited;
++
++ bool live() const { return _i.live(); }
++ typedef typename inherited::unspecified_bool_type unspecified_bool_type;
++ inline operator unspecified_bool_type() const CLICK_DEPRECATED;
++ void operator++(int) { _i.operator++(0); }
++ void operator++() { _i.operator++(); }
++
++ typedef typename HashMap<K, T *>::Pair Pair;
++ const Pair *pair() const { return reinterpret_cast<const Pair *>(_i.pair()); }
++
++ const K &key() const { return _i.key(); }
++ T *value() const { return reinterpret_cast<T *>(_i.value()); }
++
++ private:
++
++ inherited _i;
++
++ _HashMap_const_iterator(const HashMap<K, T *> *t, bool begin) : _i(t, begin) { }
++ friend class _HashMap_iterator<K, T *>;
++ template <class, class> friend class HashMap;
++
++};
++
++template <class K, class T>
++class _HashMap_iterator<K, T *> : public _HashMap_const_iterator<K, T *> { public:
++
++ typedef _HashMap_const_iterator<K, T *> inherited;
++
++ typedef typename HashMap<K, T *>::Pair Pair;
++ Pair *pair() const { return const_cast<Pair *>(inherited::pair()); }
++ T *&value() const { return pair()->value; }
++
++ private:
++
++ _HashMap_iterator(HashMap<K, T *> *t, bool begin) : inherited(t, begin) { }
++ template <class, class> friend class HashMap;
++
++};
++
++template <class K, class T>
++inline typename HashMap<K, T *>::const_iterator
++HashMap<K, T *>::begin() const
++{
++ return const_iterator(this, true);
++}
++
++template <class K, class T>
++inline typename HashMap<K, T *>::iterator
++HashMap<K, T *>::begin()
++{
++ return iterator(this, true);
++}
++
++template <class K, class T>
++inline typename HashMap<K, T *>::const_iterator
++HashMap<K, T *>::end() const
++{
++ return const_iterator(this, false);
++}
++
++template <class K, class T>
++inline typename HashMap<K, T *>::iterator
++HashMap<K, T *>::end()
++{
++ return iterator(this, false);
++}
++
++template <class K, class T>
++inline
++_HashMap_const_iterator<K, T *>::operator unspecified_bool_type() const
++{
++ return inherited::live() ? &inherited::live : 0;
++}
++
++template <class K, class V>
++inline bool
++operator==(const _HashMap_const_iterator<K, V> &a, const _HashMap_const_iterator<K, V> &b)
++{
++ return a.pair() == b.pair();
++}
++
++template <class K, class V>
++inline bool
++operator!=(const _HashMap_const_iterator<K, V> &a, const _HashMap_const_iterator<K, V> &b)
++{
++ return a.pair() != b.pair();
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/bighashmap_arena.hh click-1.6.0-27/inst/include/click/bighashmap_arena.hh
+--- click-1.6.0/inst/include/click/bighashmap_arena.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/bighashmap_arena.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,98 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/bighashmap_arena.cc" -*-
++#ifndef CLICK_BIGHASHMAP_ARENA_HH
++#define CLICK_BIGHASHMAP_ARENA_HH
++CLICK_DECLS
++
++class HashMap_Arena { public:
++
++ HashMap_Arena(uint32_t element_size);
++
++ void use() { _refcount++; }
++ void unuse();
++
++ bool detached() const { return _detached; }
++ void detach() { _detached = true; }
++
++ void *alloc();
++ void free(void *);
++
++ private:
++
++ struct Link {
++ Link *next;
++ };
++ Link *_free;
++
++ enum { NELEMENTS = 127 }; // not a power of 2 so we don't fall into a
++ // too-large bucket
++ char *_cur_buffer;
++ int _buffer_pos;
++
++ uint32_t _element_size;
++
++ char **_buffers;
++ int _nbuffers;
++ int _buffers_cap;
++
++ uint32_t _refcount;
++ bool _detached;
++
++ ~HashMap_Arena();
++ void *hard_alloc();
++
++ friend class Link; // shut up, compiler
++
++};
++
++class HashMap_ArenaFactory { public:
++
++ HashMap_ArenaFactory();
++ virtual ~HashMap_ArenaFactory();
++
++ static void static_initialize();
++ static void static_cleanup();
++
++ static HashMap_Arena *get_arena(uint32_t, HashMap_ArenaFactory * =0);
++ virtual HashMap_Arena *get_arena_func(uint32_t);
++
++ private:
++
++ HashMap_Arena **_arenas[2];
++ int _narenas[2];
++
++ static HashMap_ArenaFactory *the_factory;
++
++};
++
++inline void
++HashMap_Arena::unuse()
++{
++ _refcount--;
++ if (_refcount <= 0)
++ delete this;
++}
++
++inline void *
++HashMap_Arena::alloc()
++{
++ if (_free) {
++ void *ret = _free;
++ _free = _free->next;
++ return ret;
++ } else if (_buffer_pos > 0) {
++ _buffer_pos -= _element_size;
++ return _cur_buffer + _buffer_pos;
++ } else
++ return hard_alloc();
++}
++
++inline void
++HashMap_Arena::free(void *v)
++{
++ Link *link = reinterpret_cast<Link *>(v);
++ link->next = _free;
++ _free = link;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/bitvector.hh click-1.6.0-27/inst/include/click/bitvector.hh
+--- click-1.6.0/inst/include/click/bitvector.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/bitvector.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,248 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/bitvector.cc" -*-
++#ifndef CLICK_BITVECTOR_HH
++#define CLICK_BITVECTOR_HH
++#include <click/glue.hh>
++CLICK_DECLS
++
++class Bitvector { public:
++
++ class Bit;
++
++ Bitvector() : _max(-1), _data(&_f0), _f0(0), _f1(0) { }
++ explicit Bitvector(int);
++ explicit Bitvector(unsigned);
++ explicit Bitvector(bool b) : _max(0), _data(&_f0), _f0(b), _f1(0) { }
++ Bitvector(int, bool);
++ Bitvector(unsigned, bool);
++ Bitvector(const Bitvector &);
++ ~Bitvector() { if (_data != &_f0) delete[] _data; }
++
++ int size() const { return _max + 1; }
++
++ bool zero() const;
++
++ typedef bool (Bitvector::*unspecified_bool_type)() const;
++ operator bool() const { return !zero() ? &Bitvector::zero : 0; }
++
++ Bit operator[](int);
++ bool operator[](int) const;
++ Bit force_bit(int);
++
++ void clear();
++ void resize(int n);
++
++ bool operator==(const Bitvector &) const;
++ bool operator!=(const Bitvector &) const;
++
++ Bitvector operator~() const;
++ Bitvector operator&(const Bitvector &) const;
++ Bitvector operator|(const Bitvector &) const;
++ Bitvector operator^(const Bitvector &) const;
++ Bitvector operator-(const Bitvector &) const;
++
++ Bitvector &operator=(const Bitvector &);
++ void negate();
++ Bitvector &operator&=(const Bitvector &);
++ Bitvector &operator|=(const Bitvector &);
++ Bitvector &operator^=(const Bitvector &);
++ Bitvector &operator-=(const Bitvector &);
++ Bitvector &assign(int, bool);
++
++ void or_at(const Bitvector &, int);
++ void or_with_difference(const Bitvector &, Bitvector &diff);
++ bool nonzero_intersection(const Bitvector &) const;
++
++ // expose the implementation
++ int max_word() const { return (_max < 0 ? -1 : _max>>5); }
++ uint32_t *data_words() { return _data; }
++ const uint32_t *data_words() const { return _data; }
++
++ private:
++
++ enum { MAX_INLINE_BIT = 63, MAX_INLINE_WORD = 1 };
++
++ int _max;
++ uint32_t *_data;
++ uint32_t _f0;
++ uint32_t _f1;
++
++ void finish_copy_constructor(const Bitvector &);
++ void clear_last();
++ void resize_to_max(int, bool);
++
++};
++
++class Bitvector::Bit { public:
++
++ Bit(uint32_t &p, int off) : _p(p), _mask(1U<<off) { }
++
++ typedef Bitvector::unspecified_bool_type unspecified_bool_type;
++ inline operator unspecified_bool_type() const {
++ return (_p & _mask) != 0 ? &Bitvector::zero : 0;
++ }
++
++ bool operator=(bool b);
++ bool operator=(const Bit &);
++
++ private:
++
++ uint32_t &_p;
++ uint32_t _mask;
++
++};
++
++
++inline
++Bitvector::Bitvector(int n)
++ : _max(n - 1), _data(&_f0), _f0(0), _f1(0)
++{
++ if (_max > MAX_INLINE_BIT)
++ resize_to_max(_max, false);
++}
++
++inline
++Bitvector::Bitvector(unsigned n)
++ : _max(n - 1), _data(&_f0), _f0(0), _f1(0)
++{
++ if (_max > MAX_INLINE_BIT)
++ resize_to_max(_max, false);
++}
++
++inline
++Bitvector::Bitvector(int n, bool b)
++ : _max(n - 1), _data(&_f0), _f0(0), _f1(0)
++{
++ if (_max > MAX_INLINE_BIT)
++ resize_to_max(_max, false);
++ if (b)
++ assign(n, b);
++}
++
++inline
++Bitvector::Bitvector(unsigned n, bool b)
++ : _max(n - 1), _data(&_f0), _f0(0), _f1(0)
++{
++ if (_max > MAX_INLINE_BIT)
++ resize_to_max(_max, false);
++ if (b)
++ assign(n, b);
++}
++
++inline
++Bitvector::Bitvector(const Bitvector &o)
++ : _max(o._max), _data(&_f0), _f0(o._data[0]), _f1(o._data[1])
++{
++ if (_max > MAX_INLINE_BIT)
++ finish_copy_constructor(o);
++}
++
++inline void
++Bitvector::resize(int n)
++{
++ if (n - 1 > MAX_INLINE_BIT)
++ resize_to_max(n - 1, true);
++ _max = n - 1;
++}
++
++inline bool
++Bitvector::Bit::operator=(bool b)
++{
++ if (b)
++ _p |= _mask;
++ else
++ _p &= ~_mask;
++ return b;
++}
++
++inline bool
++Bitvector::Bit::operator=(const Bit &o)
++{
++ return *this = (bool)o;
++}
++
++inline Bitvector::Bit
++Bitvector::operator[](int i)
++{
++ assert(i >= 0 && i <= _max);
++ return Bit(_data[i>>5], i&31);
++}
++
++inline Bitvector::Bit
++Bitvector::force_bit(int i)
++{
++ assert(i >= 0);
++ if (i > _max)
++ resize(i + 1);
++ return Bit(_data[i>>5], i&31);
++}
++
++inline bool
++Bitvector::operator[](int i) const
++{
++ assert(i >= 0 && i <= _max);
++ return (_data[i>>5] & (1<<(i&31))) != 0;
++}
++
++inline bool
++Bitvector::operator==(const Bitvector &o) const
++{
++ if (_max != o._max)
++ return false;
++ else if (_max <= MAX_INLINE_BIT)
++ return memcmp(_data, o._data, 8) == 0;
++ else
++ return memcmp(_data, o._data, (max_word() + 1)*4) == 0;
++}
++
++inline bool
++Bitvector::operator!=(const Bitvector &o) const
++{
++ return !(*this == o);
++}
++
++inline Bitvector &
++Bitvector::operator-=(const Bitvector &o)
++{
++ return *this &= ~o;
++}
++
++inline Bitvector
++Bitvector::operator~() const
++{
++ Bitvector m = *this;
++ m.negate();
++ return m;
++}
++
++inline Bitvector
++Bitvector::operator&(const Bitvector &o) const
++{
++ Bitvector m = *this;
++ m &= o;
++ return m;
++}
++
++inline Bitvector
++Bitvector::operator|(const Bitvector &o) const
++{
++ Bitvector m = *this;
++ m |= o;
++ return m;
++}
++
++inline Bitvector
++Bitvector::operator^(const Bitvector &o) const
++{
++ Bitvector m = *this;
++ m ^= o;
++ return m;
++}
++
++inline Bitvector
++Bitvector::operator-(const Bitvector &o) const
++{
++ return *this & ~o;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/clp.h click-1.6.0-27/inst/include/click/clp.h
+--- click-1.6.0/inst/include/click/clp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/clp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,152 @@
++#ifndef LCDF_CLP_H
++#define LCDF_CLP_H
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* clp.h - Public interface to CLP.
++ * This file is part of CLP, the command line parser package.
++ *
++ * Copyright (c) 1997-2006 Eddie Kohler, kohler@icir.org
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file, which is available in full at
++ * http://www.pdos.lcs.mit.edu/click/license.html. The conditions include: you
++ * must preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding. */
++
++
++/* Argument types */
++#define Clp_NoArg 0
++#define Clp_ArgString 1
++#define Clp_ArgStringNotOption 2
++#define Clp_ArgBool 3
++#define Clp_ArgInt 4
++#define Clp_ArgUnsigned 5
++#define Clp_ArgDouble 6
++
++#define Clp_FirstUserType 10
++
++/* Argument type flags */
++#define Clp_DisallowOptions (1<<0) /* Argument won't resemble an option */
++
++/* Flags for individual Clp_Options */
++#define Clp_Mandatory (1<<0) /* Has mandatory argument */
++#define Clp_Optional (1<<1) /* Has optional argument */
++#define Clp_Negate (1<<2) /* Allow --no-OPT */
++#define Clp_OnlyNegated (1<<3) /* Allow --no-OPT, but not --OPT */
++#define Clp_PreferredMatch (1<<4) /* Prefer --OPT to --OPTwhatever when
++ matching option prefixes */
++
++/* Option types for Clp_SetOptionChar */
++/* Clp_NotOption 0 */
++#define Clp_Short (1<<0)
++#define Clp_Long (1<<1)
++#define Clp_ShortNegated (1<<2)
++#define Clp_LongNegated (1<<3)
++#define Clp_LongImplicit (1<<4)
++
++/* Flags for Clp_AddStringListType */
++#define Clp_AllowNumbers (1<<0)
++
++/* Return values from Clp_Next */
++#define Clp_NotOption 0
++#define Clp_Done -1
++#define Clp_BadOption -2
++#define Clp_Error -3
++
++/* Sizes of clp->val */
++#define Clp_ValSize 40
++#define Clp_ValIntSize 10
++
++
++typedef struct Clp_Option Clp_Option;
++typedef struct Clp_Parser Clp_Parser;
++typedef struct Clp_Internal Clp_Internal;
++typedef struct Clp_ParserState Clp_ParserState;
++
++typedef int (*Clp_ArgParseFunc)(Clp_Parser *, const char *, int, void *);
++typedef void (*Clp_ErrorHandler)(const char *);
++
++
++struct Clp_Option {
++
++ const char *long_name;
++ int short_name;
++
++ int option_id;
++
++ int arg_type;
++ int flags;
++
++};
++
++
++struct Clp_Parser {
++
++ int negated;
++
++ int have_arg;
++ const char *arg;
++
++ union {
++ int i;
++ unsigned u;
++ double d;
++ const char *s;
++ void *pv;
++#ifdef HAVE_INT64_TYPES
++ int64_t i64;
++ uint64_t u64;
++#endif
++ char cs[Clp_ValSize];
++ unsigned char ucs[Clp_ValSize];
++ int is[Clp_ValIntSize];
++ unsigned us[Clp_ValIntSize];
++ } val;
++
++ Clp_Internal *internal;
++
++};
++
++
++Clp_Parser * Clp_NewParser(int argc, const char * const *argv,
++ int nopt, Clp_Option *opt);
++void Clp_DeleteParser(Clp_Parser *);
++
++Clp_ErrorHandler Clp_SetErrorHandler(Clp_Parser *, Clp_ErrorHandler);
++int Clp_SetOptionChar(Clp_Parser *, int c, int option_type);
++
++int Clp_AddType
++ (Clp_Parser *, int type_id, int flags,
++ Clp_ArgParseFunc func, void *user_data);
++int Clp_AddStringListType
++ (Clp_Parser *, int type_id, int flags, ...);
++int Clp_AddStringListTypeVec
++ (Clp_Parser *, int type_id, int flags,
++ int n, char **str, int *val);
++
++const char * Clp_ProgramName(Clp_Parser *);
++
++int Clp_Next(Clp_Parser *);
++const char * Clp_Shift(Clp_Parser *, int allow_dashes);
++int Clp_SetOptionProcessing(Clp_Parser *, int option_processing);
++
++Clp_ParserState *Clp_NewParserState(void);
++void Clp_DeleteParserState(Clp_ParserState *);
++void Clp_SaveParser(Clp_Parser *, Clp_ParserState *);
++void Clp_RestoreParser(Clp_Parser *, Clp_ParserState *);
++
++int Clp_OptionError(Clp_Parser *, const char *, ...);
++int Clp_CurOptionNameBuf(Clp_Parser *, char *buf, int buflen);
++const char * Clp_CurOptionName(Clp_Parser *); /* uses static memory */
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+diff -Nurb click-1.6.0/inst/include/click/config-bsdmodule.h click-1.6.0-27/inst/include/click/config-bsdmodule.h
+--- click-1.6.0/inst/include/click/config-bsdmodule.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/config-bsdmodule.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,52 @@
++/* include/click/config-bsdmodule.h. Generated from config-bsdmodule.h.in by configure. */
++/* Process this file with configure to produce config-bsdmodule.h. -*- mode: c -*- */
++#ifndef CLICK_CONFIG_BSDMODULE_H
++#define CLICK_CONFIG_BSDMODULE_H
++
++/* Define stuff under a FreeBSD module. */
++#ifndef __FreeBSD__
++# error "I must be compiled on a FreeBSD machine"
++#endif
++#define KERNEL 1
++#define _KERNEL 1
++#define KLD_MODULE 1
++
++/* Define if your BSD kernel has Click extensions. */
++/* #undef HAVE_CLICK_BSD_KERNEL */
++
++/* Define if your BSD kernel has polling extensions. */
++/* #undef HAVE_BSD_POLLING */
++
++/* Define if Click should use an adaptive scheduler to share the CPU(s) more
++ fairly with the kernel. */
++/* #undef HAVE_ADAPTIVE_SCHEDULER */
++
++/* Include integer and other type definitions. */
++#include <sys/types.h>
++
++/* Define assert macro. */
++#define assert(x) /* nada */
++
++/* Define likely and unlikely macros. */
++#define likely(x) (x)
++#define unlikely(x) (x)
++
++#ifdef __cplusplus
++
++/* Declare operator new. */
++void *operator new(size_t) throw ();
++void *operator new[](size_t) throw ();
++
++/* Provide placement new. */
++inline void *operator new(size_t, void *v) throw () { return v; }
++#define HAVE_PLACEMENT_NEW 1
++
++/* Define macros that surround Click declarations. */
++#define CLICK_DECLS namespace Click {
++#define CLICK_ENDDECLS }
++#define CLICK_USING_DECLS using namespace Click;
++#define CLICK_NAME(name) ::Click::name
++
++#endif /* __cplusplus */
++
++#endif /* CLICK_CONFIG_BSDMODULE_H */
+diff -Nurb click-1.6.0/inst/include/click/config-linuxmodule.h click-1.6.0-27/inst/include/click/config-linuxmodule.h
+--- click-1.6.0/inst/include/click/config-linuxmodule.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/config-linuxmodule.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,153 @@
++/* include/click/config-linuxmodule.h. Generated from config-linuxmodule.h.in by configure. */
++/* Process this file with configure to produce config-linuxmodule.h. -*- mode: c -*- */
++#ifndef CLICK_CONFIG_LINUXMODULE_H
++#define CLICK_CONFIG_LINUXMODULE_H
++
++/* Define stuff under a Linux module. */
++#ifndef __linux__
++# error "I must be compiled on a Linux machine"
++#endif
++#define __KERNEL__ 1
++#define MODULE 1
++
++/* Define if your Linux kernel is running in SMP mode. */
++#define __SMP__ 1
++
++/* Define if Click should use an adaptive scheduler to share the CPU(s) more
++ fairly with the kernel. */
++/* #undef HAVE_ADAPTIVE_SCHEDULER */
++
++/* Define if your Linux kernel has Click extensions. */
++#define HAVE_CLICK_KERNEL 1
++
++/* Define if your Linux kernel has Click transmit notification extensions. */
++/* #undef HAVE_CLICK_KERNEL_TX_NOTIFY */
++
++/* Define if fast checksum functions available. */
++#define HAVE_FAST_CHECKSUM 1
++
++/* Define if 'int64_t' is typedefed to 'long' in linuxmodule. */
++/* #undef HAVE_INT64_IS_LONG_LINUXMODULE */
++
++/* Define if 'int64_t' is typedefed to 'long long' in linuxmodule. */
++#define HAVE_INT64_IS_LONG_LONG_LINUXMODULE 1
++
++/* Define to enable assertion checking. Failed assertions will print a message
++ and optionally stop the router. */
++/* #undef HAVE_KERNEL_ASSERT */
++
++/* Define if you have the <asm/alternative.h> header file. */
++#define HAVE_LINUX_ASM_ALTERNATIVE_H 1
++
++/* Define if your Linux kernel architecture defines atomic_set_mask. */
++/* #undef HAVE_LINUX_ATOMIC_SET_MASK */
++
++/* Define if your Linux kernel has polling extensions. */
++#define HAVE_LINUX_POLLING 1
++
++/* Define if your Linux kernel has read_net_skbcount. */
++/* #undef HAVE_LINUX_READ_NET_SKBCOUNT */
++
++/* Define if 'struct skb_shared_info' has a 'gso_size' member. */
++/* #undef HAVE_LINUX_SKB_SHINFO_GSO_SIZE */
++
++/* Define if 'struct skb_shared_info' has an 'ip6_frag_id' member. */
++/* #undef HAVE_LINUX_SKB_SHINFO_IP6_FRAG_ID */
++
++/* Define if 'struct skb_shared_info' has a 'tso_size' member. */
++/* #undef HAVE_LINUX_SKB_SHINFO_TSO_SIZE */
++
++/* Define if 'struct skb_shared_info' has a 'ufo_size' member. */
++/* #undef HAVE_LINUX_SKB_SHINFO_UFO_SIZE */
++
++/* Define if 'struct sk_buff' has an 'fclone' member. */
++/* #undef HAVE_LINUX_SKBUFF_FCLONE */
++
++/* Define if 'struct sk_buff' has a 'security' member. */
++/* #undef HAVE_LINUX_SKBUFF_SECURITY */
++
++/* Define if your Linux kernel exposes strlen. */
++#define HAVE_LINUX_STRLEN_EXPOSED 1
++
++/* Define if your Linux kernel has tulip_interrupt_hook. */
++/* #undef HAVE_LINUX_TULIP_INTERRUPT_HOOK */
++
++/* Define if the Click linuxmodule is compiled for a 2.6 kernel. */
++#define HAVE_LINUXMODULE_2_6 1
++
++/* Define if you have the net_enable_timestamp function. */
++/* #undef HAVE_NET_ENABLE_TIMESTAMP */
++
++/* Define if you have the netif_tx_lock function. */
++/* #undef HAVE_NETIF_TX_LOCK */
++
++/* Define if fast checksum functions require correct alignment. */
++#ifndef __i386__
++# define FAST_CHECKSUM_ALIGNED 1
++#endif
++
++/* Include integer type definitions. */
++# include <linux/autoconf.h>
++#include <linux/types.h>
++typedef ptrdiff_t intptr_t;
++//typedef unsigned long uintptr_t; /* XXX? */
++
++/* Define HAVE_INT64_IS_LONG based on HAVE_INT64_IS_LONG_LINUXMODULE. */
++#ifdef HAVE_INT64_IS_LONG_LINUXMODULE
++# define HAVE_INT64_IS_LONG HAVE_INT64_IS_LONG_LINUXMODULE
++#endif
++
++/* Define HAVE_INT64_IS_LONG_LONG based on HAVE_INT64_IS_LONG_LONG_LINUXMODULE. */
++#if HAVE_LONG_LONG && defined(HAVE_INT64_IS_LONG_LONG_LINUXMODULE)
++# define HAVE_INT64_IS_LONG_LONG HAVE_INT64_IS_LONG_LONG_LINUXMODULE
++#endif
++
++/* Define KBUILD symbols. */
++#if !defined(KBUILD_STR) && HAVE_LINUXMODULE_2_6
++# define KBUILD_STR(s) #s
++# define KBUILD_BASENAME KBUILD_STR(click)
++# define KBUILD_MODNAME KBUILD_STR(click)
++#endif
++
++#ifdef __cplusplus
++
++/* Declare operator new. */
++void *operator new(size_t) throw ();
++void *operator new[](size_t) throw ();
++
++/* Provide placement new. */
++inline void *operator new(size_t, void *v) { return v; }
++#define HAVE_PLACEMENT_NEW 1
++
++/* Define macros that surround Click declarations. */
++#define CLICK_DECLS /* */
++#define CLICK_ENDDECLS /* */
++#define CLICK_USING_DECLS /* */
++#define CLICK_NAME(name) ::name
++
++/* Fix incompatibilities between some Linux versions and Click/C++. */
++#include <click/fixconfig.h>
++
++#endif /* __cplusplus */
++
++/* Define assert macro. */
++# ifdef __cplusplus
++extern "C" {
++# endif
++void click_assert_failed(const char *file, int line, const char *problem_text);
++# ifdef __cplusplus
++}
++# endif
++
++#ifdef HAVE_KERNEL_ASSERT
++# define assert(x) ((x) ? (void)0 : click_assert_failed(__FILE__, __LINE__, #x))
++#else
++# define assert(x) /* nada */
++#endif
++
++/* Some architectures do not have builtin integer functions in kernel. */
++#if defined(__MIPSEL__) || defined(__MIPSEB__)
++# define HAVE_NO_INTEGER_BUILTINS 1
++#endif
++
++#endif /* CLICK_CONFIG_LINUXMODULE_H */
+diff -Nurb click-1.6.0/inst/include/click/config-ns.h click-1.6.0-27/inst/include/click/config-ns.h
+--- click-1.6.0/inst/include/click/config-ns.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/config-ns.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,20 @@
++/* include/click/config-ns.h. Generated from config-ns.h.in by configure. */
++/* Process this file with configure to produce config-ns.h. -*- mode: c -*- */
++#ifndef CLICK_CONFIG_NS_H
++#define CLICK_CONFIG_NS_H
++
++#ifdef __cplusplus
++
++/* Define macros that surround Click declarations. */
++#define CLICK_DECLS namespace Click {
++#define CLICK_ENDDECLS }
++#define CLICK_USING_DECLS using namespace Click;
++#define CLICK_NAME(name) ::Click::name
++
++#endif /* __cplusplus */
++
++/* Include userlevel configuration. */
++#define CLICK_USERLEVEL 1
++#include <click/config-userlevel.h>
++
++#endif /* CLICK_CONFIG_NS_H */
+diff -Nurb click-1.6.0/inst/include/click/config-userlevel.h click-1.6.0-27/inst/include/click/config-userlevel.h
+--- click-1.6.0/inst/include/click/config-userlevel.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/config-userlevel.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,249 @@
++/* include/click/config-userlevel.h. Generated from config-userlevel.h.in by configure. */
++/* Process this file with configure to produce config-userlevel.h. -*- mode: c -*- */
++#ifndef CLICK_CONFIG_USERLEVEL_H
++#define CLICK_CONFIG_USERLEVEL_H
++
++/* Define if accept() uses socklen_t. */
++#define HAVE_ACCEPT_SOCKLEN_T 1
++
++/* Define if <pcap.h> uses bpf_timeval. */
++/* #undef HAVE_BPF_TIMEVAL */
++
++/* Define if you have the <byteswap.h> header file. */
++#define HAVE_BYTESWAP_H 1
++
++/* Define to 1 if you have the declaration
++ of 'madvise', and to 0 if you don't. */
++#define HAVE_DECL_MADVISE 1
++
++/* Define to 1 if you have the declaration
++ of 'pcap_setnonblock', and to 0 if you don't. */
++#define HAVE_DECL_PCAP_SETNONBLOCK 1
++
++/* Define if you have the <dlfcn.h> header file. */
++#define HAVE_DLFCN_H 1
++
++/* Define if dynamic linking is possible. */
++#define HAVE_DYNAMIC_LINKING 1
++
++/* Define if you have the ffs function. */
++#define HAVE_FFS 1
++
++/* Define if you have the ffsl function. */
++#define HAVE_FFSL 1
++
++/* Define if you have the ffsll function. */
++#define HAVE_FFSLL 1
++
++/* Floating point arithmetic is allowed. */
++#define HAVE_FLOAT_TYPES 1
++
++/* Define if you have the <grp.h> header file. */
++#define HAVE_GRP_H 1
++
++/* Define if the last argument to EV_SET has pointer type. */
++/* #undef HAVE_EV_SET_UDATA_POINTER */
++
++/* Define if 'struct if_data' has an 'ifi_datalen' member. */
++/* #undef HAVE_IF_DATA_IFI_DATALEN */
++
++/* Define if 'int64_t' is typedefed to 'long' at user level. */
++/* #undef HAVE_INT64_IS_LONG_USERLEVEL */
++
++/* Define if 'int64_t' is typedefed to 'long long' at user level. */
++#define HAVE_INT64_IS_LONG_LONG_USERLEVEL 1
++
++/* Define if you have the <inttypes.h> header file. */
++#define HAVE_INTTYPES_H 1
++
++/* Define if you have the kqueue function. */
++/* #undef HAVE_KQUEUE */
++
++/* Define if your C library contains large file support. */
++#define HAVE_LARGE_FILE_SUPPORT 1
++
++/* Define if you have the <linux/if_tun.h> header file. */
++#define HAVE_LINUX_IF_TUN_H 1
++
++/* Define if you have the madvise function. */
++#define HAVE_MADVISE 1
++
++/* Define if you have the mmap function. */
++#define HAVE_MMAP 1
++
++/* Define if you have the <net/bpf.h> header file. */
++/* #undef HAVE_NET_BPF_H */
++
++/* Define if you have the <net/if_tap.h> header file. */
++/* #undef HAVE_NET_IF_TAP_H */
++
++/* Define if you have the <net/if_tun.h> header file. */
++/* #undef HAVE_NET_IF_TUN_H */
++
++/* Define if you have the <netdb.h> header file. */
++#define HAVE_NETDB_H 1
++
++/* Define if <new.h> exists and works. */
++/* #undef HAVE_NEW_H */
++
++/* Define if <new> exists and works. */
++#define HAVE_NEW_HDR 1
++
++/* Define if you have -lpcap and pcap.h. */
++#define HAVE_PCAP 1
++
++/* Define if you have the pcap_setnonblock function. */
++#define HAVE_PCAP_SETNONBLOCK 1
++
++/* Define if you have -lproper and prop.h, and proper operations should be
++ preferred to their non-proper counterparts. */
++/* #undef HAVE_PROPER */
++
++/* Define if you have a non-emulated <poll.h> header file. */
++#define HAVE_POLL_H 1
++
++/* Placement new is always provided below. */
++#define HAVE_PLACEMENT_NEW 1
++
++/* Define if you have the <pwd.h> header file. */
++#define HAVE_PWD_H 1
++
++/* Define if you have the sigaction function. */
++#define HAVE_SIGACTION 1
++
++/* Define if you have the snprintf function. */
++#define HAVE_SNPRINTF 1
++
++/* Define if 'struct sockaddr_in' has a 'sin_len' member. */
++/* #undef HAVE_SOCKADDR_IN_SIN_LEN */
++
++/* Define if you have the strerror function. */
++#define HAVE_STRERROR 1
++
++/* Define if you have the <strings.h> header file. */
++#define HAVE_STRINGS_H 1
++
++/* Define if you have the strtoul function. */
++#define HAVE_STRTOUL 1
++
++/* Define if you have the <sys/event.h> header file. */
++/* #undef HAVE_SYS_EVENT_H */
++
++/* Define if you have the <sys/mman.h> header file. */
++#define HAVE_SYS_MMAN_H 1
++
++/* Define if you have the tcgetpgrp function. */
++#define HAVE_TCGETPGRP 1
++
++/* Define if you have the <termio.h> header file. */
++#define HAVE_TERMIO_H 1
++
++/* Define if you have u_intXX_t types but not uintXX_t types. */
++/* #undef HAVE_U_INT_TYPES */
++
++/* Define if you have the <unistd.h> header file. */
++#define HAVE_UNISTD_H 1
++
++/* Define if a Click user-level driver might run multiple threads. */
++/* #undef HAVE_USER_MULTITHREAD */
++
++/* Define if you have the vsnprintf function. */
++#define HAVE_VSNPRINTF 1
++
++/* The size of a `off_t', as computed by sizeof. */
++#define SIZEOF_OFF_T 8
++
++
++/* Set feature test macros before anything is included. */
++#if HAVE_LARGE_FILE_SUPPORT && HAVE_INT64_TYPES
++# define _LARGEFILE_SOURCE 1
++# define _FILE_OFFSET_BITS 64
++#endif
++
++/* Include integer type definitions. */
++#ifdef HAVE_INTTYPES_H
++# include <inttypes.h>
++#endif
++#include <sys/types.h>
++
++/* Define uint types in terms of u_int types, if necessary. */
++#ifdef HAVE_U_INT_TYPES
++typedef u_int8_t uint8_t;
++typedef u_int16_t uint16_t;
++typedef u_int32_t uint32_t;
++# ifdef HAVE_INT64_TYPES
++typedef u_int64_t uint64_t;
++# endif
++typedef long intptr_t; /* XXX? */
++typedef unsigned long uintptr_t;
++#endif
++
++/* Define HAVE_INT64_IS_LONG based on HAVE_INT64_IS_LONG_USERLEVEL. */
++#ifdef HAVE_INT64_IS_LONG_USERLEVEL
++# define HAVE_INT64_IS_LONG HAVE_INT64_IS_LONG_USERLEVEL
++#endif
++
++/* Define HAVE_INT64_IS_LONG_LONG based on HAVE_INT64_IS_LONG_LONG_USERLEVEL. */
++#ifdef HAVE_INT64_IS_LONG_LONG_USERLEVEL
++# define HAVE_INT64_IS_LONG_LONG HAVE_INT64_IS_LONG_LONG_USERLEVEL
++#endif
++
++/* Define HAVE_MULTITHREAD based on HAVE_USER_MULTITHREAD. */
++#ifdef HAVE_USER_MULTITHREAD
++# define HAVE_MULTITHREAD HAVE_USER_MULTITHREAD
++#endif
++
++/* Include assert macro. */
++#include <assert.h>
++
++/* Define likely and unlikely macros. */
++#if __GNUC__ >= 3
++# define likely(x) __builtin_expect(!!(x), 1)
++# define unlikely(x) __builtin_expect(!!(x), 0)
++#else
++# define likely(x) (x)
++# define unlikely(x) (x)
++#endif
++
++/* Define if mmap is allowed. */
++#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
++# define ALLOW_MMAP 1
++#endif
++
++/* Prototype strerror if we don't have it. */
++#ifndef HAVE_STRERROR
++char *strerror(int errno);
++#endif
++
++/* Use nanosecond-granularity timestamps if they are enabled. */
++#ifdef HAVE_NANOTIMESTAMP_ENABLED
++#define HAVE_NANOTIMESTAMP 1
++#endif
++
++#ifdef __cplusplus
++
++/* Provide placement new. */
++#if HAVE_NEW_HDR
++# include <new>
++#elif HAVE_NEW_H
++# include <new.h>
++#else
++inline void *operator new(size_t, void *v) { return v; }
++#endif
++
++/* Prototype madvise if we have it, but not the prototype. */
++#if ALLOW_MMAP && HAVE_MADVISE && !HAVE_DECL_MADVISE
++extern "C" int madvise(void *addr, size_t len, int behav);
++#endif
++
++/* Define macros that surround Click declarations. */
++#ifndef CLICK_DECLS
++# define CLICK_DECLS /* */
++# define CLICK_ENDDECLS /* */
++# define CLICK_USING_DECLS /* */
++# define CLICK_NAME(name) ::name
++#endif
++
++#endif /* __cplusplus */
++
++#endif /* CLICK_CONFIG_USERLEVEL_H */
+diff -Nurb click-1.6.0/inst/include/click/config.h click-1.6.0-27/inst/include/click/config.h
+--- click-1.6.0/inst/include/click/config.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/config.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,168 @@
++/* include/click/config.h. Generated from config.h.in by configure. */
++/* Process this file with configure to produce config.h. -*- mode: c -*- */
++#ifndef CLICK_CONFIG_H
++#define CLICK_CONFIG_H
++
++/* Define to byte order of target machine. */
++#define CLICK_BYTE_ORDER 1234
++#define CLICK_BIG_ENDIAN 4321
++#define CLICK_LITTLE_ENDIAN 1234
++#define CLICK_NO_ENDIAN 0
++
++/* Define for Click memory allocation debugging. */
++/* #undef CLICK_DMALLOC */
++
++/* Version number of package */
++#define CLICK_VERSION "1.6.0"
++
++/* Define if PollDevice should run fast to get good benchmark numbers */
++/* #undef CLICK_WARP9 */
++
++/* Define if you have the __builtin_clz function. */
++#define HAVE___BUILTIN_CLZ 1
++
++/* Define if you have the __builtin_clzl function. */
++#define HAVE___BUILTIN_CLZL 1
++
++/* Define if you have the __builtin_clzll function. */
++#define HAVE___BUILTIN_CLZLL 1
++
++/* Define if you have the __builtin_ffs function. */
++#define HAVE___BUILTIN_FFS 1
++
++/* Define if you have the __builtin_ffsl function. */
++#define HAVE___BUILTIN_FFSL 1
++
++/* Define if you have the __builtin_ffsll function. */
++#define HAVE___BUILTIN_FFSLL 1
++
++/* Define if the va_list type is addressable. */
++#define HAVE_ADDRESSABLE_VA_LIST 1
++
++/* Define if right shift of signed integers acts by sign extension. */
++#define HAVE_ARITHMETIC_RIGHT_SHIFT 1
++
++/* Define if the machine is indifferent to alignment. */
++#define HAVE_INDIFFERENT_ALIGNMENT 1
++
++/* Define if you want to use Intel-specific instructions. */
++/* #undef HAVE_INTEL_CPU */
++
++/* Define if 64-bit integer types are enabled. */
++#define HAVE_INT64_TYPES 1
++
++/* Define if IPv6 support is enabled. */
++/* #undef HAVE_IP6 */
++
++/* Define if IPsec support is enabled. */
++/* #undef HAVE_IPSEC */
++
++/* Define to 1 if the system has the type `long long'. */
++#define HAVE_LONG_LONG 1
++
++/* Define if nanosecond-granularity timestamps are enabled. */
++/* #undef HAVE_NANOTIMESTAMP_ENABLED */
++
++/* Define if you want to use the stride scheduler. */
++#define HAVE_STRIDE_SCHED 1
++
++/* Define to 1 since we have Strings. */
++#define HAVE_STRING 1
++
++/* Define to 1 if the system has the type `struct timespec'. */
++#define HAVE_STRUCT_TIMESPEC 1
++
++#ifdef HAVE_STRIDE_SCHED
++/* Define if you want task scheduling to use a heap, not a linked list. */
++/* #undef HAVE_TASK_HEAP */
++#endif
++
++/* The size of a `int', as computed by sizeof. */
++#define SIZEOF_INT 4
++
++/* The size of a `long', as computed by sizeof. */
++#define SIZEOF_LONG 4
++
++/* The size of a `long long', as computed by sizeof. */
++#define SIZEOF_LONG_LONG 8
++
++/* The size of a `struct timespec', as computed by sizeof. */
++#define SIZEOF_STRUCT_TIMESPEC 8
++
++/* The size of a `struct timeval', as computed by sizeof. */
++#define SIZEOF_STRUCT_TIMEVAL 8
++
++/* Define if you want to run multithreaded Click. */
++/* #undef __MTCLICK__ */
++#define NUM_CLICK_CPUS 1
++
++#ifndef __cplusplus
++/* Define inline, if necessary. C only. */
++/* #undef inline */
++#endif
++
++#ifdef __cplusplus
++/* Explicit template instances? */
++#if __GNUC__ == 2 && __GNUC_MINOR__ < 90
++#define EXPLICIT_TEMPLATE_INSTANCES 1
++#endif
++#endif /* __cplusplus */
++
++/* Define macros for declaring packed structures. */
++#ifdef __GNUC__
++#define CLICK_PACKED_STRUCTURE(open, close) open close __attribute__((packed))
++#define CLICK_SIZE_PACKED_STRUCTURE(open, close) open close __attribute__((packed))
++#else
++#define CLICK_PACKED_STRUCTURE(open, close) _Cannot_pack_structure__Use_GCC
++#define CLICK_SIZE_PACKED_STRUCTURE(open, close) open close
++#endif
++
++/* Define macro for deprecated functions. */
++#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
++#define CLICK_DEPRECATED
++#else
++#define CLICK_DEPRECATED __attribute__((deprecated))
++#endif
++
++/* Define ARCH_IS_BIG_ENDIAN based on CLICK_BYTE_ORDER. */
++#if CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
++#define ARCH_IS_BIG_ENDIAN 1
++#elif CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++#define ARCH_IS_BIG_ENDIAN 0
++#endif
++
++/* EXPORT_ELEMENT, ELEMENT_REQUIRES, ELEMENT_PROVIDES, ELEMENT_HEADER,
++ ELEMENT_LIBS, and ELEMENT_MT_SAFE are noops. */
++#define EXPORT_ELEMENT(x)
++#define ELEMENT_REQUIRES(x)
++#define ELEMENT_PROVIDES(x)
++#define ELEMENT_HEADER(x)
++#define ELEMENT_LIBS(x)
++#define ELEMENT_MT_SAFE(x)
++
++/* Assume CLICK_USERLEVEL unless otherwise defined. */
++#if !defined(CLICK_USERLEVEL) && !defined(CLICK_TOOL) && !defined(CLICK_LINUXMODULE) && !defined(CLICK_BSDMODULE)
++# define CLICK_USERLEVEL 1
++#endif
++
++/* Define stuff under a Linux module. */
++#ifdef CLICK_LINUXMODULE
++# include <click/config-linuxmodule.h>
++#endif
++
++/* Define stuff under a FreeBSD module. */
++#ifdef CLICK_BSDMODULE
++# include <click/config-bsdmodule.h>
++#endif
++
++/* Define stuff under nsclick. */
++#ifdef CLICK_NS
++# include <click/config-ns.h>
++#endif
++
++/* Define stuff under tools or a user-level driver. */
++#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
++# include <click/config-userlevel.h>
++#endif
++
++#endif /* CLICK_CONFIG_H */
+diff -Nurb click-1.6.0/inst/include/click/confparse.hh click-1.6.0-27/inst/include/click/confparse.hh
+--- click-1.6.0/inst/include/click/confparse.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/confparse.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,510 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/confparse.cc" -*-
++#ifndef CLICK_CONFPARSE_HH
++#define CLICK_CONFPARSE_HH
++/// @cond never
++#include <click/string.hh>
++#include <click/vector.hh>
++struct in_addr;
++CLICK_DECLS
++class ErrorHandler;
++class StringAccum;
++class Timestamp;
++#ifndef CLICK_TOOL
++class Element;
++class Router;
++class Handler;
++class HandlerCall;
++# define CP_VA_PARSE_ARGS_REST Element*, ErrorHandler*, ...
++# define CP_OPT_CONTEXT , Element* context = 0
++# define CP_CONTEXT , Element* context
++# define CP_PASS_CONTEXT , context
++#else
++# define CP_VA_PARSE_ARGS_REST ErrorHandler*, ...
++# define CP_OPT_CONTEXT
++# define CP_CONTEXT
++# define CP_PASS_CONTEXT
++#endif
++#ifndef CLICK_COMPILING_CONFPARSE_CC
++# define CLICK_CONFPARSE_DEPRECATED CLICK_DEPRECATED
++#else
++# define CLICK_CONFPARSE_DEPRECATED /* */
++#endif
++#if __GNUC__ <= 3
++# define CP_SENTINEL
++#else
++# define CP_SENTINEL __attribute__((sentinel))
++#endif
++/// @endcond
++
++/// @name Argument Manipulation
++//@{
++const char* cp_skip_space(const char* begin, const char* end);
++const char* cp_skip_comment_space(const char* begin, const char* end);
++bool cp_eat_space(String &str);
++inline bool cp_is_space(const String &str);
++bool cp_is_word(const String &str);
++bool cp_is_click_id(const String &str);
++
++String cp_uncomment(const String &str);
++String cp_unquote(const String &str);
++const char* cp_process_backslash(const char* begin, const char* end, StringAccum &sa);
++String cp_quote(const String &str, bool allow_newlines = false);
++
++void cp_argvec(const String& str, Vector<String>& conf);
++String cp_unargvec(const Vector<String>& conf);
++
++void cp_spacevec(const String& str, Vector<String>& conf);
++String cp_pop_spacevec(String& str);
++String cp_unspacevec(const String* begin, const String* end);
++inline String cp_unspacevec(const Vector<String>& conf);
++//@}
++
++/// @name Direct Parsing Functions
++//@{
++enum CpErrors {
++ CPE_OK = 0,
++ CPE_FORMAT,
++ CPE_NEGATIVE,
++ CPE_OVERFLOW,
++ CPE_INVALID,
++ CPE_MEMORY,
++ CPE_NOUNITS
++};
++extern int cp_errno;
++
++// strings and words
++bool cp_string(const String& str, String* result, String *rest = 0);
++bool cp_word(const String& str, String* result, String *rest = 0);
++bool cp_keyword(const String& str, String* result, String *rest = 0);
++
++// numbers
++bool cp_bool(const String& str, bool* result);
++
++const char *cp_integer(const char* begin, const char* end, int base, int* result);
++const char *cp_integer(const char* begin, const char* end, int base, unsigned int* result);
++/// @cond never
++inline const unsigned char *cp_integer(const unsigned char* begin, const unsigned char* end, int base, unsigned int* result);
++/// @endcond
++
++#if SIZEOF_LONG == SIZEOF_INT
++// may be needed to simplify overloading
++inline const char *cp_integer(const char* begin, const char* end, int base, long* result);
++inline const char *cp_integer(const char* begin, const char* end, int base, unsigned long* result);
++#elif SIZEOF_LONG != 8
++# error "long has an odd size"
++#endif
++
++#if HAVE_INT64_TYPES
++const char *cp_integer(const char* begin, const char* end, int base, int64_t* result);
++const char *cp_integer(const char* begin, const char* end, int base, uint64_t* result);
++/// @cond never
++inline const unsigned char *cp_integer(const unsigned char* begin, const unsigned char* end, int base, uint64_t* result);
++/// @endcond
++#endif
++
++bool cp_integer(const String& str, int base, int* result);
++bool cp_integer(const String& str, int base, unsigned int* result);
++#if SIZEOF_LONG == SIZEOF_INT
++inline bool cp_integer(const String& str, int base, long* result);
++inline bool cp_integer(const String& str, int base, unsigned long* result);
++#endif
++#ifdef HAVE_INT64_TYPES
++bool cp_integer(const String& str, int base, int64_t* result);
++bool cp_integer(const String& str, int base, uint64_t* result);
++#endif
++
++inline bool cp_integer(const String& str, int* result);
++inline bool cp_integer(const String& str, unsigned int* result);
++#if SIZEOF_LONG == SIZEOF_INT
++inline bool cp_integer(const String& str, long* result);
++inline bool cp_integer(const String& str, unsigned long* result);
++#endif
++#ifdef HAVE_INT64_TYPES
++inline bool cp_integer(const String& str, int64_t* result);
++inline bool cp_integer(const String& str, uint64_t* result);
++#endif
++
++#ifdef CLICK_USERLEVEL
++bool cp_file_offset(const String& str, off_t* result);
++#endif
++
++#define CP_REAL2_MAX_FRAC_BITS 28
++bool cp_real2(const String& str, int frac_bits, int32_t* result);
++bool cp_real2(const String& str, int frac_bits, uint32_t* result);
++bool cp_real10(const String& str, int frac_digits, int32_t* result);
++bool cp_real10(const String& str, int frac_digits, uint32_t* result);
++bool cp_real10(const String& str, int frac_digits, uint32_t* result_int, uint32_t* result_frac);
++#ifdef HAVE_FLOAT_TYPES
++bool cp_double(const String& str, double* result);
++#endif
++
++bool cp_seconds_as(const String& str, int frac_digits, uint32_t* result);
++bool cp_seconds_as_milli(const String& str, uint32_t* result);
++bool cp_seconds_as_micro(const String& str, uint32_t* result);
++bool cp_time(const String& str, Timestamp* result);
++bool cp_time(const String& str, struct timeval* result);
++
++bool cp_bandwidth(const String& str, uint32_t* result);
++
++// network addresses
++class IPAddress;
++class IPAddressList;
++bool cp_ip_address(const String& str, IPAddress* result CP_OPT_CONTEXT);
++inline bool cp_ip_address(const String& str, struct in_addr* result CP_OPT_CONTEXT);
++bool cp_ip_address(const String& str, unsigned char* result CP_OPT_CONTEXT);
++bool cp_ip_prefix(const String& str, IPAddress* result_addr, IPAddress* result_mask, bool allow_bare_address CP_OPT_CONTEXT);
++bool cp_ip_prefix(const String& str, unsigned char* result_addr, unsigned char* result_mask, bool allow_bare_address CP_OPT_CONTEXT);
++bool cp_ip_prefix(const String& str, IPAddress* result_addr, IPAddress* result_mask CP_OPT_CONTEXT);
++bool cp_ip_prefix(const String& str, unsigned char* result_addr, unsigned char* result_mask CP_OPT_CONTEXT);
++bool cp_ip_address_list(const String& str, Vector<IPAddress>* result CP_OPT_CONTEXT);
++
++#ifdef HAVE_IP6
++class IP6Address;
++bool cp_ip6_address(const String& str, IP6Address* result CP_OPT_CONTEXT);
++bool cp_ip6_address(const String& str, unsigned char* result CP_OPT_CONTEXT);
++bool cp_ip6_prefix(const String& str, IP6Address* result_addr, int* result_prefix, bool allow_bare_address CP_OPT_CONTEXT);
++bool cp_ip6_prefix(const String& str, unsigned char* result_addr, int* result_prefix, bool allow_bare_address CP_OPT_CONTEXT);
++bool cp_ip6_prefix(const String& str, unsigned char* result_addr, unsigned char* result_mask, bool allow_bare_address CP_OPT_CONTEXT);
++bool cp_ip6_prefix(const String& str, IP6Address* result_addr, IP6Address* result_mask, bool allow_bare_address CP_OPT_CONTEXT);
++#endif
++
++class EtherAddress;
++bool cp_ethernet_address(const String& str, EtherAddress* result CP_OPT_CONTEXT);
++bool cp_ethernet_address(const String& str, unsigned char* result CP_OPT_CONTEXT);
++
++bool cp_tcpudp_port(const String& str, int proto, uint16_t* result CP_OPT_CONTEXT);
++
++#ifndef CLICK_TOOL
++Element *cp_element(const String& str, Element* context, ErrorHandler* errh=0);
++Element *cp_element(const String& str, Router* router, ErrorHandler* errh=0);
++bool cp_handler_name(const String& str, Element** result_element, String* result_hname, Element* context, ErrorHandler* errh=0);
++bool cp_handler(const String& str, int flags, Element** result_element, const Handler** result_handler, Element* context, ErrorHandler* errh=0);
++#endif
++
++#ifdef HAVE_IPSEC
++bool cp_des_cblock(const String& str, unsigned char* result);
++#endif
++
++#if CLICK_USERLEVEL
++bool cp_filename(const String& str, String* result);
++#endif
++//@}
++
++/// @name cp_va_kparse
++//@{
++int cp_va_kparse(const Vector<String>& conf, CP_VA_PARSE_ARGS_REST) CP_SENTINEL;
++int cp_va_kparse(const String& str, CP_VA_PARSE_ARGS_REST) CP_SENTINEL;
++int cp_va_space_kparse(const String& str, CP_VA_PARSE_ARGS_REST) CP_SENTINEL;
++int cp_va_kparse_keyword(const String& str, CP_VA_PARSE_ARGS_REST) CP_SENTINEL;
++int cp_va_kparse_remove_keywords(Vector<String>& conf, CP_VA_PARSE_ARGS_REST) CP_SENTINEL;
++
++int cp_assign_arguments(const Vector<String>& argv, const String *keys_begin, const String *keys_end, Vector<String>* values = 0);
++
++void cp_va_static_initialize();
++void cp_va_static_cleanup();
++
++/// @brief Type of flags for cp_va_kparse() items.
++enum CpKparseFlags {
++ cpkN = 0, ///< Default flags
++ cpkM = 1, ///< Argument is mandatory
++ cpkP = 2, ///< Argument may be specified positionally
++ cpkC = 4, ///< Argument presence should be confirmed
++ cpkNormal = cpkN,
++ cpkMandatory = cpkM,
++ cpkPositional = cpkP,
++ cpkConfirm = cpkC
++};
++
++/// @brief Type of argument type names for cp_va_kparse() items.
++typedef const char *CpVaParseCmd;
++
++extern const CpVaParseCmd
++ cpEnd, ///< Use as argument name. Ends cp_va argument list.
++ cpIgnoreRest, ///< Use as argument name. No result storage; causes cp_va_kparse to ignore unparsed arguments and any remaining items.
++ cpIgnore, ///< No result storage (this argument is ignored).
++ cpArgument, ///< Result storage String*, accepts any argument.
++ cpArguments, ///< Result storage Vector<String>*, accepts any number of arguments with the same keyword.
++ cpString, ///< Result storage String*, parsed by cp_string().
++ cpWord, ///< Result storage String*, parsed by cp_word().
++ cpKeyword, ///< Result storage String*, parsed by cp_keyword().
++ cpBool, ///< Result storage bool*, parsed by cp_bool().
++ cpByte, ///< Result storage unsigned char*, parsed by cp_integer().
++ cpShort, ///< Result storage short*, parsed by cp_integer().
++ cpUnsignedShort, ///< Result storage unsigned short*, parsed by cp_integer().
++ cpInteger, ///< Result storage int32_t*, parsed by cp_integer().
++ cpUnsigned, ///< Result storage uint32_t*, parsed by cp_integer().
++ cpNamedInteger, ///< Parse parameter uint32_t nameinfo_type, result storage int32_t*, parsed by NameInfo::query_int.
++#ifdef HAVE_INT64_TYPES
++ cpInteger64, ///< Result storage int64_t*, parsed by cp_integer().
++ cpUnsigned64, ///< Result storage uint64_t*, parsed by cp_integer().
++#endif
++#ifdef CLICK_USERLEVEL
++ cpFileOffset, ///< Result storage off_t*, parsed by cp_integer().
++#endif
++ cpUnsignedReal2, ///< Parse parameter int frac_bits, result storage uint32_t*, parsed by cp_real2().
++ cpReal10, ///< Parse parameter int frac_digits, result storage int32_t*, parsed by cp_real10().
++ cpUnsignedReal10, ///< Parse parameter int frac_digits, result storage uint32_t*, parsed by cp_real10().
++#ifdef HAVE_FLOAT_TYPES
++ cpDouble, ///< Result storage double*, parsed by cp_double().
++#endif
++ cpSeconds, ///< Result storage uint32_t*, parsed by cp_seconds_as() with frac_digits 0.
++ cpSecondsAsMilli, ///< Result storage uint32_t*, parsed by cp_seconds_as_milli().
++ cpSecondsAsMicro, ///< Result storage uint32_t*, parsed by cp_seconds_as_micro().
++ cpTimestamp, ///< Result storage Timestamp*, parsed by cp_time().
++ cpTimeval, ///< Result storage struct timeval*, parsed by cp_time().
++ cpInterval, ///< Result storage struct timeval*, parsed by cp_time().
++ cpBandwidth, ///< Result storage uint32_t*, parsed by cp_bandwidth().
++ cpIPAddress, ///< Result storage IPAddress* or equivalent, parsed by cp_ip_address().
++ cpIPPrefix, ///< Result storage IPAddress* addr and IPAddress *mask, parsed by cp_ip_prefix().
++ cpIPAddressOrPrefix,///< Result storage IPAddress* addr and IPAddress *mask, parsed by cp_ip_prefix().
++ cpIPAddressList, ///< Result storage Vector<IPAddress>*, parsed by cp_ip_address_list().
++ cpEthernetAddress, ///< Result storage EtherAddress*, parsed by cp_ethernet_address().
++ cpTCPPort, ///< Result storage uint16_t*, parsed by cp_tcpudp_port().
++ cpUDPPort, ///< Result storage uint16_t*, parsed by cp_tcpudp_port().
++ cpElement, ///< Result storage Element**, parsed by cp_element().
++ cpHandlerName, ///< Result storage Element** and String*, parsed by cp_handler_name().
++ cpHandlerCallRead, ///< Result storage HandlerCall*, parsed by HandlerCall.
++ cpHandlerCallWrite, ///< Result storage HandlerCall*, parsed by HandlerCall.
++ cpHandlerCallPtrRead, ///< Result storage HandlerCall**, parsed by HandlerCall::reset_read.
++ cpHandlerCallPtrWrite, ///< Result storage HandlerCall**, parsed by HandlerCall::reset_write.
++ cpIP6Address, ///< Result storage IP6Address* or equivalent, parsed by cp_ip6_address().
++ cpIP6Prefix, ///< Result storage IP6Address* addr and IP6Address* mask, parsed by cp_ip6_prefix().
++ cpIP6AddressOrPrefix,///< Result storage IP6Address* addr and IP6Address* mask, parsed by cp_ip6_prefix().
++ cpDesCblock, ///< Result storage uint8_t[8], parsed by cp_des_cblock().
++ cpFilename, ///< Result storage String*, parsed by cp_filename().
++ cpOptional, ///< cp_va_parse only: Following arguments are optional.
++ cpKeywords, ///< cp_va_parse only: Following arguments are keywords.
++ cpConfirmKeywords, ///< cp_va_parse only: Following arguments are confirmed keywords.
++ cpMandatoryKeywords,///< cp_va_parse only: Following arguments are mandatory keywords.
++ // old names, here for compatibility:
++ cpEtherAddress, // EtherAddress*
++ cpReadHandlerCall, // HandlerCall**
++ cpWriteHandlerCall; // HandlerCall**
++//@}
++
++/// @name Unparsing
++//@{
++String cp_unparse_bool(bool value);
++String cp_unparse_real2(int32_t value, int frac_bits);
++String cp_unparse_real2(uint32_t value, int frac_bits);
++#ifdef HAVE_INT64_TYPES
++String cp_unparse_real2(int64_t value, int frac_bits);
++String cp_unparse_real2(uint64_t value, int frac_bits);
++#endif
++String cp_unparse_real10(int32_t value, int frac_digits);
++String cp_unparse_real10(uint32_t value, int frac_digits);
++String cp_unparse_milliseconds(uint32_t value);
++String cp_unparse_microseconds(uint32_t value);
++String cp_unparse_interval(const Timestamp& value);
++String cp_unparse_interval(const struct timeval& value);
++String cp_unparse_bandwidth(uint32_t value);
++//@}
++
++/// @name Legacy Functions
++//@{
++int cp_va_parse(const Vector<String>& conf, CP_VA_PARSE_ARGS_REST);
++int cp_va_parse(const String& str, CP_VA_PARSE_ARGS_REST);
++int cp_va_space_parse(const String& str, CP_VA_PARSE_ARGS_REST);
++int cp_va_parse_keyword(const String& str, CP_VA_PARSE_ARGS_REST);
++int cp_va_parse_remove_keywords(Vector<String>& conf, int first, CP_VA_PARSE_ARGS_REST);
++// Argument syntax:
++// cp_va_arg ::= cpEnd // terminates argument list (not 0!)
++// | cpOptional | cpKeywords | cpIgnore... // manipulators
++// | CpVaParseCmd cmd, const char *description,
++// [Optional Helpers], Results
++// // Helpers and Results depend on 'cmd';
++// // see table above
++// | const char *keyword, CpVaParseCmd cmd, const char *description,
++// [Optional Helpers], Results
++// // keyword argument, within cpKeywords or
++// // cpMandatoryKeywords
++// | const char *keyword, CpVaParseCmd cmd, const char *description,
++// bool *keyword_given, [Optional Helpers], Results
++// // keyword argument, within cpConfirmKeywords
++// Returns the number of result arguments set, or negative on error.
++// Stores no values in the result arguments on error.
++//@}
++
++/// @name Argument Types for cp_va_kparse
++//@{
++struct cp_value;
++struct cp_argtype;
++
++typedef void (*cp_parsefunc)(cp_value* value, const String& arg,
++ ErrorHandler* errh, const char* argdesc CP_CONTEXT);
++typedef void (*cp_storefunc)(cp_value* value CP_CONTEXT);
++
++struct cp_argtype {
++ const char* name;
++ cp_argtype* next;
++ cp_parsefunc parse;
++ cp_storefunc store;
++ void* user_data;
++ int flags;
++ const char* description;
++ int internal;
++ int use_count;
++};
++
++struct cp_value {
++ // set by cp_va_parse:
++ const cp_argtype* argtype;
++ const char* keyword;
++ const char* description CLICK_CONFPARSE_DEPRECATED;
++ int extra;
++ void* store;
++ void* store2;
++ bool* store_confirm;
++ // set by parsefunc, used by storefunc:
++ union {
++ bool b;
++ int32_t i;
++ uint32_t u;
++#ifdef HAVE_INT64_TYPES
++ int64_t i64;
++ uint64_t u64;
++#endif
++#ifdef HAVE_FLOAT_TYPES
++ double d;
++#endif
++ unsigned char address[16];
++ int is[4];
++#ifndef CLICK_TOOL
++ Element* element;
++#endif
++ } v, v2;
++ String v_string;
++ String v2_string;
++};
++
++enum { cpArgNormal = 0, cpArgStore2 = 1, cpArgExtraInt = 2, cpArgAllowNumbers = 4 };
++int cp_register_argtype(const char* name, const char* description, int flags,
++ cp_parsefunc parsefunc, cp_storefunc storefunc,
++ void* user_data = 0);
++void cp_unregister_argtype(const char* name);
++
++int cp_register_stringlist_argtype(const char* name, const char* description,
++ int flags);
++int cp_extend_stringlist_argtype(const char* name, ...);
++// Takes: const char* name, int value, ...., const char* ender = (const char*)0
++//@}
++
++/// @cond never
++bool cp_seconds_as(int want_power, const String& str, uint32_t* result) CLICK_DEPRECATED;
++
++#define cp_integer64 cp_integer
++#define cp_unsigned64 cp_integer
++#define cp_unsigned cp_integer
++#define cp_unsigned_real10 cp_real10
++#define cp_unsigned_real2 cp_real2
++/// @endcond
++
++/** @brief Join the strings in @a conf with spaces and return the result.
++ *
++ * This function does not quote or otherwise protect the strings in @a conf.
++ * The caller should do that if necessary.
++ * @sa cp_unspacevec(const String *, const String *) */
++inline String cp_unspacevec(const Vector<String>& conf)
++{
++ return cp_unspacevec(conf.begin(), conf.end());
++}
++
++/** @brief Test if @a str is all spaces.
++ * @return True when every character in @a str is a space. */
++inline bool cp_is_space(const String& str)
++{
++ return cp_skip_space(str.begin(), str.end()) == str.end();
++}
++
++/** @brief Parse an integer from @a str in base 0.
++ *
++ * Same as cp_integer(str, 0, result). */
++inline bool cp_integer(const String& str, int* result)
++{
++ return cp_integer(str, 0, result);
++}
++
++inline bool cp_integer(const String& str, unsigned int* result)
++{
++ return cp_integer(str, 0, result);
++}
++
++/// @cond never
++inline const unsigned char *cp_integer(const unsigned char *begin, const unsigned char *end, int base, unsigned int* result)
++{
++ return (const unsigned char *) cp_integer((const char *) begin, (const char *) end, base, result);
++}
++/// @endcond
++
++#ifdef HAVE_INT64_TYPES
++/// @cond never
++inline const unsigned char *cp_integer(const unsigned char *begin, const unsigned char *end, int base, uint64_t* result)
++{
++ return (const unsigned char *) cp_integer((const char *) begin, (const char *) end, base, result);
++}
++/// @endcond
++
++inline bool cp_integer(const String& str, uint64_t* result)
++{
++ return cp_integer(str, 0, result);
++}
++
++inline bool cp_integer(const String& str, int64_t* result)
++{
++ return cp_integer(str, 0, result);
++}
++#endif
++
++#if SIZEOF_LONG == SIZEOF_INT
++inline const char* cp_integer(const char* begin, const char* end, int base, long* result)
++{
++ return cp_integer(begin, end, base, reinterpret_cast<int*>(result));
++}
++
++inline bool cp_integer(const String& str, int base, long* result)
++{
++ return cp_integer(str, base, reinterpret_cast<int*>(result));
++}
++
++inline bool cp_integer(const String& str, long* result)
++{
++ return cp_integer(str, reinterpret_cast<int*>(result));
++}
++
++inline const char* cp_integer(const char* begin, const char* end, int base, unsigned long* result)
++{
++ return cp_integer(begin, end, base, reinterpret_cast<unsigned int*>(result));
++}
++
++inline bool cp_integer(const String& str, int base, unsigned long* result)
++{
++ return cp_integer(str, base, reinterpret_cast<unsigned int*>(result));
++}
++
++inline bool cp_integer(const String& str, unsigned long* result)
++{
++ return cp_integer(str, reinterpret_cast<unsigned int*>(result));
++}
++#endif
++
++inline bool cp_ip_address(const String& str, struct in_addr* ina CP_CONTEXT)
++{
++ return cp_ip_address(str, reinterpret_cast<IPAddress*>(ina) CP_PASS_CONTEXT);
++}
++
++/// @cond never
++inline bool cp_seconds_as(int want_power, const String &str, uint32_t *result)
++{
++ return cp_seconds_as(str, want_power, result);
++}
++
++#undef CP_VA_ARGS_REST
++#undef CP_OPT_CONTEXT
++#undef CP_CONTEXT
++#undef CP_PASS_CONTEXT
++#undef CLICK_CONFPARSE_DEPRECATED
++#undef CP_SENTINEL
++#define cpEnd ((CpVaParseCmd) 0)
++/// @endcond
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/crc32.h click-1.6.0-27/inst/include/click/crc32.h
+--- click-1.6.0/inst/include/click/crc32.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/crc32.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,15 @@
++/* -*- related-file-name: "../../lib/crc32.c" -*- */
++#ifndef CLICK_CRC32_H
++#define CLICK_CRC32_H
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++unsigned long update_crc(unsigned long crc_accum,
++ char *data_blk_ptr,
++ int data_blk_size);
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+diff -Nurb click-1.6.0/inst/include/click/cxxprotect.h click-1.6.0-27/inst/include/click/cxxprotect.h
+--- click-1.6.0/inst/include/click/cxxprotect.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/cxxprotect.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,22 @@
++#ifdef __cplusplus
++#define new xxx_new
++#define this xxx_this
++#define delete xxx_delete
++#define class xxx_class
++#define virtual xxx_virtual
++#define typename xxx_typename
++#define private xxx_private
++#define protected xxx_protected
++#define public xxx_public
++#define namespace xxx_namespace
++#endif
++
++#ifndef CLICK_CXX_PROTECT
++# ifdef __cplusplus
++# define CLICK_CXX_PROTECT extern "C" {
++# define CLICK_CXX_UNPROTECT }
++# else
++# define CLICK_CXX_PROTECT /* nothing */
++# define CLICK_CXX_UNPROTECT /* nothing */
++# endif
++#endif
+diff -Nurb click-1.6.0/inst/include/click/cxxunprotect.h click-1.6.0-27/inst/include/click/cxxunprotect.h
+--- click-1.6.0/inst/include/click/cxxunprotect.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/cxxunprotect.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,12 @@
++#ifdef __cplusplus
++#undef new
++#undef this
++#undef delete
++#undef class
++#undef virtual
++#undef typename
++#undef private
++#undef protected
++#undef public
++#undef namespace
++#endif
+diff -Nurb click-1.6.0/inst/include/click/dequeue.cc click-1.6.0-27/inst/include/click/dequeue.cc
+--- click-1.6.0/inst/include/click/dequeue.cc 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/dequeue.cc 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,170 @@
++/*
++ * dequeue.{cc,hh} -- double-ended queue template class
++ * Douglas S. J. De Couto
++ * Based on code from Click Vector<> class (vector.{cc,hh}).
++ *
++ * Copyright (c) 2003 Massachusetts Institute of Technology
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file. These conditions include: you must
++ * preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding.
++ */
++
++#ifndef CLICK_DEQUEUE_CC
++#define CLICK_DEQUEUE_CC
++
++CLICK_ENDDECLS
++#include <click/dequeue.hh>
++CLICK_DECLS
++
++template <class T>
++DEQueue<T>::DEQueue(const DEQueue<T> &o)
++ : _l(0), _n(0), _cap(0), _head(0), _tail(0)
++{
++ *this = o;
++}
++
++template <class T>
++DEQueue<T>::~DEQueue()
++{
++ for (int i = _head, j = 0; j < _n; i = next_i(i), j++)
++ _l[i].~T();
++ CLICK_LFREE(_l, _cap * sizeof(T));
++}
++
++template <class T> DEQueue<T> &
++DEQueue<T>::operator=(const DEQueue<T> &o)
++{
++ if (&o != this) {
++ for (int i = _head, j = 0; j < _n; i = next_i(i), j++)
++ _l[i].~T();
++ _n = 0;
++ _head = 0;
++ _tail = 0;
++ if (reserve(o._n)) {
++ _n = o._n;
++ for (int i = 0, j = o._head; i < _n; i++, j = o.next_i(j))
++ new(velt(i)) T(o._l[j]);
++ _tail = _n;
++ }
++ }
++ return *this;
++}
++
++template <class T> DEQueue<T> &
++DEQueue<T>::assign(int n, const T &e)
++{
++ resize(0, e);
++ resize(n, e);
++ return *this;
++}
++
++template <class T> bool
++DEQueue<T>::reserve(int want)
++{
++ if (want < 0)
++ want = _cap > 0 ? _cap * 2 : 4;
++ if (want <= _cap)
++ return true;
++
++ T *new_l = (T *) CLICK_LALLOC(want * sizeof(T));
++ if (!new_l)
++ return false;
++
++ for (int i = _head, j = 0; j < _n; j++, i = next_i(i)) {
++ new(velt(new_l, j)) T(_l[i]);
++ _l[i].~T();
++ }
++
++ CLICK_LFREE(_l, _cap * sizeof(T));
++
++ _l = new_l;
++ _cap = want;
++ _head = 0;
++ _tail = _n;
++ return true;
++}
++
++template <class T> void
++DEQueue<T>::shrink(int nn)
++{
++ // delete els from back of queue
++ if (nn < _n) {
++ int num_to_del = _n - nn;
++ for ( ; num_to_del > 0; _tail = prev_i(_tail), num_to_del--)
++ _l[prev_i(_tail)].~T();
++ _n = nn;
++ }
++}
++
++template <class T> void
++DEQueue<T>::resize(int nn, const T &e)
++{
++ // extra/excess els are added/removed to/from back of queue
++ if (nn <= _cap || reserve(nn)) {
++ // construct new els
++ for ( ; _n < nn; _tail = next_i(_tail), _n++)
++ new(velt(_tail)) T(e);
++
++ // delete excess els
++ for ( ; nn < _n; _tail = prev_i(_tail), _n--)
++ _l[prev_i(_tail)].~T();
++ }
++}
++
++template <class T> void
++DEQueue<T>::swap(DEQueue<T> &o)
++{
++ T *l = _l;
++ int n = _n;
++ int cap = _cap;
++ int head = _head;
++ int tail = _tail;
++ _l = o._l;
++ _n = o._n;
++ _cap = o._cap;
++ _head = o._head;
++ _tail = o._tail;
++ o._l = l;
++ o._n = n;
++ o._cap = cap;
++ o._head = head;
++ o._tail = tail;
++}
++
++template <class T> inline void
++DEQueue<T>::check_rep()
++{
++ // pushes go on to back (tail), pops come from front (head).
++ // elements closer to the tail have larger indices in the array
++ // (modulo total size).
++
++ // _head is index of front
++ // _tail is 1 + index of back, i.e. where next push goes
++
++ if (!_l) {
++ assert(_n == 0);
++ assert(_cap == 0);
++ assert(_head == 0);
++ assert(_tail == 0);
++ } else {
++ assert(_head >= 0);
++ assert(_head < _cap);
++ assert(_tail >= 0);
++ assert(_tail < _cap);
++ if (_n == _cap)
++ assert(_head == _tail);
++ else
++ assert(_n == (_tail >= _head ? _tail - _head : _cap - _head + _tail));
++ }
++}
++
++
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/dequeue.hh click-1.6.0-27/inst/include/click/dequeue.hh
+--- click-1.6.0/inst/include/click/dequeue.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/dequeue.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,146 @@
++// dequeue.hh
++// Douglas S. J. De Couto
++// 26 June 2003
++
++// Inspired by Click Vector<> and SimpleQueue code
++
++#ifndef CLICK_DEQUEUE_HH
++#define CLICK_DEQUEUE_HH
++#include <click/glue.hh>
++CLICK_DECLS
++
++template <class T>
++class DEQueue {
++
++public:
++ DEQueue() : _l(0), _n(0), _cap(0), _head(0), _tail(0) { }
++ explicit DEQueue(int capacity) : _l(0), _n(0), _cap(0), _head(0), _tail(0) { reserve(capacity); }
++ DEQueue(int n, const T &e) : _l(0), _n(0), _cap(0), _head(0), _tail(0) { resize(n, e); }
++ DEQueue(const DEQueue<T> &);
++ ~DEQueue();
++
++ inline void check_rep();
++
++ int size() const { return _n; }
++
++ const T &at(int i) const { assert(i>=0 && i<_n); return _l[idx(i)]; }
++ const T &operator[](int i) const { return at(i); }
++ const T &front() const { return at(0); }
++ const T &back() const { return at(_n - 1); }
++ const T &at_u(int i) const { return _l[idx(i)]; }
++
++ T &at(int i) { assert(i>=0 && i<_n); return _l[idx(i)]; }
++ T &operator[](int i) { return at(i); }
++ T &front() { return at(0); }
++ T &back() { return at(_n - 1); }
++ T &at_u(int i) { return _l[idx(i)]; }
++
++ struct const_iterator {
++ const DEQueue &_q;
++ int _pos;
++
++ const_iterator(const DEQueue<T> &q, int p) : _q(q), _pos(p) { }
++ const_iterator(const const_iterator &i) : _q(i._q), _pos(i._pos) { }
++ const_iterator &operator++() { _pos++; return *this; }
++ const_iterator &operator--() { _pos--; return *this; }
++ const_iterator operator++(int) { const_iterator t = *this; ++*this; return t; }
++ const_iterator operator--(int) { const_iterator t = *this; --*this; return t; }
++ const_iterator &operator+=(int n) { _pos += n; return *this; }
++ const_iterator &operator-=(int n) { _pos -= n; return *this; }
++ const T &operator[](int n) const { return _q[_pos + n]; }
++ bool operator==(const const_iterator &i) const { return _pos == i._pos && _q._l == i._q._l; }
++ bool operator!=(const const_iterator &i) const { return _pos != i._pos || _q._l != i._q._l; }
++ const T &operator*() const { return _q[_pos]; }
++ const T *operator->() const { return &_q[_pos]; }
++ };
++
++ struct iterator : public const_iterator {
++ iterator(DEQueue<T> &q, int p) : const_iterator(q, p) { }
++ iterator(const iterator &i) : const_iterator(i._q, i._pos) { }
++ T &operator[](int n) const { return const_cast<T &>(const_iterator::operator[](n)); }
++ T &operator*() const { return const_cast<T &>(const_iterator::operator*()); }
++ T *operator->() const { return const_cast<T *>(const_iterator::operator->()); }
++ };
++
++ iterator begin() { return iterator(*this, 0); }
++ const_iterator begin() const { return const_iterator((DEQueue<T> &) *this, 0); }
++ iterator end() { return iterator(*this, _n); }
++ const_iterator end() const { return const_iterator((DEQueue<T> &) *this, _n); }
++
++ inline void push_back(const T &);
++ inline void pop_back();
++
++ inline void push_front(const T &);
++ inline void pop_front();
++
++ void clear() { shrink(0); }
++ bool reserve(int);
++ void resize(int nn, const T &e = T());
++
++ DEQueue<T> &operator=(const DEQueue<T> &);
++ DEQueue<T> &assign(int n, const T &e = T());
++ void swap(DEQueue<T> &);
++
++private:
++
++ T *_l;
++ int _n;
++ int _cap;
++ int _head;
++ int _tail;
++
++ int next_i(int i) const { return (i != _cap - 1 ? i + 1 : 0); }
++ int prev_i(int i) const { return (i != 0 ? i - 1 : _cap - 1); }
++ int idx(int i) const { return (i + _head) % _cap; }
++
++ void *velt(int i) const { return (void *) &_l[i]; }
++ static void *velt(T *l, int i) { return (void *) &l[i]; }
++ void shrink(int nn);
++
++ friend class iterator;
++ friend class const_iterator;
++
++};
++
++
++
++template <class T> inline void
++DEQueue<T>::push_front(const T &e)
++{
++ if (_n < _cap || reserve(-1)) {
++ _head = prev_i(_head);
++ new(velt(_head)) T(e);
++ _n++;
++ }
++}
++
++template <class T> inline void
++DEQueue<T>::pop_front()
++{
++ assert(_n > 0);
++ --_n;
++ _l[_head].~T();
++ _head = next_i(_head);
++}
++
++template <class T> inline void
++DEQueue<T>::push_back(const T &e)
++{
++ if (_n < _cap || reserve(-1)) {
++ new(velt(_tail)) T(e);
++ _n++;
++ _tail = next_i(_tail);
++ }
++}
++
++template <class T> inline void
++DEQueue<T>::pop_back()
++{
++ assert(_n > 0);
++ --_n;
++ _tail = prev_i(_tail);
++ _l[_tail].~T();
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/driver.hh click-1.6.0-27/inst/include/click/driver.hh
+--- click-1.6.0/inst/include/click/driver.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/driver.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,37 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/driver.cc" -*-
++#ifndef CLICK_DRIVER_HH
++#define CLICK_DRIVER_HH
++#include <click/package.hh>
++
++#define CLICK_DEFAULT_PROVIDES /* nada */
++
++#if CLICK_USERLEVEL
++CLICK_DECLS
++class Router;
++class Master;
++class ErrorHandler;
++class Lexer;
++class ArchiveElement;
++
++void click_static_initialize();
++void click_static_cleanup();
++
++Lexer *click_lexer();
++Router *click_read_router(String filename, bool is_expr, ErrorHandler * = 0, bool initialize = true, Master * = 0);
++
++String click_compile_archive_file(String package, const Vector<ArchiveElement> &archive, int ai, const String &target, const String &extra_flags, ErrorHandler *errh);
++
++CLICK_ENDDECLS
++#elif CLICK_TOOL
++CLICK_DECLS
++class ErrorHandler;
++class ArchiveElement;
++
++void click_static_initialize();
++
++String click_compile_archive_file(String package, const Vector<ArchiveElement> &archive, int ai, const String &target, const String &extra_flags, ErrorHandler *errh);
++
++CLICK_ENDDECLS
++#endif
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/element.hh click-1.6.0-27/inst/include/click/element.hh
+--- click-1.6.0/inst/include/click/element.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/element.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,659 @@
++// -*- 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_DECLS
++class Router;
++class Master;
++class Task;
++class Timer;
++class Element;
++class ErrorHandler;
++class Bitvector;
++class Handler;
++
++/** @file <click/element.hh>
++ * @brief Click's Element class.
++ */
++
++#define CLICK_ELEMENT_PORT_COUNT_DEPRECATED CLICK_DEPRECATED
++
++// #define CLICK_STATS 5
++
++typedef int (*HandlerHook)(int operation, String&, Element*, const Handler*, ErrorHandler*);
++typedef String (*ReadHandlerHook)(Element*, void*);
++typedef int (*WriteHandlerHook)(const String&, Element*, void*, ErrorHandler*);
++
++class Element { public:
++
++ Element();
++ virtual ~Element();
++ static int nelements_allocated;
++
++ // RUNTIME
++ virtual void push(int port, Packet*);
++ virtual Packet* pull(int port);
++ virtual Packet* simple_action(Packet*);
++
++ virtual bool run_task(Task *); // return true iff did useful work
++ virtual void run_timer(Timer *);
++#if CLICK_USERLEVEL
++ virtual void selected(int fd);
++#endif
++
++ inline void checked_output_push(int port, Packet*) const;
++
++ // ELEMENT CHARACTERISTICS
++ virtual const char *class_name() const = 0;
++
++ virtual const char *port_count() const;
++ static const char PORTS_0_0[];
++ static const char PORTS_0_1[];
++ static const char PORTS_1_0[];
++ static const char PORTS_1_1[];
++
++ 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;
++
++ virtual void *cast(const char *);
++
++ // CONFIGURATION, INITIALIZATION, AND CLEANUP
++ 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 void add_handlers();
++
++ virtual int initialize(ErrorHandler*);
++
++ virtual void take_state(Element *old_element, ErrorHandler*);
++ virtual Element *hotswap_element() const;
++
++ enum CleanupStage {
++ CLEANUP_NO_ROUTER,
++ CLEANUP_BEFORE_CONFIGURE = CLEANUP_NO_ROUTER,
++ CLEANUP_CONFIGURE_FAILED,
++ CLEANUP_CONFIGURED,
++ CLEANUP_INITIALIZE_FAILED,
++ CLEANUP_INITIALIZED,
++ CLEANUP_ROUTER_INITIALIZED,
++ CLEANUP_MANUAL
++ };
++ virtual void cleanup(CleanupStage);
++
++ static inline void static_initialize();
++ static inline void static_cleanup();
++
++ // ELEMENT ROUTER CONNECTIONS
++ String name() const;
++ String landmark() const;
++ virtual String declaration() const;
++
++ inline Router *router() const;
++ inline int eindex() const;
++ inline int eindex(Router *r) const;
++ Master *master() const;
++
++ // INPUTS AND OUTPUTS
++ inline int nports(bool isoutput) const;
++ inline int ninputs() const;
++ inline int noutputs() const;
++
++ class Port;
++ inline const Port &port(bool isoutput, int port) const;
++ inline const Port &input(int port) const;
++ inline const Port &output(int port) const;
++
++ inline bool port_active(bool isoutput, int port) const;
++ inline bool input_is_push(int port) const;
++ inline bool input_is_pull(int port) const;
++ inline bool output_is_push(int port) const;
++ inline bool output_is_pull(int port) const;
++ void port_flow(bool isoutput, int port, Bitvector*) const;
++
++ // LIVE RECONFIGURATION
++ virtual void configuration(Vector<String>&) const;
++ String configuration() const;
++
++ virtual bool can_live_reconfigure() const;
++ virtual int live_reconfigure(Vector<String>&, ErrorHandler*);
++
++#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
++
++ // HANDLERS
++ void add_read_handler(const String &name, ReadHandlerHook, void*);
++ void add_write_handler(const String &name, WriteHandlerHook, void*);
++ void set_handler(const String &name, int flags, HandlerHook, void* = 0, void* = 0);
++ int set_handler_flags(const String &name, int flags);
++ 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_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 bool active() const;
++ inline Element* element() const;
++ inline int port() const;
++
++ 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
++
++ inline Port();
++ inline Port(Element*, Element*, int);
++
++ friend class Element;
++
++ };
++
++ // DEPRECATED
++ String id() const CLICK_DEPRECATED;
++
++ inline void set_ninputs(int) CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
++ inline void set_noutputs(int) CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
++ inline void add_input() CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
++ inline void add_output() CLICK_ELEMENT_PORT_COUNT_DEPRECATED;
++
++ virtual bool run_task() CLICK_DEPRECATED;
++ virtual void run_timer() CLICK_DEPRECATED;
++
++ 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 &);
++
++ // METHODS USED BY ROUTER
++ inline void attach_router(Router* r, int n) { _router = r; _eindex = n; }
++
++ int set_nports(int, int);
++ int notify_nports(int, int, ErrorHandler *);
++ enum Processing { VAGNOSTIC, VPUSH, VPULL };
++ static int next_processing_code(const char*& p, ErrorHandler* errh);
++ void processing_vector(int* input_codes, int* output_codes, ErrorHandler*) 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);
++
++ friend class Router;
++
++};
++
++
++/** @brief Initialize static data for this element class.
++ *
++ * Elements that need to initialize global state, such as global hash tables
++ * or configuration parsing functions, should place that initialization code
++ * inside a static_initialize() static member function. Click's build
++ * machinery will find that function and cause it to be called when the
++ * element code is loaded, before any elements of the class are created.
++ *
++ * static_initialize functions are called in an arbitrary and unpredictable
++ * order (not, for example, the configure_phase() order). Element authors are
++ * responsible for handling static initialization dependencies.
++ *
++ * For Click to find a static_initialize declaration, it must appear inside
++ * the element class's class declaration on its own line and have the
++ * following prototype:
++ *
++ * @code
++ * static void static_initialize();
++ * @endcode
++ *
++ * It must also have public accessibility.
++ *
++ * @sa Element::static_cleanup
++ */
++inline void
++Element::static_initialize()
++{
++}
++
++/** @brief Clean up static data for this element class.
++ *
++ * Elements that need to free global state, such as global hash tables or
++ * configuration parsing functions, should place that code inside a
++ * static_cleanup() static member function. Click's build machinery will find
++ * that function and cause it to be called when the element code is unloaded.
++ *
++ * static_cleanup functions are called in an arbitrary and unpredictable order
++ * (not, for example, the configure_phase() order, and not the reverse of the
++ * static_initialize order). Element authors are responsible for handling
++ * static cleanup dependencies.
++ *
++ * For Click to find a static_cleanup declaration, it must appear inside the
++ * element class's class declaration on its own line and have the following
++ * prototype:
++ *
++ * @code
++ * static void static_cleanup();
++ * @endcode
++ *
++ * It must also have public accessibility.
++ *
++ * @sa Element::static_initialize
++ */
++inline void
++Element::static_cleanup()
++{
++}
++
++/** @brief Return the element's router. */
++inline Router*
++Element::router() const
++{
++ return _router;
++}
++
++/** @brief Return the element's index within its router.
++ * @invariant this == router()->element(eindex())
++ */
++inline int
++Element::eindex() const
++{
++ return _eindex;
++}
++
++/** @brief Return the element's index within router @a r.
++ *
++ * Returns -1 if @a r != router(). */
++inline int
++Element::eindex(Router* r) const
++{
++ return (router() == r ? _eindex : -1);
++}
++
++/** @brief Return the number of input or output ports.
++ * @param isoutput false for input ports, true for output ports */
++inline int
++Element::nports(bool isoutput) const
++{
++ return _nports[isoutput];
++}
++
++/** @brief Return the number of input ports. */
++inline int
++Element::ninputs() const
++{
++ return _nports[0];
++}
++
++/** @brief Return the number of output ports. */
++inline int
++Element::noutputs() const
++{
++ return _nports[1];
++}
++
++/** @brief Sets the element's number of input ports (deprecated).
++ *
++ * @param ninputs number of input ports
++ *
++ * @deprecated The set_ninputs() function is deprecated. Elements should
++ * instead use port_count() to define an acceptable range of input port
++ * counts. Elements that called set_ninputs() from configure(), setting the
++ * number of input ports based on configuration arguments, should compare the
++ * desired number of ports to ninputs() and signal an error if they disagree.
++ *
++ * This function can be called from the constructor, notify_ninputs(),
++ * notify_noutputs(), or configure(), but not from initialize() or later. */
++inline void
++Element::set_ninputs(int ninputs)
++{
++ set_nports(ninputs, _nports[1]);
++}
++
++/** @brief Sets the element's number of output ports (deprecated).
++ *
++ * @param noutputs number of output ports
++ *
++ * @deprecated The set_noutputs() function is deprecated. Elements should
++ * instead use port_count() to define an acceptable range of output port
++ * counts. Elements that called set_noutputs() from configure(), setting the
++ * number of output ports based on configuration arguments, should compare the
++ * desired number of ports to noutputs() and signal an error if they disagree.
++ *
++ * This function can be called from the constructor, notify_ninputs(),
++ * notify_noutputs(), or configure(), but not from initialize() or later. */
++inline void
++Element::set_noutputs(int noutputs)
++{
++ set_nports(_nports[0], noutputs);
++}
++
++/** @brief Adds an input port (deprecated).
++ *
++ * @deprecated See the deprecation note at set_ninputs().
++ *
++ * An abbreviation for set_ninputs(ninputs() + 1). Subject to the same
++ * restrictions as set_ninputs().
++ *
++ * @sa set_ninputs */
++inline void
++Element::add_input()
++{
++ set_nports(_nports[0] + 1, _nports[1]);
++}
++
++/** @brief Adds an output port (deprecated).
++ *
++ * @deprecated See the deprecation note at set_noutputs().
++ *
++ * An abbreviation for set_noutputs(noutputs() + 1). Subject to the same
++ * restrictions as set_noutputs().
++ *
++ * @sa set_noutputs */
++inline void
++Element::add_output()
++{
++ set_nports(_nports[0], _nports[1] + 1);
++}
++
++/** @brief Return one of the element's ports.
++ * @param isoutput false for input ports, true for output ports
++ * @param port port number
++ *
++ * An assertion fails if @a p is out of range. */
++inline const Element::Port&
++Element::port(bool isoutput, int port) const
++{
++ assert((unsigned) port < (unsigned) _nports[isoutput]);
++ return _ports[isoutput][port];
++}
++
++/** @brief Return one of the element's input ports.
++ * @param port port number
++ *
++ * An assertion fails if @a port is out of range.
++ *
++ * @sa Port, port */
++inline const Element::Port&
++Element::input(int port) const
++{
++ return Element::port(false, port);
++}
++
++/** @brief Return one of the element's output ports.
++ * @param port port number
++ *
++ * An assertion fails if @a port is out of range.
++ *
++ * @sa Port, port */
++inline const Element::Port&
++Element::output(int port) const
++{
++ return Element::port(true, port);
++}
++
++/** @brief Check whether a port is active.
++ * @param isoutput false for input ports, true for output ports
++ * @param port port number
++ *
++ * Returns true iff @a port is in range and @a port is active. Push outputs
++ * and pull inputs are active; pull outputs and push inputs are not.
++ *
++ * @sa Element::Port::active */
++inline bool
++Element::port_active(bool isoutput, int port) const
++{
++ return (unsigned) port < (unsigned) nports(isoutput)
++ && _ports[isoutput][port].active();
++}
++
++/** @brief Check whether output @a port is push.
++ *
++ * Returns true iff output @a port exists and is push. @sa port_active */
++inline bool
++Element::output_is_push(int port) const
++{
++ return port_active(true, port);
++}
++
++/** @brief Check whether output @a port is pull.
++ *
++ * Returns true iff output @a port exists and is pull. */
++inline bool
++Element::output_is_pull(int port) const
++{
++ return (unsigned) port < (unsigned) nports(true)
++ && !_ports[1][port].active();
++}
++
++/** @brief Check whether input @a port is pull.
++ *
++ * Returns true iff input @a port exists and is pull. @sa port_active */
++inline bool
++Element::input_is_pull(int port) const
++{
++ return port_active(false, port);
++}
++
++/** @brief Check whether input @a port is push.
++ *
++ * Returns true iff input @a port exists and is push. */
++inline bool
++Element::input_is_push(int port) const
++{
++ return (unsigned) port < (unsigned) nports(false)
++ && !_ports[0][port].active();
++}
++
++#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
++#endif
++
++inline
++Element::Port::Port()
++ : _e(0), _port(-2) PORT_CTOR_INIT(0)
++{
++}
++
++inline
++Element::Port::Port(Element* owner, Element* e, int p)
++ : _e(e), _port(p) PORT_CTOR_INIT(owner)
++{
++ (void) owner;
++}
++
++/** @brief Returns whether this port is active (a push output or a pull input).
++ *
++ * @sa Element::port_active
++ */
++inline bool
++Element::Port::active() const
++{
++ return _port >= 0;
++}
++
++/** @brief Returns the element connected to this active port.
++ *
++ * Returns 0 if this port is not active(). */
++inline Element*
++Element::Port::element() const
++{
++ return _e;
++}
++
++/** @brief Returns the port number of the port connected to this active port.
++ *
++ * Returns < 0 if this port is not active(). */
++inline int
++Element::Port::port() const
++{
++ return _port;
++}
++
++/** @brief Push packet @a p over this port.
++ *
++ * Pushes packet @a p downstream through the router configuration by passing
++ * it to the next element's @link Element::push() push() @endlink function.
++ * Returns when the rest of the router finishes processing @a p.
++ *
++ * This port must be an active() push output port. Usually called from
++ * element code like @link Element::output output(i) @endlink .push(p).
++ *
++ * When element code calls Element::Port::push(@a p), it relinquishes control
++ * of packet @a p. When push() returns, @a p may have been altered or even
++ * freed by downstream elements. Thus, you must not use @a p after pushing it
++ * downstream. To push a copy and keep a copy, see Packet::clone().
++ *
++ * output(i).push(p) basically behaves like the following code, although it
++ * maintains additional statistics depending on how CLICK_STATS is defined:
++ *
++ * @code
++ * output(i).element()->push(output(i).port(), p);
++ * @endcode
++ */
++inline void
++Element::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
++}
++
++/** @brief Pull a packet over this port and return it.
++ *
++ * Pulls a packet from upstream in the router configuration by calling the
++ * previous element's @link Element::pull() pull() @endlink function. When
++ * the router finishes processing, returns the result.
++ *
++ * This port must be an active() pull input port. Usually called from element
++ * code like @link Element::input input(i) @endlink .pull().
++ *
++ * input(i).pull() basically behaves like the following code, although it
++ * maintains additional statistics depending on how CLICK_STATS is defined:
++ *
++ * @code
++ * input(i).element()->pull(input(i).port())
++ * @endcode
++ */
++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;
++}
++
++/** @brief Push packet @a p to output @a port, or kill it if @a port is out of
++ * range.
++ *
++ * @param port output port number
++ * @param p packet to push
++ *
++ * If @a port is in range (>= 0 and < noutputs()), then push packet @a p
++ * forward using output(@a port).push(@a p). Otherwise, kill @a p with @a p
++ * ->kill().
++ *
++ * @note It is invalid to call checked_output_push() on a pull output @a port.
++ */
++inline void
++Element::checked_output_push(int port, Packet* p) const
++{
++ if ((unsigned) port < (unsigned) noutputs())
++ _ports[1][port].push(p);
++ else
++ p->kill();
++}
++
++#undef CONNECTION_CTOR_INIT
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/elemfilter.hh click-1.6.0-27/inst/include/click/elemfilter.hh
+--- click-1.6.0/inst/include/click/elemfilter.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/elemfilter.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,54 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/elemfilter.cc" -*-
++#ifndef CLICK_ELEMFILTER_HH
++#define CLICK_ELEMFILTER_HH
++#include <click/element.hh>
++CLICK_DECLS
++
++class ElementFilter { public:
++
++ ElementFilter() { }
++ virtual ~ElementFilter() { }
++
++ inline bool match_input(Element*, int port);
++ inline bool match_output(Element*, int port);
++ inline bool match_port(Element*, bool isoutput, int port);
++
++ enum PortType { NONE = -1, INPUT = 0, OUTPUT = 1 };
++ virtual bool check_match(Element* e, int port, PortType);
++
++ void filter(Vector<Element*>&);
++
++};
++
++class CastElementFilter : public ElementFilter { public:
++
++ CastElementFilter(const String&);
++ bool check_match(Element*, int, PortType);
++
++ private:
++
++ String _what;
++
++};
++
++
++inline bool
++ElementFilter::match_input(Element* e, int port)
++{
++ return check_match(e, port, INPUT);
++}
++
++inline bool
++ElementFilter::match_output(Element* e, int port)
++{
++ return check_match(e, port, OUTPUT);
++}
++
++inline bool
++ElementFilter::match_port(Element* e, bool isoutput, int port)
++{
++ return check_match(e, port, (PortType) isoutput);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/error.hh click-1.6.0-27/inst/include/click/error.hh
+--- click-1.6.0/inst/include/click/error.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/error.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,187 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/error.cc" -*-
++#ifndef CLICK_ERROR_HH
++#define CLICK_ERROR_HH
++#include <click/string.hh>
++#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
++# include <stdio.h>
++#endif
++#include <stdarg.h>
++#if HAVE_ADDRESSABLE_VA_LIST
++# define VA_LIST_REF_T va_list *
++# define VA_LIST_DEREF(val) (*(val))
++# define VA_LIST_REF(val) (&(val))
++#else
++# define VA_LIST_REF_T va_list
++# define VA_LIST_DEREF(val) (val)
++# define VA_LIST_REF(val) (val)
++#endif
++CLICK_DECLS
++
++class ErrorHandler { public:
++
++ enum Seriousness {
++ ERRVERBOSITY_CONTEXT= 0x8000,
++ ERRVERBOSITY_MAX = 0xFFFF,
++ ERRVERBOSITY_DEFAULT= ERRVERBOSITY_MAX,
++ ERRVERBOSITY_MASK = 0x0000FFFF,
++ ERRVERBOSITY_SHIFT = 16,
++
++ ERR_MIN_DEBUG = 0x00000000,
++ ERR_MIN_MESSAGE = 0x00010000,
++ ERR_MIN_WARNING = 0x00020000,
++ ERR_MIN_ERROR = 0x00030000,
++ ERR_MIN_FATAL = 0x00040000,
++
++ // fatal() with no explicit exit status exits with this status
++ FATAL_EXITSTATUS = 1,
++
++ ERR_DEBUG = ERR_MIN_DEBUG + ERRVERBOSITY_DEFAULT,
++ ERR_CONTEXT_MESSAGE = ERR_MIN_MESSAGE + ERRVERBOSITY_CONTEXT,
++ ERR_MESSAGE = ERR_MIN_MESSAGE + ERRVERBOSITY_DEFAULT,
++ ERR_WARNING = ERR_MIN_WARNING + ERRVERBOSITY_DEFAULT,
++ ERR_CONTEXT_ERROR = ERR_MIN_ERROR + ERRVERBOSITY_CONTEXT,
++ ERR_ERROR = ERR_MIN_ERROR + ERRVERBOSITY_DEFAULT,
++ ERR_FATAL = ERR_MIN_FATAL + ERRVERBOSITY_DEFAULT + (FATAL_EXITSTATUS << ERRVERBOSITY_SHIFT)
++ };
++
++ ErrorHandler() { }
++ virtual ~ErrorHandler() { }
++
++ static ErrorHandler *static_initialize(ErrorHandler *errh); // returns errh
++ static void static_cleanup();
++
++ static ErrorHandler *default_handler();
++ static ErrorHandler *silent_handler();
++
++ static bool has_default_handler();
++ static void set_default_handler(ErrorHandler *);
++
++ virtual int nwarnings() const = 0;
++ virtual int nerrors() const = 0;
++ virtual void reset_counts() = 0;
++ virtual int min_verbosity() const;
++
++ // seriousness < ERR_MIN_WARNING returns OK_RESULT, which is 0
++ // seriousness >= ERR_MIN_WARNING returns ERROR_RESULT, which is -EINVAL
++ static const int OK_RESULT;
++ static const int ERROR_RESULT;
++
++ void debug(const char *format, ...);
++ void message(const char *format, ...);
++ int warning(const char *format, ...);
++ int error(const char *format, ...);
++ int fatal(const char *format, ...);
++
++ void ldebug(const String &landmark, const char *format, ...);
++ void lmessage(const String &landmark, const char *format, ...);
++ int lwarning(const String &landmark, const char *format, ...);
++ int lerror(const String &landmark, const char *format, ...);
++ int lfatal(const String &landmark, const char *format, ...);
++
++ int verror(Seriousness, const String &landmark, const char *format, va_list);
++ int verror_text(Seriousness, const String &landmark, const String &text);
++
++ String make_text(Seriousness, const char *, ...);
++ virtual String make_text(Seriousness, const char *, va_list);
++ virtual String decorate_text(Seriousness, const String &, const String &);
++ virtual void handle_text(Seriousness, const String &) = 0;
++ virtual int count_error(Seriousness, const String &) = 0;
++
++ virtual void set_error_code(int);
++
++ static String prepend_lines(const String &prefix, const String &text);
++
++ // error conversions
++ struct Conversion;
++ typedef String (*ConversionHook)(int flags, VA_LIST_REF_T);
++ enum ConversionFlags {
++ ZERO_PAD = 1, PLUS_POSITIVE = 2, SPACE_POSITIVE = 4, LEFT_JUST = 8,
++ ALTERNATE_FORM = 16, UPPERCASE = 32, SIGNED = 64, NEGATIVE = 128
++ };
++ static Conversion *add_conversion(const String &, ConversionHook);
++ static int remove_conversion(Conversion *);
++
++};
++
++class BaseErrorHandler : public ErrorHandler { public:
++ BaseErrorHandler() : _nwarnings(0), _nerrors(0) { }
++ int nwarnings() const { return _nwarnings; }
++ int nerrors() const { return _nerrors; }
++ void reset_counts() { _nwarnings = _nerrors = 0; }
++ int count_error(Seriousness, const String &);
++ private:
++ int _nwarnings, _nerrors;
++};
++
++#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
++class FileErrorHandler : public BaseErrorHandler { public:
++ FileErrorHandler(FILE *, const String & = String());
++ void handle_text(Seriousness, const String &);
++ private:
++ FILE *_f;
++ String _context;
++};
++#endif
++
++class ErrorVeneer : public ErrorHandler { public:
++
++ ErrorVeneer(ErrorHandler *errh) : _errh(errh) { }
++
++ int nwarnings() const;
++ int nerrors() const;
++ void reset_counts();
++
++ String make_text(Seriousness, const char *, va_list);
++ String decorate_text(Seriousness, const String &, const String &);
++ void handle_text(Seriousness, const String &);
++ int count_error(Seriousness, const String &);
++
++ protected:
++
++ ErrorHandler *_errh;
++
++};
++
++class ContextErrorHandler : public ErrorVeneer { public:
++ ContextErrorHandler(ErrorHandler *, const String &context, const String &indent = " ", const String &context_landmark = "");
++ String decorate_text(Seriousness, const String &, const String &);
++ private:
++ String _context;
++ String _indent;
++ String _context_landmark;
++};
++
++class PrefixErrorHandler : public ErrorVeneer { public:
++ PrefixErrorHandler(ErrorHandler *, const String &prefix);
++ String decorate_text(Seriousness, const String &, const String &);
++ private:
++ String _prefix;
++};
++
++class LandmarkErrorHandler : public ErrorVeneer { public:
++ LandmarkErrorHandler(ErrorHandler *, const String &);
++ void set_landmark(const String &s) { _landmark = s; }
++ String decorate_text(Seriousness, const String &, const String &);
++ private:
++ String _landmark;
++};
++
++class VerboseFilterErrorHandler : public ErrorVeneer { public:
++ VerboseFilterErrorHandler(ErrorHandler *, int min_verbosity);
++ int min_verbosity() const;
++ void handle_text(Seriousness, const String &);
++ private:
++ int _min_verbosity;
++};
++
++#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
++class BailErrorHandler : public ErrorVeneer { public:
++ BailErrorHandler(ErrorHandler *, Seriousness = ERR_MIN_ERROR);
++ void handle_text(Seriousness, const String &);
++ private:
++ int _exit_seriousness;
++};
++#endif
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/etheraddress.hh click-1.6.0-27/inst/include/click/etheraddress.hh
+--- click-1.6.0/inst/include/click/etheraddress.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/etheraddress.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,137 @@
++// -*- related-file-name: "../../lib/etheraddress.cc" -*-
++#ifndef CLICK_ETHERADDRESS_HH
++#define CLICK_ETHERADDRESS_HH
++#include <click/string.hh>
++#include <click/glue.hh>
++CLICK_DECLS
++
++class EtherAddress { public:
++
++ inline EtherAddress();
++ explicit EtherAddress(const unsigned char *data);
++
++ typedef bool (EtherAddress::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++ inline bool is_group() const;
++
++ inline unsigned char *data();
++ inline const unsigned char *data() const;
++ inline const uint16_t *sdata() const;
++
++ inline size_t hashcode() const;
++
++ // bool operator==(EtherAddress, EtherAddress);
++ // bool operator!=(EtherAddress, EtherAddress);
++
++ String unparse() const;
++
++ inline operator String() const;
++ inline String s() const;
++
++ private:
++
++ uint16_t _data[3];
++
++};
++
++/** @brief Constructs an EtherAddress equal to 00:00:00:00:00:00. */
++inline
++EtherAddress::EtherAddress()
++{
++ _data[0] = _data[1] = _data[2] = 0;
++}
++
++/** @brief Constructs an EtherAddress from data.
++ @param data the address data, in network byte order
++
++ The bytes data[0]...data[5] are used to construct the address. */
++inline
++EtherAddress::EtherAddress(const unsigned char *data)
++{
++ memcpy(_data, data, 6);
++}
++
++/** @brief Returns true iff the address is not 00:00:00:00:00:00. */
++inline
++EtherAddress::operator unspecified_bool_type() const
++{
++ return _data[0] || _data[1] || _data[2] ? &EtherAddress::is_group : 0;
++}
++
++/** @brief Returns true iff this address is a group address.
++
++ Group addresses have the low-order bit of the first byte set to 1, as in
++ 01:00:00:00:00:00. */
++inline bool
++EtherAddress::is_group() const
++{
++ return data()[0] & 1;
++}
++
++/** @brief Returns a pointer to the address data. */
++inline const unsigned char *
++EtherAddress::data() const
++{
++ return reinterpret_cast<const unsigned char *>(_data);
++}
++
++/** @brief Returns a pointer to the address data. */
++inline unsigned char *
++EtherAddress::data()
++{
++ return reinterpret_cast<unsigned char *>(_data);
++}
++
++/** @brief Returns a pointer to the address data, as an array of uint16_ts. */
++inline const uint16_t *
++EtherAddress::sdata() const
++{
++ return _data;
++}
++
++/** @brief Unparses this address into a colon-separated hex String.
++ @sa unparse */
++inline
++EtherAddress::operator String() const
++{
++ return unparse();
++}
++
++/** @brief Unparses this address into a colon-separated hex String.
++ @sa unparse */
++inline String
++EtherAddress::s() const
++{
++ return unparse();
++}
++
++/** @relates EtherAddress
++ @brief Compares two EtherAddress objects for equality. */
++inline bool
++operator==(const EtherAddress &a, const EtherAddress &b)
++{
++ return (a.sdata()[0] == b.sdata()[0]
++ && a.sdata()[1] == b.sdata()[1]
++ && a.sdata()[2] == b.sdata()[2]);
++}
++
++/** @relates EtherAddress
++ @brief Compares two EtherAddress objects for inequality. */
++inline bool
++operator!=(const EtherAddress &a, const EtherAddress &b)
++{
++ return !(a == b);
++}
++
++class StringAccum;
++StringAccum &operator<<(StringAccum &, const EtherAddress &);
++
++inline size_t
++EtherAddress::hashcode() const
++{
++ const uint16_t *d = sdata();
++ return (d[2] | (d[1] << 16)) ^ (d[0] << 9);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ewma.hh click-1.6.0-27/inst/include/click/ewma.hh
+--- click-1.6.0/inst/include/click/ewma.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ewma.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,488 @@
++#ifndef CLICK_EWMA_HH
++#define CLICK_EWMA_HH
++#include <click/glue.hh>
++#include <click/confparse.hh>
++CLICK_DECLS
++
++/** @file <click/ewma.hh>
++ * @brief Click's classes for supporting exponentially weighted moving
++ * averages.
++ */
++
++/** @class DirectEWMAX include/click/ewma.hh <click/ewma.hh>
++ * @brief An exponentially weighted moving average.
++ *
++ * The DirectEWMAX template class represents a simple exponentially weighted
++ * moving average. The average starts out with value 0. The update()
++ * function adds a new observation to the average.
++ *
++ * The template parameter P defines three EWMA parameters: value type,
++ * stability shift, and scale factor.
++ *
++ * The value type is simply the unsigned integral type used to store the
++ * average. It is also the type of each observation. <code>unsigned</code>
++ * and <code>uint64_t</code> are examples.
++ *
++ * The stability shift specifies alpha, the stability parameter. Concretely,
++ * alpha = 1. / (2 ** stability_shift). Thus, a stability shift of 4
++ * corresponds to an alpha of 1/16.
++ *
++ * The scaling factor specifies how many bits of fraction are kept per
++ * observation. Fraction bits are necessary to account for small differences
++ * between observations. For example, consider a EWMA with value 0, alpha
++ * 1/16, and 0 bits of fraction. Assume the EWMA begins to observe a stream
++ * of observations equal to 1. Despite these observations, the EWMA's value
++ * will never change from 0, since the 1/16 alpha factor rounds the new
++ * observations down to 0. At least 4 bits of fraction are required to
++ * account for this difference. There is a tradeoff: the more bits of
++ * fraction, the more precise the EWMA, but the less bits available to
++ * account for large values.
++ *
++ * These EWMA parameters are defined by five of P's members, two typedefs and
++ * three possibly static member functions.
++ *
++ * <dl>
++ * <dt><strong>P::value_type</strong></dt>
++ * <dd>The EWMA's value type. Example: <code>unsigned</code>.</dd>
++ *
++ * <dt><strong>P::signed_value_type</strong></dt>
++ * <dd>The signed version of <code>P::value_type</code>. Used internally.
++ * Example: <code>int</code>.</dd>
++ *
++ * <dt><strong>unsigned P::stability_shift()</strong></dt>
++ * <dd>This function should return this EWMA's stability shift
++ * (see below).</dd>
++ *
++ * <dt><strong>unsigned P::scale()</strong></dt>
++ * <dd>This function should return this EWMA's scaling factor
++ * (see below).</dd>
++ *
++ * <dt><strong>unsigned P::compensation()</strong></dt>
++ * <dd>This function should return this EWMA's stability compensation,
++ * which normally equals 1 @<@< (stability_shift - 1).</dd>
++ * </dl>
++ *
++ * Since DirectEWMAX inherits from an object of type P, these members are
++ * also directly available to callers.
++ *
++ * The FixedEWMAXParameters and StabilityEWMAXParameters types are good
++ * template arguments for DirectEWMAX.
++ *
++ * @sa RateEWMAX
++ */
++template <typename P>
++class DirectEWMAX : public P { public:
++
++ typedef typename P::value_type value_type;
++
++ /** @brief Create a EWMA with initial value 0. */
++ DirectEWMAX()
++ : _avg(0) {
++ }
++
++ /** @brief Return the current scaled moving average.
++ * @note The returned value has scale() bits of fraction. */
++ value_type scaled_average() const {
++ return _avg;
++ }
++
++ /** @brief Return the current moving average.
++ * @note The returned value is unscaled. */
++ value_type unscaled_average() const {
++ return (_avg + P::compensation()) >> P::scale();
++ }
++
++ /** @brief Reset the EWMA to value 0. */
++ void clear() {
++ _avg = 0;
++ }
++
++ /** @brief Update the moving average with a new observation.
++ * @param value the observation (unscaled) */
++ inline void update(value_type value);
++
++ /** @brief Update the moving average with @a count identical observations.
++ * @param value the observation (unscaled)
++ * @param count number of observations
++ * @note This may be faster than calling update(@a value) @a count
++ * times. */
++ void update_n(value_type value, unsigned count);
++
++ /** @brief Unparse the current average into a String.
++ * @note The returned value is unscaled, but may contain a fractional
++ * part. */
++ String unparse() const;
++
++ /** @brief Update the moving average with a new observation (deprecated).
++ * @param value the observation (unscaled)
++ * @deprecated Use update() instead. */
++ inline void update_with(value_type value) CLICK_DEPRECATED {
++ update(value);
++ }
++
++ private:
++
++ value_type _avg;
++
++};
++
++template <typename P>
++inline void
++DirectEWMAX<P>::update(value_type val)
++{
++ value_type val_scaled = (val << P::scale()) + P::compensation();
++ unsigned stability = P::stability_shift();
++#if HAVE_ARITHMETIC_RIGHT_SHIFT
++ _avg += static_cast<typename P::signed_value_type>(val_scaled - _avg) >> stability;
++#else
++ if (val_scaled < _avg)
++ _avg -= (_avg - val_scaled) >> stability;
++ else
++ _avg += (val_scaled - _avg) >> stability;
++#endif
++}
++
++template <typename P>
++void
++DirectEWMAX<P>::update_n(value_type value, unsigned count)
++{
++ // XXX use table lookup
++ value_type val_scaled = value << P::scale();
++ if (count >= 100)
++ _avg = val_scaled;
++ else {
++ val_scaled += P::compensation();
++ unsigned stability = P::stability_shift();
++#if HAVE_ARITHMETIC_RIGHT_SHIFT
++ for (; count > 0; count--)
++ _avg += static_cast<typename P::signed_value_type>(val_scaled - _avg) >> stability;
++#else
++ if (val_scaled < _avg)
++ for (; count > 0; count--)
++ _avg -= (_avg - val_scaled) >> stability;
++ else
++ for (; count > 0; count--)
++ _avg += (val_scaled - _avg) >> stability;
++#endif
++ }
++}
++
++template <typename P>
++inline String
++DirectEWMAX<P>::unparse() const
++{
++ return cp_unparse_real2(scaled_average(), P::scale());
++}
++
++/** @class FixedEWMAXParameters include/click/ewma.hh <click/ewma.hh>
++ * @brief Parameters for a EWMA with constant scaling factor and stability
++ * shift.
++ *
++ * The FixedEWMAXParameters template class is used as a template argument to
++ * DirectEWMAX. It defines a EWMA with fixed constant scaling factor and
++ * stability shift. FixedEWMAXParameters's first template argument is the
++ * EWMA's stability shift, its second template argument is the EWMA's scaling
++ * factor, its third template argument is the EWMA's value type, and the
++ * fourth template argument is the EWMA's signed value type.
++ *
++ * Example 1: <code>DirectEWMAX@<FixedEWMAXParameters@<4, 10, unsigned, int@>
++ * @></code> defines a EWMA with alpha 1/16 (stability shift 4), scaling
++ * factor 10, and value type unsigned. (These are the default parameters
++ * available in the DirectEWMA typedef.)
++ *
++ * Example 2: <code>DirectEWMAX@<FixedEWMAXParameters@<3, 10, uint64_t,
++ * int64_t@> @></code> defines a EWMA with alpha 1/8 (stability shift 3),
++ * scaling factor 10, and value type uint64_t.
++ */
++template <unsigned STABILITY, unsigned SCALE, typename T = unsigned, typename U = int>
++class FixedEWMAXParameters { public:
++
++ typedef T value_type;
++ typedef U signed_value_type;
++
++ /** @brief Returns this EWMA's stability shift.
++ * @return the 1st template parameter */
++ static unsigned stability_shift() {
++ return STABILITY;
++ }
++
++ /** @brief Returns this EWMA's scaling factor (bits of fraction).
++ * @return the 2nd template parameter */
++ static unsigned scale() {
++ return SCALE;
++ }
++
++ /** @brief Returns this EWMA's compensation.
++ * @return 1 << (stability_shift() - 1) */
++ static unsigned compensation() {
++ return 1 << (STABILITY - 1);
++ }
++
++};
++
++/** @brief A DirectEWMAX with stability shift 4 (alpha 1/16), scaling factor
++ * 10 (10 bits of fraction), and underlying type <code>unsigned</code>. */
++typedef DirectEWMAX<FixedEWMAXParameters<4, 10> > DirectEWMA;
++
++/** @brief A DirectEWMAX with stability shift 3 (alpha 1/8), scaling factor
++ * 10 (10 bits of fraction), and underlying type <code>unsigned</code>. */
++typedef DirectEWMAX<FixedEWMAXParameters<3, 10> > FastDirectEWMA;
++
++
++/** @class StabilityEWMAXParameters include/click/ewma.hh <click/ewma.hh>
++ * @brief Parameters for a EWMA with constant scaling factor
++ * and user-settable alpha.
++ *
++ * The StabilityEWMAXParameters template class is used as a template argument
++ * to DirectEWMAX. It defines a EWMA with fixed constant scaling factor.
++ * StabilityEWMAXParameters's first template argument is the EWMA's scaling
++ * factor, its second template argument is the EWMA's value type, and the
++ * third template argument is the EWMA's signed value type.
++ *
++ * Example: <code>DirectEWMAX@<StabilityEWMAXParameters@<10, unsigned, int@>
++ * @></code> defines a EWMA with user-settable alpha (stability shift)
++ * initially equal to 1/16, scaling factor 10, and value type unsigned.
++ *
++ * A <code>DirectEWMAX@<StabilityEWMAXParameters@<...@> @></code> object has
++ * stability_shift() and set_stability_shift() methods.
++ */
++template <unsigned SCALE, typename T = unsigned, typename U = int>
++class StabilityEWMAXParameters { public:
++
++ typedef T value_type;
++ typedef U signed_value_type;
++
++ /** @brief Create a StabilityEWMAXParameters with initial alpha 1/16. */
++ StabilityEWMAXParameters()
++ : _stability(4) {
++ }
++
++ /** @brief Return the current stability shift.
++ *
++ * The current alpha equals 1. / (2 ** stability_shift()). */
++ unsigned stability_shift() const {
++ return _stability;
++ }
++
++ /** @brief Set the current stability shift.
++ * @param stability_shift new value */
++ void set_stability_shift(unsigned stability_shift) {
++ _stability = stability_shift;
++ }
++
++ /** @brief Returns this EWMA's scaling factor (bits of fraction).
++ * @return the 1st template parameter */
++ static unsigned scale() {
++ return SCALE;
++ }
++
++ /** @brief Returns this EWMA's compensation.
++ * @return 1 << (stability_shift() - 1) */
++ unsigned compensation() const {
++ return 1 << (stability_shift() - 1);
++ }
++
++ private:
++
++ unsigned _stability;
++
++};
++
++
++
++/** @class RateEWMAX include/click/ewma.hh <click/ewma.hh>
++ * @brief An exponentially weighted moving average used to measure a rate.
++ *
++ * The RateEWMAX template class represents an exponentially weighted moving
++ * average that measures a <em>rate</em>: a value that changes over time.
++ * The average starts out with value 0.
++ *
++ * RateEWMAX adds to DirectEWMAX a concept of epochs, which are periods of
++ * time. A RateEWMAX object collects samples over the current epoch. When
++ * the epoch closes, the collected sample count is used to update the moving
++ * average. Thus, the moving average is measured in samples per epoch. The
++ * rate() and unparse_rate() member functions return the rate in samples per
++ * <em>second</em>, rather than per epoch.
++ *
++ * Note that it often makes sense to call update() before calling
++ * scaled_average(), rate(), or unparse_rate(), in case an epoch or two has
++ * passed and the average should take account of passing time.
++ *
++ * The template parameter P defines the EWMA parameters required by
++ * DirectEWMAX, and three others: a rate count, an epoch measurement, and an
++ * epoch frequency.
++ *
++ * The rate count is the number of rates measured per object. Usually it is
++ * 1.
++ *
++ * The epoch measurement is a function that returns the current epoch as an
++ * unsigned number. Epochs should increase monotonically.
++ *
++ * The epoch frequency is the number of epochs per second, and is only used
++ * by rate() and unparse_rate().
++ *
++ * These are defined by:
++ *
++ * <dl>
++ * <dt><strong>P::rate_count</strong></dt>
++ * <dd>The rate count, as a static constant (for example, defined by an
++ * enum).</dd>
++ *
++ * <dt><strong>unsigned P::epoch()</strong></dt>
++ * <dd>This function returns the current epoch number.</dd>
++ *
++ * <dt><strong>unsigned P::epoch_frequency()</strong></dt>
++ * <dd>This function returns the number of epochs per second.</dd>
++ * </dl>
++ *
++ * Since RateEWMAX inherits from an object of type P, these members are
++ * also directly available to callers.
++ *
++ * The RateEWMAXParameters type is a good template argument for DirectEWMAX.
++ *
++ * @sa RateEWMAX
++ */
++template <typename P>
++class RateEWMAX : public P { public:
++
++ typedef typename P::value_type value_type;
++ typedef typename P::signed_value_type signed_value_type;
++
++ /** @brief Create a rate EWMA with initial value(s) 0. */
++ RateEWMAX() {
++ _current_epoch = P::epoch();
++ for (unsigned i = 0; i < P::rate_count; i++)
++ _current[i] = 0;
++ }
++
++ /** @brief Return the current scaled moving average.
++ * @param ratenum rate index (0 <= ratenum < rate_count)
++ * @note The returned value has scale() bits of fraction.
++ * @note scaled_average() does not check the current epoch.
++ * If an epoch might have passed since the last update(), you
++ * should call update(0, @a ratenum) before calling this
++ * function. */
++ signed_value_type scaled_average(unsigned ratenum = 0) const {
++ // note: return type must be signed!
++ return _avg[ratenum].scaled_average();
++ }
++
++ /** @brief Return the current rate in samples per second.
++ * @param ratenum rate index (0 <= ratenum < rate_count)
++ * @note The returned value is unscaled.
++ * @note rate() does not check the current epoch.
++ * If an epoch might have passed since the last update(), you
++ * should call update(0, @a ratenum) before calling this
++ * function. */
++ inline int rate(unsigned ratenum = 0) const;
++
++ /** @brief Update the sample count for the current epoch.
++ * @param delta increment for current epoch sample count
++ * @param ratenum rate index (0 <= ratenum < rate_count)
++ * @note If the epoch has changed since the last update(),
++ * this function applies the last epoch's sample count (if any)
++ * to the relevant moving average, accounts for any passage of
++ * time (in case one or more epochs have passed with no samples),
++ * and clears the sample count for the new epoch. */
++ inline void update(signed_value_type delta, unsigned ratenum = 0);
++
++ /** @brief Unparse the current average into a String.
++ * @param ratenum rate index (0 <= ratenum < rate_count)
++ * @note The returned value is unscaled, but may contain a fractional
++ * part.
++ * @note unparse_rate() does not check the current epoch.
++ * If an epoch might have passed since the last update(), you
++ * should call update(0, @a ratenum) before calling this
++ * function. */
++ String unparse_rate(unsigned ratenum = 0) const;
++
++ private:
++
++ unsigned _current_epoch;
++ value_type _current[P::rate_count];
++ DirectEWMAX<P> _avg[P::rate_count];
++
++ inline void update_time(unsigned now);
++
++};
++
++/** @class RateEWMAXParameters include/click/ewma.hh <click/ewma.hh>
++ * @brief Parameters for a RateEWMA with constant scaling factor
++ * and alpha, one rate count, and epochs of jiffies.
++ *
++ * The RateEWMAXParameters template class is used as a template argument
++ * to RateEWMAX. It defines a EWMA with fixed constant scaling factor and
++ * alpha and one rate count. The EWMA uses jiffies as epochs. Template
++ * parameters are as for DirectEWMAXParameters.
++ *
++ * Example: <code>RateEWMAX@<RateEWMAXParameters@<4, 10, unsigned, int@>
++ * @></code> defines a rate EWMA with user-settable alpha (stability shift)
++ * initially equal to 1/16, scaling factor 10, and value type unsigned.
++ */
++template <unsigned STABILITY, unsigned SCALE, typename T = unsigned, typename U = int>
++class RateEWMAXParameters : public FixedEWMAXParameters<STABILITY, SCALE, T, U> { public:
++ enum {
++ rate_count = 1
++ };
++
++ /** @brief Return the current epoch number.
++ * @note RateEWMAXParameters measures epochs in jiffies. */
++ static unsigned epoch() {
++ return click_jiffies();
++ }
++
++ /** @brief Return the number of epochs (jiffies) per second. */
++ static unsigned epoch_frequency() {
++ return CLICK_HZ;
++ }
++};
++
++/** @brief A RateEWMAX with stability shift 4 (alpha 1/16), scaling factor 10
++ * (10 bits of fraction), one rate, and underlying type <code>unsigned</code>
++ * that measures epochs in jiffies. */
++typedef RateEWMAX<RateEWMAXParameters<4, 10> > RateEWMA;
++
++
++template <typename P>
++inline void
++RateEWMAX<P>::update_time(unsigned now)
++{
++ unsigned jj = _current_epoch;
++ if (now != jj) {
++ for (unsigned i = 0; i < P::rate_count; i++) {
++ // adjust the average rate using the last measured packets
++ _avg[i].update(_current[i]);
++
++ // adjust for time w/ no packets
++ if (jj + 1 != now)
++ _avg[i].update_n(0, now - jj - 1);
++ _current[i] = 0;
++ }
++ _current_epoch = now;
++ }
++}
++
++template <typename P>
++inline void
++RateEWMAX<P>::update(signed_value_type delta, unsigned ratenum)
++{
++ update_time(P::epoch());
++ _current[ratenum] += delta;
++}
++
++template <typename P>
++inline int
++RateEWMAX<P>::rate(unsigned ratenum) const
++{
++ return (scaled_average(ratenum) * P::epoch_frequency()) >> _avg[ratenum].scale();
++}
++
++template <typename P>
++inline String
++RateEWMAX<P>::unparse_rate(unsigned ratenum) const
++{
++ return cp_unparse_real2(scaled_average(ratenum) * P::epoch_frequency(), _avg[ratenum].scale());
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/fixconfig.h click-1.6.0-27/inst/include/click/fixconfig.h
+--- click-1.6.0/inst/include/click/fixconfig.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/fixconfig.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,13 @@
++#ifndef CLICK_FIXCONFIG_H
++#define CLICK_FIXCONFIG_H 1
++
++#if CLICK_LINUXMODULE && HAVE_LINUX_ASM_ALTERNATIVE_H
++// The .smp_locks section and C++-style weak linkage interact badly.
++# if CONFIG_SMP && (defined(__i386__) || defined(__x86_64__))
++# include <asm/alternative.h>
++# undef LOCK_PREFIX
++# define LOCK_PREFIX "lock ; "
++# endif
++#endif
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/gaprate.hh click-1.6.0-27/inst/include/click/gaprate.hh
+--- click-1.6.0/inst/include/click/gaprate.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/gaprate.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,96 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/gaprate.cc" -*-
++#ifndef CLICK_GAPRATE_HH
++#define CLICK_GAPRATE_HH
++#include <click/timestamp.hh>
++CLICK_DECLS
++class ErrorHandler;
++
++class GapRate { public:
++
++ inline GapRate();
++ inline GapRate(unsigned);
++
++ unsigned rate() const { return _rate; }
++
++ inline void set_rate(unsigned);
++ void set_rate(unsigned, ErrorHandler *);
++ inline void reset();
++
++ inline bool need_update(const Timestamp &);
++ void update() { _sec_count++; }
++ void update_with(int incr) { _sec_count += incr; }
++
++ enum { UGAP_SHIFT = 12 };
++ enum { MAX_RATE = 1000000U << UGAP_SHIFT };
++
++ private:
++
++ unsigned _ugap;
++ int _sec_count;
++ long _tv_sec;
++ unsigned _rate;
++#if DEBUG_GAPRATE
++ Timestamp _last;
++#endif
++
++};
++
++inline void
++GapRate::reset()
++{
++ _tv_sec = -1;
++#if DEBUG_GAPRATE
++ _last.set_sec(0);
++#endif
++}
++
++inline void
++GapRate::set_rate(unsigned rate)
++{
++ if (rate > MAX_RATE)
++ rate = MAX_RATE;
++ _rate = rate;
++ _ugap = (rate == 0 ? MAX_RATE + 1 : MAX_RATE / rate);
++#if DEBUG_GAPRATE
++ click_chatter("ugap: %u", _ugap);
++#endif
++ reset();
++}
++
++inline
++GapRate::GapRate()
++{
++ set_rate(0);
++}
++
++inline
++GapRate::GapRate(unsigned rate)
++{
++ set_rate(rate);
++}
++
++inline bool
++GapRate::need_update(const Timestamp &now)
++{
++ unsigned need = (now.usec() << UGAP_SHIFT) / _ugap;
++
++ if (_tv_sec < 0) {
++ // 27.Feb.2005: often OK to send a packet after reset unless rate is
++ // 0 -- requested by Bart Braem
++ // check include/click/gaprate.hh (1.2)
++ _tv_sec = now.sec();
++ _sec_count = need + ((now.usec() << UGAP_SHIFT) - (need * _ugap) > _ugap / 2);
++ } else if (now.sec() > _tv_sec) {
++ _tv_sec = now.sec();
++ if (_sec_count > 0)
++ _sec_count -= _rate;
++ }
++
++#if DEBUG_GAPRATE
++ click_chatter("%{timestamp} -> %u @ %u [%d]", &now, need, _sec_count, (int)need >= _sec_count);
++#endif
++ return ((int)need >= _sec_count);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/glue.hh click-1.6.0-27/inst/include/click/glue.hh
+--- click-1.6.0/inst/include/click/glue.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/glue.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,420 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/glue.cc" -*-
++#ifndef CLICK_GLUE_HH
++#define CLICK_GLUE_HH
++// Removes many common #include <header>s and abstracts differences between
++// kernel and user space, and between operating systems.
++
++// HEADERS
++
++#if CLICK_LINUXMODULE
++
++# define _LOOSE_KERNEL_NAMES 1 /* define ino_t, off_t, etc. */
++# undef __KERNEL_STRICT_NAMES
++# ifndef __OPTIMIZE__
++# define __OPTIMIZE__ 1 /* get ntohl() macros. otherwise undefined. */
++# endif
++# include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++# ifdef WANT_MOD_USE_COUNT
++# define __NO_VERSION__
++# include <linux/module.h>
++# define HAVE_MOD_USE_COUNT 1
++# endif
++# include <linux/kernel.h>
++# include <linux/version.h>
++# include <linux/string.h>
++# include <linux/skbuff.h>
++# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
++# include <linux/malloc.h>
++# include <linux/vmalloc.h>
++# include <linux/interrupt.h>
++# else
++# include <linux/hardirq.h>
++# endif
++# include <linux/ctype.h>
++# include <linux/time.h>
++# include <linux/errno.h>
++CLICK_CXX_UNPROTECT
++# include <click/cxxunprotect.h>
++
++#elif CLICK_BSDMODULE
++
++# include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++# include <sys/ctype.h>
++# include <sys/systm.h>
++# include <sys/time.h>
++# include <sys/param.h>
++# include <sys/kernel.h>
++# include <sys/mbuf.h>
++# include <sys/malloc.h>
++# include <sys/libkern.h>
++# include <sys/proc.h>
++# include <sys/sysproto.h>
++CLICK_CXX_UNPROTECT
++# include <click/cxxunprotect.h>
++
++#else /* CLICK_USERLEVEL */
++
++# include <stdio.h>
++# include <stdlib.h>
++# include <string.h>
++# include <ctype.h>
++# include <errno.h>
++# include <limits.h>
++# include <sys/socket.h>
++# include <netinet/in.h>
++# include <sys/time.h>
++# ifdef CLICK_NS
++extern "C" int simclick_gettimeofday(struct timeval *);
++# endif
++
++#endif
++
++
++// DEBUGGING OUTPUT
++extern "C" {
++void click_chatter(const char *fmt, ...);
++}
++
++
++// DEBUG MALLOC
++
++#if CLICK_DMALLOC && (CLICK_LINUXMODULE || CLICK_BSDMODULE)
++extern uint32_t click_dmalloc_where;
++# define CLICK_DMALLOC_REG(s) do { const unsigned char *__str = reinterpret_cast<const unsigned char *>(s); click_dmalloc_where = (__str[0]<<24) | (__str[1]<<16) | (__str[2]<<8) | __str[3]; } while (0)
++#else
++# define CLICK_DMALLOC_REG(s)
++#endif
++
++
++// LALLOC
++
++#if CLICK_LINUXMODULE
++# define CLICK_LALLOC(size) (click_lalloc((size)))
++# define CLICK_LFREE(p, size) (click_lfree((p), (size)))
++extern "C" {
++void *click_lalloc(size_t size);
++void click_lfree(volatile void *p, size_t size);
++}
++#else
++# define CLICK_LALLOC(size) ((void *)(new uint8_t[(size)]))
++# define CLICK_LFREE(p, size) delete[] ((uint8_t *)(p))
++#endif
++
++
++// RANDOMNESS
++
++CLICK_DECLS
++extern void click_random_srandom(); // srand(), but use true randomness
++CLICK_ENDDECLS
++
++#if CLICK_LINUXMODULE
++extern "C" {
++extern uint32_t click_random_seed;
++extern void srandom(uint32_t);
++#define RAND_MAX 2147483647
++inline uint32_t
++random()
++{
++ click_random_seed = click_random_seed*69069L + 1;
++ return (click_random_seed ^ jiffies) & RAND_MAX;
++}
++}
++#endif
++
++
++// SORTING
++
++int click_qsort(void *base, size_t n, size_t size, int (*compar)(const void *, const void *, void *), void *thunk);
++int click_qsort(void *base, size_t n, size_t size, int (*compar)(const void *, const void *));
++
++
++// OTHER
++
++#if CLICK_LINUXMODULE
++
++// current processor
++# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
++# define click_current_processor() (current_thread_info()->cpu)
++# else
++# define click_current_processor() (current->processor)
++# endif
++
++// provide a definition for net_device for kernel compatibility
++# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
++typedef struct device net_device;
++# define dev_get_by_name dev_get
++# endif
++
++extern "C" {
++
++long strtol(const char *, char **, int);
++
++inline unsigned long
++strtoul(const char *nptr, char **endptr, int base)
++{
++ return simple_strtoul(nptr, endptr, base);
++}
++
++# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && __GNUC__ == 2 && __GNUC_MINOR__ == 96
++int click_strcmp(const char *, const char *);
++
++inline int
++strcmp(const char *a, const char *b)
++{
++ return click_strcmp(a, b);
++}
++# endif
++
++}
++
++#elif CLICK_BSDMODULE
++
++/* Char-type glue */
++
++# define _U 0x01 /* upper */
++# define _L 0x02 /* lower */
++# define _D 0x04 /* digit */
++# define _C 0x08 /* cntrl */
++# define _P 0x10 /* punct */
++# define _S 0x20 /* white space (space/lf/tab) */
++# define _X 0x40 /* hex digit */
++# define _SP 0x80 /* hard space (0x20) */
++
++extern unsigned char _ctype[];
++
++# define __ismask(x) (_ctype[(int)(unsigned char)(x)])
++# define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
++
++# define strchr(s, c) index(s, c)
++
++# define memmove(dst, src, len) bcopy((src), (dst), (len))
++
++typedef struct ifnet net_device;
++
++#else /* not CLICK_LINUXMODULE || CLICK_BSDMODULE */
++
++// provide a definition for net_device
++typedef struct device net_device;
++
++#endif /* CLICK_LINUXMODULE */
++
++
++// COMPILE-TIME ASSERTION CHECKING
++
++#define static_assert(c) switch (c) case 0: case (c):
++
++
++// TIMEVALS AND JIFFIES
++
++#if CLICK_LINUXMODULE
++# define click_gettimeofday(tvp) (do_gettimeofday(tvp))
++# define click_jiffies() ((unsigned)jiffies)
++# define CLICK_HZ HZ
++#elif CLICK_BSDMODULE
++# define click_gettimeofday(tvp) (getmicrotime(tvp))
++# define click_jiffies() ((unsigned)ticks)
++# define CLICK_HZ hz
++#else
++#ifndef CLICK_NS
++# define click_gettimeofday(tvp) (gettimeofday(tvp, (struct timezone *)0))
++#else
++# define click_gettimeofday(tvp) (simclick_gettimeofday(tvp))
++#endif
++CLICK_DECLS
++unsigned click_jiffies();
++CLICK_ENDDECLS
++# define CLICK_HZ 100
++#endif
++
++
++// TIMEVAL OPERATIONS
++
++#ifndef timercmp
++// Convenience macros for operations on timevals.
++// NOTE: 'timercmp' does not work for >= or <=.
++# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
++# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
++# define timercmp(a, b, CMP) \
++ (((a)->tv_sec == (b)->tv_sec) ? \
++ ((a)->tv_usec CMP (b)->tv_usec) : \
++ ((a)->tv_sec CMP (b)->tv_sec))
++#endif
++#ifndef timeradd
++# define timeradd(a, b, result) \
++ do { \
++ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
++ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
++ if ((result)->tv_usec >= 1000000) \
++ { \
++ ++(result)->tv_sec; \
++ (result)->tv_usec -= 1000000; \
++ } \
++ } while (0)
++#endif
++#ifndef timersub
++# define timersub(a, b, result) \
++ do { \
++ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
++ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
++ if ((result)->tv_usec < 0) { \
++ --(result)->tv_sec; \
++ (result)->tv_usec += 1000000; \
++ } \
++ } while (0)
++#endif
++
++#ifndef CLICK_TIMEVAL_OPERATORS
++
++inline struct timeval
++make_timeval(int sec, int usec)
++{
++ struct timeval tv;
++ tv.tv_sec = sec;
++ tv.tv_usec = usec;
++ return tv;
++}
++
++inline bool
++operator==(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec;
++}
++
++inline bool
++operator!=(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec != b.tv_sec || a.tv_usec != b.tv_usec;
++}
++
++inline bool
++operator<(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec < b.tv_usec);
++}
++
++inline bool
++operator<=(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec < b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec <= b.tv_usec);
++}
++
++inline bool
++operator>=(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec >= b.tv_usec);
++}
++
++inline bool
++operator>(const struct timeval &a, const struct timeval &b)
++{
++ return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec);
++}
++
++inline struct timeval &
++operator+=(struct timeval &a, const struct timeval &b)
++{
++ a.tv_sec += b.tv_sec;
++ a.tv_usec += b.tv_usec;
++ if (a.tv_usec >= 1000000) {
++ a.tv_sec++;
++ a.tv_usec -= 1000000;
++ }
++ return a;
++}
++
++inline struct timeval &
++operator-=(struct timeval &a, const struct timeval &b)
++{
++ a.tv_sec -= b.tv_sec;
++ a.tv_usec -= b.tv_usec;
++ if (a.tv_usec < 0) {
++ a.tv_sec--;
++ a.tv_usec += 1000000;
++ }
++ return a;
++}
++
++inline struct timeval
++operator+(struct timeval a, const struct timeval &b)
++{
++ a += b;
++ return a;
++}
++
++inline struct timeval
++operator-(struct timeval a, const struct timeval &b)
++{
++ a -= b;
++ return a;
++}
++
++#endif
++
++CLICK_DECLS
++class StringAccum;
++StringAccum &operator<<(StringAccum &, const struct timeval &);
++CLICK_ENDDECLS
++
++
++// BYTE ORDER
++
++#if CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++# define le16_to_cpu(x) (x)
++# define cpu_to_le16(x) (x)
++# define le32_to_cpu(x) (x)
++# define cpu_to_le32(x) (x)
++#elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN && defined(__APPLE__)
++# include <machine/byte_order.h>
++# define le16_to_cpu(x) NXSwapShort((x))
++# define cpu_to_le16(x) NXSwapShort((x))
++# define le32_to_cpu(x) NXSwapInt((x))
++# define cpu_to_le32(x) NXSwapInt((x))
++#elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN && HAVE_BYTESWAP_H
++# include <byteswap.h>
++# define le16_to_cpu(x) bswap_16((x))
++# define cpu_to_le16(x) bswap_16((x))
++# define le32_to_cpu(x) bswap_32((x))
++# define cpu_to_le32(x) bswap_32((x))
++#else
++/* leave them undefined */
++#endif
++
++
++// CYCLE COUNTS
++
++CLICK_DECLS
++
++#if HAVE_INT64_TYPES
++typedef uint64_t click_cycles_t;
++#else
++typedef uint32_t click_cycles_t;
++#endif
++
++inline click_cycles_t
++click_get_cycles()
++{
++#if CLICK_LINUXMODULE && HAVE_INT64_TYPES && __i386__
++ uint64_t x;
++ __asm__ __volatile__ ("rdtsc" : "=A" (x));
++ return x;
++#elif CLICK_LINUXMODULE && HAVE_INT64_TYPES && __x86_64__
++ uint32_t xlo, xhi;
++ __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
++ return xlo | (((uint64_t) xhi) << 32);
++#elif CLICK_LINUXMODULE && __i386__
++ uint32_t xlo, xhi;
++ __asm__ __volatile__ ("rdtsc" : "=a" (xlo), "=d" (xhi));
++ return xhi ? 0xFFFFFFFF : xlo;
++#elif CLICK_BSDMODULE
++ return rdtsc();
++#else
++ // add other architectures here
++ return 0;
++#endif
++}
++
++CLICK_ENDDECLS
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/handlercall.hh click-1.6.0-27/inst/include/click/handlercall.hh
+--- click-1.6.0/inst/include/click/handlercall.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/handlercall.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,527 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/handlercall.cc" -*-
++#ifndef CLICK_HANDLERCALL_HH
++#define CLICK_HANDLERCALL_HH
++#include <click/router.hh>
++CLICK_DECLS
++
++/** @brief Convenience class for calling handlers.
++ *
++ * The HandlerCall class simplifies the process of calling Click handlers.
++ * (The lower-level interface is the Handler class.) HandlerCall is used in
++ * two ways: (1) to call handlers immediately via static member functions,
++ * and (2) to set up future handler calls via HandlerCall objects. The
++ * immediate handler call functions take handler names as arguments and
++ * perform all necessary error checks before calling handlers, if any. A
++ * HandlerCall object encapsulates a handler reference (possibly including
++ * parameters), again automating all necessary error checks.
++ *
++ * <h2>Immediate Handler Calls</h2>
++ *
++ * This example code shows how to use the HandlerCall functions for calling
++ * handlers immediately.
++ *
++ * @code
++ * class YourElement { ...
++ * Element *_other;
++ * }
++ *
++ * void YourElement::function() {
++ * // Call _other's "config" read handler.
++ * String result = HandlerCall::call_read(_other, "config");
++ *
++ * // The same, providing an error handler to print errors.
++ * ErrorHandler *errh = ErrorHandler::default_handler();
++ * result = HandlerCall::call_read(_other, "config", errh);
++ * // (Each function takes an optional last argument of "errh".)
++ *
++ * // Call the "foo.config" read handler. Search for element "foo" in
++ * // the current compound element context.
++ * result = HandlerCall::call_read("foo.config", this);
++ *
++ * // Call the global "config" read handler for the current router.
++ * result = HandlerCall::call_read("config", this);
++ *
++ * // Call _other's "stop" write handler with empty value.
++ * int success = HandlerCall::call_write(_other, "stop");
++ *
++ * // Call _other's "config" write handler with value "blah".
++ * success = HandlerCall::call_write(_other, "config", "blah");
++ *
++ * // Call the "foo.config" write handler with value "blah".
++ * success = HandlerCall::call_write("foo.config blah", this);
++ * // Or, alternately:
++ * success = HandlerCall::call_write("foo.config", "blah", this);
++ * }
++ * @endcode
++ *
++ * <h2>HandlerCall Objects</h2>
++ *
++ * This example code shows how to use the HandlerCall objects to call
++ * handlers with simplified error checking.
++ *
++ * @code
++ * class YourElement { ...
++ * HandlerCall _read_call;
++ * HandlerCall _write_call;
++ * }
++ *
++ * YourElement::YourElement()
++ * : _read_call(), _write_call() {
++ * }
++ *
++ * int YourElement::configure(Vector<String> &conf, ErrorHandler *errh) {
++ * return cp_va_parse(conf, this, errh,
++ * cpOptional,
++ * cpHandlerCallRead, "read call", &_read_call,
++ * cpHandlerCallWrite, "write call", &_write_call,
++ * cpEnd);
++ * }
++ *
++ * int YourElement::initialize(ErrorHandler *errh) {
++ * if ((_read_call && _read_call.initialize_read(this, errh) < 0)
++ * || (_write_call && _write_call.initialize_write(this, errh) < 0))
++ * return -1;
++ * return 0;
++ * }
++ *
++ * void YourElement::function() {
++ * // call _read_call, print result
++ * if (_read_call)
++ * click_chatter("%s", _read_call.call_read());
++ *
++ * // call _write_call with error handler
++ * if (_write_call)
++ * _write_call.call_write(ErrorHandler::default_handler());
++ * }
++ * @endcode
++ *
++ * If usually your element's handler calls aren't used, you can save a small
++ * amount of space by using pointers to HandlerCall objects, as in this
++ * example. The cpHandlerCallPtrRead and cpHandlerCallPtrWrite types allow
++ * the _read_call and _write_call members to start out as null pointers.
++ *
++ * @code
++ * class YourElement { ...
++ * HandlerCall *_read_call;
++ * HandlerCall *_write_call;
++ * }
++ *
++ * YourElement::YourElement()
++ * : _read_call(0), _write_call(0) {
++ * }
++ *
++ * int YourElement::configure(Vector<String> &conf, ErrorHandler *errh) {
++ * return cp_va_parse(conf, this, errh,
++ * cpOptional,
++ * cpHandlerCallPtrRead, "read call", &_read_call,
++ * cpHandlerCallPtrWrite, "write call", &_write_call,
++ * cpEnd);
++ * }
++ *
++ * int YourElement::initialize(ErrorHandler *errh) {
++ * if ((_read_call && _read_call->initialize_read(this, errh) < 0)
++ * || (_write_call && _write_call->initialize_write(this, errh) < 0))
++ * return -1;
++ * return 0;
++ * }
++ *
++ * void YourElement::cleanup(CleanupStage) {
++ * delete _read_call;
++ * delete _write_call;
++ * }
++ *
++ * void YourElement::function() {
++ * // call _read_call, print result
++ * if (_read_call)
++ * click_chatter("%s", _read_call->call_read());
++ *
++ * // call _write_call with error handler
++ * if (_write_call)
++ * _write_call->call_write(ErrorHandler::default_handler());
++ * }
++ * @endcode
++ */
++class HandlerCall { public:
++
++ /** @name Immediate Handler Calls */
++ //@{
++ static String call_read(Element *e, const String &hname,
++ ErrorHandler *errh = 0);
++ static String call_read(const String &hdesc, Element *context,
++ ErrorHandler *errh = 0);
++ static int call_write(Element *e, const String &hname,
++ ErrorHandler *errh = 0);
++ static int call_write(Element *e, const String &hname, const String &value,
++ ErrorHandler *errh = 0);
++ static int call_write(const String &hdesc,
++ Element *context, ErrorHandler *errh = 0);
++ static int call_write(const String &hdesc, const String &value,
++ Element *context, ErrorHandler *errh = 0);
++ //@}
++
++
++
++ /** @brief Construct an empty HandlerCall.
++ *
++ * Any attempt to read, write, or initialize the HandlerCall will
++ * fail. */
++ HandlerCall()
++ : _e(0), _h(Handler::blank_handler()) {
++ }
++
++ /** @brief Construct a HandlerCall described by @a hdesc.
++ * @param hdesc handler description <tt>"[ename.]hname[ value]"</tt>
++ *
++ * Although the resulting HandlerCall isn't empty, it must be initialized
++ * before it can be used. It returns false for initialized(). The
++ * handler description is not checked for syntax errors, though;
++ * initialize() does that. */
++ HandlerCall(const String &hdesc)
++ : _e(reinterpret_cast<Element *>(4)), _h(Handler::blank_handler()),
++ _value(hdesc) {
++ }
++
++
++ enum Flags {
++ OP_READ = Handler::OP_READ, OP_WRITE = Handler::OP_WRITE,
++ PREINITIALIZE = 4
++ };
++
++ /** @brief Initialize the HandlerCall.
++ * @param flags zero or more of OP_READ, OP_WRITE, PREINITIALIZE
++ * @param context optional element context
++ * @param errh optional error handler
++ * @return 0 on success, negative on failure
++ *
++ * Initializes the HandlerCall object. The handler description supplied
++ * to the constructor is parsed and checked for syntax errors. Any
++ * element reference is looked up relative to @a context, if any. (For
++ * example, if @a hdesc was "x.config" and @a context's name is
++ * "aaa/bbb/ccc", this will search for elements named aaa/bbb/x, aaa/x,
++ * and finally x. If @a context is null, then the description must refer
++ * to a global handler.) If OP_READ is set in @a flags, then there
++ * must be a read handler named appropriately; if OP_WRITE is set,
++ * then there must be a write handler.
++ *
++ * Initialization fails if the handler description was bogus (for
++ * example, an empty string, or something like "*#!$&!(#&$."), if the
++ * named handler does not exist, if a read handler description has
++ * parameters but the read handler doesn't actually take parameters, and
++ * so forth. If @a errh is nonnull, errors are reported there. The
++ * HandlerCall becomes empty on failure: empty() will return true, and
++ * (bool) *this will return false. Future call_read() and call_write()
++ * attempts will correctly fail.
++ *
++ * If the PREINITIALIZE flag is set, the initialize function will check
++ * whether the router's handlers are ready (Router::handlers_ready()).
++ * If handlers are not ready, then initialize() will check for syntax
++ * errors, but not actually look up the handler (since we don't know yet
++ * whether or not the handler exists). Absent a syntax error,
++ * initialize() will return 0 for success even though the HandlerCall
++ * remains uninitialized. */
++ int initialize(int flags, Element *context, ErrorHandler *errh = 0);
++
++ /** @brief Initialize the HandlerCall for reading.
++ * @param context optional element context
++ * @param errh optional error handler
++ *
++ * Equivalent to @link initialize(int, Element*, ErrorHandler*)
++ * initialize@endlink(OP_READ, @a context, @a errh). */
++ inline int initialize_read(Element *context, ErrorHandler *errh = 0);
++
++ /** @brief Initialize the HandlerCall for writing.
++ * @param context optional element context
++ * @param errh optional error handler
++ *
++ * Equivalent to @link initialize(int, Element*, ErrorHandler*)
++ * initialize@endlink(OP_WRITE, @a context, @a errh). */
++ inline int initialize_write(Element *context, ErrorHandler *errh = 0);
++
++
++ typedef bool (HandlerCall::*unspecified_bool_type)() const;
++
++ /** @brief Test if HandlerCall is empty.
++ * @return True if HandlerCall is not empty, false otherwise.
++ *
++ * Valid HandlerCall objects have been successfully initialized. */
++ operator unspecified_bool_type() const {
++ return _h != Handler::blank_handler() || _e ? &HandlerCall::empty : 0;
++ }
++
++ /** @brief Test if HandlerCall is empty.
++ * @return True if HandlerCall is empty, false otherwise. */
++ bool empty() const {
++ return _h == Handler::blank_handler() && !_e;
++ }
++
++ /** @brief Test if HandlerCall is initialized.
++ * @return True if HandlerCall is initialized, false otherwise. */
++ bool initialized() const {
++ return _h != Handler::blank_handler();
++ }
++
++
++ /** @brief Call a read handler.
++ * @param errh optional error handler
++ * @return Read handler result.
++ *
++ * Fails and returns the empty string if this HandlerCall is invalid or
++ * not a read handler. If @a errh is nonnull, then any errors are
++ * reported there, whether from HandlerCall or the handler itself. */
++ inline String call_read(ErrorHandler *errh = 0) const;
++
++ /** @brief Call a write handler.
++ * @param errh optional error handler
++ * @return Write handler result.
++ *
++ * Fails and returns -EINVAL if this HandlerCall is invalid or not a
++ * write handler. If @a errh is nonnull, then any errors are reported
++ * there, whether from HandlerCall or the handler itself. */
++ inline int call_write(ErrorHandler *errh = 0) const;
++
++ /** @brief Call a write handler with an additional value.
++ * @param value_ext write value extension
++ * @param errh optional error handler
++ * @return Write handler result.
++ *
++ * The @a value_ext is appended to the write value before the handler is
++ * called. (For example, consider a handler with description "a.set
++ * value". call_write("foo") will call "a.set value foo".) Fails and
++ * returns -EINVAL if this HandlerCall is invalid or not a write handler.
++ * If @a errh is nonnull, then any errors are reported there, whether
++ * from HandlerCall or the handler itself. */
++ inline int call_write(const String &value_ext, ErrorHandler *errh = 0) const;
++
++
++ /** @brief Create and initialize a HandlerCall from @a hdesc.
++ * @param hcall stores the HandlerCall result
++ * @param hdesc handler description "[ename.]hname[ value]"
++ * @param flags initialization flags (OP_READ, OP_WRITE, PREINITIALIZE)
++ * @param context optional element context
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Creates a HandlerCall and initializes it. Behaves somewhat like:
++ *
++ * @code
++ * hcall = new HandlerCall(hdesc);
++ * return hcall->initialize(flags, context, errh);
++ * @endcode
++ *
++ * However, (1) if initialization fails, then @a hcall is untouched; and
++ * (2) if initialization succeeds and @a hcall is not null, then the
++ * existing HandlerCall is assigned so that it corresponds to the new one
++ * (no new memory allocations).
++ *
++ * If @a errh is nonnull, then any errors are reported there. */
++ static int reset(HandlerCall *&hcall, const String &hdesc, int flags,
++ Element *context, ErrorHandler *errh = 0);
++
++ /** @brief Create and initialize a HandlerCall on element @a e.
++ * @param hcall stores the HandlerCall result
++ * @param e relevant element, if any
++ * @param hname handler name
++ * @param value handler value
++ * @param flags initialization flags (OP_READ, OP_WRITE, PREINITIALIZE)
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Creates a HandlerCall and initializes it. Behaves analogously to
++ * reset(HandlerCall*&, const String&, int, Element*, ErrorHandler*). */
++ static int reset(HandlerCall *&hcall,
++ Element *e, const String &hname, const String &value,
++ int flags, ErrorHandler *errh = 0);
++
++
++ /** @brief Create and initialize a read HandlerCall from @a hdesc.
++ * @param hcall stores the HandlerCall result
++ * @param hdesc handler description "[ename.]hdesc[ param]"
++ * @param context optional element context
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Equivalent to
++ * @link reset(HandlerCall*&, const String&, int, Element*, ErrorHandler*) reset@endlink(@a hcall, @a hdesc, OP_READ, @a context, @a errh). */
++ static inline int reset_read(HandlerCall *&hcall, const String &hdesc,
++ Element *context, ErrorHandler *errh = 0);
++
++ /** @brief Create and initialize a read HandlerCall from @a hdesc.
++ * @param hcall stores the HandlerCall result
++ * @param e relevant element, if any
++ * @param hname handler name
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Equivalent to
++ * @link reset(HandlerCall*&, Element*, const String&, const String&, int, ErrorHandler*) reset@endlink(@a hcall, @a e, @a hname, String(), OP_READ, @a context, @a errh). */
++ static inline int reset_read(HandlerCall *&hcall,
++ Element *e, const String &hname,
++ ErrorHandler *errh = 0);
++
++ /** @brief Create and initialize a write HandlerCall from @a hdesc.
++ * @param hcall stores the HandlerCall result
++ * @param hdesc handler description "[ename.]hdesc[ value]"
++ * @param context optional element context
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Equivalent to
++ * @link reset(HandlerCall*&, const String&, int, Element*, ErrorHandler*) reset@endlink(@a hcall, @a hdesc, OP_WRITE, @a context, @a errh). */
++ static inline int reset_write(HandlerCall *&hcall, const String &hdesc,
++ Element *context, ErrorHandler *errh = 0);
++
++ /** @brief Create and initialize a read HandlerCall from @a hdesc.
++ * @param hcall stores the HandlerCall result
++ * @param e relevant element, if any
++ * @param hname handler name
++ * @param value write handler value
++ * @param errh optional error handler
++ * @return 0 on success, -EINVAL on failure
++ *
++ * Equivalent to
++ * @link reset(HandlerCall*&, Element*, const String&, const String&, int, ErrorHandler*) reset@endlink(@a hcall, @a e, @a hname, @ value, OP_WRITE, @a context, @a errh). */
++ static inline int reset_write(HandlerCall *&hcall,
++ Element *e, const String &hname,
++ const String &value = String(),
++ ErrorHandler *errh = 0);
++
++
++ /** @brief Return the Element corresponding to this HandlerCall.
++ *
++ * Returns null if invalid. A global handler may return some
++ * Router::root_element() or null. */
++ Element *element() const {
++ return _e;
++ }
++
++ /** @brief Return the Handler corresponding to this HandlerCall.
++ *
++ * Returns Handler::blank_handler() if invalid. */
++ const Handler *handler() const {
++ return _h;
++ }
++
++ /** @brief Return the write handler value and/or read handler parameters.
++ *
++ * Returns the empty string if invalid. */
++ const String &value() const {
++ return initialized() ? _value : String::empty_string();
++ }
++
++ /** @brief Sets the write handler value and/or read handler parameters.
++ * @param value new value and/or parameters
++ *
++ * Does nothing if invalid. */
++ void set_value(const String &value) {
++ if (initialized())
++ _value = value;
++ }
++
++ /** @brief Return a String that will parse into an equivalent HandlerCall.
++ *
++ * Will work even if the HandlerCall has not been initialized. */
++ String unparse() const;
++
++ /** @brief Make this HandlerCall empty.
++ *
++ * Subsequent attempts to read, write, or initialize the HandlerCall will
++ * fail. */
++ void clear() {
++ _e = 0;
++ _h = Handler::blank_handler();
++ _value = String();
++ }
++
++
++ /** @cond never */
++ enum { CHECK_READ = OP_READ, CHECK_WRITE = OP_WRITE };
++ /** @endcond never */
++
++ private:
++
++ Element *_e;
++ const Handler *_h;
++ String _value;
++
++ int parse(int flags, Element*, ErrorHandler*);
++ int assign(Element*, const String&, const String&, int flags, ErrorHandler*);
++
++};
++
++inline int
++HandlerCall::reset_read(HandlerCall*& hcall, const String& hdesc, Element* context, ErrorHandler* errh)
++{
++ return reset(hcall, hdesc, OP_READ, context, errh);
++}
++
++inline int
++HandlerCall::reset_write(HandlerCall*& hcall, const String& hdesc, Element* context, ErrorHandler* errh)
++{
++ return reset(hcall, hdesc, OP_WRITE, context, errh);
++}
++
++inline int
++HandlerCall::reset_read(HandlerCall*& hcall, Element* e, const String& hname, ErrorHandler* errh)
++{
++ return reset(hcall, e, hname, String(), OP_READ, errh);
++}
++
++inline int
++HandlerCall::reset_write(HandlerCall*& hcall, Element* e, const String& hname, const String& value, ErrorHandler* errh)
++{
++ return reset(hcall, e, hname, value, OP_WRITE, errh);
++}
++
++inline int
++HandlerCall::initialize_read(Element* context, ErrorHandler* errh)
++{
++ return initialize(OP_READ, context, errh);
++}
++
++inline int
++HandlerCall::initialize_write(Element* context, ErrorHandler* errh)
++{
++ return initialize(OP_WRITE, context, errh);
++}
++
++inline String
++HandlerCall::call_read(ErrorHandler *errh) const
++{
++ return _h->call_read(_e, _value, false, errh);
++}
++
++inline int
++HandlerCall::call_write(ErrorHandler *errh) const
++{
++ return _h->call_write(_value, _e, false, errh);
++}
++
++inline int
++HandlerCall::call_write(const String &value_ext, ErrorHandler *errh) const
++{
++ if (_value && value_ext)
++ return _h->call_write(_value + " " + value_ext, _e, false, errh);
++ else
++ return _h->call_write(_value ? _value : value_ext, _e, false, errh);
++}
++
++/** @brief Call a write handler specified by element and handler name.
++ * @param e relevant element, if any
++ * @param hname handler name
++ * @param errh optional error handler
++ * @return handler result, or -EINVAL on error
++ *
++ * Searches for a write handler named @a hname on element @a e. If the
++ * handler exists, calls it (with empty write value) and returns the result.
++ * If @a errh is nonnull, then errors, such as a missing handler or a
++ * read-only handler, are reported there. If @a e is some router's @link
++ * Router::root_element() root element@endlink, calls the global write
++ * handler named @a hname on that router. */
++inline int
++HandlerCall::call_write(Element *e, const String &hname, ErrorHandler *errh)
++{
++ return call_write(e, hname, String(), errh);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/hashcode.hh click-1.6.0-27/inst/include/click/hashcode.hh
+--- click-1.6.0/inst/include/click/hashcode.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/hashcode.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,73 @@
++#ifndef CLICK_HASHCODE_HH
++#define CLICK_HASHCODE_HH
++CLICK_DECLS
++
++template <typename T>
++inline size_t
++hashcode(const T &x)
++{
++ return x.hashcode();
++}
++
++inline size_t hashcode(char c) {
++ return c;
++}
++
++inline size_t hashcode(signed char c) {
++ return c;
++}
++
++inline size_t hashcode(unsigned char c) {
++ return c;
++}
++
++inline size_t hashcode(short s) {
++ return s;
++}
++
++inline size_t hashcode(unsigned short us) {
++ return us;
++}
++
++inline size_t hashcode(int i) {
++ return i;
++}
++
++inline size_t hashcode(unsigned u) {
++ return u;
++}
++
++inline size_t hashcode(long l) {
++ return l;
++}
++
++inline size_t hashcode(unsigned long ul) {
++ return ul;
++}
++
++#if HAVE_LONG_LONG
++inline size_t hashcode(long long ll) {
++ return ll;
++}
++
++inline size_t hashcode(unsigned long long ull) {
++ return ull;
++}
++#endif
++
++#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
++inline size_t hashcode(int64_t q) {
++ return q;
++}
++
++inline size_t hashcode(uint64_t uq) {
++ return uq;
++}
++#endif
++
++inline size_t hashcode(void *v) {
++ return reinterpret_cast<uintptr_t>(v) >> 3;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/hashmap.cc click-1.6.0-27/inst/include/click/hashmap.cc
+--- click-1.6.0/inst/include/click/hashmap.cc 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/hashmap.cc 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,23 @@
++/*
++ * hashmap.{cc,hh} -- a simple, stupid hash table template
++ * Eddie Kohler
++ *
++ * Copyright (c) 1999-2000 Massachusetts Institute of Technology
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file. These conditions include: you must
++ * preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding.
++ */
++
++#ifndef CLICK_HASHMAP_CC
++#define CLICK_HASHMAP_CC
++
++#include <click/bighashmap.cc>
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/hashmap.hh click-1.6.0-27/inst/include/click/hashmap.hh
+--- click-1.6.0/inst/include/click/hashmap.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/hashmap.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,7 @@
++#ifndef CLICK_HASHMAP_HH
++#define CLICK_HASHMAP_HH
++
++// This file is here for compatibility only.
++#include <click/bighashmap.hh>
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ino.hh click-1.6.0-27/inst/include/click/ino.hh
+--- click-1.6.0/inst/include/click/ino.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ino.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,128 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/ino.cc" -*-
++#ifndef CLICK_INO_HH
++#define CLICK_INO_HH
++#include <click/string.hh>
++CLICK_DECLS
++class Router;
++
++// NB: inode number 0 is reserved for the system.
++#define INO_DIRTYPE(ino) ((ino) >> 28)
++#define INO_ELEMENTNO(ino) ((int)((ino) & 0xFFFFU) - 1)
++#define INO_HANDLERNO(ino) ((((ino) & 0xFFFFU) ? 0 : Router::FIRST_GLOBAL_HANDLER) + (((ino) >> 16) & 0x7FFFU))
++#define INO_DT_H 0x1U /* handlers only */
++#define INO_DT_N 0x2U /* names */
++#define INO_DT_HN 0x3U /* handlers + names */
++#define INO_DT_GLOBAL 0x5U /* handlers + names + all #s */
++#define INO_DT_HAS_H(ino) (INO_DIRTYPE((ino)) & INO_DT_H)
++#define INO_DT_HAS_N(ino) (INO_DIRTYPE((ino)) >= INO_DT_N)
++#define INO_DT_HAS_U(ino) (INO_DIRTYPE((ino)) == INO_DT_GLOBAL)
++
++#define INO_MKHANDLER(e, hi) ((((hi) & 0x7FFFU) << 16) | (((e) + 1) & 0xFFFFU) | 0x80000000U)
++#define INO_MKHDIR(e) ((INO_DT_H << 28) | (((e) + 1) & 0xFFFFU))
++#define INO_MKNDIR(e) ((INO_DT_N << 28) | (((e) + 1) & 0xFFFFU))
++#define INO_MKHNDIR(e) ((INO_DT_HN << 28) | (((e) + 1) & 0xFFFFU))
++#define INO_GLOBALDIR (INO_DT_GLOBAL << 28)
++#define INO_ISHANDLER(ino) (((ino) & 0x80000000U) != 0)
++
++#define INO_DEBUG 0
++
++class ClickIno { public:
++
++ void initialize();
++ void cleanup();
++
++ uint32_t generation() const { return _generation; }
++
++ // All operations should be called with a configuration lock held.
++ inline int prepare(Router*, uint32_t);
++ int nlink(ino_t);
++ ino_t lookup(ino_t dir, const String& component);
++
++ // readdir doesn't handle '.' or '..'.
++ // It returns 0 for "filldir failed, have more", 1 for "out", <0 on error.
++ typedef bool (*filldir_t)(const char* name, int name_len, ino_t ino, int dirtype, uint32_t f_pos, void* thunk);
++ int readdir(ino_t dir, uint32_t& f_pos, filldir_t, void* thunk);
++
++#if INO_DEBUG
++ String info() const;
++#endif
++
++ struct Entry {
++ // Name of this entry.
++ String name;
++
++ // Corresponding eindex plus 1. Might be larger than the number of
++ // elements in the router, because of fake directories added for
++ // compound "elements".
++ uint16_t elementno_plus1;
++
++ // '_x[i].xindex' equals the index in _x of the entry for element
++ // number 'i - 1'.
++ uint16_t xindex;
++
++ // Number of child entries. 'name' is guaranteed to be a prefix of
++ // every child entry.
++ uint16_t skip;
++
++ // See enum below. X_FAKE is true on fake directories added for
++ // compound elements; X_HANDLER_CONFLICT is true if this element name
++ // conflicts with a handler; X_SUBDIR_CONFLICTS_CALCULATED is true if
++ // we've already checked for name conflicts on this element's
++ // children.
++ uint16_t flags;
++ };
++
++ private:
++
++ enum { X_FAKE = 1, X_HANDLER_CONFLICT = 2, X_SUBDIR_CONFLICTS_CALCULATED = 4 };
++
++ Entry* _x;
++ int _nentries;
++ int _cap;
++ Router* _router;
++ uint32_t _generation;
++
++ inline int xindex(int elementno) const;
++ inline int next_xindex(int elementno) const;
++ inline int elementno(int xindex) const;
++
++ int name_search(const String& n, int first_xi, int last_xi, int name_offset) const;
++
++ int grow(int min_size);
++ void calculate_handler_conflicts(int);
++ int true_prepare(Router*, uint32_t);
++
++};
++
++
++inline int
++ClickIno::prepare(Router* router, uint32_t generation)
++{
++ if (generation != _generation)
++ return true_prepare(router, generation);
++ else
++ return 0;
++}
++
++inline int
++ClickIno::xindex(int elementno) const
++{
++ assert(elementno >= -1 && elementno < _nentries - 1);
++ return _x[elementno + 1].xindex;
++}
++
++inline int
++ClickIno::next_xindex(int elementno) const
++{
++ int xi = xindex(elementno);
++ return xi + _x[xi].skip + 1;
++}
++
++inline int
++ClickIno::elementno(int xindex) const
++{
++ return _x[xindex].elementno_plus1 - 1;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/integers.hh click-1.6.0-27/inst/include/click/integers.hh
+--- click-1.6.0/inst/include/click/integers.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/integers.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,93 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/integers.cc" -*-
++#ifndef CLICK_INTEGERS_HH
++#define CLICK_INTEGERS_HH
++#if !HAVE___BUILTIN_FFS && HAVE_FFS && HAVE_STRINGS_H
++# include <strings.h>
++#endif
++CLICK_DECLS
++
++#ifdef HAVE_INT64_TYPES
++
++inline uint64_t htonq(uint64_t x) {
++ uint32_t hi = x >> 32;
++ uint32_t lo = x & 0xffffffff;
++ return (((uint64_t)htonl(lo)) << 32) | htonl(hi);
++}
++
++inline uint64_t ntohq(uint64_t x) {
++ uint32_t hi = x >> 32;
++ uint32_t lo = x & 0xffffffff;
++ return (((uint64_t)ntohl(lo)) << 32) | ntohl(hi);
++}
++
++#endif
++
++// MSB is bit #1
++#if HAVE___BUILTIN_CLZ && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_msb(uint32_t x) {
++ return (x ? __builtin_clz(x) + 1 : 0);
++}
++#else
++# define NEED_FFS_MSB_UINT32_T 1
++int ffs_msb(uint32_t);
++#endif
++
++#ifdef HAVE_INT64_TYPES
++# if HAVE___BUILTIN_CLZLL && SIZEOF_LONG_LONG == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_msb(uint64_t x) {
++ return (x ? __builtin_clzll(x) + 1 : 0);
++}
++# elif HAVE___BUILTIN_CLZL && SIZEOF_LONG == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_msb(uint64_t x) {
++ return (x ? __builtin_clzl(x) + 1 : 0);
++}
++# elif HAVE___BUILTIN_CLZ && SIZEOF_INT == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_msb(uint64_t x) {
++ return (x ? __builtin_clz(x) + 1 : 0);
++}
++# else
++# define NEED_FFS_MSB_UINT64_T 1
++int ffs_msb(uint64_t);
++# endif
++#endif
++
++// LSB is bit #1
++#if HAVE___BUILTIN_FFS && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_lsb(uint32_t x) {
++ return __builtin_ffs(x);
++}
++#elif HAVE_FFS && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_lsb(uint32_t x) {
++ return ffs(x);
++}
++#else
++# define NEED_FFS_LSB_UINT32_T 1
++int ffs_lsb(uint32_t);
++#endif
++
++#ifdef HAVE_INT64_TYPES
++# if HAVE___BUILTIN_FFSLL && SIZEOF_LONG_LONG == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_lsb(uint64_t x) {
++ return __builtin_ffsll(x);
++}
++# elif HAVE___BUILTIN_FFSL && SIZEOF_LONG == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_lsb(uint64_t x) {
++ return __builtin_ffsl(x);
++}
++# elif HAVE___BUILTIN_FFS && SIZEOF_INT == 8 && !HAVE_NO_INTEGER_BUILTINS
++inline int ffs_lsb(uint64_t x) {
++ return __builtin_ffs(x);
++}
++# else
++# define NEED_FFS_LSB_UINT64_T 1
++int ffs_lsb(uint64_t);
++# endif
++#endif
++
++uint32_t int_sqrt(uint32_t);
++#if HAVE_INT64_TYPES && !CLICK_LINUXMODULE
++uint64_t int_sqrt(uint64_t);
++#endif
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ip6address.hh click-1.6.0-27/inst/include/click/ip6address.hh
+--- click-1.6.0/inst/include/click/ip6address.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ip6address.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,191 @@
++// -*- related-file-name: "../../lib/ip6address.cc" -*-
++#ifndef CLICK_IP6ADDRESS_HH
++#define CLICK_IP6ADDRESS_HH
++#include <click/string.hh>
++#include <clicknet/ip6.h>
++#include <click/ipaddress.hh>
++#include <click/etheraddress.hh>
++CLICK_DECLS
++
++class IP6Address { public:
++
++ IP6Address();
++ explicit IP6Address(const unsigned char *);
++ explicit IP6Address(IPAddress ip);
++ explicit IP6Address(const String &); // "fec0:0:0:1::1"
++ explicit IP6Address(const click_in6_addr &a) : _addr(a) { }
++ static IP6Address make_prefix(int);
++
++ typedef size_t (IP6Address::*unspecified_bool_type)() const;
++ operator unspecified_bool_type() const;
++
++ operator const click_in6_addr &() const { return _addr; }
++ operator click_in6_addr &() { return _addr; }
++ const click_in6_addr &in6_addr() const { return _addr; }
++ click_in6_addr &in6_addr() { return _addr; }
++
++ unsigned char *data() { return &_addr.s6_addr[0]; }
++ const unsigned char *data() const { return &_addr.s6_addr[0]; }
++ unsigned *data32() { return &_addr.s6_addr32[0]; }
++ const unsigned *data32() const { return &_addr.s6_addr32[0]; }
++
++ inline size_t hashcode() const;
++
++ int mask_to_prefix_len() const;
++ bool matches_prefix(const IP6Address &addr, const IP6Address &mask) const;
++ bool mask_as_specific(const IP6Address &) const;
++
++ bool ether_address(EtherAddress &) const;
++ bool ip4_address(IPAddress &) const;
++
++ // bool operator==(const IP6Address &, const IP6Address &);
++ // bool operator!=(const IP6Address &, const IP6Address &);
++
++ // IP6Address operator&(const IP6Address &, const IP6Address &);
++ // IP6Address operator|(const IP6Address &, const IP6Address &);
++ // IP6Address operator~(const IP6Address &);
++
++ IP6Address &operator&=(const IP6Address &);
++ IP6Address &operator&=(const click_in6_addr &);
++ IP6Address &operator|=(const IP6Address &);
++ IP6Address &operator|=(const click_in6_addr &);
++
++ IP6Address &operator=(const click_in6_addr &);
++
++ String unparse() const;
++ String unparse_expanded() const;
++
++ operator String() const { return unparse(); }
++ String s() const { return unparse(); }
++
++ private:
++
++ click_in6_addr _addr;
++
++};
++
++inline
++IP6Address::operator unspecified_bool_type() const
++{
++ const unsigned *ai = data32();
++ return ai[0] || ai[1] || ai[2] || ai[3] ? &IP6Address::hashcode : 0;
++}
++
++inline bool
++operator==(const IP6Address &a, const IP6Address &b)
++{
++ const unsigned *ai = a.data32(), *bi = b.data32();
++ return ai[0] == bi[0] && ai[1] == bi[1] && ai[2] == bi[2] && ai[3] == bi[3];
++}
++
++inline bool
++operator!=(const IP6Address &a, const IP6Address &b)
++{
++ const unsigned *ai = a.data32(), *bi = b.data32();
++ return ai[0] != bi[0] || ai[1] != bi[1] || ai[2] != bi[2] || ai[3] != bi[3];
++}
++
++class StringAccum;
++StringAccum &operator<<(StringAccum &, const IP6Address &);
++
++inline bool
++IP6Address::matches_prefix(const IP6Address &addr, const IP6Address &mask) const
++{
++ const unsigned *xi = data32(), *ai = addr.data32(), *mi = mask.data32();
++ return ((xi[0] ^ ai[0]) & mi[0]) == 0
++ && ((xi[1] ^ ai[1]) & mi[1]) == 0
++ && ((xi[2] ^ ai[2]) & mi[2]) == 0
++ && ((xi[3] ^ ai[3]) & mi[3]) == 0;
++}
++
++inline bool
++IP6Address::mask_as_specific(const IP6Address &mask) const
++{
++ const unsigned *xi = data32(), *mi = mask.data32();
++ return ((xi[0] & mi[0]) == mi[0] && (xi[1] & mi[1]) == mi[1]
++ && (xi[2] & mi[2]) == mi[2] && (xi[3] & mi[3]) == mi[3]);
++}
++
++inline IP6Address &
++IP6Address::operator&=(const IP6Address &b)
++{
++ unsigned *ai = data32();
++ const unsigned *bi = b.data32();
++ ai[0] &= bi[0]; ai[1] &= bi[1]; ai[2] &= bi[2]; ai[3] &= bi[3];
++ return *this;
++}
++
++inline IP6Address &
++IP6Address::operator&=(const click_in6_addr &b)
++{
++ unsigned *ai = data32();
++ const unsigned *bi = b.s6_addr32;
++ ai[0] &= bi[0]; ai[1] &= bi[1]; ai[2] &= bi[2]; ai[3] &= bi[3];
++ return *this;
++}
++
++inline IP6Address &
++IP6Address::operator|=(const IP6Address &b)
++{
++ unsigned *ai = data32();
++ const unsigned *bi = b.data32();
++ ai[0] |= bi[0]; ai[1] |= bi[1]; ai[2] |= bi[2]; ai[3] |= bi[3];
++ return *this;
++}
++
++inline IP6Address &
++IP6Address::operator|=(const click_in6_addr &b)
++{
++ unsigned *ai = data32();
++ const unsigned *bi = b.s6_addr32;
++ ai[0] |= bi[0]; ai[1] |= bi[1]; ai[2] |= bi[2]; ai[3] |= bi[3];
++ return *this;
++}
++
++inline IP6Address
++operator&(const IP6Address &a, const IP6Address &b)
++{
++ const unsigned *ai = a.data32(), *bi = b.data32();
++ IP6Address result;
++ unsigned *ri = result.data32();
++ ri[0] = ai[0] & bi[0]; ri[1] = ai[1] & bi[1];
++ ri[2] = ai[2] & bi[2]; ri[3] = ai[3] & bi[3];
++ return result;
++}
++
++inline IP6Address
++operator|(const IP6Address &a, const IP6Address &b)
++{
++ const unsigned *ai = a.data32(), *bi = b.data32();
++ IP6Address result;
++ unsigned *ri = result.data32();
++ ri[0] = ai[0] | bi[0]; ri[1] = ai[1] | bi[1];
++ ri[2] = ai[2] | bi[2]; ri[3] = ai[3] | bi[3];
++ return result;
++}
++
++inline IP6Address
++operator~(const IP6Address &a)
++{
++ const unsigned *ai = a.data32();
++ IP6Address result;
++ unsigned *ri = result.data32();
++ ri[0] = ~ai[0]; ri[1] = ~ai[1]; ri[2] = ~ai[2]; ri[3] = ~ai[3];
++ return result;
++}
++
++inline IP6Address &
++IP6Address::operator=(const click_in6_addr &a)
++{
++ _addr = a;
++ return *this;
++}
++
++inline size_t
++IP6Address::hashcode() const
++{
++ return data32()[3];
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ip6flowid.hh click-1.6.0-27/inst/include/click/ip6flowid.hh
+--- click-1.6.0/inst/include/click/ip6flowid.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ip6flowid.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,105 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/ip6flowid.cc" -*-
++#ifndef CLICK_IP6FLOWID_HH
++#define CLICK_IP6FLOWID_HH
++#include <click/ip6address.hh>
++#include <click/hashcode.hh>
++CLICK_DECLS
++class Packet;
++
++class IP6FlowID { public:
++
++ inline IP6FlowID();
++ inline IP6FlowID(const IP6Address &, uint16_t, const IP6Address &, uint16_t);
++ explicit IP6FlowID(Packet *);
++
++ typedef const IP6Address &(IP6FlowID::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++
++ const IP6Address &saddr() const { return _saddr; }
++ const IP6Address &daddr() const { return _daddr; }
++ uint16_t sport() const { return _sport; }
++ uint16_t dport() const { return _dport; }
++
++ void set_saddr(const IP6Address &a) { _saddr = a; }
++ void set_daddr(const IP6Address &a) { _daddr = a; }
++ void set_sport(uint16_t p) { _sport = p; }
++ void set_dport(uint16_t p) { _dport = p; }
++
++ inline IP6FlowID rev() const;
++
++ inline size_t hashcode() const;
++
++ String unparse() const;
++ operator String() const { return unparse(); }
++ String s() const { return unparse(); }
++
++ protected:
++
++ // note: several functions depend on this field order!
++ IP6Address _saddr;
++ IP6Address _daddr;
++ uint16_t _sport; // network byte order
++ uint16_t _dport; // network byte order
++
++};
++
++inline
++IP6FlowID::IP6FlowID()
++ : _saddr(), _daddr(), _sport(0), _dport(0)
++{
++}
++
++inline
++IP6FlowID::IP6FlowID(const IP6Address &saddr, uint16_t sport,
++ const IP6Address &daddr, uint16_t dport)
++ : _saddr(saddr), _daddr(daddr), _sport(sport), _dport(dport)
++{
++}
++
++inline
++IP6FlowID::operator unspecified_bool_type() const
++{
++ return _saddr || _daddr ? &IP6FlowID::saddr : 0;
++}
++
++inline IP6FlowID
++IP6FlowID::rev() const
++{
++ return IP6FlowID(_daddr, _dport, _saddr, _sport);
++}
++
++
++#define ROT(v, r) ((v)<<(r) | ((unsigned)(v))>>(32-(r)))
++
++#if 0
++inline size_t
++IP6FlowID::hashcode() const
++{
++ return (ROT(_saddr.hashcode(), 13)
++ ^ ROT(_daddr.hashcode(), 23) ^ (_sport | (_dport<<16)));
++}
++#endif
++
++inline size_t IP6FlowID::hashcode() const
++{
++ // more complicated hashcode, but causes less collision
++ uint16_t s = ntohs(sport());
++ uint16_t d = ntohs(dport());
++ size_t sx = CLICK_NAME(hashcode)(saddr());
++ size_t dx = CLICK_NAME(hashcode)(daddr());
++ return (ROT(sx, s%16)
++ ^ ROT(dx, 31-d%16))
++ ^ ((d << 16) | s);
++}
++
++#undef ROT
++
++inline bool
++operator==(const IP6FlowID &a, const IP6FlowID &b)
++{
++ return a.dport() == b.dport() && a.sport() == b.sport()
++ && a.daddr() == b.daddr() && a.saddr() == b.saddr();
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ip6table.hh click-1.6.0-27/inst/include/click/ip6table.hh
+--- click-1.6.0/inst/include/click/ip6table.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ip6table.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,39 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/ip6table.cc" -*-
++#ifndef CLICK_IP6TABLE_HH
++#define CLICK_IP6TABLE_HH
++#include <click/glue.hh>
++#include <click/vector.hh>
++#include <click/ip6address.hh>
++CLICK_DECLS
++
++// IP6 routing table.
++// Lookup by longest prefix.
++// Each entry contains a gateway and an output index.
++
++class IP6Table { public:
++
++ IP6Table();
++ ~IP6Table();
++
++ bool lookup(const IP6Address &dst, IP6Address &gw, int &index) const;
++
++ void add(const IP6Address &dst, const IP6Address &mask, const IP6Address &gw, int index);
++ void del(const IP6Address &dst, const IP6Address &mask);
++ void clear() { _v.clear(); }
++ String dump();
++
++ private:
++
++ struct Entry {
++ IP6Address _dst;
++ IP6Address _mask;
++ IP6Address _gw;
++ int _index;
++ int _valid;
++ };
++ Vector<Entry> _v;
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ipaddress.hh click-1.6.0-27/inst/include/click/ipaddress.hh
+--- click-1.6.0/inst/include/click/ipaddress.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ipaddress.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,342 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/ipaddress.cc" -*-
++#ifndef CLICK_IPADDRESS_HH
++#define CLICK_IPADDRESS_HH
++#include <click/string.hh>
++#include <click/glue.hh>
++#include <clicknet/ip.h>
++CLICK_DECLS
++class StringAccum;
++
++class IPAddress { public:
++
++ inline IPAddress();
++ explicit IPAddress(const unsigned char*);
++ inline IPAddress(unsigned int); // network byte order IP address
++ inline explicit IPAddress(int); // network byte order IP address
++ inline explicit IPAddress(unsigned long); // network byte order IP address
++ inline explicit IPAddress(long); // network byte order IP address
++ explicit IPAddress(const String&); // "18.26.4.99"
++ inline IPAddress(struct in_addr);
++ static IPAddress make_prefix(int prefix_len);
++
++ typedef uint32_t (IPAddress::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++
++ inline uint32_t addr() const;
++ inline operator uint32_t() const;
++
++ inline struct in_addr in_addr() const;
++ inline operator struct in_addr() const;
++
++ inline unsigned char* data();
++ inline const unsigned char* data() const;
++
++ inline size_t hashcode() const;
++
++ int mask_to_prefix_len() const;
++ inline bool matches_prefix(IPAddress addr, IPAddress mask) const;
++ inline bool mask_as_specific(IPAddress mask) const;
++ inline bool mask_more_specific(IPAddress mask) const;
++
++ // bool operator==(IPAddress, IPAddress);
++ // bool operator==(IPAddress, uint32_t);
++ // bool operator!=(IPAddress, IPAddress);
++ // bool operator!=(IPAddress, uint32_t);
++
++ // IPAddress operator&(IPAddress, IPAddress);
++ // IPAddress operator|(IPAddress, IPAddress);
++ // IPAddress operator^(IPAddress, IPAddress);
++ // IPAddress operator~(IPAddress);
++
++ inline IPAddress& operator&=(IPAddress);
++ inline IPAddress& operator|=(IPAddress);
++ inline IPAddress& operator^=(IPAddress);
++
++ String unparse() const;
++ String unparse_mask() const;
++ String unparse_with_mask(IPAddress) const;
++
++ inline String s() const;
++ inline operator String() const;
++
++ private:
++
++ uint32_t _addr;
++
++};
++
++/** @brief Constructs an IPAddress equal to 0.0.0.0. */
++inline
++IPAddress::IPAddress()
++ : _addr(0)
++{
++}
++
++/** @brief Constructs an IPAddress from an integer in network byte order.
++ @param a the address, in network byte order */
++inline
++IPAddress::IPAddress(unsigned int a)
++ : _addr(a)
++{
++}
++
++/** @brief Constructs an IPAddress from an integer in network byte order.
++ @param a the address, in network byte order */
++inline
++IPAddress::IPAddress(int a)
++ : _addr(a)
++{
++}
++
++/** @brief Constructs an IPAddress from an integer in network byte order.
++ @param a the address, in network byte order */
++inline
++IPAddress::IPAddress(unsigned long a)
++ : _addr(a)
++{
++}
++
++/** @brief Constructs an IPAddress from an integer in network byte order.
++ @param a the address, in network byte order */
++inline
++IPAddress::IPAddress(long a)
++ : _addr(a)
++{
++}
++
++/** @brief Constructs an IPAddress from a struct in_addr.
++ @param ina the address */
++inline
++IPAddress::IPAddress(struct in_addr ina)
++ : _addr(ina.s_addr)
++{
++}
++
++/** @brief Returns true iff the address is not 0.0.0.0. */
++inline
++IPAddress::operator unspecified_bool_type() const
++{
++ return _addr != 0 ? &IPAddress::addr : 0;
++}
++
++/** @brief Returns the address as a uint32_t in network byte order. */
++inline
++IPAddress::operator uint32_t() const
++{
++ return _addr;
++}
++
++/** @brief Returns the address as a uint32_t in network byte order. */
++inline uint32_t
++IPAddress::addr() const
++{
++ return _addr;
++}
++
++/** @relates IPAddress
++ @brief Compares two IPAddress objects for equality. */
++inline bool
++operator==(IPAddress a, IPAddress b)
++{
++ return a.addr() == b.addr();
++}
++
++/** @relates IPAddress
++ @brief Compares an IPAddress with a network-byte-order address value for
++ equality.
++ @param a an address
++ @param b an address value in network byte order */
++inline bool
++operator==(IPAddress a, uint32_t b)
++{
++ return a.addr() == b;
++}
++
++/** @relates IPAddress
++ @brief Compares two IPAddress objects for inequality. */
++inline bool
++operator!=(IPAddress a, IPAddress b)
++{
++ return a.addr() != b.addr();
++}
++
++/** @relates IPAddress
++ @brief Compares an IPAddress with a network-byte-order address value for
++ inequality.
++ @param a an address
++ @param b an address value in network byte order */
++inline bool
++operator!=(IPAddress a, uint32_t b)
++{
++ return a.addr() != b;
++}
++
++/** @brief Returns a pointer to the address data.
++
++ Since the address is stored in network byte order, data()[0] is the top 8
++ bits of the address, data()[1] the next 8 bits, and so forth. */
++inline const unsigned char*
++IPAddress::data() const
++{
++ return reinterpret_cast<const unsigned char*>(&_addr);
++}
++
++/** @brief Returns a pointer to the address data.
++
++ Since the address is stored in network byte order, data()[0] is the top 8
++ bits of the address, data()[1] the next 8 bits, and so forth. */
++inline unsigned char*
++IPAddress::data()
++{
++ return reinterpret_cast<unsigned char*>(&_addr);
++}
++
++/** @brief Returns a struct in_addr corresponding to the address. */
++inline struct in_addr
++IPAddress::in_addr() const
++{
++ struct in_addr ia;
++ ia.s_addr = _addr;
++ return ia;
++}
++
++/** @brief Returns a struct in_addr corresponding to the address. */
++inline
++IPAddress::operator struct in_addr() const
++{
++ return in_addr();
++}
++
++StringAccum& operator<<(StringAccum&, IPAddress);
++
++/** @brief Returns true iff this address matches the address prefix
++ @a addr/@a mask.
++ @param addr prefix address
++ @param mask prefix mask
++
++ Equivalent to (@a addr & @a mask) == (*this & @a mask). The prefix address
++ @a addr may be nonzero outside the @a mask. */
++inline bool
++IPAddress::matches_prefix(IPAddress addr, IPAddress mask) const
++{
++ return ((this->addr() ^ addr.addr()) & mask.addr()) == 0;
++}
++
++/** @brief Returns true iff this address, considered as a prefix mask, is at
++ least as specific as @a mask.
++ @param mask prefix mask
++
++ Longer prefix masks are more specific than shorter ones. For example,
++ make_prefix(20).mask_as_specific(make_prefix(18)) is true, but
++ make_prefix(10).mask_as_specific(make_prefix(14)) is false.
++
++ Equivalent to (*this & @a mask) == @a mask. */
++inline bool
++IPAddress::mask_as_specific(IPAddress mask) const
++{
++ return (addr() & mask.addr()) == mask.addr();
++}
++
++/** @brief Returns true iff this prefix mask is more specific than @a mask.
++ @param mask prefix mask
++
++ Both this address and @a mask must be prefix masks -- i.e.,
++ mask_to_prefix_len() returns 0-32. Returns true iff this address contains
++ a longer prefix than @a mask. For example,
++ make_prefix(20).mask_more_specific(make_prefix(18)) is true, but
++ make_prefix(20).mask_more_specific(make_prefix(20)) is false. */
++inline bool
++IPAddress::mask_more_specific(IPAddress mask) const
++{
++ return ((addr() << 1) & mask.addr()) == mask.addr();
++}
++
++/** @relates IPAddress
++ @brief Calculates the IPAddress representing the bitwise-and of @a a and
++ @a b. */
++inline IPAddress
++operator&(IPAddress a, IPAddress b)
++{
++ return IPAddress(a.addr() & b.addr());
++}
++
++/** @brief Assign this address to its bitwise-and with @a a. */
++inline IPAddress&
++IPAddress::operator&=(IPAddress a)
++{
++ _addr &= a._addr;
++ return *this;
++}
++
++/** @relates IPAddress
++ @brief Calculates the IPAddress representing the bitwise-or of @a a and
++ @a b. */
++inline IPAddress
++operator|(IPAddress a, IPAddress b)
++{
++ return IPAddress(a.addr() | b.addr());
++}
++
++/** @brief Assign this address to its bitwise-or with @a a. */
++inline IPAddress&
++IPAddress::operator|=(IPAddress a)
++{
++ _addr |= a._addr;
++ return *this;
++}
++
++/** @relates IPAddress
++ @brief Calculates the IPAddress representing the bitwise-xor of @a a and
++ @a b. */
++inline IPAddress
++operator^(IPAddress a, IPAddress b)
++{
++ return IPAddress(a.addr() ^ b.addr());
++}
++
++/** @brief Assign this address to its bitwise-xor with @a a. */
++inline IPAddress&
++IPAddress::operator^=(IPAddress a)
++{
++ _addr ^= a._addr;
++ return *this;
++}
++
++/** @relates IPAddress
++ @brief Calculates the IPAddress representing the bitwise complement
++ of @a a. */
++inline IPAddress
++operator~(IPAddress a)
++{
++ return IPAddress(~a.addr());
++}
++
++/** @brief Hash function.
++ * @return The hash value of this IPAddress.
++ *
++ * Equal IPAddress objects always have equal hashcode() values.
++ */
++inline size_t
++IPAddress::hashcode() const
++{
++ return addr();
++}
++
++/** @brief Unparses this address into a dotted-quad format String.
++ @sa unparse */
++inline
++IPAddress::operator String() const
++{
++ return unparse();
++}
++
++/** @brief Unparses this address into a dotted-quad format String.
++ @sa unparse */
++inline String
++IPAddress::s() const
++{
++ return unparse();
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/ipflowid.hh click-1.6.0-27/inst/include/click/ipflowid.hh
+--- click-1.6.0/inst/include/click/ipflowid.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/ipflowid.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,106 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/ipflowid.cc" -*-
++#ifndef CLICK_IPFLOWID_HH
++#define CLICK_IPFLOWID_HH
++#include <click/ipaddress.hh>
++#include <click/hashcode.hh>
++CLICK_DECLS
++class Packet;
++
++class IPFlowID { public:
++
++ IPFlowID();
++ IPFlowID(IPAddress, uint16_t, IPAddress, uint16_t);
++ explicit IPFlowID(const Packet *); // reads ip_header and udp_header
++ explicit IPFlowID(const click_ip *); // also reads adjacent TCP/UDP header
++
++ typedef IPAddress (IPFlowID::*unspecified_bool_type)() const;
++ operator unspecified_bool_type() const;
++
++ IPAddress saddr() const { return _saddr; }
++ IPAddress daddr() const { return _daddr; }
++ uint16_t sport() const { return _sport; }
++ uint16_t dport() const { return _dport; }
++
++ void set_saddr(IPAddress a) { _saddr = a; }
++ void set_daddr(IPAddress a) { _daddr = a; }
++ void set_sport(uint16_t p) { _sport = p; } // network order
++ void set_dport(uint16_t p) { _dport = p; } // network order
++
++ IPFlowID rev() const;
++
++ inline size_t hashcode() const;
++
++ String unparse() const;
++ operator String() const { return unparse(); }
++ String s() const { return unparse(); }
++
++ protected:
++
++ // note: several functions depend on this field order!
++ IPAddress _saddr;
++ IPAddress _daddr;
++ uint16_t _sport; // network byte order
++ uint16_t _dport; // network byte order
++
++};
++
++inline
++IPFlowID::IPFlowID()
++ : _saddr(), _daddr(), _sport(0), _dport(0)
++{
++}
++
++inline
++IPFlowID::IPFlowID(IPAddress saddr, uint16_t sport,
++ IPAddress daddr, uint16_t dport)
++ : _saddr(saddr), _daddr(daddr), _sport(sport), _dport(dport)
++{
++}
++
++inline
++IPFlowID::operator unspecified_bool_type() const
++{
++ return _saddr || _daddr ? &IPFlowID::saddr : 0;
++}
++
++inline IPFlowID
++IPFlowID::rev() const
++{
++ return IPFlowID(_daddr, _dport, _saddr, _sport);
++}
++
++
++#define ROT(v, r) ((v)<<(r) | ((unsigned)(v))>>(32-(r)))
++
++inline size_t IPFlowID::hashcode() const
++{
++ // more complicated hashcode, but causes less collision
++ uint16_t s = ntohs(sport());
++ uint16_t d = ntohs(dport());
++ size_t sx = CLICK_NAME(hashcode)(saddr());
++ size_t dx = CLICK_NAME(hashcode)(daddr());
++ return (ROT(sx, s%16)
++ ^ ROT(dx, 31-d%16))
++ ^ ((d << 16) | s);
++}
++
++#undef ROT
++
++inline bool
++operator==(const IPFlowID &a, const IPFlowID &b)
++{
++ return a.dport() == b.dport() && a.sport() == b.sport()
++ && a.daddr() == b.daddr() && a.saddr() == b.saddr();
++}
++
++inline bool
++operator!=(const IPFlowID &a, const IPFlowID &b)
++{
++ return a.dport() != b.dport() || a.sport() != b.sport()
++ || a.daddr() != b.daddr() || a.saddr() != b.saddr();
++}
++
++StringAccum &operator<<(StringAccum &, const IPFlowID &);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/iptable.hh click-1.6.0-27/inst/include/click/iptable.hh
+--- click-1.6.0/inst/include/click/iptable.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/iptable.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,38 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/iptable.cc" -*-
++#ifndef CLICK_IPTABLE_HH
++#define CLICK_IPTABLE_HH
++#include <click/glue.hh>
++#include <click/vector.hh>
++#include <click/ipaddress.hh>
++CLICK_DECLS
++
++// IP routing table.
++// Lookup by longest prefix.
++// Each entry contains a gateway and an output index.
++
++class IPTable { public:
++
++ IPTable();
++ ~IPTable();
++
++ bool lookup(IPAddress dst, IPAddress &gw, int &index) const;
++
++ void add(IPAddress dst, IPAddress mask, IPAddress gw, int index);
++ void del(IPAddress dst, IPAddress mask);
++ void clear() { _v.clear(); }
++
++ private:
++
++ struct Entry {
++ IPAddress dst;
++ IPAddress mask;
++ IPAddress gw;
++ int index;
++ bool valid() const { return mask || !dst; }
++ };
++ Vector<Entry> _v;
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/lexer.hh click-1.6.0-27/inst/include/click/lexer.hh
+--- click-1.6.0/inst/include/click/lexer.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/lexer.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,194 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/lexer.cc" -*-
++#ifndef CLICK_LEXER_HH
++#define CLICK_LEXER_HH
++#include <click/hashmap.hh>
++#include <click/router.hh>
++#include <click/glue.hh>
++#include <click/variableenv.hh>
++CLICK_DECLS
++class LexerExtra;
++
++enum Lexemes {
++ lexEOF = 0,
++ lexIdent = 256,
++ lexVariable,
++ lexArrow,
++ lex2Colon,
++ lex2Bar,
++ lex3Dot,
++ lexTunnel,
++ lexElementclass,
++ lexRequire,
++ lexDefine
++};
++
++class Lexeme { public:
++
++ Lexeme() : _kind(lexEOF) { }
++ Lexeme(int k, const String &s) : _kind(k), _s(s) { }
++
++ int kind() const { return _kind; }
++ bool is(int k) const { return _kind == k; }
++
++ const String &string() const { return _s; }
++ String &string() { return _s; }
++
++ private:
++
++ int _kind;
++ String _s;
++
++};
++
++class Lexer { public:
++
++ enum { TUNNEL_TYPE = 0, ERROR_TYPE = 1 };
++
++ class TunnelEnd;
++ class Compound;
++ typedef Router::Hookup Hookup;
++
++ Lexer();
++ virtual ~Lexer();
++
++ int begin_parse(const String &data, const String &filename, LexerExtra *, ErrorHandler * = 0);
++ void end_parse(int);
++
++ VariableEnvironment &global_scope() { return _global_scope; }
++ ErrorHandler *errh() const { return _errh; }
++
++ String remaining_text() const;
++ void set_remaining_text(const String &);
++
++ const Lexeme &lex();
++ void unlex(const Lexeme &);
++ String lex_config();
++ String landmark() const;
++
++ bool expect(int, bool report_error = true);
++
++ typedef Element *(*ElementFactory)(uintptr_t);
++#ifdef CLICK_LINUXMODULE
++ int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, struct module *module, bool scoped = false);
++#else
++ int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, bool scoped = false);
++#endif
++ int element_type(const String &) const;
++ int force_element_type(String);
++
++ void element_type_names(Vector<String> &) const;
++
++ int remove_element_type(int t) { return remove_element_type(t, 0); }
++
++ void connect(int element1, int port1, int element2, int port2);
++ String element_name(int) const;
++ String element_landmark(int) const;
++
++ void add_tunnel(String, String);
++
++ bool yport(int &port);
++ bool yelement(int &element, bool comma_ok);
++ void ydeclaration(const String &first_element = String());
++ bool yconnection();
++ void yelementclass();
++ void ytunnel();
++ void ycompound_arguments(Compound *);
++ int ycompound(String name = String());
++ void yrequire();
++ void yvar();
++ bool ystatement(bool nested = false);
++
++ Router *create_router(Master *);
++
++ private:
++
++ // lexer
++ String _big_string;
++
++ const char *_data;
++ const char *_end;
++ const char *_pos;
++
++ String _filename;
++ String _original_filename;
++ unsigned _lineno;
++ LexerExtra *_lextra;
++
++ const char *skip_line(const char *);
++ const char *skip_slash_star(const char *);
++ const char *skip_backslash_angle(const char *);
++ const char *skip_quote(const char *, char);
++ const char *process_line_directive(const char *);
++ Lexeme next_lexeme();
++ static String lexeme_string(int);
++
++ // parser
++ enum { TCIRCLE_SIZE = 8 };
++ Lexeme _tcircle[TCIRCLE_SIZE];
++ int _tpos;
++ int _tfull;
++
++ // element types
++ struct ElementType {
++ ElementFactory factory;
++ uintptr_t thunk;
++#ifdef CLICK_LINUXMODULE
++ struct module *module;
++#endif
++ String name;
++ int next;
++ };
++ HashMap<String, int> _element_type_map;
++ Vector<ElementType> _element_types;
++ enum { ET_SCOPED = 0x80000000, ET_TMASK = 0x7FFFFFFF, ET_NULL = 0x7FFFFFFF };
++ int _last_element_type;
++ int _free_element_type;
++ VariableEnvironment _global_scope;
++
++ // elements
++ HashMap<String, int> _element_map;
++ Compound *_c;
++
++ TunnelEnd *_definputs;
++ TunnelEnd *_defoutputs;
++
++ // compound elements
++ int _anonymous_offset;
++
++ // requirements
++ Vector<String> _requirements;
++
++ // errors
++ ErrorHandler *_errh;
++
++ int lerror(const char *, ...);
++
++ String anon_element_name(const String &) const;
++ String deanonymize_element_name(const String &, int);
++ int get_element(String, int, const String & = String(), const String & = String());
++ int lexical_scoping_in() const;
++ void lexical_scoping_out(int);
++ int remove_element_type(int, int *);
++ int make_compound_element(int);
++ void expand_compound_element(int, VariableEnvironment &);
++ void add_router_connections(int, const Vector<int> &, Router *);
++
++ void find_connections(const Hookup &, bool, Vector<Hookup> &) const;
++ void expand_connection(const Hookup &, bool, Vector<Hookup> &) const;
++
++ friend class Compound;
++ friend class TunnelEnd;
++
++};
++
++class LexerExtra { public:
++
++ LexerExtra() { }
++ virtual ~LexerExtra() { }
++
++ virtual void require(String, ErrorHandler *);
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/llrpc.h click-1.6.0-27/inst/include/click/llrpc.h
+--- click-1.6.0/inst/include/click/llrpc.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/llrpc.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,182 @@
++#ifndef CLICK_LLRPC_H
++#define CLICK_LLRPC_H
++#if CLICK_LINUXMODULE
++# include <linux/errno.h>
++# include <linux/ioctl.h>
++#else
++# include <errno.h>
++# include <sys/ioctl.h>
++#endif
++
++/* Click low-level RPC interface */
++
++/* Ioctl numbers are not consistent across platforms unless you #define
++ HAVE_PORTABLE_LLRPC. */
++#define _CLICK_NET_IOC_VOID 0x20000000
++#define _CLICK_NET_IOC_OUT 0x40000000
++#define _CLICK_NET_IOC_IN 0x80000000
++#if HAVE_PORTABLE_LLRPC || !defined(__linux__)
++# define _CLICK_IOC_VOID _CLICK_NET_IOC_VOID
++# define _CLICK_IOC_OUT _CLICK_NET_IOC_OUT
++# define _CLICK_IOC_IN _CLICK_NET_IOC_IN
++#else
++# define _CLICK_IOC_VOID (_IOC_NONE << _IOC_DIRSHIFT)
++# define _CLICK_IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
++# define _CLICK_IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
++#endif
++#define _CLICK_IOC_BASE_MASK 0x0FFFFFFF
++#define _CLICK_IOC_SAFE 0x00008000
++#define _CLICK_IOC_FLAT 0x00004000
++#define _CLICK_IOC_SIZE(io) ((io) >> 16 & 0xFFF)
++
++/* _CLICK_IO[S]: data transfer direction unknown, pass pointer unchanged;
++ _CLICK_IOR[S]: data of specified size sent from kernel to user;
++ _CLICK_IOW[S]: data of specified size sent from user to kernel;
++ _CLICK_IOWR[S]: data of specified size transferred in both directions. */
++
++/* "Non-safe" LLRPCs will not be performed in parallel with other LLRPCs or
++ handlers. */
++#define _CLICK_IOX(d, n, sz) ((d) | ((sz) << 16) | (n))
++#define _CLICK_IO(n) _CLICK_IOX(_CLICK_IOC_VOID, (n), 0)
++#define _CLICK_IOR(n, sz) _CLICK_IOX(_CLICK_IOC_OUT, (n), (sz))
++#define _CLICK_IOW(n, sz) _CLICK_IOX(_CLICK_IOC_IN, (n), (sz))
++#define _CLICK_IOWR(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT, (n), (sz))
++
++/* "Safe" LLRPCs may be performed in parallel with read handlers and other
++ safe LLRPCs, but not with write handlers or unsafe LLRPCs. */
++#define _CLICK_IOS(n) _CLICK_IOX(_CLICK_IOC_VOID|_CLICK_IOC_SAFE, (n), 0)
++#define _CLICK_IORS(n, sz) _CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_SAFE, (n), (sz))
++#define _CLICK_IOWS(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_SAFE, (n), (sz))
++#define _CLICK_IOWRS(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_SAFE, (n), (sz))
++
++/* "Flat" LLRPCs do not contain pointers -- all data read or written is
++ contained in the size. They can be safe or unsafe. */
++#define _CLICK_IORF(n, sz) _CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_FLAT, (n), (sz))
++#define _CLICK_IOWF(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_FLAT, (n), (sz))
++#define _CLICK_IOWRF(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_FLAT, (n), (sz))
++#define _CLICK_IORSF(n, sz) _CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
++#define _CLICK_IOWSF(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
++#define _CLICK_IOWRSF(n, sz) _CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
++
++#define CLICK_LLRPC_PROXY _CLICK_IO(0)
++#define CLICK_LLRPC_GET_RATE _CLICK_IOWRSF(1, 4)
++#define CLICK_LLRPC_GET_RATES _CLICK_IOS(2)
++#define CLICK_LLRPC_GET_COUNT _CLICK_IOWRSF(3, 4)
++#define CLICK_LLRPC_GET_COUNTS _CLICK_IOS(4)
++#define CLICK_LLRPC_GET_SWITCH _CLICK_IORSF(5, 4)
++#define CLICK_LLRPC_SET_SWITCH _CLICK_IOWF(6, 4)
++#define CLICK_LLRPC_MAP_IPADDRESS _CLICK_IOWRF(7, 4)
++#define CLICK_LLRPC_IPREWRITER_MAP_TCP _CLICK_IOWRSF(8, 12)
++#define CLICK_LLRPC_IPREWRITER_MAP_UDP _CLICK_IOWRSF(9, 12)
++#define CLICK_LLRPC_IPRATEMON_LEVEL_FWD_AVG _CLICK_IO(10)
++#define CLICK_LLRPC_IPRATEMON_LEVEL_REV_AVG _CLICK_IO(11)
++#define CLICK_LLRPC_IPRATEMON_FWD_N_REV_AVG _CLICK_IO(12)
++#define CLICK_LLRPC_IPRATEMON_SET_ANNO_LEVEL _CLICK_IO(13)
++
++#define CLICK_IOC_TOUSERDEVICE_GET_MULTI _CLICK_IOS(14)
++#define CLICK_IOC_TOUSERDEVICE_SET_MULTI _CLICK_IOS(15)
++
++struct click_llrpc_proxy_st {
++ void* proxied_handler; /* const Router::Handler* */
++ uint32_t proxied_command;
++ void* proxied_data;
++};
++
++#define CLICK_LLRPC_COUNTS_SIZE 8
++struct click_llrpc_counts_st {
++ uint32_t n;
++ uint32_t keys[CLICK_LLRPC_COUNTS_SIZE];
++ uint32_t values[CLICK_LLRPC_COUNTS_SIZE];
++};
++
++
++/* data manipulation */
++
++#if CLICK_USERLEVEL
++
++# define CLICK_LLRPC_GET_DATA(local, remote, size) (memcpy(local, remote, size), 0)
++# define CLICK_LLRPC_PUT_DATA(remote, local, size) (memcpy(remote, local, size), 0)
++# define CLICK_LLRPC_GET(local_obj, remote_addr) (memcpy(&(local_obj), remote_addr, sizeof(local_obj)), 0)
++# define CLICK_LLRPC_PUT(remote_addr, local_obj) (memcpy(remote_addr, &(local_obj), sizeof(local_obj)), 0)
++
++#elif CLICK_LINUXMODULE
++
++# ifdef __cplusplus
++# define __CLICK_LLRPC_CAST(x) reinterpret_cast< x >
++extern "C" {
++# include <asm/uaccess.h>
++}
++# else
++# define __CLICK_LLRPC_CAST(x) (x)
++# include <asm/uaccess.h>
++# endif
++
++# define __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size) \
++ (copy_from_user(local, remote, size) > 0 ? -EFAULT : 0)
++# define __CLICK_LLRPC_CONSTANT_GET_DATA(local, remote, size) \
++ (size == 1 ? get_user(*__CLICK_LLRPC_CAST(unsigned char *)(local), __CLICK_LLRPC_CAST(unsigned char *)(remote)) \
++ : (size == 2 ? get_user(*__CLICK_LLRPC_CAST(unsigned short *)(local), __CLICK_LLRPC_CAST(unsigned short *)(remote)) \
++ : (size == 4 ? get_user(*__CLICK_LLRPC_CAST(unsigned *)(local), __CLICK_LLRPC_CAST(unsigned *)(remote)) \
++ : __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size))))
++
++# define __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size) \
++ (copy_to_user(remote, local, size) > 0 ? -EFAULT : 0)
++# define __CLICK_LLRPC_CONSTANT_PUT_DATA(remote, local, size) \
++ (size == 1 ? put_user(*__CLICK_LLRPC_CAST(const unsigned char *)(local), __CLICK_LLRPC_CAST(unsigned char *)(remote)) \
++ : (size == 2 ? put_user(*__CLICK_LLRPC_CAST(const unsigned short *)(local), __CLICK_LLRPC_CAST(unsigned short *)(remote)) \
++ : (size == 4 ? put_user(*__CLICK_LLRPC_CAST(const unsigned *)(local), __CLICK_LLRPC_CAST(unsigned *)(remote)) \
++ : __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size))))
++
++# define CLICK_LLRPC_GET_DATA(local, remote, size) \
++ (__builtin_constant_p(size) && size <= 4 \
++ ? __CLICK_LLRPC_CONSTANT_GET_DATA(local, remote, size) \
++ : __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size))
++# define CLICK_LLRPC_PUT_DATA(remote, local, size) \
++ (__builtin_constant_p(size) && size <= 4 \
++ ? __CLICK_LLRPC_CONSTANT_PUT_DATA(remote, local, size) \
++ : __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size))
++
++# define CLICK_LLRPC_GET(local_obj, remote_addr) \
++ get_user((local_obj), (remote_addr))
++# define CLICK_LLRPC_PUT(remote_addr, local_obj) \
++ put_user((local_obj), (remote_addr))
++
++#elif CLICK_BSDMODULE
++
++/*
++ * XXX LLRPC isn't implemented for BSD yet.
++ */
++
++# define CLICK_LLRPC_GET_DATA(local, remote, size) ((void)(local), (void)(remote), (void)(size), -EFAULT)
++# define CLICK_LLRPC_PUT_DATA(remote, local, size) ((void)(local), (void)(remote), (void)(size), -EFAULT)
++# define CLICK_LLRPC_GET(local_obj, remote_addr) ((void)(local_obj), (void)(remote_addr), -EFAULT)
++# define CLICK_LLRPC_PUT(remote_addr, local_obj) ((void)(local_obj), (void)(remote_addr), -EFAULT)
++
++#endif
++
++/* CLICK_NTOH_LLRPC: portable LLRPC numbers to host LLRPC numbers */
++/* CLICK_HTON_LLRPC: host LLRPC numbers to portable LLRPC numbers */
++/* both macros are only suitable for integer constants and the like */
++#if _CLICK_IOC_VOID != _CLICK_NET_IOC_VOID || _CLICK_IOC_OUT != _CLICK_NET_IOC_OUT || _CLICK_IOC_IN != _CLICK_NET_IOC_IN
++# define CLICK_LLRPC_NTOH(command) \
++ (((command) & _CLICK_NET_IOC_VOID ? _CLICK_IOC_VOID : 0) \
++ | ((command) & _CLICK_NET_IOC_OUT ? _CLICK_IOC_OUT : 0) \
++ | ((command) & _CLICK_NET_IOC_IN ? _CLICK_IOC_IN : 0) \
++ | ((command) & _CLICK_IOC_BASE_MASK))
++# define CLICK_LLRPC_HTON(command) \
++ (((command) & _CLICK_IOC_VOID ? _CLICK_NET_IOC_VOID : 0) \
++ | ((command) & _CLICK_IOC_OUT ? _CLICK_NET_IOC_OUT : 0) \
++ | ((command) & _CLICK_IOC_IN ? _CLICK_NET_IOC_IN : 0) \
++ | ((command) & _CLICK_IOC_BASE_MASK))
++#else
++# define CLICK_LLRPC_NTOH(command) (command)
++# define CLICK_LLRPC_HTON(command) (command)
++#endif
++
++/* sanity checks */
++#ifdef __FreeBSD__
++# if _CLICK_IOC_VOID != IOC_VOID || _CLICK_IOC_OUT != IOC_OUT || _CLICK_IOC_IN != IOC_IN
++# error "bad _CLICK_IOC constants"
++# endif
++#endif
++#endif
+diff -Nurb click-1.6.0/inst/include/click/master.hh click-1.6.0-27/inst/include/click/master.hh
+--- click-1.6.0/inst/include/click/master.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/master.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,265 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/master.cc" -*-
++#ifndef CLICK_MASTER_HH
++#define CLICK_MASTER_HH
++#include <click/vector.hh>
++#include <click/timer.hh>
++#include <click/task.hh>
++#include <click/sync.hh>
++#include <click/atomic.hh>
++#if CLICK_USERLEVEL
++# include <unistd.h>
++# include <signal.h>
++# if HAVE_POLL_H
++# include <poll.h>
++# endif
++#endif
++#if CLICK_NS
++# include <click/simclick.h>
++#endif
++CLICK_DECLS
++class Element;
++
++#define CLICK_DEBUG_MASTER 0
++
++class Master { public:
++
++ Master(int nthreads);
++ ~Master();
++
++ void use();
++ void unuse();
++
++ void pause();
++ inline void unpause();
++
++ inline int nthreads() const;
++ inline RouterThread* thread(int id) const;
++
++ const volatile int* stopper_ptr() const { return &_stopper; }
++
++ Timestamp next_timer_expiry() const { return _timer_expiry; }
++ void run_timers();
++
++#if CLICK_USERLEVEL
++ int add_select(int fd, Element*, int mask);
++ int remove_select(int fd, Element*, int mask);
++ void run_selects(bool more_tasks);
++
++ int add_signal_handler(int signo, Router*, const String &handler);
++ int remove_signal_handler(int signo, Router*, const String &handler);
++ inline void run_signals();
++#endif
++
++ void kill_router(Router*);
++
++#if CLICK_NS
++ void initialize_ns(simclick_node_t *simnode);
++ simclick_node_t *simnode() const { return _simnode; }
++#endif
++
++#if CLICK_DEBUG_MASTER
++ String info() const;
++#endif
++
++#if CLICK_USERLEVEL
++ static sig_atomic_t signals_pending;
++#endif
++
++ private:
++
++ // stick _timer_expiry here so it will most likely fit in a cache line,
++ // & we don't have to worry about its parts being updated separately
++ Timestamp _timer_expiry;
++
++#if CLICK_LINUXMODULE
++ spinlock_t _master_lock;
++ struct task_struct *_master_lock_task;
++ int _master_lock_count;
++#endif
++ atomic_uint32_t _master_paused;
++ inline void lock_master();
++ inline void unlock_master();
++
++ // ROUTERS
++ Router* _routers;
++ int _refcount;
++ void register_router(Router*);
++ void prepare_router(Router*);
++ void run_router(Router*, bool foreground);
++ void unregister_router(Router*);
++
++ // THREADS
++ Vector<RouterThread*> _threads;
++
++ // DRIVERMANAGER
++ volatile int _stopper;
++ inline void set_stopper(int);
++ bool check_driver();
++
++ // PENDING TASKS
++ uintptr_t _pending_head;
++ volatile uintptr_t *_pending_tail;
++ SpinlockIRQ _task_lock;
++ void process_pending(RouterThread*);
++
++ // TIMERS
++ Vector<Timer*> _timer_heap;
++#if CLICK_LINUXMODULE
++ spinlock_t _timer_lock;
++ struct task_struct *_timer_task;
++#endif
++ void lock_timers();
++ bool attempt_lock_timers();
++ void unlock_timers();
++ void timer_reheapify_from(int, Timer*, bool will_delete);
++
++#if CLICK_USERLEVEL
++ // SELECT
++# if HAVE_SYS_EVENT_H && HAVE_KQUEUE
++ int _kqueue;
++ int _selected_callno;
++ Vector<int> _selected_callnos;
++# endif
++# if !HAVE_POLL_H
++ struct pollfd {
++ int fd;
++ int events;
++ };
++ fd_set _read_select_fd_set;
++ fd_set _write_select_fd_set;
++ int _max_select_fd;
++# endif /* HAVE_POLL_H */
++ Vector<struct pollfd> _pollfds;
++ Vector<Element*> _read_poll_elements;
++ Vector<Element*> _write_poll_elements;
++ Spinlock _select_lock;
++ void remove_pollfd(int pi, int event);
++# if HAVE_SYS_EVENT_H && HAVE_KQUEUE
++ void run_selects_kqueue(bool);
++# endif
++# if HAVE_POLL_H
++ void run_selects_poll(bool);
++# else
++ void run_selects_select(bool);
++# endif
++
++ // SIGNALS
++ struct SignalInfo {
++ int signo;
++ Router *router;
++ String handler;
++ SignalInfo *next;
++ };
++ SignalInfo *_siginfo;
++ bool _signal_adding;
++ Spinlock _signal_lock;
++ void process_signals();
++#endif
++
++#if CLICK_NS
++ simclick_node_t *_simnode;
++#endif
++
++ Master(const Master&);
++ Master& operator=(const Master&);
++
++ friend class Task;
++ friend class Timer;
++ friend class RouterThread;
++ friend class Router;
++
++};
++
++inline int
++Master::nthreads() const
++{
++ return _threads.size() - 2;
++}
++
++inline RouterThread*
++Master::thread(int id) const
++{
++ // return the requested thread, or the quiescent thread if there's no such
++ // thread
++ if ((unsigned)(id + 2) < (unsigned)_threads.size())
++ return _threads.at_u(id + 2);
++ else
++ return _threads.at_u(1);
++}
++
++#if CLICK_USERLEVEL
++inline void
++Master::run_signals()
++{
++ if (signals_pending)
++ process_signals();
++}
++#endif
++
++inline void
++Master::set_stopper(int s)
++{
++ _stopper = s;
++}
++
++inline void
++Master::lock_master()
++{
++#if CLICK_LINUXMODULE
++ if (current != _master_lock_task) {
++ spin_lock(&_master_lock);
++ _master_lock_task = current;
++ } else
++ _master_lock_count++;
++#endif
++}
++
++inline void
++Master::unlock_master()
++{
++#if CLICK_LINUXMODULE
++ assert(current == _master_lock_task);
++ if (_master_lock_count == 0) {
++ _master_lock_task = 0;
++ spin_unlock(&_master_lock);
++ } else
++ _master_lock_count--;
++#endif
++}
++
++inline void
++Master::unpause()
++{
++ _master_paused--;
++}
++
++inline void
++Master::lock_timers()
++{
++#if CLICK_LINUXMODULE
++ if (current != _timer_task)
++ spin_lock(&_timer_lock);
++#endif
++}
++
++inline bool
++Master::attempt_lock_timers()
++{
++#if CLICK_LINUXMODULE
++ return spin_trylock(&_timer_lock);
++#else
++ return true;
++#endif
++}
++
++inline void
++Master::unlock_timers()
++{
++#if CLICK_LINUXMODULE
++ if (current != _timer_task)
++ spin_unlock(&_timer_lock);
++#endif
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/md5.h click-1.6.0-27/inst/include/click/md5.h
+--- click-1.6.0/inst/include/click/md5.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/md5.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,146 @@
++/* -*- related-file-name: "../../lib/md5.cc" -*-
++ Copyright (c) 2006-2007 Regents of the University of California
++ Altered for Click by Eddie Kohler. */
++/*
++ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
++
++ This software is provided 'as-is', without any express or implied
++ warranty. In no event will the authors be held liable for any damages
++ arising from the use of this software.
++
++ Permission is granted to anyone to use this software for any purpose,
++ including commercial applications, and to alter it and redistribute it
++ freely, subject to the following restrictions:
++
++ 1. The origin of this software must not be misrepresented; you must not
++ claim that you wrote the original software. If you use this software
++ in a product, an acknowledgment in the product documentation would be
++ appreciated but is not required.
++ 2. Altered source versions must be plainly marked as such, and must not be
++ misrepresented as being the original software.
++ 3. This notice may not be removed or altered from any source distribution.
++
++ L. Peter Deutsch
++ ghost@aladdin.com
++
++ */
++/*
++ Independent implementation of MD5 (RFC 1321).
++
++ This code implements the MD5 Algorithm defined in RFC 1321, whose
++ text is available at
++ http://www.ietf.org/rfc/rfc1321.txt
++ The code is derived from the text of the RFC, including the test suite
++ (section A.5) but excluding the rest of Appendix A. It does not include
++ any code or documentation that is identified in the RFC as being
++ copyrighted.
++
++ The original and principal author of md5.h is L. Peter Deutsch
++ <ghost@aladdin.com>. Other authors are noted in the change history
++ that follows (in reverse chronological order):
++
++ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
++ references to Ghostscript; clarified derivation from RFC 1321;
++ now handles byte order either statically or dynamically.
++ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
++ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
++ added conditionalization for C++ compilation from Martin
++ Purschke <purschke@bnl.gov>.
++ 1999-05-03 lpd Original version.
++ */
++
++#ifndef CLICK_MD5_H
++#define CLICK_MD5_H
++#if CLICK_LINUXMODULE
++#include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++#include <linux/crypto.h>
++#include <asm/scatterlist.h>
++CLICK_CXX_UNPROTECT
++#include <click/cxxunprotect.h>
++
++typedef struct crypto_tfm *md5_state_t;
++
++static inline void md5_init(md5_state_t *pms) {
++ *pms = crypto_alloc_tfm("md5", 0);
++ if (*pms)
++ crypto_digest_init(*pms);
++}
++
++static inline void md5_append(md5_state_t *pms, const unsigned char *data, int nbytes) {
++ if (*pms) {
++ struct scatterlist sg[1];
++ sg[0].page = virt_to_page(data);
++ sg[0].offset = offset_in_page(data);
++ sg[0].length = nbytes;
++ crypto_digest_update(*pms, sg, 1);
++ }
++}
++
++static inline void md5_finish(md5_state_t *pms, const unsigned char digest[16]) {
++ if (*pms)
++ crypto_digest_final(*pms, digest);
++}
++
++static inline void md5_free(md5_state_t *pms) {
++ crypto_free_tfm(*pms);
++}
++
++#else
++
++/*
++ * This package supports both compile-time and run-time determination of CPU
++ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
++ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
++ * defined as non-zero, the code will be compiled to run only on big-endian
++ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
++ * run on either big- or little-endian CPUs, but will run slightly less
++ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
++ */
++
++typedef unsigned char md5_byte_t; /* 8-bit byte */
++typedef uint32_t md5_word_t; /* 32-bit word */
++
++/* Define the state of the MD5 Algorithm. */
++typedef struct md5_state_s {
++ md5_word_t count[2]; /* message length in bits, lsw first */
++ md5_word_t abcd[4]; /* digest buffer */
++ md5_byte_t buf[64]; /* accumulate block */
++} md5_state_t;
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++/* Initialize the algorithm. */
++void md5_init(md5_state_t *pms);
++
++/* Append a string to the message. */
++void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
++
++/* Finish the message and return the digest. */
++#define MD5_DIGEST_SIZE 16
++void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
++
++/* Finish the message and return the digest in ASCII. DOES NOT write a
++ terminating NUL character.
++ If 'allow_at == 0', the digest uses characters [A-Za-z0-9_], and has
++ length between MD5_TEXT_DIGEST_SIZE and MD5_TEXT_DIGEST_MAX_SIZE.
++ If 'allow_at != 0', the digest uses characters [A-Za-z0-9_@], and has
++ length of exactly MD5_TEXT_DIGEST_SIZE.
++ Returns the number of characters written. Again, this will NOT include
++ a terminating NUL. */
++#define MD5_TEXT_DIGEST_SIZE 22 /* min len */
++#define MD5_TEXT_DIGEST_MAX_SIZE 26 /* max len if !allow_at */
++int md5_finish_text(md5_state_t *pms, char *text_digest, int allow_at);
++
++#define md5_free(pms) /* do nothing */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
++#endif
++
+diff -Nurb click-1.6.0/inst/include/click/nameinfo.hh click-1.6.0-27/inst/include/click/nameinfo.hh
+--- click-1.6.0/inst/include/click/nameinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/nameinfo.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,210 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/nameinfo.cc" -*-
++#ifndef CLICK_NAMEINFO_HH
++#define CLICK_NAMEINFO_HH
++#include <click/string.hh>
++#include <click/vector.hh>
++#include <click/straccum.hh>
++CLICK_DECLS
++class Element;
++class NameDB;
++class ErrorHandler;
++
++class NameInfo { public:
++
++ NameInfo();
++ ~NameInfo();
++
++ static void static_initialize();
++ static void static_cleanup();
++
++ enum {
++ T_NONE = 0,
++ T_SCHEDULEINFO = 0x00000001,
++ T_SCRIPT_INSN = 0x00000002,
++ T_SIGNO = 0x00000003,
++ T_ETHERNET_ADDR = 0x01000001,
++ T_IP_ADDR = 0x04000001,
++ T_IP_PREFIX = 0x04000002,
++ T_IP_PROTO = 0x04000003,
++ T_IPFILTER_TYPE = 0x04000004,
++ T_TCP_OPT = 0x04000005,
++ T_ICMP_TYPE = 0x04010000,
++ T_ICMP_CODE = 0x04010100,
++ T_IP_PORT = 0x04020000,
++ T_TCP_PORT = 0x04020006,
++ T_UDP_PORT = 0x04020011,
++ T_IP_FIELDNAME = 0x04030000,
++ T_ICMP_FIELDNAME = 0x04030001,
++ T_TCP_FIELDNAME = 0x04030006,
++ T_UDP_FIELDNAME = 0x04030011,
++ T_IP6_ADDR = 0x06000001,
++ T_IP6_PREFIX = 0x06000002
++ };
++
++ static NameDB *getdb(uint32_t type, const Element *prefix, int value_size, bool create);
++ static void installdb(NameDB *db, const Element *prefix);
++ static void removedb(NameDB *db);
++
++ static bool query(uint32_t type, const Element *prefix, const String &name, void *value_store, int value_size);
++ static bool query_int(uint32_t type, const Element *prefix, const String &name, int32_t *value_store);
++ static bool query_int(uint32_t type, const Element *prefix, const String &name, uint32_t *value_store);
++ static String revquery(uint32_t type, const Element *prefix, const void *value, int value_size);
++ static inline String revquery_int(uint32_t type, const Element *prefix, int32_t value);
++ static inline void define(uint32_t type, const Element *prefix, const String &name, const void *value, int value_size);
++ static inline void define_int(uint32_t type, const Element *prefix, const String &name, int32_t value);
++
++#ifdef CLICK_NAMEDB_CHECK
++ void check(ErrorHandler *);
++ static void check(const Element *, ErrorHandler *);
++#endif
++
++ private:
++
++ Vector<NameDB *> _namedb_roots;
++ Vector<NameDB *> _namedbs;
++
++ inline NameDB *install_dynamic_sentinel() { return (NameDB *) this; }
++ NameDB *namedb(uint32_t type, int value_size, const String &prefix, NameDB *installer);
++
++#ifdef CLICK_NAMEDB_CHECK
++ uintptr_t _check_generation;
++ void checkdb(NameDB *db, NameDB *parent, ErrorHandler *errh);
++#endif
++
++};
++
++
++class NameDB { public:
++
++ inline NameDB(uint32_t type, const String &prefix, int value_size);
++ virtual ~NameDB() { }
++
++ uint32_t type() const { return _type; }
++ int value_size() const { return _value_size; }
++ const String &prefix() const { return _prefix; }
++ NameDB *prefix_parent() const { return _prefix_parent; }
++
++ virtual bool query(const String &name, void *value, int vsize) = 0;
++ virtual String revfind(const void *value, int vsize);
++ virtual void define(const String &name, const void *value, int vsize);
++ inline void define_int(const String &name, int32_t value);
++
++#ifdef CLICK_NAMEDB_CHECK
++ virtual void check(ErrorHandler *);
++#endif
++
++ private:
++
++ uint32_t _type;
++ String _prefix;
++ int _value_size;
++ NameDB *_prefix_parent;
++ NameDB *_prefix_sibling;
++ NameDB *_prefix_child;
++ NameInfo *_installed;
++
++#ifdef CLICK_NAMEDB_CHECK
++ uintptr_t _check_generation;
++#endif
++
++ friend class NameInfo;
++
++};
++
++class StaticNameDB : public NameDB { public:
++
++ struct Entry {
++ const char *name;
++ uint32_t value;
++ };
++
++ inline StaticNameDB(uint32_t type, const String &prefix, const Entry *entry, int nentry);
++
++ bool query(const String &name, void *value, int vsize);
++ String revfind(const void *value, int vsize);
++
++#ifdef CLICK_NAMEDB_CHECK
++ void check(ErrorHandler *);
++#endif
++
++ private:
++
++ const Entry *_entries;
++ int _nentries;
++
++};
++
++class DynamicNameDB : public NameDB { public:
++
++ inline DynamicNameDB(uint32_t type, const String &prefix, int vsize);
++
++ bool query(const String &name, void *value, int vsize);
++ void define(const String &name, const void *value, int vsize);
++ String revfind(const void *value, int vsize);
++
++#ifdef CLICK_NAMEDB_CHECK
++ void check(ErrorHandler *);
++#endif
++
++ private:
++
++ Vector<String> _names;
++ StringAccum _values;
++ int _sorted;
++
++ void *find(const String &name, bool create);
++ void sort();
++
++};
++
++
++inline
++NameDB::NameDB(uint32_t type, const String &prefix, int vsize)
++ : _type(type), _prefix(prefix), _value_size(vsize),
++ _prefix_parent(0), _prefix_sibling(0), _prefix_child(0), _installed(0)
++{
++#ifdef CLICK_NAMEDB_CHECK
++ _check_generation = 0;
++#endif
++}
++
++inline
++StaticNameDB::StaticNameDB(uint32_t type, const String &prefix, const Entry *entry, int nentry)
++ : NameDB(type, prefix, sizeof(entry->value)), _entries(entry), _nentries(nentry)
++{
++}
++
++inline
++DynamicNameDB::DynamicNameDB(uint32_t type, const String &prefix, int vsize)
++ : NameDB(type, prefix, vsize), _sorted(0)
++{
++}
++
++inline String
++NameInfo::revquery_int(uint32_t type, const Element *e, int32_t value)
++{
++ return revquery(type, e, &value, sizeof(value));
++}
++
++inline void
++NameInfo::define(uint32_t type, const Element *e, const String &name, const void *value, int vsize)
++{
++ if (NameDB *db = getdb(type, e, vsize, true))
++ db->define(name, value, vsize);
++}
++
++inline void
++NameInfo::define_int(uint32_t type, const Element *e, const String &name, const int32_t value)
++{
++ if (NameDB *db = getdb(type, e, sizeof(value), true))
++ db->define(name, &value, sizeof(value));
++}
++
++inline void
++NameDB::define_int(const String &name, const int32_t value)
++{
++ define(name, &value, sizeof(value));
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/notifier.hh click-1.6.0-27/inst/include/click/notifier.hh
+--- click-1.6.0/inst/include/click/notifier.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/notifier.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,488 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/notifier.cc" -*-
++#ifndef CLICK_NOTIFIER_HH
++#define CLICK_NOTIFIER_HH
++#include <click/task.hh>
++#include <click/atomic.hh>
++CLICK_DECLS
++
++class NotifierSignal { public:
++
++ inline NotifierSignal(); // always active
++ inline NotifierSignal(atomic_uint32_t* value, uint32_t mask);
++
++ static inline NotifierSignal idle_signal();
++ static inline NotifierSignal busy_signal();
++ static inline NotifierSignal overderived_signal();
++ static inline NotifierSignal uninitialized_signal();
++
++ typedef bool (NotifierSignal::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++ inline bool active() const;
++
++ inline bool idle() const;
++ inline bool busy() const;
++ inline bool overderived() const;
++ inline bool initialized() const;
++
++ inline void set_active(bool active);
++
++ NotifierSignal& operator+=(const NotifierSignal& a);
++
++ String unparse() const;
++
++ static void static_initialize();
++
++ private:
++
++ atomic_uint32_t* _value;
++ uint32_t _mask;
++
++ enum { TRUE_MASK = 1, FALSE_MASK = 2, OVERDERIVED_MASK = 4,
++ UNINITIALIZED_MASK = 8 };
++ static atomic_uint32_t static_value;
++ friend bool operator==(const NotifierSignal&, const NotifierSignal&);
++ friend bool operator!=(const NotifierSignal&, const NotifierSignal&);
++ friend NotifierSignal operator+(NotifierSignal, const NotifierSignal&);
++
++};
++
++class Notifier { public:
++
++ enum SearchOp { SEARCH_STOP = 0, SEARCH_CONTINUE, SEARCH_CONTINUE_WAKE };
++
++ inline Notifier(SearchOp = SEARCH_STOP);
++ inline Notifier(const NotifierSignal &, SearchOp = SEARCH_STOP);
++ virtual ~Notifier();
++
++ int initialize(Router *);
++
++ inline const NotifierSignal &signal() const;
++ inline SearchOp search_op() const;
++
++ inline bool active() const;
++
++ inline void set_active(bool active);
++ inline void wake();
++ inline void sleep();
++
++ virtual int add_listener(Task*);
++ virtual void remove_listener(Task*);
++ virtual int add_dependent_signal(NotifierSignal*);
++
++ static const char EMPTY_NOTIFIER[];
++ static const char FULL_NOTIFIER[];
++
++ static NotifierSignal upstream_empty_signal(Element* e, int port, Task* task, Notifier* dependent_notifier = 0);
++ static NotifierSignal downstream_full_signal(Element* e, int port, Task* task, Notifier* dependent_notifier = 0);
++
++ private:
++
++ NotifierSignal _signal;
++ SearchOp _search_op;
++
++};
++
++class ActiveNotifier : public Notifier { public:
++
++ ActiveNotifier(SearchOp = SEARCH_STOP);
++ ~ActiveNotifier();
++
++ int add_listener(Task*); // complains on out of memory
++ void remove_listener(Task*);
++ int add_dependent_signal(NotifierSignal*);
++ void listeners(Vector<Task*>&) const;
++
++ inline void set_active(bool active, bool schedule = true);
++ inline void wake();
++ inline void sleep();
++
++ private:
++
++ typedef union {
++ Task *t;
++ NotifierSignal *s;
++ void *v;
++ } task_or_signal_t;
++
++ Task* _listener1;
++ task_or_signal_t* _listeners;
++
++ int listener_change(void *what, int where, bool rem);
++
++ ActiveNotifier(const ActiveNotifier&); // does not exist
++ ActiveNotifier& operator=(const ActiveNotifier&); // does not exist
++
++};
++
++
++/** @brief Construct a busy signal.
++ *
++ * The returned signal is always active.
++ */
++inline
++NotifierSignal::NotifierSignal()
++ : _value(&static_value), _mask(TRUE_MASK)
++{
++}
++
++/** @brief Construct an activity signal.
++ *
++ * Elements should not use this constructor directly.
++ * @sa Router::new_notifier_signal
++ */
++inline
++NotifierSignal::NotifierSignal(atomic_uint32_t* value, uint32_t mask)
++ : _value(value), _mask(mask)
++{
++}
++
++/** @brief Return an idle signal.
++ *
++ * The returned signal is never active.
++ */
++inline NotifierSignal
++NotifierSignal::idle_signal()
++{
++ return NotifierSignal(&static_value, 0);
++}
++
++/** @brief Return a busy signal.
++ *
++ * The returned signal is always active.
++ */
++inline NotifierSignal
++NotifierSignal::busy_signal()
++{
++ return NotifierSignal(&static_value, TRUE_MASK);
++}
++
++/** @brief Return an overderived busy signal.
++ *
++ * Overderived signals replace derived signals that are too complex to
++ * represent. An overderived signal, like a busy signal, is always active.
++ */
++inline NotifierSignal
++NotifierSignal::overderived_signal()
++{
++ return NotifierSignal(&static_value, OVERDERIVED_MASK | TRUE_MASK);
++}
++
++/** @brief Return an uninitialized signal.
++ *
++ * Unintialized signals may be used occasionally as placeholders for true
++ * signals to be added later. Uninitialized signals are never active.
++ */
++inline NotifierSignal
++NotifierSignal::uninitialized_signal()
++{
++ return NotifierSignal(&static_value, UNINITIALIZED_MASK);
++}
++
++/** @brief Return whether the signal is active.
++ * @return true iff the signal is currently active.
++ */
++inline bool
++NotifierSignal::active() const
++{
++ return (*_value & _mask) != 0;
++}
++
++/** @brief Return whether the signal is active.
++ * @return true iff the signal is currently active.
++ */
++inline
++NotifierSignal::operator unspecified_bool_type() const
++{
++ return active() ? &NotifierSignal::active : 0;
++}
++
++/** @brief Return whether the signal is idle.
++ * @return true iff the signal is idle, i.e. it will never be active.
++ */
++inline bool
++NotifierSignal::idle() const
++{
++ return !_mask;
++}
++
++/** @brief Return whether the signal is busy.
++ * @return true iff the signal is busy, i.e. it will always be active.
++ *
++ * @note An overderived_signal() is busy(), but a busy_signal() is not
++ * overderived().
++ */
++inline bool
++NotifierSignal::busy() const
++{
++ return (_value == &static_value && (_mask & TRUE_MASK));
++}
++
++/** @brief Return whether the signal is overderived.
++ * @return true iff the signal equals overderived_signal().
++ *
++ * @note An overderived_signal() is busy(), but a busy_signal() is not
++ * overderived().
++ */
++inline bool
++NotifierSignal::overderived() const
++{
++ return (_value == &static_value && (_mask & OVERDERIVED_MASK));
++}
++
++/** @brief Return whether the signal is initialized.
++ * @return true iff the signal doesn't equal uninitialized_signal().
++ */
++inline bool
++NotifierSignal::initialized() const
++{
++ return (_value != &static_value || !(_mask & UNINITIALIZED_MASK));
++}
++
++/** @brief Set whether the signal is active.
++ * @param active true iff the signal is active
++ *
++ * Use this function to set whether a basic signal is active.
++ *
++ * It is illegal to call set_active() on derived, idle, busy, or overderived
++ * signals. Some of these actions may cause an assertion failure.
++ */
++inline void
++NotifierSignal::set_active(bool active)
++{
++ assert(_value != &static_value);
++ if (active)
++ *_value |= _mask;
++ else
++ *_value &= ~_mask;
++}
++
++/** @relates NotifierSignal
++ * @brief Compare two NotifierSignals for equality.
++ *
++ * Returns true iff the two NotifierSignals are the same -- i.e., they combine
++ * information about exactly the same sets of basic signals.
++ *
++ * All idle() signals compare equal. busy_signal() and overderived_signal()
++ * do not compare equal, however.
++ */
++inline bool
++operator==(const NotifierSignal& a, const NotifierSignal& b)
++{
++ return (a._mask == b._mask && (a._value == b._value || a._mask == 0));
++}
++
++/** @relates NotifierSignal
++ * @brief Compare two NotifierSignals for inequality.
++ *
++ * Returns true iff !(@a a == @a b).
++ */
++inline bool
++operator!=(const NotifierSignal& a, const NotifierSignal& b)
++{
++ return !(a == b);
++}
++
++/** @relates NotifierSignal
++ * @brief Return a derived signal.
++ *
++ * Returns a derived signal that combines information from its arguments. The
++ * result will be active whenever @a a and/or @a b is active. If the
++ * combination of @a a and @a b is too complex to represent, returns an
++ * overderived signal; this trivially follows the invariant since it is always
++ * active.
++ *
++ * Signal derivation is commutative and associative. The following special
++ * combinations are worth remembering:
++ *
++ * - An idle() signal plus any other signal @a a equals @a a. Thus,
++ * idle_signal() is the identity for signal derivation.
++ * - A busy() signal plus any other signal is busy(). Thus, busy_signal()
++ * is the "zero element" for signal derivation.
++ *
++ * @sa NotifierSignal::operator+=
++ */
++inline NotifierSignal
++operator+(NotifierSignal a, const NotifierSignal& b)
++{
++ return a += b;
++}
++
++/** @brief Constructs a Notifier.
++ * @param search_op controls notifier path search
++ *
++ * This function constructs a Notifier object. The Notifier's associated
++ * NotifierSignal is initially idle; it becomes associated with a signal after
++ * initialize() is called.
++ *
++ * The @a search_op argument controls path search. The rest of this entry
++ * describes it further.
++ *
++ * Elements interested in notification generally search for Notifier objects
++ * along all possible packet paths upstream (or downstream) of one of their
++ * ports. When a Notifier is found along a path, further searching along that
++ * path is cut off, so only the closest Notifiers are found. Sometimes,
++ * however, it makes more sense to continue searching for more Notifiers. The
++ * correct behavior is Notifier-specific, and is controlled by this method.
++ * When the search encounters a Notifier, it consults the Notifier's @a
++ * search_op variable supplied to the constructor. It should equal one of
++ * three SearchOp constants, which correspond to the following behavior:
++ *
++ * <dl>
++ * <dt>SEARCH_STOP</dt>
++ * <dd>Stop searching along this path. This is the default.</dd>
++ * <dt>SEARCH_CONTINUE</dt>
++ * <dd>Continue searching along this path.</dd>
++ * <dt>SEARCH_CONTINUE_WAKE</dt>
++ * <dd>Continue searching along this path, but any further Notifiers should
++ * only be used for adding and removing listeners; ignore their NotifierSignal
++ * objects. This operation is useful, for example, for schedulers that store
++ * packets temporarily. Such schedulers provide their own NotifierSignal,
++ * since the scheduler may still hold a packet even when all upstream sources
++ * are empty, but since they aren't packet sources, they don't know when
++ * new packets arrive and can't wake up sleeping listeners. During
++ * initialization, such schedulers should call Notifier::upstream_empty_signal,
++ * passing their own Notifier as the fourth argument. This will ensure that
++ * their signal is turned on appropriately whenever an upstream queue becomes
++ * nonempty.</dd>
++ * </dl>
++ */
++inline
++Notifier::Notifier(SearchOp search_op)
++ : _signal(NotifierSignal::uninitialized_signal()), _search_op(search_op)
++{
++}
++
++/** @brief Constructs a Notifier associated with a given signal.
++ * @param signal the associated NotifierSignal
++ * @param search_op controls notifier path search
++ *
++ * This function constructs a Notifier object associated with a specific
++ * NotifierSignal, such as NotifierSignal::idle_signal(). Calling
++ * initialize() on this Notifier will not change the associated
++ * NotifierSignal. The @a search_op argument is as in
++ * Notifier::Notifier(SearchOp), above.
++ */
++inline
++Notifier::Notifier(const NotifierSignal &signal, SearchOp search_op)
++ : _signal(signal), _search_op(search_op)
++{
++}
++
++/** @brief Return this Notifier's associated NotifierSignal.
++ *
++ * Every Notifier object corresponds to one NotifierSignal; this method
++ * returns it. The signal is @link NotifierSignal::idle idle() @endlink
++ * before initialize() is called.
++ */
++inline const NotifierSignal &
++Notifier::signal() const
++{
++ return _signal;
++}
++
++/** @brief Return this Notifier's search operation.
++ *
++ * @sa Notifier() for a detailed explanation of search operations.
++ */
++inline Notifier::SearchOp
++Notifier::search_op() const
++{
++ return _search_op;
++}
++
++/** @brief Returns whether the associated signal is active.
++ *
++ * Same as signal().active().
++ */
++inline bool
++Notifier::active() const
++{
++ return _signal.active();
++}
++
++/** @brief Sets the associated signal's activity.
++ * @param active true iff the signal should be active
++ */
++inline void
++Notifier::set_active(bool active)
++{
++ _signal.set_active(active);
++}
++
++/** @brief Sets the associated signal to active.
++ * @sa set_active
++ */
++inline void
++Notifier::wake()
++{
++ set_active(true);
++}
++
++/** @brief Sets the associated signal to inactive.
++ * @sa set_active
++ */
++inline void
++Notifier::sleep()
++{
++ set_active(false);
++}
++
++/** @brief Sets the associated signal's activity, possibly scheduling any
++ * listener tasks.
++ * @param active true iff the signal should be active
++ * @param schedule if true, wake up listener tasks
++ *
++ * If @a active and @a schedule are both true, and the signal was previously
++ * inactive, then any listener Tasks are scheduled with Task::reschedule().
++ *
++ * @sa wake, sleep, add_listener
++ */
++inline void
++ActiveNotifier::set_active(bool active, bool schedule)
++{
++ if (active != Notifier::active()) {
++ // 2007.Sep.6: Perhaps there was a race condition here. Make sure
++ // that we set the notifier to active BEFORE rescheduling downstream
++ // tasks. This is because, in a multithreaded environment, a task we
++ // reschedule might run BEFORE we set the notifier; after which it
++ // would go to sleep forever.
++ Notifier::set_active(active);
++
++ if (active && schedule) {
++ if (_listener1)
++ _listener1->reschedule();
++ else if (task_or_signal_t *tos = _listeners) {
++ for (; tos->t; tos++)
++ tos->t->reschedule();
++ for (tos++; tos->s; tos++)
++ tos->s->set_active(true);
++ }
++ }
++ }
++}
++
++/** @brief Sets the associated signal to active and schedules any listener
++ * tasks.
++ *
++ * If the signal was previously inactive, then any listener Tasks are
++ * scheduled with Task::reschedule().
++ *
++ * @sa set_active, add_listener
++ */
++inline void
++ActiveNotifier::wake()
++{
++ set_active(true, true);
++}
++
++/** @brief Sets the associated signal to inactive.
++ * @sa set_active
++ */
++inline void
++ActiveNotifier::sleep()
++{
++ set_active(false, true);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/package.hh click-1.6.0-27/inst/include/click/package.hh
+--- click-1.6.0/inst/include/click/package.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/package.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,28 @@
++#ifndef CLICK_PACKAGE_HH
++#define CLICK_PACKAGE_HH
++#include <click/vector.hh>
++#include <click/string.hh>
++CLICK_DECLS
++#ifndef CLICK_TOOL
++class Element;
++#endif
++CLICK_ENDDECLS
++
++extern "C" {
++
++void click_provide(const char *);
++void click_unprovide(const char *);
++bool click_has_provision(const char *);
++void click_public_packages(CLICK_NAME(Vector)<CLICK_NAME(String)> &);
++
++#if CLICK_LINUXMODULE
++int click_add_element_type(const char *element_name, CLICK_NAME(Element) *(*factory)(uintptr_t thunk), uintptr_t thunk, struct module *);
++void click_remove_element_type(int);
++#elif !CLICK_TOOL
++int click_add_element_type(const char *element_name, CLICK_NAME(Element) *(*factory)(uintptr_t thunk), uintptr_t thunk);
++void click_remove_element_type(int);
++#endif
++
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/packet.hh click-1.6.0-27/inst/include/click/packet.hh
+--- click-1.6.0/inst/include/click/packet.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/packet.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,1171 @@
++// -*- related-file-name: "../../lib/packet.cc" -*-
++#ifndef CLICK_PACKET_HH
++#define CLICK_PACKET_HH
++#include <click/ipaddress.hh>
++#include <click/ip6address.hh>
++#include <click/glue.hh>
++#include <click/timestamp.hh>
++#if CLICK_LINUXMODULE
++# include <click/skbmgr.hh>
++#else
++# include <click/atomic.hh>
++#endif
++struct click_ether;
++struct click_ip;
++struct click_icmp;
++struct click_ip6;
++struct click_tcp;
++struct click_udp;
++
++#if CLICK_NS
++# include <click/simclick.h>
++#endif
++
++
++CLICK_DECLS
++
++class IP6Address;
++class WritablePacket;
++
++class Packet { public:
++
++ // PACKET CREATION
++ enum { DEFAULT_HEADROOM = 28, MIN_BUFFER_LENGTH = 64 };
++
++ static WritablePacket *make(uint32_t);
++ static WritablePacket *make(const char *, uint32_t);
++ static WritablePacket *make(const unsigned char *, uint32_t);
++ static WritablePacket *make(uint32_t, const unsigned char *, uint32_t, uint32_t);
++
++#if CLICK_LINUXMODULE
++ // Packet::make(sk_buff *) wraps a Packet around an existing sk_buff.
++ // Packet now owns the sk_buff (ie we don't increment skb->users).
++ static Packet *make(struct sk_buff *);
++ struct sk_buff *skb() { return (struct sk_buff *)this; }
++ const struct sk_buff *skb() const { return (const struct sk_buff*)this; }
++#elif CLICK_BSDMODULE
++ // Packet::make(mbuf *) wraps a Packet around an existing mbuf.
++ // Packet now owns the mbuf.
++ static Packet *make(struct mbuf *);
++ struct mbuf *m() { return _m; }
++ const struct mbuf *m() const { return (const struct mbuf *)_m; }
++ struct mbuf *steal_m();
++#else /* User-space */
++ static WritablePacket *make(unsigned char *, uint32_t, void (*destructor)(unsigned char *, size_t));
++#endif
++
++ inline void kill();
++
++ inline bool shared() const;
++ Packet *clone();
++ WritablePacket *uniqueify();
++
++ inline const unsigned char *data() const;
++ inline const unsigned char *end_data() const;
++ inline uint32_t length() const;
++ inline uint32_t headroom() const;
++ inline uint32_t tailroom() const;
++ inline const unsigned char *buffer() const;
++ inline const unsigned char *end_buffer() const;
++ inline uint32_t buffer_length() const;
++
++ WritablePacket *push(uint32_t nb); // Add more space before packet.
++ WritablePacket *push_mac_header(uint32_t nb);
++ Packet *nonunique_push(uint32_t nb);
++ void pull(uint32_t nb); // Get rid of initial bytes.
++ WritablePacket *put(uint32_t nb); // Add bytes to end of pkt.
++ Packet *nonunique_put(uint32_t nb);
++ void take(uint32_t nb); // Delete bytes from end of pkt.
++
++ Packet *shift_data(int offset, bool free_on_failure = true);
++#if CLICK_USERLEVEL
++ inline void shrink_data(const unsigned char *, uint32_t length);
++ inline void change_headroom_and_length(uint32_t headroom, uint32_t length);
++#endif
++
++ // HEADER ANNOTATIONS
++ inline const unsigned char *mac_header() const;
++ inline void set_mac_header(const unsigned char *);
++ inline void set_mac_header(const unsigned char *, uint32_t);
++ inline int mac_header_offset() const;
++ inline uint32_t mac_header_length() const;
++ inline int mac_length() const;
++
++ inline const unsigned char *network_header() const;
++ inline void set_network_header(const unsigned char *, uint32_t);
++ inline void set_network_header_length(uint32_t);
++ inline int network_header_offset() const;
++ inline uint32_t network_header_length() const;
++ inline int network_length() const;
++
++ inline const unsigned char *transport_header() const;
++ inline int transport_header_offset() const;
++ inline int transport_length() const;
++
++ // CONVENIENCE HEADER ANNOTATIONS
++ inline const click_ether *ether_header() const;
++ inline void set_ether_header(const click_ether *);
++
++ inline const click_ip *ip_header() const;
++ inline void set_ip_header(const click_ip *, uint32_t);
++ inline int ip_header_offset() const;
++ inline uint32_t ip_header_length() const;
++
++ inline const click_ip6 *ip6_header() const;
++ inline void set_ip6_header(const click_ip6 *);
++ inline void set_ip6_header(const click_ip6 *, uint32_t);
++ inline int ip6_header_offset() const;
++ inline uint32_t ip6_header_length() const;
++
++ inline const click_icmp *icmp_header() const;
++ inline const click_tcp *tcp_header() const;
++ inline const click_udp *udp_header() const;
++
++ // LINKS
++ inline Packet *next() const;
++ inline Packet *&next();
++ inline void set_next(Packet *p);
++
++ // ANNOTATIONS
++
++ private:
++ struct Anno;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ const Anno *anno() const { return (const Anno *)skb()->cb; }
++ Anno *anno() { return (Anno *)skb()->cb; }
++#else /* User-space and BSD kernel module */
++ const Anno *anno() const { return (const Anno *)_cb; }
++ Anno *anno() { return (Anno *)_cb; }
++#endif
++ public:
++
++ enum PacketType { // must agree with if_packet.h
++ HOST = 0, BROADCAST = 1, MULTICAST = 2, OTHERHOST = 3, OUTGOING = 4,
++ LOOPBACK = 5, FASTROUTE = 6
++ };
++
++ enum { ADDR_ANNO_SIZE = 16 };
++
++ uint8_t *addr_anno() { return anno()->addr.c; }
++ const uint8_t *addr_anno() const { return anno()->addr.c; }
++ IPAddress dst_ip_anno() const;
++ void set_dst_ip_anno(IPAddress);
++ const IP6Address &dst_ip6_anno() const;
++ void set_dst_ip6_anno(const IP6Address &);
++
++ inline const Timestamp ×tamp_anno() const;
++ inline Timestamp ×tamp_anno();
++ inline void set_timestamp_anno(const Timestamp &);
++
++ inline net_device *device_anno() const;
++ inline void set_device_anno(net_device *);
++
++ inline PacketType packet_type_anno() const;
++ inline void set_packet_type_anno(PacketType);
++
++#if CLICK_LINUXMODULE
++# ifdef HAVE_INT64_TYPES
++ uint64_t perfctr_anno() const { return anno()->perfctr; }
++ void set_perfctr_anno(uint64_t pc) { anno()->perfctr = pc; }
++# endif
++
++#else /* User-space and BSD kernel module */
++
++#if CLICK_NS
++ class SimPacketinfoWrapper {
++ public:
++ simclick_simpacketinfo _pinfo;
++ SimPacketinfoWrapper() {
++ // The uninitialized value for the simulator packet data can't be
++ // all zeros (0 is a valid packet id) or random junk out of memory
++ // since the simulator will look at this info to see if the packet
++ // was originally generated by it. Accidental collisions with other
++ // packet IDs or bogus packet IDs can cause weird things to happen. So we
++ // set it to all -1 here to keep the simulator from getting confused.
++ memset(&_pinfo,-1,sizeof(_pinfo));
++ }
++ };
++ simclick_simpacketinfo* get_sim_packetinfo() {
++ return &(_sim_packetinfo._pinfo);
++ }
++ void set_sim_packetinfo(simclick_simpacketinfo* pinfo) {
++ _sim_packetinfo._pinfo = *pinfo;
++ }
++#endif
++#endif
++
++ enum { USER_ANNO_SIZE = 24,
++ USER_ANNO_US_SIZE = 12,
++ USER_ANNO_S_SIZE = 12,
++ USER_ANNO_U_SIZE = 6,
++ USER_ANNO_I_SIZE = 6 };
++
++ uint8_t user_anno_c(int i) const { return anno()->user.c[i]; }
++ void set_user_anno_c(int i, uint8_t v) { anno()->user.c[i] = v; }
++ uint16_t user_anno_us(int i) const { return anno()->user.us[i]; }
++ void set_user_anno_us(int i, uint16_t v) { anno()->user.us[i] = v; }
++ int16_t user_anno_s(int i) const { return anno()->user.us[i]; }
++ void set_user_anno_s(int i, int16_t v) { anno()->user.s[i] = v; }
++ uint32_t user_anno_u(int i) const { return anno()->user.u[i]; }
++ void set_user_anno_u(int i, uint32_t v) { anno()->user.u[i] = v; }
++ int32_t user_anno_i(int i) const { return anno()->user.i[i]; }
++ void set_user_anno_i(int i, int32_t v) { anno()->user.i[i] = v; }
++
++ const uint8_t *all_user_anno() const { return &anno()->user.c[0]; }
++ uint8_t *all_user_anno() { return &anno()->user.c[0]; }
++ const uint32_t *all_user_anno_u() const { return &anno()->user.u[0]; }
++ uint32_t *all_user_anno_u() { return &anno()->user.u[0]; }
++
++ void clear_annotations();
++ void copy_annotations(const Packet *);
++
++ inline const unsigned char *buffer_data() const CLICK_DEPRECATED;
++
++ private:
++
++ // Anno must fit in sk_buff's char cb[48].
++ struct Anno {
++ union {
++ char ch[ADDR_ANNO_SIZE];
++ uint8_t c[ADDR_ANNO_SIZE];
++ uint32_t ip4;
++ } addr;
++
++ union {
++ uint8_t c[USER_ANNO_SIZE];
++ uint16_t us[USER_ANNO_US_SIZE];
++ int16_t s[USER_ANNO_S_SIZE];
++ uint32_t u[USER_ANNO_U_SIZE];
++ int32_t i[USER_ANNO_I_SIZE];
++ } user;
++ // flag allocations: see packet_anno.hh
++
++#if (CLICK_LINUXMODULE || CLICK_BSDMODULE) && defined(HAVE_INT64_TYPES)
++ uint64_t perfctr;
++#endif
++ };
++
++#if !CLICK_LINUXMODULE
++ // User-space and BSD kernel module implementations.
++ atomic_uint32_t _use_count;
++ Packet *_data_packet;
++ /* mimic Linux sk_buff */
++ unsigned char *_head; /* start of allocated buffer */
++ unsigned char *_data; /* where the packet starts */
++ unsigned char *_tail; /* one beyond end of packet */
++ unsigned char *_end; /* one beyond end of allocated buffer */
++# if CLICK_USERLEVEL
++ void (*_destructor)(unsigned char *, size_t);
++# endif
++ unsigned char _cb[48];
++ unsigned char *_mac;
++ unsigned char *_nh;
++ unsigned char *_h;
++ PacketType _pkt_type;
++ Timestamp _timestamp;
++# if CLICK_BSDMODULE
++ struct mbuf *_m;
++# endif
++ Packet *_next;
++# if CLICK_NS
++ SimPacketinfoWrapper _sim_packetinfo;
++# endif
++#endif
++
++ Packet();
++ Packet(const Packet &);
++ ~Packet();
++ Packet &operator=(const Packet &);
++
++#if !CLICK_LINUXMODULE
++ Packet(int, int, int) { }
++ static WritablePacket *make(int, int, int);
++ bool alloc_data(uint32_t, uint32_t, uint32_t);
++#endif
++#if CLICK_BSDMODULE
++ static void assimilate_mbuf(Packet *p);
++ void assimilate_mbuf();
++#endif
++
++ inline void shift_header_annotations(int32_t shift);
++ WritablePacket *expensive_uniqueify(int32_t extra_headroom, int32_t extra_tailroom, bool free_on_failure);
++ WritablePacket *expensive_push(uint32_t nbytes);
++ WritablePacket *expensive_put(uint32_t nbytes);
++
++ friend class WritablePacket;
++
++};
++
++
++class WritablePacket : public Packet { public:
++
++ inline unsigned char *data() const;
++ inline unsigned char *end_data() const;
++ inline unsigned char *buffer() const;
++ inline unsigned char *end_buffer() const;
++ inline unsigned char *mac_header() const;
++ inline click_ether *ether_header() const;
++ inline unsigned char *network_header() const;
++ inline click_ip *ip_header() const;
++ inline click_ip6 *ip6_header() const;
++ inline unsigned char *transport_header() const;
++ inline click_icmp *icmp_header() const;
++ inline click_tcp *tcp_header() const;
++ inline click_udp *udp_header() const;
++
++ inline unsigned char *buffer_data() const CLICK_DEPRECATED;
++
++ private:
++
++ WritablePacket() { }
++ WritablePacket(const Packet &) { }
++ ~WritablePacket() { }
++
++ friend class Packet;
++
++};
++
++
++
++inline const unsigned char *
++Packet::data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->data;
++#else
++ return _data;
++#endif
++}
++
++inline const unsigned char *
++Packet::end_data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->tail;
++#else
++ return _tail;
++#endif
++}
++
++inline uint32_t
++Packet::length() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->len;
++#else
++ return _tail - _data;
++#endif
++}
++
++inline uint32_t
++Packet::headroom() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->data - skb()->head;
++#else
++ return _data - _head;
++#endif
++}
++
++inline uint32_t
++Packet::tailroom() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end - skb()->tail;
++#else
++ return _end - _tail;
++#endif
++}
++
++inline const unsigned char *
++Packet::buffer() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->head;
++#else
++ return _head;
++#endif
++}
++
++inline const unsigned char *
++Packet::end_buffer() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end;
++#else
++ return _end;
++#endif
++}
++
++inline uint32_t
++Packet::buffer_length() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->end - skb()->head;
++#else
++ return _end - _head;
++#endif
++}
++
++inline const unsigned char *
++Packet::buffer_data() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->head;
++#else
++ return _head;
++#endif
++}
++
++
++inline Packet *
++Packet::next() const
++{
++#if CLICK_LINUXMODULE
++ return (Packet *)(skb()->next);
++#else
++ return _next;
++#endif
++}
++
++inline Packet *&
++Packet::next()
++{
++#if CLICK_LINUXMODULE
++ return (Packet *&)(skb()->next);
++#else
++ return _next;
++#endif
++}
++
++inline void
++Packet::set_next(Packet *p)
++{
++#if CLICK_LINUXMODULE
++ skb()->next = p->skb();
++#else
++ _next = p;
++#endif
++}
++
++inline const unsigned char *
++Packet::mac_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb_mac_header(skb());
++#else
++ return _mac;
++#endif
++}
++
++inline const unsigned char *
++Packet::network_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb_network_header(skb());
++#else
++ return _nh;
++#endif
++}
++
++inline const unsigned char *
++Packet::transport_header() const
++{
++#if CLICK_LINUXMODULE
++ return skb_transport_header(skb());
++#else
++ return _h;
++#endif
++}
++
++inline const click_ether *
++Packet::ether_header() const
++{
++ return reinterpret_cast<const click_ether *>(mac_header());
++}
++
++inline const click_ip *
++Packet::ip_header() const
++{
++ return reinterpret_cast<const click_ip *>(network_header());
++}
++
++inline const click_ip6 *
++Packet::ip6_header() const
++{
++ return reinterpret_cast<const click_ip6 *>(network_header());
++}
++
++inline const click_icmp *
++Packet::icmp_header() const
++{
++ return reinterpret_cast<const click_icmp *>(transport_header());
++}
++
++inline const click_tcp *
++Packet::tcp_header() const
++{
++ return reinterpret_cast<const click_tcp *>(transport_header());
++}
++
++inline const click_udp *
++Packet::udp_header() const
++{
++ return reinterpret_cast<const click_udp *>(transport_header());
++}
++
++inline int
++Packet::mac_length() const
++{
++ return end_data() - mac_header();
++}
++
++inline int
++Packet::network_length() const
++{
++ return end_data() - network_header();
++}
++
++inline int
++Packet::transport_length() const
++{
++ return end_data() - transport_header();
++}
++
++inline const Timestamp &
++Packet::timestamp_anno() const
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ return *(const Timestamp *) &skb()->stamp;
++# else
++ return *(const Timestamp *) &skb()->tstamp;
++# endif
++#else
++ return _timestamp;
++#endif
++}
++
++inline Timestamp &
++Packet::timestamp_anno()
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ return *(Timestamp *) &skb()->stamp;
++# else
++ return *(Timestamp *) &skb()->tstamp;
++# endif
++#else
++ return _timestamp;
++#endif
++}
++
++inline void
++Packet::set_timestamp_anno(const Timestamp ×tamp)
++{
++#if CLICK_LINUXMODULE
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
++ memcpy(&skb()->stamp, ×tamp, 8);
++# else
++ memcpy(&skb()->tstamp, ×tamp, 8);
++# endif
++#else
++ _timestamp = timestamp;
++#endif
++}
++
++inline net_device *
++Packet::device_anno() const
++{
++#if CLICK_LINUXMODULE
++ return skb()->dev;
++#elif CLICK_BSDMODULE
++ if (m())
++ return m()->m_pkthdr.rcvif;
++ else
++ return 0;
++#else
++ return 0;
++#endif
++}
++
++inline void
++Packet::set_device_anno(net_device *dev)
++{
++#if CLICK_LINUXMODULE
++ skb()->dev = dev;
++#elif CLICK_BSDMODULE
++ if (m())
++ m()->m_pkthdr.rcvif = dev;
++#else
++ (void) dev;
++#endif
++}
++
++inline Packet::PacketType
++Packet::packet_type_anno() const
++{
++#if CLICK_LINUXMODULE
++ return (PacketType)(skb()->pkt_type & PACKET_TYPE_MASK);
++#else
++ return _pkt_type;
++#endif
++}
++
++inline void
++Packet::set_packet_type_anno(PacketType p)
++{
++#if CLICK_LINUXMODULE
++ skb()->pkt_type = (skb()->pkt_type & PACKET_CLEAN) | p;
++#else
++ _pkt_type = p;
++#endif
++}
++
++inline WritablePacket *
++Packet::make(uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)0, len, 0);
++}
++
++inline WritablePacket *
++Packet::make(const char *s, uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)s, len, 0);
++}
++
++inline WritablePacket *
++Packet::make(const unsigned char *s, uint32_t len)
++{
++ return make(DEFAULT_HEADROOM, (const unsigned char *)s, len, 0);
++}
++
++#if CLICK_LINUXMODULE
++inline Packet *
++Packet::make(struct sk_buff *skb)
++{
++ if (atomic_read(&skb->users) == 1) {
++ skb_orphan(skb);
++ return reinterpret_cast<Packet *>(skb);
++ } else {
++ Packet *p = reinterpret_cast<Packet *>(skb_clone(skb, GFP_ATOMIC));
++ atomic_dec(&skb->users);
++ return p;
++ }
++}
++#endif
++
++
++inline void
++Packet::kill()
++{
++#if CLICK_LINUXMODULE
++ struct sk_buff *b = skb();
++ b->next = b->prev = 0;
++# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
++ b->list = 0;
++# endif
++ skbmgr_recycle_skbs(b);
++#else
++ if (_use_count.dec_and_test())
++ delete this;
++#endif
++}
++
++
++#if CLICK_BSDMODULE /* BSD kernel module */
++inline void
++Packet::assimilate_mbuf(Packet *p)
++{
++ struct mbuf *m = p->m();
++
++ if (!m) return;
++
++ p->_head = (unsigned char *)
++ (m->m_flags & M_EXT ? m->m_ext.ext_buf :
++ m->m_flags & M_PKTHDR ? m->m_pktdat :
++ m->m_dat);
++ p->_data = (unsigned char *)m->m_data;
++ p->_tail = (unsigned char *)(m->m_data + m->m_len);
++ p->_end = p->_head + (
++ m->m_flags & M_EXT ? MCLBYTES :
++ m->m_flags & M_PKTHDR ? MHLEN :
++ MLEN);
++}
++
++inline void
++Packet::assimilate_mbuf()
++{
++ assimilate_mbuf(this);
++}
++
++inline Packet *
++Packet::make(struct mbuf *m)
++{
++ if (!(m->m_flags & M_PKTHDR))
++ panic("trying to construct Packet from a non-packet mbuf");
++
++ Packet *p = new Packet;
++ if (m->m_pkthdr.len != m->m_len) {
++ /* click needs contiguous data */
++ // click_chatter("m_pulldown, Click needs contiguous data");
++
++ if (m_pulldown(m, 0, m->m_pkthdr.len, NULL) == NULL)
++ panic("m_pulldown failed");
++ }
++ p->_m = m;
++ assimilate_mbuf(p);
++
++ return p;
++}
++#endif
++
++inline bool
++Packet::shared() const
++{
++#if CLICK_LINUXMODULE
++ return skb_cloned(const_cast<struct sk_buff *>(skb()));
++#else
++ return (_data_packet || _use_count > 1);
++#endif
++}
++
++inline WritablePacket *
++Packet::uniqueify()
++{
++ if (!shared())
++ return static_cast<WritablePacket *>(this);
++ else
++ return expensive_uniqueify(0, 0, true);
++}
++
++inline WritablePacket *
++Packet::push(uint32_t nbytes)
++{
++ if (headroom() >= nbytes && !shared()) {
++ WritablePacket *q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_data -= nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_data -= nbytes;
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return q;
++ } else
++ return expensive_push(nbytes);
++}
++
++inline Packet *
++Packet::nonunique_push(uint32_t nbytes)
++{
++ if (headroom() >= nbytes) {
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _data -= nbytes;
++# if CLICK_BSDMODULE
++ m()->m_data -= nbytes;
++ m()->m_len += nbytes;
++ m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return this;
++ } else
++ return expensive_push(nbytes);
++}
++
++/* Get rid of some bytes at the start of a packet */
++inline void
++Packet::pull(uint32_t nbytes)
++{
++ if (nbytes > length()) {
++ click_chatter("Packet::pull %d > length %d\n", nbytes, length());
++ nbytes = length();
++ }
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_pull(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _data += nbytes;
++# if CLICK_BSDMODULE
++ m()->m_data += nbytes;
++ m()->m_len -= nbytes;
++ m()->m_pkthdr.len -= nbytes;
++# endif
++#endif
++}
++
++inline WritablePacket *
++Packet::put(uint32_t nbytes)
++{
++ if (tailroom() >= nbytes && !shared()) {
++ WritablePacket *q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_put(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_tail += nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return q;
++ } else
++ return expensive_put(nbytes);
++}
++
++inline Packet *
++Packet::nonunique_put(uint32_t nbytes)
++{
++ if (tailroom() >= nbytes) {
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_put(skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ _tail += nbytes;
++# if CLICK_BSDMODULE
++ m()->m_len += nbytes;
++ m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ return this;
++ } else
++ return expensive_put(nbytes);
++}
++
++/* Get rid of some bytes at the end of a packet */
++inline void
++Packet::take(uint32_t nbytes)
++{
++ if (nbytes > length()) {
++ click_chatter("Packet::take %d > length %d\n", nbytes, length());
++ nbytes = length();
++ }
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->tail -= nbytes;
++ skb()->len -= nbytes;
++#else /* User-space and BSD kernel module */
++ _tail -= nbytes;
++# if CLICK_BSDMODULE
++ m()->m_len -= nbytes;
++ m()->m_pkthdr.len -= nbytes;
++# endif
++#endif
++}
++
++#if CLICK_USERLEVEL
++inline void
++Packet::shrink_data(const unsigned char *d, uint32_t length)
++{
++ assert(_data_packet);
++ if (d >= _head && d + length >= d && d + length <= _end) {
++ _head = _data = const_cast<unsigned char *>(d);
++ _tail = _end = const_cast<unsigned char *>(d + length);
++ }
++}
++
++inline void
++Packet::change_headroom_and_length(uint32_t headroom, uint32_t length)
++{
++ if (headroom + length <= buffer_length()) {
++ _data = _head + headroom;
++ _tail = _data + length;
++ }
++}
++#endif
++
++inline const IP6Address &
++Packet::dst_ip6_anno() const
++{
++ return *reinterpret_cast<const IP6Address *>(anno()->addr.ch);
++}
++
++inline void
++Packet::set_dst_ip6_anno(const IP6Address &a)
++{
++ memcpy(anno()->addr.ch, &a, 16);
++}
++
++inline IPAddress
++Packet::dst_ip_anno() const
++{
++ return IPAddress(anno()->addr.ip4);
++}
++
++inline void
++Packet::set_dst_ip_anno(IPAddress a)
++{
++ anno()->addr.ip4 = a.addr();
++}
++
++inline void
++Packet::set_mac_header(const unsigned char *h)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->mac_header = const_cast<unsigned char *>(h);
++#else /* User-space and BSD kernel module */
++ _mac = const_cast<unsigned char *>(h);
++#endif
++}
++
++inline void
++Packet::set_mac_header(const unsigned char *h, uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->mac_header = const_cast<unsigned char *>(h);
++ skb()->network_header = const_cast<unsigned char *>(h) + len;
++#else /* User-space and BSD kernel module */
++ _mac = const_cast<unsigned char *>(h);
++ _nh = const_cast<unsigned char *>(h) + len;
++#endif
++}
++
++inline void
++Packet::set_ether_header(const click_ether *h)
++{
++ set_mac_header(reinterpret_cast<const unsigned char *>(h), 14);
++}
++
++inline WritablePacket *
++Packet::push_mac_header(uint32_t nbytes)
++{
++ WritablePacket *q;
++ if (headroom() >= nbytes && !shared()) {
++ q = (WritablePacket *)this;
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ __skb_push(q->skb(), nbytes);
++#else /* User-space and BSD kernel module */
++ q->_data -= nbytes;
++# if CLICK_BSDMODULE
++ q->m()->m_data -= nbytes;
++ q->m()->m_len += nbytes;
++ q->m()->m_pkthdr.len += nbytes;
++# endif
++#endif
++ } else if ((q = expensive_push(nbytes)))
++ /* nada */;
++ else
++ return 0;
++ q->set_mac_header(q->data(), nbytes);
++ return q;
++}
++
++inline void
++Packet::set_network_header(const unsigned char *h, uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->network_header = const_cast<unsigned char *>(h);
++ skb()->transport_header = const_cast<unsigned char *>(h) + len;
++#else /* User-space and BSD kernel module */
++ _nh = const_cast<unsigned char *>(h);
++ _h = const_cast<unsigned char *>(h) + len;
++#endif
++}
++
++inline void
++Packet::set_network_header_length(uint32_t len)
++{
++#if CLICK_LINUXMODULE /* Linux kernel module */
++ skb()->transport_header = skb()->network_header + len;
++#else /* User-space and BSD kernel module */
++ _h = _nh + len;
++#endif
++}
++
++inline void
++Packet::set_ip_header(const click_ip *iph, uint32_t len)
++{
++ set_network_header(reinterpret_cast<const unsigned char *>(iph), len);
++}
++
++inline void
++Packet::set_ip6_header(const click_ip6 *ip6h, uint32_t len)
++{
++ set_network_header(reinterpret_cast<const unsigned char *>(ip6h), len);
++}
++
++inline void
++Packet::set_ip6_header(const click_ip6 *ip6h)
++{
++ set_ip6_header(ip6h, 40);
++}
++
++inline int
++Packet::mac_header_offset() const
++{
++ return mac_header() - data();
++}
++
++inline uint32_t
++Packet::mac_header_length() const
++{
++ return network_header() - mac_header();
++}
++
++inline int
++Packet::network_header_offset() const
++{
++ return network_header() - data();
++}
++
++inline uint32_t
++Packet::network_header_length() const
++{
++ return transport_header() - network_header();
++}
++
++inline int
++Packet::ip_header_offset() const
++{
++ return network_header_offset();
++}
++
++inline uint32_t
++Packet::ip_header_length() const
++{
++ return network_header_length();
++}
++
++inline int
++Packet::ip6_header_offset() const
++{
++ return network_header_offset();
++}
++
++inline uint32_t
++Packet::ip6_header_length() const
++{
++ return network_header_length();
++}
++
++inline int
++Packet::transport_header_offset() const
++{
++ return transport_header() - data();
++}
++
++inline void
++Packet::clear_annotations()
++{
++ memset(anno(), '\0', sizeof(Anno));
++ set_packet_type_anno(HOST);
++ set_device_anno(0);
++ set_timestamp_anno(Timestamp());
++ set_mac_header(0);
++ set_network_header(0, 0);
++ set_next(0);
++}
++
++inline void
++Packet::copy_annotations(const Packet *p)
++{
++ *anno() = *p->anno();
++ set_packet_type_anno(p->packet_type_anno());
++ set_device_anno(p->device_anno());
++ set_timestamp_anno(p->timestamp_anno());
++}
++
++inline void
++Packet::shift_header_annotations(int32_t shift)
++{
++#if CLICK_USERLEVEL || CLICK_BSDMODULE
++ _mac += (_mac ? shift : 0);
++ _nh += (_nh ? shift : 0);
++ _h += (_h ? shift : 0);
++#else
++ struct sk_buff *mskb = skb();
++ mskb->mac_header += (mskb->mac_header ? shift : 0);
++ mskb->network_header += (mskb->network_header ? shift : 0);
++ mskb->transport_header += (mskb->transport_header ? shift : 0);
++#endif
++}
++
++
++inline unsigned char *
++WritablePacket::data() const
++{
++ return const_cast<unsigned char *>(Packet::data());
++}
++
++inline unsigned char *
++WritablePacket::end_data() const
++{
++ return const_cast<unsigned char *>(Packet::end_data());
++}
++
++inline unsigned char *
++WritablePacket::buffer() const
++{
++ return const_cast<unsigned char *>(Packet::buffer());
++}
++
++inline unsigned char *
++WritablePacket::end_buffer() const
++{
++ return const_cast<unsigned char *>(Packet::end_buffer());
++}
++
++inline unsigned char *
++WritablePacket::buffer_data() const
++{
++ return const_cast<unsigned char *>(Packet::buffer());
++}
++
++inline unsigned char *
++WritablePacket::mac_header() const
++{
++ return const_cast<unsigned char *>(Packet::mac_header());
++}
++
++inline unsigned char *
++WritablePacket::network_header() const
++{
++ return const_cast<unsigned char *>(Packet::network_header());
++}
++
++inline unsigned char *
++WritablePacket::transport_header() const
++{
++ return const_cast<unsigned char *>(Packet::transport_header());
++}
++
++inline click_ether *
++WritablePacket::ether_header() const
++{
++ return const_cast<click_ether *>(Packet::ether_header());
++}
++
++inline click_ip *
++WritablePacket::ip_header() const
++{
++ return const_cast<click_ip *>(Packet::ip_header());
++}
++
++inline click_ip6 *
++WritablePacket::ip6_header() const
++{
++ return const_cast<click_ip6 *>(Packet::ip6_header());
++}
++
++inline click_icmp *
++WritablePacket::icmp_header() const
++{
++ return const_cast<click_icmp *>(Packet::icmp_header());
++}
++
++inline click_tcp *
++WritablePacket::tcp_header() const
++{
++ return const_cast<click_tcp *>(Packet::tcp_header());
++}
++
++inline click_udp *
++WritablePacket::udp_header() const
++{
++ return const_cast<click_udp *>(Packet::udp_header());
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/packet_anno.hh click-1.6.0-27/inst/include/click/packet_anno.hh
+--- click-1.6.0/inst/include/click/packet_anno.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/packet_anno.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,61 @@
++#ifndef CLICK_PACKET_ANNO_HH
++#define CLICK_PACKET_ANNO_HH
++
++// byte 0
++#define PAINT_ANNO(p) ((p)->user_anno_c(0))
++#define SET_PAINT_ANNO(p, v) ((p)->set_user_anno_c(0, (v)))
++#define PAINT_ANNO_OFFSET 0
++#define PAINT_ANNO_LENGTH 1
++
++// byte 1
++#define ICMP_PARAMPROB_ANNO(p) ((p)->user_anno_c(1))
++#define SET_ICMP_PARAMPROB_ANNO(p, v) ((p)->set_user_anno_c(1, (v)))
++
++// byte 3
++#define FIX_IP_SRC_ANNO(p) ((p)->user_anno_c(3))
++#define SET_FIX_IP_SRC_ANNO(p, v) ((p)->set_user_anno_c(3, (v)))
++
++// bytes 4-7
++#define AGGREGATE_ANNO(p) ((p)->user_anno_u(1))
++#define SET_AGGREGATE_ANNO(p, v) ((p)->set_user_anno_u(1, (v)))
++
++#define FWD_RATE_ANNO(p) ((p)->user_anno_i(1))
++#define SET_FWD_RATE_ANNO(p, v) ((p)->set_user_anno_i(1, (v)))
++
++#define MISC_IP_ANNO(p) ((p)->user_anno_u(1))
++#define SET_MISC_IP_ANNO(p, v) ((p)->set_user_anno_i(1, (v).addr()))
++
++// bytes 8-11
++#define EXTRA_PACKETS_ANNO(p) ((p)->user_anno_u(2))
++#define SET_EXTRA_PACKETS_ANNO(p, v) ((p)->set_user_anno_u(2, (v)))
++
++#define REV_RATE_ANNO(p) ((p)->user_anno_i(2))
++#define SET_REV_RATE_ANNO(p, v) ((p)->set_user_anno_i(2, (v)))
++
++// byte 10
++#define SEND_ERR_ANNO(p) ((p)->user_anno_c(10))
++#define SET_SEND_ERR_ANNO(p, v) ((p)->set_user_anno_c(10, (v)))
++
++// byte 11
++#define GRID_ROUTE_CB_ANNO(p) ((p)->user_anno_c(11))
++#define SET_GRID_ROUTE_CB_ANNO(p, v) ((p)->set_user_anno_c(11, (v)))
++
++// bytes 12-15
++#define EXTRA_LENGTH_ANNO(p) ((p)->user_anno_u(3))
++#define SET_EXTRA_LENGTH_ANNO(p, v) ((p)->set_user_anno_u(3, (v)))
++
++// bytes 16-23
++#define PACKET_NUMBER_ANNO(p, n) ((p)->user_anno_u(4 + (n)))
++#define SET_PACKET_NUMBER_ANNO(p, n, v) ((p)->set_user_anno_u(4 + (n), (v)))
++
++// bytes 16-23
++#define FIRST_TIMESTAMP_ANNO(p) (*((Timestamp*) ((p)->all_user_anno_u() + 4)))
++#define SET_FIRST_TIMESTAMP_ANNO(p, v) (*((Timestamp*) ((p)->all_user_anno_u() + 4)) = (v))
++
++// bytes 16-23
++#define IPSEC_SPI_ANNO(p) ((p)->user_anno_u(4))
++#define SET_IPSEC_SPI_ANNO(p, v) ((p)->set_user_anno_u(4, (v)))
++#define IPSEC_SA_DATA_REFERENCE_ANNO(p) ((p)->user_anno_u(5))
++#define SET_IPSEC_SA_DATA_REFERENCE_ANNO(p, v) ((p)->set_user_anno_u(5, (v)))
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/pair.hh click-1.6.0-27/inst/include/click/pair.hh
+--- click-1.6.0/inst/include/click/pair.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/pair.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,56 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_PAIR_HH
++#define CLICK_PAIR_HH
++#include <click/hashcode.hh>
++CLICK_DECLS
++
++template <class T, class U>
++struct Pair {
++ T first;
++ U second;
++ Pair() : first(), second() { }
++ Pair(const T &t, const U &u) : first(t), second(u) { }
++ typedef size_t (Pair<T, U>::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++ inline size_t hashcode() const;
++};
++
++template <class T, class U>
++inline Pair<T, U>::operator unspecified_bool_type() const
++{
++ return first || second ? &Pair<T, U>::hashcode : 0;
++}
++
++template <class T, class U>
++inline bool operator==(const Pair<T, U> &a, const Pair<T, U> &b)
++{
++ return a.first == b.first && a.second == b.second;
++}
++
++template <class T, class U>
++inline bool operator!=(const Pair<T, U> &a, const Pair<T, U> &b)
++{
++ return a.first != b.first || a.second != b.second;
++}
++
++template <class T, class U>
++inline bool operator<(const Pair<T, U> &a, const Pair<T, U> &b)
++{
++ return a.first < b.first
++ || (!(b.first < a.first) && a.second < b.second);
++}
++
++template <class T, class U>
++inline size_t Pair<T, U>::hashcode() const
++{
++ return (CLICK_NAME(hashcode)(first) << 13) ^ CLICK_NAME(hashcode)(second);
++}
++
++template <class T, class U>
++inline Pair<T, U> make_pair(const T &t, const U &u)
++{
++ return Pair<T, U>(t, u);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/pathvars.h click-1.6.0-27/inst/include/click/pathvars.h
+--- click-1.6.0/inst/include/click/pathvars.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/pathvars.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,39 @@
++/* include/click/pathvars.h. Generated from pathvars.h.in by configure. */
++/* Process this file with configure to produce pathvars.h. -*- mode: c -*- */
++#ifndef CLICK_PATHVARS_H
++#define CLICK_PATHVARS_H
++
++/* Directory for binaries. */
++#define CLICK_BINDIR "/d/click/click-1.6.0-27/inst/bin"
++
++/* Directory for packages and kernel module. */
++#define CLICK_LIBDIR "/d/click/click-1.6.0-27/inst/lib"
++
++/* Directory for shared files. */
++#define CLICK_DATADIR "/d/click/click-1.6.0-27/inst/share/click"
++
++/* FreeBSD kernel include directory. */
++#define FREEBSD_INCLUDEDIR "/usr/include"
++
++/* Define if the BSD kernel module driver was compiled. */
++/* #undef HAVE_BSDMODULE_DRIVER */
++
++/* Define if the Click kernel module should provide clickfs. */
++#define HAVE_CLICKFS 1
++
++/* Define if the expat library is available. */
++#define HAVE_EXPAT 1
++
++/* Define if the Click linuxmodule is compiled for a 2.6 kernel. */
++#define HAVE_LINUXMODULE_2_6 1
++
++/* Define if the Linux kernel module driver was compiled. */
++#define HAVE_LINUXMODULE_DRIVER 1
++
++/* Define if the user-level driver was compiled. */
++#define HAVE_USERLEVEL_DRIVER 1
++
++/* Directory containing Linux sources. */
++#define LINUX_SRCDIR "/d/kernels/linux-2.6.27.10-clickport"
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/perfctr-i586.hh click-1.6.0-27/inst/include/click/perfctr-i586.hh
+--- click-1.6.0/inst/include/click/perfctr-i586.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/perfctr-i586.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,33 @@
++#ifndef CLICK_PERFCTR_HH
++#define CLICK_PERFCTR_HH
++#ifdef __KERNEL__
++#include <click/glue.hh>
++#include <asm/msr.h>
++#endif
++
++#define DCU_MISS_OUTSTANDING 0x48
++#define INST_RETIRED 0xC0
++#define IFU_FETCH 0x80
++#define IFU_FETCH_MISS 0x81
++#define IFU_MEM_STALL 0x86
++#define L2_LINES_IN 0x24
++#define L2_LINES_OUT 0x26
++#define L2_IFETCH 0x28 | (0xF<<8)
++#define L2_LD 0x29 | (0xF<<8)
++#define L2_LINES_OUTM 0x27
++#define L2_RQSTS 0x2E | (0xF<<8)
++#define BUS_LOCK_CLOCKS 0x63
++#define BUS_TRAN_RFO 0x66
++#define BUS_TRAN_INVAL 0x69
++#define BUS_TRAN_MEM 0x6F
++
++#define MSR_OS (1<<17)
++#define MSR_OCCURRENCE (1<<18)
++#define MSR_ENABLE (1<<22)
++#define MSR_FLAGS0 (MSR_OS|MSR_OCCURRENCE|MSR_ENABLE)
++#define MSR_FLAGS1 (MSR_OS|MSR_OCCURRENCE)
++
++#define MSR_EVNTSEL0 0x186
++#define MSR_EVNTSEL1 0x187
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/router.hh click-1.6.0-27/inst/include/click/router.hh
+--- click-1.6.0/inst/include/click/router.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/router.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,699 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/router.cc" -*-
++#ifndef CLICK_ROUTER_HH
++#define CLICK_ROUTER_HH
++#include <click/element.hh>
++#include <click/timer.hh>
++#include <click/sync.hh>
++#include <click/task.hh>
++#include <click/standard/threadsched.hh>
++#if CLICK_NS
++# include <click/simclick.h>
++#endif
++CLICK_DECLS
++class Master;
++class ElementFilter;
++class RouterThread;
++class HashMap_ArenaFactory;
++class NotifierSignal;
++class ThreadSched;
++class Handler;
++class NameInfo;
++
++class Router { public:
++
++ /** @name Public Member Functions */
++ //@{
++ // MASTER
++ inline Master* master() const;
++
++ // STATUS
++ inline bool initialized() const;
++ inline bool handlers_ready() const;
++ inline bool running() const;
++
++ // RUNCOUNT AND RUNCLASS
++ enum { STOP_RUNCOUNT = -2147483647 - 1 };
++ inline int32_t runcount() const;
++ void adjust_runcount(int32_t delta);
++ void set_runcount(int32_t rc);
++ inline void please_stop_driver();
++
++ // ELEMENTS
++ inline const Vector<Element*>& elements() const;
++ inline int nelements() const;
++ // eindex -1 returns root_element(), other out-of-range indexes return 0
++ inline Element* element(int eindex) const;
++ inline Element* root_element() const;
++ static Element* element(const Router *router, int eindex);
++
++ Element* find(const String& name, ErrorHandler* errh = 0) const;
++ Element* find(const String& name, String context, ErrorHandler* errh = 0) const;
++ Element* find(const String& name, Element* context, ErrorHandler* errh = 0) const;
++
++ int downstream_elements(Element* e, int port, ElementFilter* filter, Vector<Element*>& result);
++ int upstream_elements(Element* e, int port, ElementFilter* filter, Vector<Element*>& result);
++
++ const String& ename(int eindex) const;
++ const String& elandmark(int eindex) const;
++ const String& econfiguration(int eindex) const;
++ void set_econfiguration(int eindex, const String& conf);
++
++ // HANDLERS
++ enum { FIRST_GLOBAL_HANDLER = 0x40000000 };
++ static int hindex(const Element* e, const String& hname);
++ static void element_hindexes(const Element* e, Vector<int>& result);
++
++ // 'const Handler*' results last until that element/handlername modified
++ static const Handler* handler(const Router* router, int hindex);
++ static const Handler* handler(const Element* e, const String& hname);
++
++ static void add_read_handler(const Element* e, const String& hname, ReadHandlerHook hook, void* thunk);
++ static void add_write_handler(const Element* e, const String& hname, WriteHandlerHook hook, void* thunk);
++ static void set_handler(const Element* e, const String& hname, int mask, HandlerHook hook, void* thunk1 = 0, void* thunk2 = 0);
++ static int change_handler_flags(const Element* e, const String& hname, uint32_t clear_flags, uint32_t set_flags);
++
++ // ATTACHMENTS AND REQUIREMENTS
++ void* attachment(const String& aname) const;
++ void*& force_attachment(const String& aname);
++ void* set_attachment(const String& aname, void* value);
++
++ ErrorHandler* chatter_channel(const String& channel_name) const;
++ HashMap_ArenaFactory* arena_factory() const;
++
++ inline ThreadSched* thread_sched() const;
++ inline void set_thread_sched(ThreadSched* scheduler);
++ inline int initial_home_thread_id(Task* task, bool scheduled) const;
++
++ inline NameInfo* name_info() const;
++ NameInfo* force_name_info();
++
++ // UNPARSING
++ inline const String& configuration_string() const;
++ void unparse(StringAccum& sa, const String& indent = String()) const;
++ void unparse_requirements(StringAccum& sa, const String& indent = String()) const;
++ void unparse_classes(StringAccum& sa, const String& indent = String()) const;
++ void unparse_declarations(StringAccum& sa, const String& indent = String()) const;
++ void unparse_connections(StringAccum& sa, const String& indent = String()) const;
++
++ String element_ports_string(int eindex) const;
++ //@}
++
++ // INITIALIZATION
++ /** @name Internal Functions */
++ //@{
++ Router(const String& configuration, Master* master);
++ ~Router();
++
++ static void static_initialize();
++ static void static_cleanup();
++
++ inline void use();
++ void unuse();
++
++ inline const Vector<String>& requirements() const;
++ void add_requirement(const String& requirement);
++ int add_element(Element* e, const String& name, const String& conf, const String& landmark);
++ int add_connection(int from_idx, int from_port, int to_idx, int to_port);
++#if CLICK_LINUXMODULE
++ int add_module_ref(struct module* module);
++#endif
++
++ inline Router* hotswap_router() const;
++ void set_hotswap_router(Router* router);
++
++ int initialize(ErrorHandler* errh);
++ void activate(bool foreground, ErrorHandler* errh);
++ inline void activate(ErrorHandler* errh);
++
++ int new_notifier_signal(NotifierSignal& signal);
++ //@}
++
++ /** @cond never */
++ // Needs to be public for Lexer, etc., but not useful outside
++ struct Hookup {
++ int idx;
++ int port;
++ Hookup() : idx(-1) { }
++ Hookup(int i, int p) : idx(i), port(p) { }
++ };
++ /** @endcond never */
++
++#if CLICK_NS
++ simclick_node_t *simnode() const;
++ int sim_get_ifid(const char* ifname);
++ int sim_listen(int ifid, int element);
++ int sim_if_ready(int ifid);
++ int sim_write(int ifid, int ptype, const unsigned char *, int len,
++ simclick_simpacketinfo *pinfo);
++ int sim_incoming_packet(int ifid, int ptype, const unsigned char *,
++ int len, simclick_simpacketinfo* pinfo);
++ void sim_trace(const char* event);
++ int sim_get_node_id();
++ int sim_get_next_pkt_id();
++
++ protected:
++ Vector<Vector<int> *> _listenvecs;
++ Vector<int>* sim_listenvec(int ifid);
++#endif
++
++ private:
++
++ enum {
++ ROUTER_NEW, ROUTER_PRECONFIGURE, ROUTER_PREINITIALIZE,
++ ROUTER_LIVE, ROUTER_DEAD // order is important
++ };
++ enum {
++ RUNNING_DEAD = -2, RUNNING_INACTIVE = -1, RUNNING_PREPARING = 0,
++ RUNNING_BACKGROUND = 1, RUNNING_ACTIVE = 2
++ };
++
++ Master* _master;
++
++ atomic_uint32_t _runcount;
++
++ atomic_uint32_t _refcount;
++
++ Vector<Element*> _elements;
++ Vector<String> _element_names;
++ Vector<String> _element_configurations;
++ Vector<String> _element_landmarks;
++ Vector<int> _element_configure_order;
++
++ Vector<Hookup> _hookup_from;
++ Vector<Hookup> _hookup_to;
++
++ /** @cond never */
++ struct Gport {
++ Vector<int> e2g;
++ Vector<int> g2e;
++ int size() const { return g2e.size(); }
++ };
++ /** @endcond never */
++ Gport _gports[2];
++
++ Vector<int> _hookup_gports[2];
++
++ Vector<String> _requirements;
++
++ volatile int _state;
++ bool _have_connections : 1;
++ volatile int _running;
++
++ Vector<int> _ehandler_first_by_element;
++ Vector<int> _ehandler_to_handler;
++ Vector<int> _ehandler_next;
++
++ Vector<int> _handler_first_by_name;
++
++ enum { HANDLER_BUFSIZ = 256 };
++ Handler** _handler_bufs;
++ int _nhandlers_bufs;
++ int _free_handler;
++
++ Vector<String> _attachment_names;
++ Vector<void*> _attachments;
++
++ Element* _root_element;
++ String _configuration;
++
++ enum { NOTIFIER_SIGNALS_CAPACITY = 4096 };
++ atomic_uint32_t* _notifier_signals;
++ int _n_notifier_signals;
++ HashMap_ArenaFactory* _arena_factory;
++ Router* _hotswap_router;
++ ThreadSched* _thread_sched;
++ mutable NameInfo* _name_info;
++
++ Router* _next_router;
++
++#if CLICK_LINUXMODULE
++ Vector<struct module*> _modules;
++#endif
++
++ Router(const Router&);
++ Router& operator=(const Router&);
++
++ void remove_hookup(int);
++ void hookup_error(const Hookup&, bool, const char*, ErrorHandler*);
++ int check_hookup_elements(ErrorHandler*);
++ int check_hookup_range(ErrorHandler*);
++ int check_hookup_completeness(ErrorHandler*);
++
++ int processing_error(const Hookup&, const Hookup&, bool, int, ErrorHandler*);
++ int check_push_and_pull(ErrorHandler*);
++
++ void make_gports();
++ int ngports(bool isout) const { return _gports[isout].g2e.size(); }
++ inline int gport(bool isoutput, const Hookup&) const;
++ inline Hookup gport_hookup(bool isoutput, int) const;
++ void gport_list_elements(bool, const Bitvector&, Vector<Element*>&) const;
++ void make_hookup_gports();
++
++ void set_connections();
++
++ String context_message(int element_no, const char*) const;
++ int element_lerror(ErrorHandler*, Element*, const char*, ...) const;
++
++ // private handler methods
++ void initialize_handlers(bool, bool);
++ inline Handler* xhandler(int) const;
++ int find_ehandler(int, const String&, bool allow_star) const;
++ static inline Handler fetch_handler(const Element*, const String&);
++ void store_local_handler(int, const Handler&);
++ static void store_global_handler(const Handler&);
++ static inline void store_handler(const Element*, const Handler&);
++
++ int global_port_flow(bool forward, Element* first_element, int first_port, ElementFilter* stop_filter, Bitvector& results);
++
++ // global handlers
++ static String router_read_handler(Element*, void*);
++
++ /** @cond never */
++ friend class Master;
++ friend class Task;
++ friend int Element::set_nports(int, int);
++ /** @endcond never */
++
++};
++
++
++class Handler { public:
++
++ enum Flags {
++ OP_READ = 0x001, OP_WRITE = 0x002,
++ READ_PARAM = 0x004, ONE_HOOK = 0x008,
++ SPECIAL_FLAGS = OP_READ | OP_WRITE | READ_PARAM | ONE_HOOK,
++ EXCLUSIVE = 0x010, RAW = 0x020,
++ DRIVER_FLAG_0 = 0x040, DRIVER_FLAG_1 = 0x080,
++ DRIVER_FLAG_2 = 0x100, DRIVER_FLAG_3 = 0x200,
++ USER_FLAG_SHIFT = 10, USER_FLAG_0 = 1 << USER_FLAG_SHIFT
++ };
++
++ inline const String &name() const;
++ inline uint32_t flags() const;
++ inline void *thunk1() const;
++ inline void *thunk2() const;
++
++ inline bool readable() const;
++ inline bool read_param() const;
++ inline bool read_visible() const;
++ inline bool writable() const;
++ inline bool write_visible() const;
++ inline bool visible() const;
++ inline bool exclusive() const;
++ inline bool raw() const;
++
++ inline String call_read(Element *e, ErrorHandler *errh = 0) const;
++ String call_read(Element *e, const String ¶m, bool raw,
++ ErrorHandler *errh) const;
++ int call_write(const String &value, Element *e, bool raw,
++ ErrorHandler *errh) const;
++
++ String unparse_name(Element *e) const;
++ static String unparse_name(Element *e, const String &hname);
++
++ static inline const Handler *blank_handler();
++
++ private:
++
++ String _name;
++ union {
++ HandlerHook h;
++ struct {
++ ReadHandlerHook r;
++ WriteHandlerHook w;
++ } rw;
++ } _hook;
++ void *_thunk1;
++ void *_thunk2;
++ uint32_t _flags;
++ int _use_count;
++ int _next_by_name;
++
++ static const Handler *the_blank_handler;
++
++ Handler(const String & = String());
++
++ bool compatible(const Handler &) const;
++
++ friend class Router;
++
++};
++
++/* The largest size a write handler is allowed to have. */
++#define LARGEST_HANDLER_WRITE 65536
++
++
++inline bool
++operator==(const Router::Hookup& a, const Router::Hookup& b)
++{
++ return a.idx == b.idx && a.port == b.port;
++}
++
++inline bool
++operator!=(const Router::Hookup& a, const Router::Hookup& b)
++{
++ return a.idx != b.idx || a.port != b.port;
++}
++
++/** @brief Increment the router's reference count.
++ *
++ * Routers are reference counted objects. A Router is created with one
++ * reference, which is held by its Master object. Normally the Router and
++ * all its elements will be deleted when the Master drops this reference, but
++ * you can preserve the Router for longer by adding a reference yourself. */
++inline void
++Router::use()
++{
++ _refcount++;
++}
++
++/** @brief Return true iff the router is currently running.
++ *
++ * A running router has been successfully initialized (so running() implies
++ * initialized()), and has not stopped yet. */
++inline bool
++Router::running() const
++{
++ return _running > 0;
++}
++
++/** @brief Return true iff the router has been successfully initialized. */
++inline bool
++Router::initialized() const
++{
++ return _state == ROUTER_LIVE;
++}
++
++/** @brief Return true iff the router's handlers have been initialized.
++ *
++ * handlers_ready() returns false until each element's
++ * Element::add_handlers() method has been called. This happens after
++ * Element::configure(), but before Element::initialize(). */
++inline bool
++Router::handlers_ready() const
++{
++ return _state > ROUTER_PRECONFIGURE;
++}
++
++/** @brief Returns a vector containing all the router's elements.
++ * @invariant elements()[i] == element(i) for all i in range. */
++inline const Vector<Element*>&
++Router::elements() const
++{
++ return _elements;
++}
++
++/** @brief Returns the number of elements in the router. */
++inline int
++Router::nelements() const
++{
++ return _elements.size();
++}
++
++/** @brief Returns the element with index @a eindex.
++ * @param eindex element index, or -1 for root_element()
++ * @invariant If eindex(i) isn't null, then eindex(i)->@link Element::eindex eindex@endlink() == i.
++ *
++ * This function returns the element with index @a eindex. If @a eindex ==
++ * -1, returns root_element(). If @a eindex is otherwise out of range,
++ * returns null. */
++inline Element*
++Router::element(int eindex) const
++{
++ return element(this, eindex);
++}
++
++/** @brief Returns this router's root element.
++ *
++ * Every router has a root Element. This element has Element::eindex -1 and
++ * name "". It is not configured or initialized, and doesn't appear in the
++ * configuration; it exists only for convenience, when other Click code needs
++ * to refer to some arbitrary element at the top level of the compound
++ * element hierarchy. */
++inline Element*
++Router::root_element() const
++{
++ return _root_element;
++}
++
++inline const Vector<String>&
++Router::requirements() const
++{
++ return _requirements;
++}
++
++inline ThreadSched*
++Router::thread_sched() const
++{
++ return _thread_sched;
++}
++
++inline void
++Router::set_thread_sched(ThreadSched* ts)
++{
++ _thread_sched = ts;
++}
++
++inline int
++Router::initial_home_thread_id(Task* t, bool scheduled) const
++{
++ if (!_thread_sched)
++ return ThreadSched::THREAD_UNKNOWN;
++ else
++ return _thread_sched->initial_home_thread_id(t, scheduled);
++}
++
++inline NameInfo*
++Router::name_info() const
++{
++ return _name_info;
++}
++
++/** @brief Returns the Master object for this router. */
++inline Master*
++Router::master() const
++{
++ return _master;
++}
++
++/** @brief Return the router's runcount.
++ *
++ * The runcount is an integer that determines whether the router is running.
++ * A running router has positive runcount. Decrementing the router's runcount
++ * to zero or below will cause the router to stop, although elements like
++ * DriverManager can intercept the stop request and continue processing.
++ *
++ * Elements request that the router stop its processing by calling
++ * adjust_runcount() or please_stop_driver(). */
++inline int32_t
++Router::runcount() const
++{
++ return _runcount.value();
++}
++
++/** @brief Request a driver stop by adjusting the runcount by -1.
++ * @note Equivalent to adjust_runcount(-1). */
++inline void
++Router::please_stop_driver()
++{
++ adjust_runcount(-1);
++}
++
++/** @brief Returns the router's initial configuration string.
++ * @return The configuration string specified to the constructor. */
++inline const String&
++Router::configuration_string() const
++{
++ return _configuration;
++}
++
++inline void
++Router::activate(ErrorHandler* errh)
++{
++ activate(true, errh);
++}
++
++/** @brief Finds an element named @a name.
++ * @param name element name
++ * @param errh optional error handler
++ *
++ * Returns the unique element named @a name, if any. If no element named @a
++ * name is found, reports an error to @a errh and returns null. The error is
++ * "<tt>no element named 'name'</tt>". If @a errh is null, no error is
++ * reported.
++ *
++ * This function is equivalent to find(const String&, String, ErrorHandler*)
++ * with a context argument of the empty string. */
++inline Element *
++Router::find(const String& name, ErrorHandler *errh) const
++{
++ return find(name, "", errh);
++}
++
++inline HashMap_ArenaFactory*
++Router::arena_factory() const
++{
++ return _arena_factory;
++}
++
++/** @brief Returns the currently-installed router this router will eventually
++ * replace.
++ *
++ * This function is only meaningful during a router's initialization. If this
++ * router was installed with the hotswap option, then hotswap_router() will
++ * return the currently-installed router that this router will eventually
++ * replace (assuming error-free initialization). Otherwise, hotswap_router()
++ * will return 0.
++ */
++inline Router*
++Router::hotswap_router() const
++{
++ return _hotswap_router;
++}
++
++inline
++Handler::Handler(const String &name)
++ : _name(name), _thunk1(0), _thunk2(0), _flags(0), _use_count(0),
++ _next_by_name(-1)
++{
++ _hook.rw.r = 0;
++ _hook.rw.w = 0;
++}
++
++inline bool
++Handler::compatible(const Handler& o) const
++{
++ return (_hook.rw.r == o._hook.rw.r && _hook.rw.w == o._hook.rw.w
++ && _thunk1 == o._thunk1 && _thunk2 == o._thunk2
++ && _flags == o._flags);
++}
++
++/** @brief Returns this handler's name. */
++inline const String&
++Handler::name() const
++{
++ return _name;
++}
++
++/** @brief Returns this handler's flags.
++
++ The result is a bitwise-or of flags from the Flags enumeration type. */
++inline uint32_t
++Handler::flags() const
++{
++ return _flags;
++}
++
++/** @brief Returns this handler's first callback data. */
++inline void*
++Handler::thunk1() const
++{
++ return _thunk1;
++}
++
++/** @brief Returns this handler's second callback data. */
++inline void*
++Handler::thunk2() const
++{
++ return _thunk2;
++}
++
++/** @brief Returns true iff this is a valid read handler. */
++inline bool
++Handler::readable() const
++{
++ return _flags & OP_READ;
++}
++
++/** @brief Returns true iff this is a valid read handler that may accept
++ parameters. */
++inline bool
++Handler::read_param() const
++{
++ return _flags & READ_PARAM;
++}
++
++/** @brief Returns true iff this is a valid visible read handler.
++
++ Only visible handlers may be called from outside the router
++ configuration. */
++inline bool
++Handler::read_visible() const
++{
++ return _flags & OP_READ;
++}
++
++/** @brief Returns true iff this is a valid write handler. */
++inline bool
++Handler::writable() const
++{
++ return _flags & OP_WRITE;
++}
++
++/** @brief Returns true iff this is a valid visible write handler.
++
++ Only visible handlers may be called from outside the router
++ configuration. */
++inline bool
++Handler::write_visible() const
++{
++ return _flags & OP_WRITE;
++}
++
++/** @brief Returns true iff this handler is visible. */
++inline bool
++Handler::visible() const
++{
++ return _flags & (OP_READ | OP_WRITE);
++}
++
++/** @brief Returns true iff this handler is exclusive.
++
++ Exclusive means mutually exclusive with all other router processing. In
++ the Linux kernel module driver, reading or writing an exclusive handler
++ using the Click filesystem will first lock all router threads and
++ handlers. */
++inline bool
++Handler::exclusive() const
++{
++ return _flags & EXCLUSIVE;
++}
++
++/** @brief Returns true iff quotes should be removed when calling this
++ handler.
++
++ A raw handler expects and returns raw text. Click will unquote quoted
++ text before passing it to a raw handler, and (in the Linux kernel module)
++ will not add a courtesy newline to the end of a raw handler's value. */
++inline bool
++Handler::raw() const
++{
++ return _flags & RAW;
++}
++
++/** @brief Call a read handler without parameters.
++ @param e element on which to call the handler
++ @param errh error handler
++
++ The element must be nonnull; to call a global handler, pass the relevant
++ router's Router::root_element(). @a errh may be null, in which case
++ errors are ignored. */
++inline String
++Handler::call_read(Element* e, ErrorHandler* errh) const
++{
++ return call_read(e, String(), false, errh);
++}
++
++/** @brief Returns a handler incapable of doing anything.
++ *
++ * The returned handler returns false for readable() and writable()
++ * and has flags() of zero. */
++inline const Handler *
++Handler::blank_handler()
++{
++ return the_blank_handler;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/routerthread.hh click-1.6.0-27/inst/include/click/routerthread.hh
+--- click-1.6.0/inst/include/click/routerthread.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/routerthread.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,328 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/routerthread.cc" -*-
++#ifndef CLICK_ROUTERTHREAD_HH
++#define CLICK_ROUTERTHREAD_HH
++#include <click/sync.hh>
++#include <click/vector.hh>
++#if CLICK_LINUXMODULE
++# include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++# include <linux/sched.h>
++CLICK_CXX_UNPROTECT
++# include <click/cxxunprotect.h>
++#endif
++#if CLICK_BSDMODULE
++# include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++# include <sys/systm.h>
++CLICK_CXX_UNPROTECT
++# include <click/cxxunprotect.h>
++#endif
++
++#define CLICK_DEBUG_SCHEDULING 0
++
++// NB: user must #include <click/task.hh> before <click/routerthread.hh>.
++// We cannot #include <click/task.hh> ourselves because of circular #include
++// dependency.
++CLICK_DECLS
++
++class RouterThread
++#ifndef HAVE_TASK_HEAP
++ : private Task
++#endif
++{ public:
++
++ enum { THREAD_QUIESCENT = -1, THREAD_STRONG_UNSCHEDULE = -2,
++ THREAD_UNKNOWN = -1000 };
++
++ inline int thread_id() const;
++
++ // Task list functions
++ inline bool active() const;
++ inline Task *task_begin() const;
++ inline Task *task_next(Task *task) const;
++ inline Task *task_end() const;
++
++ inline void lock_tasks();
++ inline bool attempt_lock_tasks();
++ inline void unlock_tasks();
++
++ inline Master* master() const;
++ void driver();
++ void driver_once();
++
++ void unschedule_router_tasks(Router*);
++
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ // min_cpu_share() and max_cpu_share() are expressed on a scale with
++ // Task::MAX_UTILIZATION == 100%.
++ unsigned min_cpu_share() const { return _min_click_share; }
++ unsigned max_cpu_share() const { return _max_click_share; }
++ unsigned cur_cpu_share() const { return _cur_click_share; }
++ void set_cpu_share(unsigned min_share, unsigned max_share);
++#endif
++
++#if CLICK_LINUXMODULE || CLICK_BSDMODULE
++ bool greedy() const { return _greedy; }
++ void set_greedy(bool g) { _greedy = g; }
++#endif
++
++ inline void wake();
++
++#if CLICK_DEBUG_SCHEDULING
++ enum { S_RUNNING, S_PAUSED, S_TIMER, S_BLOCKED };
++ int thread_state() const { return _thread_state; }
++ static String thread_state_name(int);
++ uint32_t driver_epoch() const { return _driver_epoch; }
++ uint32_t driver_task_epoch() const { return _driver_task_epoch; }
++ timeval task_epoch_time(uint32_t epoch) const;
++# if CLICK_LINUXMODULE
++ struct task_struct *sleeper() const { return _linux_task; }
++# endif
++#endif
++
++ unsigned _tasks_per_iter;
++ unsigned _iters_per_timers;
++ unsigned _iters_per_os;
++
++ private:
++
++#ifdef HAVE_TASK_HEAP
++ Vector<Task*> _task_heap;
++ int _task_heap_hole;
++ unsigned _pass;
++#endif
++
++ Master *_master;
++ int _id;
++
++#if CLICK_LINUXMODULE
++ struct task_struct *_linux_task;
++ spinlock_t _lock;
++ atomic_uint32_t _task_lock_waiting;
++#endif
++
++ uint32_t _any_pending;
++
++#if CLICK_LINUXMODULE
++ bool _greedy;
++#endif
++
++#if CLICK_BSDMODULE
++ // XXX FreeBSD
++ u_int64_t _old_tsc; /* MARKO - temp. */
++ void *_sleep_ident;
++ int _oticks;
++ bool _greedy;
++#endif
++
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ enum { C_CLICK, C_KERNEL, NCLIENTS };
++ struct Client { // top-level stride clients
++ unsigned pass;
++ unsigned stride;
++ int tickets;
++ Client() : pass(0), tickets(0) { }
++ };
++ Client _clients[NCLIENTS];
++ unsigned _global_pass; // global pass
++ unsigned _max_click_share; // maximum allowed Click share of CPU
++ unsigned _min_click_share; // minimum allowed Click share of CPU
++ unsigned _cur_click_share; // current Click share
++#endif
++
++#if CLICK_DEBUG_SCHEDULING
++ int _thread_state;
++ uint32_t _driver_epoch;
++ uint32_t _driver_task_epoch;
++ enum { TASK_EPOCH_BUFSIZ = 32 };
++ uint32_t _task_epoch_first;
++ timeval _task_epoch_time[TASK_EPOCH_BUFSIZ];
++#endif
++
++ // called by Master
++ RouterThread(Master *, int);
++ ~RouterThread();
++
++ // task requests
++ inline void add_pending();
++
++ // task running functions
++ inline void driver_lock_tasks();
++ inline void driver_unlock_tasks();
++ inline void run_tasks(int ntasks);
++ inline void run_os();
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ void client_set_tickets(int client, int tickets);
++ inline void client_update_pass(int client, const struct timeval &before, const struct timeval &after);
++ inline void check_restride(struct timeval &before, const struct timeval &now, int &restride_iter);
++#endif
++#ifdef HAVE_TASK_HEAP
++ void task_reheapify_from(int pos, Task*);
++#endif
++
++ friend class Task;
++ friend class Master;
++
++};
++
++
++/** @brief Returns this thread's ID.
++ *
++ * The result is >= 0 for true threads, and < 0 for threads that never run any
++ * of their associated Tasks.
++ */
++inline int
++RouterThread::thread_id() const
++{
++ return _id;
++}
++
++/** @brief Returns this thread's associated Master. */
++inline Master*
++RouterThread::master() const
++{
++ return _master;
++}
++
++/** @brief Returns whether any tasks are scheduled.
++ *
++ * Returns false iff no tasks are scheduled and no events are pending. Since
++ * not all events actually matter (for example, a Task might have been
++ * scheduled and then subsequently unscheduled), active() may temporarily
++ * return true even when no real events are outstanding.
++ */
++inline bool
++RouterThread::active() const
++{
++#ifdef HAVE_TASK_HEAP
++ return _task_heap.size() != 0 || _any_pending;
++#else
++ return ((const Task *)_next != this) || _any_pending;
++#endif
++}
++
++/** @brief Returns the beginning of the scheduled task list.
++ *
++ * Each RouterThread maintains a list of all currently-scheduled tasks.
++ * Elements may traverse this list with the task_begin(), task_next(), and
++ * task_end() functions, using iterator-like code such as:
++ *
++ * @code
++ * thread->lock_tasks();
++ * for (Task *t = thread->task_begin();
++ * t != thread->task_end();
++ * t = thread->task_next(t)) {
++ * // ... do something with t...
++ * }
++ * thread->unlock_tasks();
++ * @endcode
++ *
++ * The thread's task lock must be held during the traversal, as shown above.
++ *
++ * The return value may not be a real task. Test it against task_end() before
++ * use.
++ *
++ * @sa task_next, task_end, lock_tasks, unlock_tasks
++ */
++inline Task *
++RouterThread::task_begin() const
++{
++#ifdef HAVE_TASK_HEAP
++ int p = _task_heap_hole;
++ return (p < _task_heap.size() ? _task_heap[p] : 0);
++#else
++ return _next;
++#endif
++}
++
++/** @brief Returns the task following @a task in the scheduled task list.
++ * @param task the current task
++ *
++ * The return value may not be a real task. Test it against task_end() before
++ * use. However, the @a task argument must be a real task; do not attempt to
++ * call task_next(task_end()).
++ *
++ * @sa task_begin for usage, task_end
++ */
++inline Task *
++RouterThread::task_next(Task *task) const
++{
++#ifdef HAVE_TASK_HEAP
++ int p = task->_schedpos + 1;
++ return (p < _task_heap.size() ? _task_heap[p] : 0);
++#else
++ return task->_next;
++#endif
++}
++
++/** @brief Returns the end of the scheduled task list.
++ *
++ * The return value is not a real task
++ *
++ * @sa task_begin for usage, task_next
++ */
++inline Task *
++RouterThread::task_end() const
++{
++#ifdef HAVE_TASK_HEAP
++ return 0;
++#else
++ return (Task *) this;
++#endif
++}
++
++inline void
++RouterThread::lock_tasks()
++{
++#if CLICK_LINUXMODULE
++ if (unlikely(current != _linux_task)) {
++ _task_lock_waiting++;
++ spin_lock(&_lock);
++ _task_lock_waiting--;
++ }
++#endif
++}
++
++inline bool
++RouterThread::attempt_lock_tasks()
++{
++#if CLICK_LINUXMODULE
++ if (likely(current == _linux_task))
++ return true;
++ return spin_trylock(&_lock);
++#else
++ return true;
++#endif
++}
++
++inline void
++RouterThread::unlock_tasks()
++{
++#if CLICK_LINUXMODULE
++ if (unlikely(current != _linux_task))
++ spin_unlock(&_lock);
++#endif
++}
++
++inline void
++RouterThread::wake()
++{
++#if CLICK_LINUXMODULE
++ if (_linux_task)
++ wake_up_process(_linux_task);
++#endif
++#if CLICK_BSDMODULE && !BSD_NETISRSCHED
++ if (_sleep_ident)
++ wakeup_one(&_sleep_ident);
++#endif
++}
++
++inline void
++RouterThread::add_pending()
++{
++ _any_pending = 1;
++ wake();
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/simclick.h click-1.6.0-27/inst/include/click/simclick.h
+--- click-1.6.0/inst/include/click/simclick.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/simclick.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,114 @@
++#ifndef SIMCLICK_H
++#define SIMCLICK_H
++/*
++ * simclick.h
++ *
++ * API for sending packets to Click. Mostly intended for use
++ * by a network simulator which wants to use Click to do routing.
++ *
++ */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * Packet types used - generally going to be ethernet, but could
++ * possibly be something else I suppose...
++ */
++#define SIMCLICK_PTYPE_UNKNOWN 0
++#define SIMCLICK_PTYPE_ETHER 1
++#define SIMCLICK_PTYPE_IP 2
++
++/*
++ * Not a whole lot to this. We have to create a click router object
++ * and also send packets and trigger events.
++ */
++
++/*
++ * This contains per packet data we need to preserve when the packet gets
++ * dragged through click. Heavily biased towards ns-2 right now.
++ */
++typedef struct {
++ int id; /* Simulator ID number for the packet */
++ int fid; /* Simulator flow ID number for the packet */
++ int simtype; /* Original simulator packet type - useful
++ * for morphing between raw and simulator
++ * packet types */
++} simclick_simpacketinfo;
++
++
++/*
++ * Opaque handles for the sim and click instances
++ */
++typedef struct simclick_node {
++ void *clickinfo;
++ struct timeval curtime;
++} simclick_node_t;
++
++int simclick_click_create(simclick_node_t *sim, const char *router_file);
++
++int simclick_click_send(simclick_node_t *sim,
++ int ifid,int type,const unsigned char* data,int len,
++ simclick_simpacketinfo* pinfo);
++int simclick_sim_send(simclick_node_t *sim,
++ int ifid,int type, const unsigned char* data,int len,
++ simclick_simpacketinfo*);
++
++void simclick_click_run(simclick_node_t *sim);
++
++void simclick_click_kill(simclick_node_t *sim);
++
++/*
++ * simclick_click_read_handler will allocate a buffer of adequate length
++ * to receive the handler information. This buffer must be freed
++ * by the caller. If a non-null value for the "memalloc" parameter
++ * is passed in, simclick_click_read_handler will use that function
++ * to allocate the memory. If there's a null value there, "malloc" will
++ * be used by default. The "memparam" parameter is a caller-specified
++ * value which will be passed back to the memory allocation function.
++ */
++typedef void* (*SIMCLICK_MEM_ALLOC)(size_t,void*);
++char* simclick_click_read_handler(simclick_node_t *sim,
++ const char* elementname,
++ const char* handlername,
++ SIMCLICK_MEM_ALLOC memalloc,
++ void* memparam);
++
++int simclick_click_write_handler(simclick_node_t *sim,
++ const char* elemname, const char* handlername,
++ const char* writestring);
++
++/*
++ * We also provide a gettimeofday substitute which utilizes the
++ * state info passed to us by the simulator.
++ */
++int simclick_gettimeofday(struct timeval* tv);
++
++/*
++ * The simulated system also has to provide a few services to click,
++ * notably some way of injecting packets back into the system,
++ * mapping interface names to id numbers, and arranging for click
++ * to execute at a specified time in the future.
++ * We implement
++ */
++#define SIMCLICK_VERSION 0 // none
++#define SIMCLICK_SUPPORTS 1 // int call
++#define SIMCLICK_IFID_FROM_NAME 2 // const char *ifname
++#define SIMCLICK_IPADDR_FROM_NAME 3 // const char *ifname, char *buf, int len
++#define SIMCLICK_MACADDR_FROM_NAME 4 // const char *ifname, char *buf, int len
++#define SIMCLICK_SCHEDULE 5 // struct timeval *when
++#define SIMCLICK_GET_NODE_NAME 6 // char *buf, int len
++#define SIMCLICK_IF_READY 7 // int ifid
++#define SIMCLICK_TRACE 8 // const char *event
++#define SIMCLICK_GET_NODE_ID 9 // none
++#define SIMCLICK_GET_NEXT_PKT_ID 10 // none
++#define SIMCLICK_CHANGE_CHANNEL 11 // int ifid, int channelid
++
++int simclick_sim_command(simclick_node_t *sim, int cmd, ...);
++int simclick_click_command(simclick_node_t *sim, int cmd, ...);
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+diff -Nurb click-1.6.0/inst/include/click/skbmgr.hh click-1.6.0-27/inst/include/click/skbmgr.hh
+--- click-1.6.0/inst/include/click/skbmgr.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/skbmgr.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,16 @@
++// -*- c-basic-offset: 2; related-file-name: "../../linuxmodule/skbmgr.cc" -*-
++#ifndef CLICK_SKBMGR_HH
++#define CLICK_SKBMGR_HH
++CLICK_DECLS
++
++void skbmgr_init();
++void skbmgr_cleanup();
++
++/* allocate skbs. Number of skbs allocated is stored in the want variable */
++struct sk_buff *skbmgr_allocate_skbs(unsigned headroom, unsigned size, int *want);
++
++/* recycle skb back into pool */
++void skbmgr_recycle_skbs(struct sk_buff *);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/addressinfo.hh click-1.6.0-27/inst/include/click/standard/addressinfo.hh
+--- click-1.6.0/inst/include/click/standard/addressinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/addressinfo.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,109 @@
++// -*- c-basic-offset: 2; related-file-name: "../../../elements/standard/addressinfo.cc" -*-
++#ifndef CLICK_ADDRESSINFO_HH
++#define CLICK_ADDRESSINFO_HH
++#include <click/element.hh>
++#include <click/hashmap.hh>
++#ifdef HAVE_IP6
++# include <click/ip6address.hh>
++#endif
++CLICK_DECLS
++
++/*
++=c
++
++AddressInfo(NAME ADDRESS [ADDRESS...], ...)
++
++=s information
++
++specifies address information
++
++=io
++
++None
++
++=d
++
++Lets you use mnemonic names for IPv4 and IPv6 addresses, IPv4 and IPv6
++address prefixes, and Ethernet addresses. Each argument has the form `NAME
++ADDRESS [ADDRESS...]', which associates the given ADDRESSes with NAME. For
++example, if a configuration contains this AddressInfo element,
++
++ AddressInfo(mauer 10.0.0.1, mazu 10.0.0.10);
++
++then other configuration strings can use C<mauer> and C<mazu> as mnemonics
++for the IP addresses 10.0.0.1 and 10.0.0.10, respectively.
++
++The mnemonic names introduced by AddressInfo elements are local with
++respect to compound elements. That is, names created inside a compound
++element apply only within that compound element and its subelements. For
++example:
++
++ AddressInfo(mauer 10.0.0.1);
++ compound :: {
++ AddressInfo(mazu 10.0.0.10);
++ ... -> IPEncap(6, mauer, mazu) -> ... // OK
++ };
++ ... -> IPEncap(6, mauer, mazu) -> ... // error: `mazu' undefined
++
++Any name can be simultaneously associated with an IP address, an IP network
++address, and an Ethernet address. The kind of address that is returned is
++generally determined from context. For example:
++
++ AddressInfo(mauer 10.0.0.1/8 00:50:BA:85:84:A9);
++ ... -> IPEncap(6, mauer, ...) // as IP address
++ -> EtherEncap(0x0800, mauer, ...) -> ... // as Ethernet address
++ ... -> ARPResponder(mauer) -> ... // as IP prefix AND Ethernet address!
++
++An optional suffix makes the context unambiguous. C<NAME> is an ambiguous
++reference to some address, but C<NAME:ip> is always an IPv4 address,
++C<NAME:ipnet> is always an IPv4 network address (IPv4 address prefix),
++C<NAME:ip6> is always an IPv6 address, C<NAME:ip6net> is always an IPv6
++network address, and C<NAME:eth> is always an Ethernet address.
++
++=head1 DEFAULT ADDRESSES
++
++If you do not define an address for a given name, AddressInfo will use the
++default, if any. Defaults are as follows:
++
++=over 2
++
++=item *
++
++If DEVNAME is the name of an Ethernet device, then C<DEVNAME:eth> defaults to
++DEVNAME's Ethernet address. (At userlevel, this works only on BSD and Linux.)
++
++=item *
++
++C<DEVNAME:ip> defaults to the first primary IPv4 address associated with the
++device DEVNAME.
++
++=back
++
++These defaults are not available on all platforms.
++
++=a
++
++PortInfo */
++
++class AddressInfo : public Element { public:
++
++ AddressInfo();
++ ~AddressInfo();
++
++ const char *class_name() const { return "AddressInfo"; }
++
++ int configure_phase() const { return CONFIGURE_PHASE_FIRST; }
++ int configure(Vector<String> &, ErrorHandler *);
++
++ static bool query_ip(String, unsigned char *, Element *);
++ static bool query_ip_prefix(String, unsigned char *, unsigned char *, Element *);
++#ifdef HAVE_IP6
++ static bool query_ip6(String, unsigned char *, Element *);
++ static bool query_ip6_prefix(String, unsigned char *, int *, Element *);
++#endif
++ static bool query_ethernet(String, unsigned char *, Element *);
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/alignmentinfo.hh click-1.6.0-27/inst/include/click/standard/alignmentinfo.hh
+--- click-1.6.0/inst/include/click/standard/alignmentinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/alignmentinfo.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,49 @@
++// -*- c-basic-offset: 2; related-file-name: "../../../elements/standard/alignmentinfo.cc" -*-
++#ifndef CLICK_ALIGNMENTINFO_HH
++#define CLICK_ALIGNMENTINFO_HH
++#include <click/element.hh>
++CLICK_DECLS
++
++/*
++ * =c
++ * AlignmentInfo(ELEMENT [MODULUS OFFSET ...], ...)
++ * =s information
++ * specifies alignment information
++ * =io
++ * None
++ * =d
++ * Provides information about the packet alignment specified elements can
++ * expect. Each configuration argument has the form
++ * `ELEMENT [MODULUS0 OFFSET0 MODULUS1 OFFSET1 ...]',
++ * where there are zero or more MODULUS-OFFSET pairs.
++ * All packets arriving at ELEMENT's
++ * I<n>th input will start `OFFSETI<n>' bytes
++ * off from a `MODULUSI<n>'-byte boundary.
++ * =n
++ * This element is inserted automatically by click-align(1).
++ * =a Align, click-align(1)
++ */
++
++class AlignmentInfo : public Element { public:
++
++ AlignmentInfo();
++ ~AlignmentInfo();
++
++ const char *class_name() const { return "AlignmentInfo"; }
++ int configure_phase() const { return CONFIGURE_PHASE_INFO; }
++ int configure(Vector<String> &, ErrorHandler *);
++
++ bool query1(Element *, int port, int &chunk, int &offset) const;
++ static bool query(Element *, int port, int &chunk, int &offset);
++
++ private:
++
++ Vector<int> _elem_offset;
++ Vector<int> _elem_icount;
++ Vector<int> _chunks;
++ Vector<int> _offsets;
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/errorelement.hh click-1.6.0-27/inst/include/click/standard/errorelement.hh
+--- click-1.6.0/inst/include/click/standard/errorelement.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/errorelement.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,36 @@
++// -*- c-basic-offset: 4; related-file-name: "../../../elements/standard/errorelement.cc" -*-
++#ifndef CLICK_ERRORELEMENT_HH
++#define CLICK_ERRORELEMENT_HH
++#include <click/element.hh>
++CLICK_DECLS
++
++/*
++ * =c
++ * Error(...)
++ * =s debugging
++ * always fails
++ * =d
++ * The Error element always fails to initialize. It has any number of inputs
++ * and outputs, and accepts any configuration string without complaint. It is
++ * useful to prevent a router from initializing while avoiding
++ * spurious error messages about bad configuration strings or connections.
++ * =a Message
++ */
++
++class ErrorElement : public Element { public:
++
++ ErrorElement();
++ ~ErrorElement();
++
++ const char *class_name() const { return "Error"; }
++ const char *port_count() const { return "-/-"; }
++ const char *processing() const { return AGNOSTIC; }
++ const char *flow_code() const { return "x/y"; }
++
++ int configure(Vector<String> &, ErrorHandler *);
++ int initialize(ErrorHandler *);
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/portinfo.hh click-1.6.0-27/inst/include/click/standard/portinfo.hh
+--- click-1.6.0/inst/include/click/standard/portinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/portinfo.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,73 @@
++// -*- c-basic-offset: 4; related-file-name: "../../../elements/standard/portinfo.cc" -*-
++#ifndef CLICK_PORTINFO_HH
++#define CLICK_PORTINFO_HH
++#include <click/element.hh>
++#include <click/hashmap.hh>
++CLICK_DECLS
++
++/*
++=c
++
++PortInfo(NAME PORT[/PROTOCOL], ...)
++
++=s information
++
++stores named TCP/UDP port information
++
++=io
++
++None
++
++=d
++
++Lets you use mnemonic names for TCP and UDP ports. Each argument has the form
++`NAME PORT[/PROTOCOL]', which associates the given PORT/PROTOCOL pair with the
++NAME. If PROTOCOL is left off, the NAME applies to both TCP and UDP. For
++example, in a configuration containing
++
++ PortInfo(ssh 22, http 80),
++
++configuration strings can use C<ssh> and C<http> as mnemonics for the port
++numbers 22 and 80, respectively.
++
++PortInfo names are local with respect to compound elements. That is, names
++created inside a compound element apply only within that compound element and
++its subelements. For example:
++
++ PortInfo(src 10);
++ compound :: {
++ PortInfo(dst 100);
++ ... -> UDPIPEncap(1.0.0.1, src, 2.0.0.1, dst) -> ... // OK
++ };
++ ... -> UDPIPEncap(1.0.0.1, src, 2.0.0.1, dst) -> ...
++ // error: `dst' undefined
++
++=n
++
++If you do not define a port for a given name, PortInfo will use the default,
++if any. At user level, PortInfo uses the L<getservbyname(3)> function to look
++up ports by name. In the kernel, there are no default ports.
++
++PortInfo will parse arguments containing more than one name, as `C<NAME
++PORT/PROTOCOL NAME...>', and comments starting with `C<#>' are ignored. Thus,
++lines from F</etc/services> can be used verbatim as PortInfo configuration
++arguments.
++
++=a
++
++AddressInfo */
++
++class PortInfo : public Element { public:
++
++ PortInfo();
++ ~PortInfo();
++
++ const char *class_name() const { return "PortInfo"; }
++
++ int configure_phase() const { return CONFIGURE_PHASE_FIRST; }
++ int configure(Vector<String> &, ErrorHandler *);
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/scheduleinfo.hh click-1.6.0-27/inst/include/click/standard/scheduleinfo.hh
+--- click-1.6.0/inst/include/click/standard/scheduleinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/scheduleinfo.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,105 @@
++// -*- c-basic-offset: 4; related-file-name: "../../../elements/standard/scheduleinfo.cc" -*-
++#ifndef CLICK_SCHEDULEINFO_HH
++#define CLICK_SCHEDULEINFO_HH
++#include <click/element.hh>
++CLICK_DECLS
++
++/*
++=c
++
++ScheduleInfo(ELEMENT PARAM, ...)
++
++=s information
++
++specifies scheduling parameters
++
++=io
++
++None
++
++=d
++
++Provides scheduling parameters for specified elements. Each configuration
++argument has the form `ELEMENT PARAM', meaning that the element
++named ELEMENT has scheduling parameter PARAM. Scheduling
++parameters are real numbers that set how often one element should be
++scheduled in relation to another. For example,
++if elements A and B have
++scheduling parameters 2 and 0.5, respectively, then A will be scheduled
++2/0.5 = 4 times as often as B. The default scheduling parameter is 1.
++
++ScheduleInfo elements inside a compound element can specify scheduling
++parameters for that compound's components.
++Outer ScheduleInfo elements
++can specify a ``scheduling parameter'' for the compound
++element as a whole. This ``scheduling parameter'' is really a scaling
++factor affecting the compound's components. For example, consider this
++configuration,
++
++ elementclass Compound {
++ i :: InfiniteSource -> output;
++ ScheduleInfo(i 0.5);
++ }
++ c :: Compound -> Discard;
++ ScheduleInfo(c 4);
++
++which is the same as the following configuration, after compound elements
++are expanded.
++
++ c/i :: InfiniteSource -> Discard@3 :: Discard;
++ c/ScheduleInfo@2 :: ScheduleInfo(i 0.5);
++ ScheduleInfo@4 :: ScheduleInfo(c 4);
++
++The name of the first ScheduleInfo element starts with `c/', so it is
++used to look up scheduling parameters for elements named `c/I<whatever>'.
++V<>(This includes all components of the compound element `c'.)
++The second ScheduleInfo element, however, has no slash in its name,
++so it is used to look up all scheduling parameters,
++including scaling factors for compound elements.
++The InfiniteSource's final scaling parameter will be 2:
++the scaling factor 4 times the local scheduling parameter 0.5.
++
++An outer ScheduleInfo element can override local scheduling parameters.
++For example, if the second ScheduleInfo element above was
++
++ ScheduleInfo@4 :: ScheduleInfo(c 4, c/i 10.5)
++
++then the InfiniteSource's final scaling parameter would be 10.5.
++*/
++
++class ScheduleInfo : public Element { public:
++
++ enum { FRAC_BITS = 10 };
++
++ ScheduleInfo();
++ ~ScheduleInfo();
++
++ const char* class_name() const { return "ScheduleInfo"; }
++
++ int configure_phase() const { return CONFIGURE_PHASE_INFO; }
++ int configure(Vector<String>&, ErrorHandler*);
++
++ bool query(const String&, int&) const;
++ bool query_prefixes(const String&, int&, String&) const;
++ static int query(Element*, ErrorHandler*);
++ static void initialize_task(Element*, Task*, bool sched, ErrorHandler*);
++ static void initialize_task(Element*, Task*, ErrorHandler*);
++ static void join_scheduler(Element*, Task*, ErrorHandler*);
++
++};
++
++
++inline void
++ScheduleInfo::initialize_task(Element* e, Task* t, ErrorHandler* errh)
++{
++ initialize_task(e, t, true, errh);
++}
++
++inline void
++ScheduleInfo::join_scheduler(Element* e, Task* t, ErrorHandler* errh)
++{
++ initialize_task(e, t, true, errh);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/storage.hh click-1.6.0-27/inst/include/click/standard/storage.hh
+--- click-1.6.0/inst/include/click/standard/storage.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/storage.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,49 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_STORAGE_HH
++#define CLICK_STORAGE_HH
++CLICK_DECLS
++
++class Storage { public:
++
++ Storage() : _head(0), _tail(0) { }
++
++ operator bool() const { return _head != _tail; }
++ bool empty() const { return _head == _tail; }
++ int size() const;
++ int size(int head, int tail) const;
++ int capacity() const { return _capacity; }
++
++ int head() const { return _head; }
++ int tail() const { return _tail; }
++
++ int next_i(int i) const { return (i!=_capacity ? i+1 : 0); }
++ int prev_i(int i) const { return (i!=0 ? i-1 : _capacity); }
++
++ // to be used with care
++ void set_capacity(int c) { _capacity = c; }
++ void set_head(int h) { _head = h; }
++ void set_tail(int t) { _tail = t; }
++
++ protected:
++
++ int _capacity;
++ volatile int _head;
++ volatile int _tail;
++
++};
++
++inline int
++Storage::size(int head, int tail) const
++{
++ int x = tail - head;
++ return (x >= 0 ? x : _capacity + x + 1);
++}
++
++inline int
++Storage::size() const
++{
++ return size(_head, _tail);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/standard/threadsched.hh click-1.6.0-27/inst/include/click/standard/threadsched.hh
+--- click-1.6.0/inst/include/click/standard/threadsched.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/standard/threadsched.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,19 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_THREADSCHED_HH
++#define CLICK_THREADSCHED_HH
++CLICK_DECLS
++
++class ThreadSched { public:
++
++ enum { THREAD_QUIESCENT = -1, THREAD_STRONG_UNSCHEDULE = -2,
++ THREAD_UNKNOWN = -1000 };
++
++ ThreadSched() { }
++ virtual ~ThreadSched() { }
++
++ virtual int initial_home_thread_id(Task *, bool);
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/straccum.hh click-1.6.0-27/inst/include/click/straccum.hh
+--- click-1.6.0/inst/include/click/straccum.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/straccum.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,518 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/straccum.cc" -*-
++#ifndef CLICK_STRACCUM_HH
++#define CLICK_STRACCUM_HH
++#include <click/glue.hh>
++#include <click/string.hh>
++#ifdef CLICK_LINUXMODULE
++# include <asm/string.h>
++#elif defined(CLICK_BSDMODULE)
++# include <sys/systm.h>
++#else /* User-space */
++# include <string.h>
++#endif
++CLICK_DECLS
++
++/** @file <click/straccum.hh>
++ @brief Click's StringAccum class, used to construct Strings efficiently from pieces.
++*/
++
++class StringAccum { public:
++
++ /** @brief Create an empty StringAccum (with length 0). */
++ StringAccum()
++ : _s(0), _len(0), _cap(0) {
++ }
++
++ explicit inline StringAccum(int);
++
++ /** @brief Destroy a StringAccum, freeing its memory. */
++ ~StringAccum() {
++ if (_cap >= 0)
++ CLICK_LFREE(_s, _cap);
++ }
++
++ /** @brief Return the contents of the StringAccum.
++ @return The StringAccum's contents.
++
++ The return value is null if the StringAccum is empty or out-of-memory.
++ The returned data() value points to writable memory (unless the
++ StringAccum itself is const). */
++ inline const char *data() const {
++ return reinterpret_cast<const char *>(_s);
++ }
++
++ /** @overload */
++ inline char *data() {
++ return reinterpret_cast<char *>(_s);
++ }
++
++ /** @brief Return the length of the StringAccum. */
++ int length() const {
++ return _len;
++ }
++
++ /** @brief Return the StringAccum's current capacity.
++
++ The capacity is the maximum length the StringAccum can hold without
++ incurring a memory allocation. Returns -1 for out-of-memory
++ StringAccums. */
++ int capacity() const {
++ return _cap;
++ }
++
++ typedef int (StringAccum::*unspecified_bool_type)() const;
++
++ /** @brief Return true iff the StringAccum contains characters.
++
++ Returns false for empty and out-of-memory StringAccums. */
++ operator unspecified_bool_type() const {
++ return _len != 0 ? &StringAccum::capacity : 0;
++ }
++
++ /** @brief Returns true iff the StringAccum does not contain characters.
++
++ Returns true for empty and out-of-memory StringAccums. */
++ bool operator!() const {
++ return _len == 0;
++ }
++
++ /** @brief Returns true iff the StringAccum is out-of-memory. */
++ bool out_of_memory() const {
++ return _cap < 0;
++ }
++
++ const char *c_str();
++
++ /** @brief Returns the <a>i</a>th character in the string.
++ @param i character index.
++
++ @pre 0 <= @a i < length() */
++ char operator[](int i) const {
++ assert(i>=0 && i<_len);
++ return static_cast<char>(_s[i]);
++ }
++
++ /** @brief Returns a reference to the <a>i</a>th character in the string.
++ @param i character index.
++
++ @pre 0 <= @a i < length() */
++ char &operator[](int i) {
++ assert(i>=0 && i<_len);
++ return reinterpret_cast<char &>(_s[i]);
++ }
++
++ /** @brief Returns the last character in the string.
++ @pre length() > 0 */
++ char back() const {
++ assert(_len > 0);
++ return static_cast<char>(_s[_len - 1]);
++ }
++
++ /** @brief Returns a reference to the last character in the string.
++ @pre length() > 0 */
++ char &back() {
++ assert(_len > 0);
++ return reinterpret_cast<char &>(_s[_len - 1]);
++ }
++
++ inline void clear();
++
++ inline char *reserve(int n);
++ void set_length(int len);
++ void adjust_length(int delta);
++ inline char *extend(int nadjust, int nreserve = 0);
++ void pop_back(int n = 1);
++
++ inline void append(char c);
++ inline void append(unsigned char c);
++ void append_fill(int c, int len);
++
++ inline void append(const char *suffix, int len);
++ inline void append(const unsigned char *suffix, int len);
++ inline void append(const char *begin, const char *end);
++
++ void append_numeric(String::uint_large_t num, int base = 10, bool uppercase = true);
++ void append_numeric(String::int_large_t num, int base = 10, bool uppercase = true);
++
++ StringAccum &snprintf(int n, const char *format, ...);
++
++ String take_string();
++
++ void swap(StringAccum &o);
++
++ // see also operator<< declarations below
++
++ void forward(int delta) CLICK_DEPRECATED;
++
++ private:
++
++ unsigned char *_s;
++ int _len;
++ int _cap;
++
++ void make_out_of_memory();
++ inline void safe_append(const char *, int);
++ bool grow(int);
++
++ StringAccum(const StringAccum &);
++ StringAccum &operator=(const StringAccum &);
++
++ friend StringAccum &operator<<(StringAccum &, const char *);
++
++};
++
++inline StringAccum &operator<<(StringAccum &, char);
++inline StringAccum &operator<<(StringAccum &, unsigned char);
++inline StringAccum &operator<<(StringAccum &, const char *);
++inline StringAccum &operator<<(StringAccum &, const String &);
++inline StringAccum &operator<<(StringAccum &, const StringAccum &);
++#ifdef HAVE_PERMSTRING
++inline StringAccum &operator<<(StringAccum &, PermString);
++#endif
++
++inline StringAccum &operator<<(StringAccum &, bool);
++inline StringAccum &operator<<(StringAccum &, short);
++inline StringAccum &operator<<(StringAccum &, unsigned short);
++inline StringAccum &operator<<(StringAccum &, int);
++inline StringAccum &operator<<(StringAccum &, unsigned);
++StringAccum &operator<<(StringAccum &, long);
++StringAccum &operator<<(StringAccum &, unsigned long);
++#if HAVE_LONG_LONG
++inline StringAccum &operator<<(StringAccum &, long long);
++inline StringAccum &operator<<(StringAccum &, unsigned long long);
++#endif
++#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
++inline StringAccum &operator<<(StringAccum &, int64_t);
++inline StringAccum &operator<<(StringAccum &, uint64_t);
++#endif
++#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
++StringAccum &operator<<(StringAccum &, double);
++#endif
++
++StringAccum &operator<<(StringAccum &, void *);
++
++
++/** @brief Create a StringAccum with room for at least @a capacity characters.
++ @param capacity initial capacity.
++
++ If @a capacity <= 0, the StringAccum is created empty. If @a capacity is
++ too large (so that @a capacity bytes of memory can't be allocated), the
++ StringAccum is created as out-of-memory. */
++inline
++StringAccum::StringAccum(int capacity)
++ : _len(0)
++{
++ assert(capacity >= 0);
++ if (capacity) {
++ _s = (unsigned char *) CLICK_LALLOC(capacity);
++ _cap = (_s ? capacity : -1);
++ } else {
++ _s = 0;
++ _cap = 0;
++ }
++}
++
++/** @brief Reserve space for at least @a n characters.
++ @param n number of characters to reserve.
++ @return a pointer to at least @a n characters, or null if allocation fails.
++ @pre @a n >= 0
++
++ reserve() does not change the string's length(), only its capacity(). In
++ a frequent usage pattern, code calls reserve(), passing an upper bound on
++ the characters that could be written by a series of operations. After
++ writing into the returned buffer, adjust_length() is called to account for
++ the number of characters actually written. */
++inline char *
++StringAccum::reserve(int n)
++{
++ assert(n >= 0);
++ if (_len + n <= _cap || grow(_len + n))
++ return (char *)(_s + _len);
++ else
++ return 0;
++}
++
++/** @brief Adjust the StringAccum's length.
++ @param delta length adjustment
++ @pre If @a delta > 0, then length() + @a delta <= capacity().
++ If @a delta < 0, then length() + delta >= 0.
++
++ The StringAccum's length after adjust_length(@a delta) equals its old
++ length plus @a delta. Generally adjust_length() is used after a call to
++ reserve().
++ @sa set_length */
++inline void
++StringAccum::adjust_length(int delta) {
++ assert(_len + delta >= 0 && _len + delta <= _cap);
++ _len += delta;
++}
++
++/** @brief Adjust the StringAccum's length (deprecated).
++ @param delta length adjustment.
++ @deprecated Use adjust_length() instead. */
++inline void
++StringAccum::forward(int delta)
++{
++ adjust_length(delta);
++}
++
++/** @brief Reserve space and adjust length in one operation.
++ @param nadjust number of characters to reserve and adjust length.
++ @param nreserve additional characters to reserve.
++ @pre @a nadjust >= 0 and @a nreserve >= 0
++
++ This operation combines the effects of reserve(@a nadjust + @a nreserve)
++ and adjust_length(@a nadjust). Returns the result of the reserve() call. */
++inline char *
++StringAccum::extend(int nadjust, int nreserve)
++{
++ assert(nadjust >= 0 && nreserve >= 0);
++ char *c = reserve(nadjust + nreserve);
++ if (c)
++ _len += nadjust;
++ return c;
++}
++
++/** @brief Remove characters from the end of the StringAccum.
++ @param n number of characters to remove.
++ @pre @a n >= 0
++
++ Same as adjust_length(-@a n). */
++inline void
++StringAccum::pop_back(int n) {
++ assert(n >= 0 && _len >= n);
++ _len -= n;
++}
++
++/** @brief Sets the StringAccum's length to @a len.
++ @param len new length in characters.
++ @pre 0 <= @a len <= capacity()
++ @sa adjust_length */
++inline void
++StringAccum::set_length(int len) {
++ assert(len >= 0 && _len <= _cap);
++ _len = len;
++}
++
++/** @brief Extend the StringAccum by character @a c.
++ @param c character to extend */
++inline void
++StringAccum::append(char c)
++{
++ if (_len < _cap || grow(_len))
++ _s[_len++] = c;
++}
++
++/** @overload */
++inline void
++StringAccum::append(unsigned char c)
++{
++ append(static_cast<char>(c));
++}
++
++inline void
++StringAccum::safe_append(const char *s, int len)
++{
++ if (char *x = extend(len))
++ memcpy(x, s, len);
++}
++
++/** @brief Append the first @a len characters of @a suffix to this StringAccum.
++ @param suffix data to append
++ @param len length of data
++
++ If @a len < 0, treats @a suffix as a null-terminated C string. */
++inline void
++StringAccum::append(const char *suffix, int len)
++{
++ if (len < 0)
++ len = strlen(suffix);
++ if (len == 0 && suffix == String::out_of_memory_data())
++ make_out_of_memory();
++ safe_append(suffix, len);
++}
++
++/** @overload */
++inline void
++StringAccum::append(const unsigned char *suffix, int len)
++{
++ append(reinterpret_cast<const char *>(suffix), len);
++}
++
++/** @brief Append the data from @a begin to @a end to the end of this StringAccum.
++
++ Does nothing if @a begin >= @a end. */
++inline void
++StringAccum::append(const char *begin, const char *end)
++{
++ if (begin < end)
++ safe_append(begin, end - begin);
++ else if (begin == String::out_of_memory_data())
++ make_out_of_memory();
++}
++
++/** @brief Clear the StringAccum's comments.
++
++ All characters in the StringAccum are erased. This operation also resets
++ the StringAccum's out-of-memory status. */
++inline void
++StringAccum::clear()
++{
++ if (_cap < 0)
++ _cap = 0, _s = 0;
++ _len = 0;
++}
++
++/** @relates StringAccum
++ @brief Append character @a c to StringAccum @a sa.
++ @return @a sa
++ @note Same as @a sa.append(@a c). */
++inline StringAccum &
++operator<<(StringAccum &sa, char c)
++{
++ sa.append(c);
++ return sa;
++}
++
++/** @relates StringAccum
++ @brief Append character @a c to StringAccum @a sa.
++ @return @a sa
++ @note Same as @a sa.append(@a c). */
++inline StringAccum &
++operator<<(StringAccum &sa, unsigned char c)
++{
++ sa.append(c);
++ return sa;
++}
++
++/** @relates StringAccum
++ @brief Append null-terminated C string @a cstr to StringAccum @a sa.
++ @return @a sa
++ @note Same as @a sa.append(@a cstr, -1). */
++inline StringAccum &
++operator<<(StringAccum &sa, const char *cstr)
++{
++ sa.append(cstr, -1);
++ return sa;
++}
++
++/** @relates StringAccum
++ @brief Append "true" or "false" to @a sa, depending on @a b.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, bool b)
++{
++ return sa << (b ? "true" : "false");
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a i to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, short i)
++{
++ return sa << static_cast<long>(i);
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a u to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, unsigned short u)
++{
++ return sa << static_cast<unsigned long>(u);
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a i to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, int i)
++{
++ return sa << static_cast<long>(i);
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a u to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, unsigned u)
++{
++ return sa << static_cast<unsigned long>(u);
++}
++
++#if HAVE_LONG_LONG
++/** @relates StringAccum
++ @brief Append decimal representation of @a q to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, long long q)
++{
++ sa.append_numeric(static_cast<String::int_large_t>(q));
++ return sa;
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a q to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, unsigned long long q)
++{
++ sa.append_numeric(static_cast<String::uint_large_t>(q));
++ return sa;
++}
++#endif
++
++#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
++/** @relates StringAccum
++ @brief Append decimal representation of @a q to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, int64_t q)
++{
++ sa.append_numeric(static_cast<String::int_large_t>(q));
++ return sa;
++}
++
++/** @relates StringAccum
++ @brief Append decimal representation of @a q to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, uint64_t q)
++{
++ sa.append_numeric(static_cast<String::uint_large_t>(q));
++ return sa;
++}
++#endif
++
++/** @relates StringAccum
++ @brief Append the contents of @a str to @a sa.
++ @return @a sa */
++StringAccum &
++operator<<(StringAccum &sa, const String &str)
++{
++ sa.append(str.data(), str.length());
++ return sa;
++}
++
++#ifdef HAVE_PERMSTRING
++inline StringAccum &
++operator<<(StringAccum &sa, PermString s)
++{
++ sa.safe_append(s.c_str(), s.length());
++ return sa;
++}
++#endif
++
++/** @relates StringAccum
++ @brief Append the contents of @a sb to @a sa.
++ @return @a sa */
++inline StringAccum &
++operator<<(StringAccum &sa, const StringAccum &sb)
++{
++ sa.append(sb.data(), sb.length());
++ return sa;
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/string.hh click-1.6.0-27/inst/include/click/string.hh
+--- click-1.6.0/inst/include/click/string.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/string.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,718 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/string.cc" -*-
++#ifndef CLICK_STRING_HH
++#define CLICK_STRING_HH
++#ifdef HAVE_PERMSTRING
++# include "permstr.hh"
++#endif
++#include <click/algorithm.hh>
++#include <click/atomic.hh>
++CLICK_DECLS
++
++class String { public:
++
++ // Call static_initialize() before any function which might deal with
++ // Strings, and declare a String::Initializer in any file in which you
++ // declare static global Strings.
++ static void static_initialize();
++ static void static_cleanup();
++ struct Initializer { Initializer(); };
++
++ inline String();
++ inline String(const String &str);
++ inline String(const char *cstr);
++ inline String(const char *s, int len);
++ inline String(const char *begin, const char *end);
++ explicit inline String(bool b);
++ explicit inline String(char c);
++ explicit inline String(unsigned char c);
++ explicit String(int i);
++ explicit String(unsigned u);
++ explicit String(long i);
++ explicit String(unsigned long u);
++#if HAVE_LONG_LONG
++ explicit String(long long q);
++ explicit String(unsigned long long q);
++#endif
++#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
++ explicit String(int64_t q);
++ explicit String(uint64_t q);
++#endif
++#ifdef CLICK_USERLEVEL
++ explicit String(double d);
++#endif
++ inline ~String();
++
++ static inline const String &empty_string();
++ static String garbage_string(int len); // len garbage characters
++ static String stable_string(const char *s, int len = -1); // stable read-only mem.
++ static inline String stable_string(const char *begin, const char *end);
++
++#if HAVE_INT64_TYPES && (!HAVE_LONG_LONG || SIZEOF_LONG_LONG <= 8)
++ typedef int64_t int_large_t;
++ typedef uint64_t uint_large_t;
++#elif HAVE_LONG_LONG
++ typedef long long int_large_t;
++ typedef unsigned long long uint_large_t;
++#else
++ typedef long int_large_t;
++ typedef unsigned long uint_large_t;
++#endif
++
++ static String numeric_string(int_large_t num, int base = 10, bool uppercase = true);
++ static String numeric_string(uint_large_t num, int base = 10, bool uppercase = true);
++
++ inline int length() const;
++ inline const char *data() const;
++
++ typedef const char *const_iterator;
++ typedef const_iterator iterator;
++ inline const_iterator begin() const;
++ inline const_iterator end() const;
++
++ typedef int (String::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++
++ inline char operator[](int i) const;
++ inline char at(int i) const;
++ inline char front() const;
++ inline char back() const;
++
++ const char *c_str() const; // pointer returned is semi-transient
++
++ size_t hashcode() const;
++
++ bool equals(const char *s, int len) const;
++ // bool operator==(const String &, const String &);
++ // bool operator==(const String &, const char *);
++ // bool operator==(const char *, const String &);
++ // bool operator!=(const String &, const String &);
++ // bool operator!=(const String &, const char *);
++ // bool operator!=(const char *, const String &);
++
++ static inline int compare(const String &a, const String &b);
++ inline int compare(const String &str) const;
++ int compare(const char *s, int len) const;
++ // bool operator<(const String &, const String &);
++ // bool operator<=(const String &, const String &);
++ // bool operator>(const String &, const String &);
++ // bool operator>=(const String &, const String &);
++
++ inline String substring(const char *begin, const char *end) const;
++ String substring(int pos, int len) const;
++ inline String substring(int pos) const;
++
++ int find_left(char c, int start = 0) const;
++ int find_left(const String &s, int start = 0) const;
++ int find_right(char c, int start = 0x7FFFFFFF) const;
++
++ String lower() const; // lowercase
++ String upper() const; // uppercase
++ String printable() const; // quote non-ASCII characters
++ String trim_space() const; // trim space from right
++ String quoted_hex() const; // hex enclosed in '\<...>'
++
++ inline String &operator=(const String &str);
++ inline String &operator=(const char *cstr);
++
++ void append(const char *s, int len);
++ inline void append(const char *begin, const char *end);
++ void append_fill(int c, int len);
++ char *append_garbage(int len);
++ inline String &operator+=(const String &str);
++ inline String &operator+=(const char *cstr);
++ inline String &operator+=(char c);
++
++ // String operator+(String, const String &);
++ // String operator+(String, const char *);
++ // String operator+(const char *, const String &);
++ // String operator+(String, PermString);
++ // String operator+(PermString, const String &);
++ // String operator+(PermString, const char *);
++ // String operator+(const char *, PermString);
++ // String operator+(PermString, PermString);
++ // String operator+(String, char);
++
++ inline bool data_shared() const;
++ char *mutable_data();
++ char *mutable_c_str();
++
++ inline bool out_of_memory() const;
++ static inline const String &out_of_memory_string();
++ static inline const char *out_of_memory_data();
++
++ private:
++
++ /** @cond never */
++ struct Memo {
++ atomic_uint32_t _refcount;
++ uint32_t _capacity;
++ atomic_uint32_t _dirty;
++ char *_real_data;
++
++ Memo();
++ Memo(char *, int, int);
++ Memo(int, int);
++ ~Memo();
++ };
++ /** @endcond never */
++
++ mutable const char *_data; // mutable for c_str()
++ mutable int _length;
++ mutable Memo *_memo;
++
++ inline String(const char *, int, Memo *);
++
++ inline void assign(const String &) const;
++ void assign(const char *, int);
++ inline void deref() const;
++ void make_out_of_memory();
++
++ static Memo *null_memo;
++ static Memo *permanent_memo;
++ static Memo *oom_memo;
++ static String *null_string_p;
++ static String *oom_string_p;
++ static const char oom_string_data;
++
++ static String claim_string(char *, int, int); // claim memory
++
++ friend class String::Initializer;
++ friend class StringAccum;
++
++};
++
++
++inline
++String::String(const char *data, int length, Memo *memo)
++ : _data(data), _length(length), _memo(memo)
++{
++ _memo->_refcount++;
++}
++
++inline void
++String::assign(const String &str) const
++{
++ _data = str._data;
++ _length = str._length;
++ _memo = str._memo;
++ _memo->_refcount++;
++}
++
++inline void
++String::deref() const
++{
++ if (_memo->_refcount.dec_and_test())
++ delete _memo;
++}
++
++/** @brief Create an empty String (with length 0). */
++inline
++String::String()
++ : _data(null_memo->_real_data), _length(0), _memo(null_memo)
++{
++ _memo->_refcount++;
++}
++
++/** @brief Create a String containing a copy of the C string @a cstr.
++ * @param cstr a null-terminated C string.
++ * @return A String containing the characters of @a cstr, up to but not
++ * including the terminating null character.
++ *
++ * If @a cstr equals String::out_of_memory_data(), returns an
++ * out-of-memory string.
++ */
++inline
++String::String(const char *cstr)
++{
++ assign(cstr, -1);
++}
++
++/** @brief Create a String containing a copy of the first @a len characters of
++ * string @a s.
++ * @param s a string.
++ * @param len number of characters to take from @a cc. If @a len @< 0, then
++ * takes @c strlen(@a s) characters.
++ * @return A String containing @a len characters of @a s.
++ *
++ * If @a s equals String::out_of_memory_data(), returns an
++ * out-of-memory string.
++ */
++inline
++String::String(const char *s, int len)
++{
++ assign(s, len);
++}
++
++/** @brief Create a String containing a copy of the characters from @a begin
++ * to @a end.
++ * @param begin first character in string (begin iterator).
++ * @param end pointer one past last character in string (end iterator).
++ * @return A String containing the characters from @a begin to @a end.
++ *
++ * Returns a null string if @a begin @> @a end.
++ * If @a begin equals String::out_of_memory_data(), returns an
++ * out-of-memory string.
++ */
++inline
++String::String(const char *begin, const char *end)
++{
++ assign(begin, (end > begin ? end - begin : 0));
++}
++
++/** @brief Create a String equal to "true" or "false" depending on the
++ * value of @a b.
++ * @param b a boolean variable.
++ */
++inline
++String::String(bool b)
++ : _data(b ? "true" : "false"), _length(b ? 4 : 5), _memo(permanent_memo)
++{
++ _memo->_refcount++;
++}
++
++/** @brief Create a String containing the single character @a c.
++ * @param c a character.
++ */
++inline
++String::String(char c)
++{
++ assign(&c, 1);
++}
++
++/** @brief Create a String containing the single character @a c.
++ * @param c an unsigned character.
++ */
++inline
++String::String(unsigned char c)
++{
++ assign(reinterpret_cast<char *>(&c), 1);
++}
++
++/** @brief Create a String containing a copy of the String @a str.
++ * @param str a String.
++ */
++inline
++String::String(const String &str)
++{
++ assign(str);
++}
++
++/** @brief Destroy a String, freeing memory if necessary. */
++inline
++String::~String()
++{
++ deref();
++}
++
++/** @brief Return the string's length. */
++inline int
++String::length() const
++{
++ return _length;
++}
++
++/** @brief Return a pointer to the string's data.
++ *
++ * Only the first length() characters are valid, and the string data might not
++ * be null-terminated. */
++inline const char *
++String::data() const
++{
++ return _data;
++}
++
++/** @brief Return an iterator for the first character in the string.
++ *
++ * String iterators are simply pointers into string data, so they are quite
++ * efficient. @sa String::data */
++inline String::const_iterator
++String::begin() const
++{
++ return _data;
++}
++
++/** @brief Return an iterator for the end of the string.
++ *
++ * The return value points one character beyond the last character in the
++ * string. */
++inline String::const_iterator
++String::end() const
++{
++ return _data + _length;
++}
++
++/** @brief Returns true iff the string is nonempty. */
++inline
++String::operator unspecified_bool_type() const
++{
++ return _length != 0 ? &String::length : 0;
++}
++
++/** @brief Returns the @a i th character in the string.
++ *
++ * Does not check bounds.
++ * @sa String::at */
++inline char
++String::operator[](int i) const
++{
++ return _data[i];
++}
++
++/** @brief Returns the @a i th character in the string.
++ *
++ * Checks bounds: an assertion will fail if @a i is less than 0 or not less
++ * than length().
++ * @sa String::operator[]
++ */
++inline char
++String::at(int i) const
++{
++ assert(i >= 0 && i < _length);
++ return _data[i];
++}
++
++/** @brief Returns the first character in the string.
++ *
++ * Does not do check bounds. Same as (*this)[0]. */
++inline char
++String::front() const
++{
++ return _data[0];
++}
++
++/** @brief Returns the last character in the string.
++ *
++ * Does not check bounds. Same as (*this)[length() - 1]. */
++inline char
++String::back() const
++{
++ return _data[_length - 1];
++}
++
++/** @brief Return true iff the String's data is shared or immutable. */
++inline bool
++String::data_shared() const
++{
++ return !_memo->_capacity || _memo->_refcount != 1;
++}
++
++/** @brief Return an empty String.
++ *
++ * Returns a global constant, so it's quicker than String::String().
++ */
++inline const String &
++String::empty_string()
++{
++ return *null_string_p;
++}
++
++/** @brief Return a String that directly references the character data in
++ * [@a begin, @a end).
++ * @param begin pointer to the first character in the character data.
++ * @param end pointer one beyond the last character in the character data.
++ *
++ * This function is suitable for static constant strings whose data is known
++ * to stay around forever, such as C string constants. Returns a null string
++ * if @a begin @> @a end.
++ */
++inline String
++String::stable_string(const char *begin, const char *end)
++{
++ if (begin < end)
++ return String::stable_string(begin, end - begin);
++ else
++ return String();
++}
++
++/** @brief Return a substring of the current string starting at @a begin and
++ * ending before @a end.
++ * @param begin pointer to the first character in the desired substring.
++ * @param end pointer one beyond the last character in the desired substring.
++ *
++ * Returns a null string if @a begin @> @a end, or if @a begin or @a end is
++ * out of range (i.e., either less than this->begin() or greater than
++ * this->end()).
++ */
++inline String
++String::substring(const char *begin, const char *end) const
++{
++ if (begin < end && begin >= _data && end <= _data + _length)
++ return String(begin, end - begin, _memo);
++ else
++ return String();
++}
++
++/** @brief Return the suffix of the current string starting at index @a pos.
++ *
++ * Same as String::substring(@a pos, INT_MAX).
++ */
++inline String
++String::substring(int pos) const
++{
++ return substring(pos, _length);
++}
++
++/** @brief Compare two strings.
++ * @param a first string to compare
++ * @param b second string to compare
++ *
++ * Returns 0 if @a a == @a b, negative if @a a @< @a b in lexicographic
++ * order, and positive if @a a @> @a b in lexicographic order.
++ */
++inline int
++String::compare(const String &a, const String &b)
++{
++ return a.compare(b);
++}
++
++/** @brief Compare this string with string @a str.
++ *
++ * Same as String::compare(*this, @a str).
++ * @sa String::compare(const String &a, const String &b) */
++inline int
++String::compare(const String &str) const
++{
++ return compare(str._data, str._length);
++}
++
++/** @relates String
++ * @brief Compares two strings for equality.
++ *
++ * Returns true iff the two operands have the same lengths and the same
++ * characters in the same order. At most one of the operands can be a
++ * null-terminated C string.
++ * @sa String::compare
++ */
++inline bool
++operator==(const String &a, const String &b)
++{
++ return a.equals(b.data(), b.length());
++}
++
++/** @relates String */
++inline bool
++operator==(const char *a, const String &b)
++{
++ return b.equals(a, -1);
++}
++
++/** @relates String */
++inline bool
++operator==(const String &a, const char *b)
++{
++ return a.equals(b, -1);
++}
++
++/** @relates String
++ * @brief Compare two Strings for inequality.
++ *
++ * Returns true iff !(@a a == @a b). At most one of the operands can be a
++ * null-terminated C string. */
++inline bool
++operator!=(const String &a, const String &b)
++{
++ return !a.equals(b.data(), b.length());
++}
++
++/** @relates String */
++inline bool
++operator!=(const char *a, const String &b)
++{
++ return !b.equals(a, -1);
++}
++
++/** @relates String */
++inline bool
++operator!=(const String &a, const char *b)
++{
++ return !a.equals(b, -1);
++}
++
++/** @relates String
++ * @brief Compare two Strings.
++ *
++ * Returns true iff @a a @< @a b in lexicographic order.
++ * @sa String::compare
++ */
++inline bool
++operator<(const String &a, const String &b)
++{
++ return a.compare(b.data(), b.length()) < 0;
++}
++
++/** @relates String
++ * @brief Compare two Strings.
++ *
++ * Returns true iff @a a @<= @a b in lexicographic order.
++ * @sa String::compare
++ */
++inline bool
++operator<=(const String &a, const String &b)
++{
++ return a.compare(b.data(), b.length()) <= 0;
++}
++
++/** @relates String
++ * @brief Compare two Strings.
++ *
++ * Returns true iff @a a @> @a b in lexicographic order.
++ * @sa String::compare
++ */
++inline bool
++operator>(const String &a, const String &b)
++{
++ return a.compare(b.data(), b.length()) > 0;
++}
++
++/** @relates String
++ * @brief Compare two Strings.
++ *
++ * Returns true iff @a a @>= @a b in lexicographic order.
++ * @sa String::compare
++ */
++inline bool
++operator>=(const String &a, const String &b)
++{
++ return a.compare(b.data(), b.length()) >= 0;
++}
++
++/** @brief Makes this string a copy of @a str. */
++inline String &
++String::operator=(const String &str)
++{
++ if (&str != this) {
++ deref();
++ assign(str);
++ }
++ return *this;
++}
++
++/** @brief Make this string a copy of the C string @a cstr. */
++inline String &
++String::operator=(const char *cstr)
++{
++ deref();
++ assign(cstr, -1);
++ return *this;
++}
++
++/** @brief Appends the data from @a begin to @a end to the end of this string.
++ *
++ * Does nothing if @a begin @>= @a end. */
++inline void
++String::append(const char *begin, const char *end)
++{
++ if (begin < end)
++ append(begin, end - begin);
++}
++
++/** @brief Append a copy of @a str to the end of this string.
++ *
++ * Returns the result. */
++inline String &
++String::operator+=(const String &str)
++{
++ append(str._data, str._length);
++ return *this;
++}
++
++/** @brief Append a copy of the C string @a cstr to the end of this string.
++ *
++ * Returns the result. */
++inline String &
++String::operator+=(const char *cstr)
++{
++ append(cstr, -1);
++ return *this;
++}
++
++/** @brief Append the character @a c to the end of this string.
++ *
++ * Returns the result. */
++inline String &
++String::operator+=(char c)
++{
++ append(&c, 1);
++ return *this;
++}
++
++/** @relates String
++ * @brief Concatenate the operands and return the result.
++ *
++ * At most one of the two operands can be a null-terminated C string. */
++inline String
++operator+(String a, const String &b)
++{
++ a += b;
++ return a;
++}
++
++/** @relates String */
++inline String
++operator+(String a, const char *b)
++{
++ a.append(b, -1);
++ return a;
++}
++
++/** @relates String */
++inline String
++operator+(const char *a, const String &b)
++{
++ String s1(a);
++ s1 += b;
++ return s1;
++}
++
++/** @relates String
++ * @brief Concatenate the operands and return the result.
++ *
++ * The second operand is a single character. */
++inline String
++operator+(String a, char b)
++{
++ a.append(&b, 1);
++ return a;
++}
++
++/** @brief Returns true iff this is an out-of-memory string. */
++inline bool
++String::out_of_memory() const
++{
++ return _data == &oom_string_data;
++}
++
++/** @brief Return a reference to an out-of-memory String. */
++inline const String &
++String::out_of_memory_string()
++{
++ return *oom_string_p;
++}
++
++/** @brief Return the data pointer used for out-of-memory strings.
++ *
++ * The returned value may be dereferenced; it points to a null character.
++ */
++inline const char *
++String::out_of_memory_data()
++{
++ return &oom_string_data;
++}
++
++// find methods
++
++inline const char *rfind(const char *begin, const char *end, char c)
++{
++ for (const char *bb = end - 1; bb >= begin; bb--)
++ if (*bb == c)
++ return bb;
++ return end;
++}
++
++inline const char *find(const String &s, char c)
++{
++ return find(s.begin(), s.end(), c);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/sync.hh click-1.6.0-27/inst/include/click/sync.hh
+--- click-1.6.0/inst/include/click/sync.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/sync.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,467 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_SYNC_HH
++#define CLICK_SYNC_HH
++#include <click/glue.hh>
++#include <click/atomic.hh>
++#if CLICK_LINUXMODULE && defined(__SMP__)
++# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
++# include <linux/threads.h>
++# else
++# include <linux/tasks.h>
++# endif
++# include <linux/sched.h>
++# define my_cpu click_current_processor()
++# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
++# define num_possible_cpus() smp_num_cpus
++# endif
++#endif
++CLICK_DECLS
++
++// loop-in-cache spinlock implementation: 8 bytes. if the size of this class
++// changes, change size of padding in ReadWriteLock below.
++
++/** @file <click/sync.hh>
++ * @brief Classes for synchronizing among multiple CPUs, particularly in the
++ * Linux kernel.
++ */
++
++/** @class Spinlock
++ * @brief A spinlock for SMP Click threads.
++ *
++ * The Spinlock class abstracts a spinlock, or polling mutex, in SMP Click.
++ * This is a type of mutual-exclusion lock in which acquiring the lock is a
++ * polling operation (basically a "while (lock.acquired()) do nothing;" loop).
++ * Spinlocks can be used to synchronize access to shared data among multiple
++ * Click SMP threads. Spinlocks should not be held for long periods of time:
++ * use them for quick updates and such.
++ *
++ * Spinlock operations do nothing unless Click was compiled with SMP support
++ * (with --enable-multithread). Therefore, Spinlock should not be used to,
++ * for example, synchronize handlers with main element threads. See also
++ * SpinlockIRQ.
++ *
++ * The main Spinlock operations are acquire(), which acquires the lock, and
++ * release(), which releases the lock. attempt() acquires the lock only if it
++ * can be acquired instantaneously.
++ *
++ * It is OK for a thread to acquire a lock it has already acquired, but you
++ * must release it as many times as you have acquired it.
++ */
++class Spinlock { public:
++
++ inline Spinlock();
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ inline ~Spinlock();
++#endif
++
++ inline void acquire();
++ inline void release();
++ inline bool attempt();
++ inline bool nested() const;
++
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ private:
++ volatile unsigned short _lock;
++ unsigned short _depth;
++ int _owner;
++#endif
++
++};
++
++/** @brief Create a Spinlock. */
++inline
++Spinlock::Spinlock()
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ : _lock(0), _depth(0), _owner(-1)
++#endif
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++# if !defined(__i386__) && !defined(__x86_64__)
++# error "no multithread support for non i386 click"
++# endif
++#endif
++}
++
++#if CLICK_LINUXMODULE && defined(__SMP__)
++inline
++Spinlock::~Spinlock()
++{
++ if (_lock != 0)
++ click_chatter("warning: freeing unreleased lock");
++}
++#endif
++
++/** @brief Acquires the Spinlock.
++ *
++ * On return, this thread has acquired the lock. The function will spin
++ * indefinitely until the lock is acquired. It is OK to acquire a lock you
++ * have already acquired, but you must release it as many times as you have
++ * acquired it.
++ */
++inline void
++Spinlock::acquire()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ if (_owner == my_cpu) {
++ _depth++;
++ return;
++ }
++
++ register unsigned short content = 1;
++ test_and_set:
++ asm volatile ("xchgw %0,%1"
++ : "=r" (content), "=m" (_lock)
++ : "0" (content), "m" (_lock));
++ if (content != 0) {
++ while(_lock != 0)
++ asm volatile ("" : : : "memory");
++ goto test_and_set;
++ }
++
++ _owner = my_cpu;
++ _depth++;
++#endif
++}
++
++/** @brief Attempts to acquire the Spinlock.
++ * @return True iff the Spinlock was acquired.
++ *
++ * This function will acquire the lock and return true only if the Spinlock
++ * can be acquired right away, without retries.
++ */
++inline bool
++Spinlock::attempt()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ if (_owner == my_cpu) {
++ _depth++;
++ return true;
++ }
++
++ register unsigned short content = 1;
++ asm volatile ("xchgw %0,%1"
++ : "=r" (content), "=m" (_lock)
++ : "0" (content), "m" (_lock));
++ if (content != 0)
++ return false;
++ else {
++ _owner = my_cpu;
++ _depth++;
++ return true;
++ }
++#else
++ return true;
++#endif
++}
++
++/** @brief Releases the Spinlock.
++ *
++ * The Spinlock must have been previously acquired by either Spinlock::acquire
++ * or Spinlock::attempt.
++ */
++inline void
++Spinlock::release()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ if (_owner != my_cpu)
++ click_chatter("releasing someone else's lock");
++ if (_depth > 0)
++ _depth--;
++ else
++ click_chatter("lock already freed");
++ if (_depth == 0) {
++ _owner = -1;
++ _lock = 0;
++ }
++#endif
++}
++
++/** @brief Returns true iff the Spinlock has been acquired more than once by
++ * the current thread.
++ */
++inline bool
++Spinlock::nested() const
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ return _depth > 1;
++#else
++ return false;
++#endif
++}
++
++
++/** @class SpinlockIRQ
++ * @brief A spinlock that disables interrupts.
++ *
++ * The SpinlockIRQ class abstracts a spinlock, or polling mutex, that also
++ * turns off interrupts. Spinlocks are a type of mutual-exclusion lock in
++ * which acquiring the lock is a polling operation (basically a "while
++ * (lock.acquired()) do nothing;" loop). The SpinlockIRQ variant can be used
++ * to protect Click data structures from interrupts and from other threads.
++ * Very few objects in Click need this protection; the Click Master object,
++ * which protects the task list, uses it, but that's hidden from users.
++ * Spinlocks should not be held for long periods of time: use them for quick
++ * updates and such.
++ *
++ * In the Linux kernel, SpinlockIRQ is equivalent to a combination of
++ * local_irq_save and the spinlock_t type.
++ *
++ * The SpinlockIRQ operations are acquire(), which acquires the lock, and
++ * release(), which releases the lock.
++ *
++ * It is NOT OK for a SpinlockIRQ thread to acquire a lock it has already
++ * acquired.
++ */
++class SpinlockIRQ { public:
++
++ inline SpinlockIRQ();
++
++#if CLICK_LINUXMODULE
++ typedef unsigned long flags_t;
++#else
++ typedef int flags_t;
++#endif
++
++ inline flags_t acquire();
++ inline void release(flags_t);
++
++#if CLICK_LINUXMODULE
++ private:
++ spinlock_t _lock;
++#endif
++
++};
++
++/** @brief Creates a SpinlockIRQ. */
++inline
++SpinlockIRQ::SpinlockIRQ()
++{
++#if CLICK_LINUXMODULE
++ spin_lock_init(&_lock);
++#endif
++}
++
++/** @brief Acquires the SpinlockIRQ.
++ * @return The current state of the interrupt flags.
++ */
++inline SpinlockIRQ::flags_t
++SpinlockIRQ::acquire()
++{
++#if CLICK_LINUXMODULE
++ flags_t flags;
++ spin_lock_irqsave(&_lock, flags);
++ return flags;
++#else
++ return 0;
++#endif
++}
++
++/** @brief Releases the SpinlockIRQ.
++ * @param flags The value returned by SpinlockIRQ::acquire().
++ */
++inline void
++SpinlockIRQ::release(flags_t flags)
++{
++#if CLICK_LINUXMODULE
++ spin_unlock_irqrestore(&_lock, flags);
++#else
++ (void) flags;
++#endif
++}
++
++
++// read-write lock
++//
++// on read: acquire local read lock
++// on write: acquire every read lock
++//
++// alternatively, we could use a read counter and a write lock. we don't do
++// that because we'd like to avoid a cache miss for read acquires. this makes
++// reads very fast, and writes more expensive
++
++/** @class ReadWriteLock
++ * @brief A read/write lock.
++ *
++ * The ReadWriteLock class abstracts a read/write lock in SMP Click. Multiple
++ * SMP Click threads can hold read locks simultaneously, but if any thread
++ * holds a write lock, then no other thread holds any kind of lock. The
++ * read/write lock is implemented with Spinlock objects, so acquiring a lock
++ * is a polling operation. ReadWriteLocks can be used to synchronize access
++ * to shared data among multiple Click SMP threads. ReadWriteLocks should not
++ * be held for long periods of time: use them for quick updates and such.
++ *
++ * ReadWriteLock operations do nothing unless Click was compiled with SMP
++ * support (with --enable-multithread). Therefore, ReadWriteLock should not
++ * be used to, for example, synchronize handlers with main element threads.
++ *
++ * The main ReadWriteLock operations are acquire_read() and acquire_write(),
++ * which acquire the lock for reading or writing, respectively, and
++ * release_read() and release_write(), which similarly release the lock.
++ * attempt_read() and attempt_write() acquire the lock only if it can be
++ * acquired instantaneously.
++ *
++ * It is OK for a thread to acquire a lock it has already acquired, but you
++ * must release it as many times as you have acquired it.
++ *
++ * ReadWriteLock objects are relatively large in terms of memory usage; don't
++ * create too many of them.
++ */
++class ReadWriteLock { public:
++
++ inline ReadWriteLock();
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ inline ~ReadWriteLock();
++#endif
++
++ inline void acquire_read();
++ inline bool attempt_read();
++ inline void release_read();
++ inline void acquire_write();
++ inline bool attempt_write();
++ inline void release_write();
++
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ private:
++ // allocate 32 bytes (size of a cache line) for every member
++ struct lock_t {
++ Spinlock _lock;
++ unsigned char reserved[24];
++ } *_l;
++#endif
++
++};
++
++/** @brief Creates a ReadWriteLock. */
++inline
++ReadWriteLock::ReadWriteLock()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ _l = new lock_t[num_possible_cpus()];
++#endif
++}
++
++#if CLICK_LINUXMODULE && defined(__SMP__)
++inline
++ReadWriteLock::~ReadWriteLock()
++{
++ delete[] _l;
++}
++#endif
++
++/** @brief Acquires the ReadWriteLock for reading.
++ *
++ * On return, this thread has acquired the lock for reading. The function
++ * will spin indefinitely until the lock is acquired. It is OK to acquire a
++ * lock you have already acquired, but you must release it as many times as
++ * you have acquired it.
++ *
++ * @sa Spinlock::acquire
++ */
++inline void
++ReadWriteLock::acquire_read()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ assert(my_cpu >= 0);
++ _l[my_cpu]._lock.acquire();
++#endif
++}
++
++/** @brief Attempts to acquire the ReadWriteLock for reading.
++ * @return True iff the ReadWriteLock was acquired.
++ *
++ * This function will acquire the lock for reading and return true only if the
++ * ReadWriteLock can be acquired right away, without retries.
++ */
++inline bool
++ReadWriteLock::attempt_read()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ assert(my_cpu >= 0);
++ return _l[my_cpu]._lock.attempt();
++#else
++ return true;
++#endif
++}
++
++/** @brief Releases the ReadWriteLock for reading.
++ *
++ * The ReadWriteLock must have been previously acquired by either
++ * ReadWriteLock::acquire_read or ReadWriteLock::attempt_read. Do not call
++ * release_read() on a lock that was acquired for writing.
++ */
++inline void
++ReadWriteLock::release_read()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ assert(my_cpu >= 0);
++ _l[my_cpu]._lock.release();
++#endif
++}
++
++/** @brief Acquires the ReadWriteLock for writing.
++ *
++ * On return, this thread has acquired the lock for writing. The function
++ * will spin indefinitely until the lock is acquired. It is OK to acquire a
++ * lock you have already acquired, but you must release it as many times as
++ * you have acquired it.
++ *
++ * @sa ReadWriteLock::acquire_read
++ */
++inline void
++ReadWriteLock::acquire_write()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ for (unsigned i = 0; i < num_possible_cpus(); i++)
++ _l[i]._lock.acquire();
++#endif
++}
++
++/** @brief Attempts to acquire the ReadWriteLock for writing.
++ * @return True iff the ReadWriteLock was acquired.
++ *
++ * This function will acquire the lock for writing and return true only if the
++ * ReadWriteLock can be acquired right away, without retries. Note, however,
++ * that acquiring a ReadWriteLock requires as many operations as there are
++ * CPUs.
++ *
++ * @sa ReadWriteLock::attempt_read
++ */
++inline bool
++ReadWriteLock::attempt_write()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ bool all = true;
++ unsigned i;
++ for (i = 0; i < num_possible_cpus(); i++)
++ if (!(_l[i]._lock.attempt())) {
++ all = false;
++ break;
++ }
++ if (!all)
++ for (unsigned j = 0; j < i; j++)
++ _l[j]._lock.release();
++ return all;
++#else
++ return true;
++#endif
++}
++
++/** @brief Releases the ReadWriteLock for writing.
++ *
++ * The ReadWriteLock must have been previously acquired by either
++ * ReadWriteLock::acquire_write or ReadWriteLock::attempt_write. Do not call
++ * release_write() on a lock that was acquired for reading.
++ *
++ * @sa ReadWriteLock::release_read
++ */
++inline void
++ReadWriteLock::release_write()
++{
++#if CLICK_LINUXMODULE && defined(__SMP__)
++ for (unsigned i = 0; i < num_possible_cpus(); i++)
++ _l[i]._lock.release();
++#endif
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/task.hh click-1.6.0-27/inst/include/click/task.hh
+--- click-1.6.0/inst/include/click/task.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/task.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,582 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/task.cc" -*-
++#ifndef CLICK_TASK_HH
++#define CLICK_TASK_HH
++#include <click/element.hh>
++#include <click/sync.hh>
++#if __MTCLICK__
++# include <click/atomic.hh>
++# include <click/ewma.hh>
++#endif
++CLICK_DECLS
++
++#if CLICK_BSDMODULE
++extern "C" {
++ #include <sys/lock.h>
++ #include <sys/mutex.h>
++}
++#else
++#define GIANT_REQUIRED
++#endif
++
++#define PASS_GT(a, b) ((int)(a - b) > 0)
++
++typedef bool (*TaskHook)(Task *, void *);
++class RouterThread;
++class TaskList;
++class Master;
++
++class Task { public:
++
++#ifdef HAVE_STRIDE_SCHED
++ enum { STRIDE1 = 1U<<16, MAX_STRIDE = 1U<<31 };
++ enum { MAX_TICKETS = 1<<15, DEFAULT_TICKETS = 1<<10 };
++#endif
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ enum { MAX_UTILIZATION = 1000 };
++#endif
++
++ inline Task(TaskHook hook, void *thunk);
++ inline Task(Element *e); // call element->run_task()
++ ~Task();
++
++ inline TaskHook hook() const;
++ inline void *thunk() const;
++ inline Element *element() const;
++
++ inline bool scheduled() const;
++
++ void unschedule();
++ inline void reschedule();
++
++ void strong_unschedule();
++ void strong_reschedule();
++
++#ifdef HAVE_TASK_HEAP
++ void fast_reschedule();
++#else
++ inline void fast_reschedule();
++#endif
++
++ inline int home_thread_id() const;
++ void move_thread(int thread_id);
++
++#ifdef HAVE_STRIDE_SCHED
++ inline int tickets() const;
++ inline void set_tickets(int n);
++ inline void adjust_tickets(int delta);
++#endif
++
++ inline bool initialized() const;
++ void initialize(Router *, bool scheduled);
++ void initialize(Element *, bool scheduled);
++ inline RouterThread *thread() const;
++ Master *master() const;
++
++ inline void call_hook();
++
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ inline unsigned runs() const;
++ inline unsigned work_done() const;
++ inline unsigned utilization() const;
++ inline void clear_runs();
++#endif
++#if __MTCLICK__
++ inline int cycles() const;
++ inline unsigned cycle_runs() const;
++ inline void update_cycles(unsigned c);
++#endif
++
++ private:
++
++ /* if gcc keeps this ordering, we may get some cache locality on a 16 or 32
++ * byte cache line: the first three fields are used in list traversal */
++
++#ifdef HAVE_TASK_HEAP
++ int _schedpos;
++#else
++ Task* _prev;
++ Task* _next;
++#endif
++ unsigned _should_be_scheduled;
++
++#ifdef HAVE_STRIDE_SCHED
++ unsigned _pass;
++ unsigned _stride;
++ int _tickets;
++#endif
++
++ TaskHook _hook;
++ void* _thunk;
++
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ unsigned _runs;
++ unsigned _work_done;
++#endif
++#if __MTCLICK__
++ DirectEWMA _cycles;
++ unsigned _cycle_runs;
++#endif
++
++ RouterThread* _thread;
++ int _home_thread_id;
++
++ Router* _router;
++
++ volatile uintptr_t _pending_nextptr;
++
++ Task(const Task&);
++ Task& operator=(const Task&);
++ void cleanup();
++
++ void add_pending();
++ void process_pending(RouterThread*);
++ inline void fast_schedule();
++ void true_reschedule();
++ inline void lock_tasks();
++ inline bool attempt_lock_tasks();
++
++ static bool error_hook(Task*, void*);
++
++ inline void fast_unschedule(bool should_be_scheduled);
++
++ static inline Task *pending_to_task(uintptr_t);
++ inline Task *pending_to_task() const;
++
++ friend class RouterThread;
++ friend class Master;
++
++};
++
++
++// need RouterThread's definition for inline functions
++CLICK_ENDDECLS
++#include <click/routerthread.hh>
++CLICK_DECLS
++
++
++/** @brief Construct a task that calls @a hook with @a thunk argument.
++ *
++ * @param hook task hook
++ * @param thunk user data for task hook
++ *
++ * Constructs a task that, when fired, calls the @a hook function like so:
++ *
++ * @code
++ * bool work_done = hook(task, thunk);
++ * @endcode
++ *
++ * where @a task is a pointer to this task. The @a hook should return true if
++ * the task accomplished some meaningful work, and false if it did not. For
++ * example, a task that polls a network driver for packets should return true
++ * if it emits at least one packet, and false if no packets were available.
++ */
++inline
++Task::Task(TaskHook hook, void* thunk)
++#ifdef HAVE_TASK_HEAP
++ : _schedpos(-1),
++#else
++ : _prev(0), _next(0),
++#endif
++ _should_be_scheduled(false),
++#ifdef HAVE_STRIDE_SCHED
++ _pass(0), _stride(0), _tickets(-1),
++#endif
++ _hook(hook), _thunk(thunk),
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ _runs(0), _work_done(0),
++#endif
++#if __MTCLICK__
++ _cycle_runs(0),
++#endif
++ _thread(0), _home_thread_id(-1),
++ _router(0), _pending_nextptr(0)
++{
++}
++
++/** @brief Construct a task that calls @a e ->@link Element::run_task(Task *)
++ * run_task()@endlink.
++ *
++ * @param e element to call
++ *
++ * Constructs a task that, when fired, calls the element @a e's @link
++ * Element::run_task(Task *) run_task()@endlink method, passing this Task
++ * as an argument.
++ *
++ * @sa Task(TaskHook, void *)
++ */
++inline
++Task::Task(Element* e)
++#ifdef HAVE_TASK_HEAP
++ : _schedpos(-1),
++#else
++ : _prev(0), _next(0),
++#endif
++ _should_be_scheduled(false),
++#ifdef HAVE_STRIDE_SCHED
++ _pass(0), _stride(0), _tickets(-1),
++#endif
++ _hook(0), _thunk(e),
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ _runs(0), _work_done(0),
++#endif
++#if __MTCLICK__
++ _cycle_runs(0),
++#endif
++ _thread(0), _home_thread_id(-1),
++ _router(0), _pending_nextptr(0)
++{
++}
++
++/** @brief Returns true iff the task has been initialize()d. */
++inline bool
++Task::initialized() const
++{
++ return _router != 0;
++}
++
++/** @brief Returns true iff the task is currently scheduled to run.
++ *
++ * This function will return false for a task in reschedule-pending state,
++ * where the task will soon be rescheduled but isn't right now due to locking
++ * issues.
++ */
++inline bool
++Task::scheduled() const
++{
++#if HAVE_TASK_HEAP
++ return _schedpos >= 0;
++#else
++ return _prev != 0;
++#endif
++}
++
++/** @brief Returns the task's hook function.
++ *
++ * Returns null if the task was constructed with the Task(Element *)
++ * constructor.
++ */
++inline TaskHook
++Task::hook() const
++{
++ return _hook;
++}
++
++/** @brief Returns the task's thunk (the user data passed to its hook).
++ */
++inline void *
++Task::thunk() const
++{
++ return _thunk;
++}
++
++/** @brief Returns the task's associated element, if any.
++ *
++ * Only works if the task was constructed with the Task(Element *)
++ * constructor.
++ */
++inline Element *
++Task::element() const
++{
++ return _hook ? 0 : reinterpret_cast<Element*>(_thunk);
++}
++
++/** @brief Returns the task's home thread ID.
++ *
++ * This is the @link RouterThread::thread_id() thread_id()@endlink of the
++ * thread on which this Task would run if it were scheduled. This need not
++ * equal the ID of the current thread(), since changes in home_thread_id()
++ * aren't always implemented immediately (because of locking issues).
++ */
++inline int
++Task::home_thread_id() const
++{
++ return _home_thread_id;
++}
++
++/** @brief Returns the thread on which this element is currently scheduled, or
++ * would be scheduled.
++ *
++ * Usually, task->thread()->@link RouterThread::thread_id()
++ * thread_id()@endlink == task->home_thread_id(). They can differ, however,
++ * if move_thread() was called but the task hasn't yet been moved to
++ * the new thread, or if the task was strongly unscheduled with
++ * strong_unschedule(). (In this last case, task->thread()->@link
++ * RouterThread::thread_id() thread_id()@endlink ==
++ * RouterThread::THREAD_STRONG_UNSCHEDULE.)
++ */
++inline RouterThread *
++Task::thread() const
++{
++ return _thread;
++}
++
++inline void
++Task::fast_unschedule(bool should_be_scheduled)
++{
++#if CLICK_LINUXMODULE
++ assert(!in_interrupt());
++#endif
++#if CLICK_BSDMODULE
++ GIANT_REQUIRED;
++#endif
++ if (scheduled()) {
++#ifdef HAVE_TASK_HEAP
++ Task* back = _thread->_task_heap.back();
++ _thread->_task_heap.pop_back();
++ if (_thread->_task_heap.size() > 0)
++ _thread->task_reheapify_from(_schedpos, back);
++ _schedpos = -1;
++#else
++ _next->_prev = _prev;
++ _prev->_next = _next;
++ _next = _prev = 0;
++#endif
++ }
++ _should_be_scheduled = should_be_scheduled;
++}
++
++#ifdef HAVE_STRIDE_SCHED
++
++/** @brief Returns the task's number of tickets.
++ *
++ * Tasks with larger numbers of tickets are scheduled more often. Tasks are
++ * initialized with tickets() == DEFAULT_TICKETS.
++ *
++ * @sa set_tickets, adjust_tickets
++ */
++inline int
++Task::tickets() const
++{
++ return _tickets;
++}
++
++/** @brief Sets the task's number of tickets.
++ * @param n the ticket count
++ *
++ * The ticket count @a n is pinned in the range [1, MAX_TICKETS].
++ *
++ * @sa tickets, adjust_tickets
++ */
++inline void
++Task::set_tickets(int n)
++{
++ if (n > MAX_TICKETS)
++ n = MAX_TICKETS;
++ else if (n < 1)
++ n = 1;
++ _tickets = n;
++ _stride = STRIDE1 / n;
++ assert(_stride < MAX_STRIDE);
++}
++
++/** @brief Add @a delta to the Task's ticket count.
++ * @param delta adjustment to the ticket count
++ *
++ * The ticket count cannot be adjusted below 1 or above MAX_TICKETS.
++ *
++ * @sa set_tickets
++ */
++inline void
++Task::adjust_tickets(int delta)
++{
++ set_tickets(_tickets + delta);
++}
++
++# ifndef HAVE_TASK_HEAP
++/** @brief Reschedules the task. The task's current thread must be currently
++ * locked.
++ *
++ * This accomplishes the same function as reschedule(), but does a faster job
++ * because it assumes the task's thread lock is held. Generally, this can be
++ * guaranteed only from within a task's run_task() hook function.
++ */
++inline void
++Task::fast_reschedule()
++{
++ assert(_thread);
++# if CLICK_LINUXMODULE
++ // tasks never run at interrupt time in Linux
++ assert(!in_interrupt());
++# endif
++# if CLICK_BSDMODULE
++ GIANT_REQUIRED;
++# endif
++
++ if (!scheduled()) {
++ // increase pass
++ _pass += _stride;
++
++# if 0
++ // look for 'n' immediately before where we should be scheduled
++ Task* n = _thread->_prev;
++ while (n != _thread && PASS_GT(n->_pass, _pass))
++ n = n->_prev;
++
++ // schedule after 'n'
++ _next = n->_next;
++ _prev = n;
++ n->_next = this;
++ _next->_prev = this;
++# else
++ // look for 'n' immediately after where we should be scheduled
++ Task* n = _thread->_next;
++# ifdef CLICK_BSDMODULE /* XXX MARKO a race occured here when not spl'ed */
++ while (n->_next != NULL && n != _thread && !PASS_GT(n->_pass, _pass))
++# else
++ while (n != _thread && !PASS_GT(n->_pass, _pass))
++# endif
++ n = n->_next;
++
++ // schedule before 'n'
++ _prev = n->_prev;
++ _next = n;
++ _prev->_next = this;
++ n->_prev = this;
++# endif
++ }
++}
++# endif /* !HAVE_TASK_HEAP */
++
++inline void
++Task::fast_schedule()
++{
++ GIANT_REQUIRED;
++ assert(_tickets >= 1);
++ _pass = _thread->_pass;
++ fast_reschedule();
++}
++
++#else /* !HAVE_STRIDE_SCHED */
++
++inline void
++Task::fast_reschedule()
++{
++ assert(_thread);
++#if CLICK_LINUXMODULE
++ // tasks never run at interrupt time
++ assert(!in_interrupt());
++#endif
++#if CLICK_BSDMODULE
++ // assert(!intr_nesting_level);
++ GIANT_REQUIRED;
++#endif
++ if (!scheduled()) {
++ _prev = _thread->_prev;
++ _next = _thread;
++ _thread->_prev = this;
++ _thread->_next = this;
++ }
++}
++
++inline void
++Task::fast_schedule()
++{
++ fast_reschedule();
++}
++
++#endif /* HAVE_STRIDE_SCHED */
++
++
++/** @brief Reschedules the task.
++ *
++ * The task is rescheduled on its home thread. The task will eventually run
++ * (unless the home thread is quiescent). Due to locking issues, the task may
++ * not be scheduled right away -- scheduled() may not immediately return true.
++ *
++ * @sa unschedule, strong_reschedule
++ */
++inline void
++Task::reschedule()
++{
++ GIANT_REQUIRED;
++ if (!scheduled())
++ true_reschedule();
++}
++
++
++/** @brief Call the task's hook.
++ *
++ * This function is generally called by the RouterThread implementation; there
++ * should be no need to call it yourself.
++ */
++inline void
++Task::call_hook()
++{
++#if __MTCLICK__
++ _cycle_runs++;
++#endif
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++ _runs++;
++ if (!_hook)
++ _work_done += ((Element*)_thunk)->run_task(this);
++ else
++ _work_done += _hook(this, _thunk);
++#else
++ if (!_hook)
++ (void) ((Element*)_thunk)->run_task(this);
++ else
++ (void) _hook(this, _thunk);
++#endif
++}
++
++#ifdef HAVE_ADAPTIVE_SCHEDULER
++inline unsigned
++Task::runs() const
++{
++ return _runs;
++}
++
++inline unsigned
++Task::work_done() const
++{
++ return _work_done;
++}
++
++inline unsigned
++Task::utilization() const
++{
++ return (_runs ? (MAX_UTILIZATION * _work_done) / _runs : 0);
++}
++
++inline void
++Task::clear_runs()
++{
++ _runs = _work_done = 0;
++}
++#endif
++
++#if __MTCLICK__
++inline int
++Task::cycles() const
++{
++ return _cycles.unscaled_average();
++}
++
++inline unsigned
++Task::cycle_runs() const
++{
++ return _cycle_runs;
++}
++
++inline void
++Task::update_cycles(unsigned c)
++{
++ _cycles.update(c);
++ _cycle_runs = 0;
++}
++#endif
++
++inline Task *
++Task::pending_to_task(uintptr_t ptr)
++{
++ return reinterpret_cast<Task *>(ptr & ~(uintptr_t) 3);
++}
++
++inline Task *
++Task::pending_to_task() const
++{
++ return pending_to_task(_pending_nextptr);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/timer.hh click-1.6.0-27/inst/include/click/timer.hh
+--- click-1.6.0/inst/include/click/timer.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/timer.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,243 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/timer.cc" -*-
++#ifndef CLICK_TIMER_HH
++#define CLICK_TIMER_HH
++#include <click/sync.hh>
++#include <click/glue.hh>
++#include <click/element.hh>
++#include <click/timestamp.hh>
++CLICK_DECLS
++class Element;
++class Router;
++class Timer;
++class Task;
++
++typedef void (*TimerHook)(Timer *, void *);
++
++class Timer { public:
++
++ Timer();
++ Timer(TimerHook hook, void *thunk);
++ Timer(Element *element); // call element->run_timer()
++ Timer(Task *task); // call task->reschedule()
++ inline ~Timer();
++
++ void set_hook(TimerHook hook, void *thunk);
++ void set_hook(Element *element);
++ void set_hook(Task *task);
++
++ inline bool initialized() const;
++ inline bool scheduled() const;
++ inline const Timestamp &expiry() const;
++
++ inline void initialize(Router*);
++ inline void initialize(Element*);
++
++ void schedule_at(const Timestamp &when);
++ inline void reschedule_at(const Timestamp &when); // synonym
++
++ inline void schedule_now();
++ void schedule_after(const Timestamp &delta);
++ inline void schedule_after_sec(uint32_t delta_sec);
++ inline void schedule_after_msec(uint32_t delta_msec);
++ inline void reschedule_after(const Timestamp &delta);
++ inline void reschedule_after_sec(uint32_t delta_sec);
++ inline void reschedule_after_msec(uint32_t delta_msec);
++
++ void unschedule();
++
++ inline void schedule_after_s(uint32_t delta_sec) CLICK_DEPRECATED;
++ inline void schedule_after_ms(uint32_t delta_sec) CLICK_DEPRECATED;
++ inline void reschedule_after_s(uint32_t delta_sec) CLICK_DEPRECATED;
++ inline void reschedule_after_ms(uint32_t delta_sec) CLICK_DEPRECATED;
++
++ private:
++
++ int _schedpos;
++ Timestamp _expiry;
++ TimerHook _hook;
++ void *_thunk;
++ Router *_router;
++
++ Timer(const Timer &);
++ Timer &operator=(const Timer &);
++
++ friend class Master;
++
++};
++
++/** @brief Destroy a Timer, unscheduling it first if necessary. */
++inline
++Timer::~Timer()
++{
++ if (scheduled())
++ unschedule();
++}
++
++/** @brief Returns true iff the Timer has been initialized. */
++inline bool
++Timer::initialized() const
++{
++ return _router != 0;
++}
++
++/** @brief Returns true iff the Timer is currently scheduled. */
++inline bool
++Timer::scheduled() const
++{
++ return _schedpos >= 0;
++}
++
++/** @brief Returns the Timer's current expiration time.
++ *
++ * The expiration time is the absolute time at which the timer is next
++ * scheduled to fire. If the timer is not currently scheduled, then expiry()
++ * returns the last assigned expiration time. */
++inline const Timestamp &
++Timer::expiry() const
++{
++ return _expiry;
++}
++
++/** @brief Initialize the timer.
++ *
++ * @param router the containing router
++ *
++ * Before a timer can be used, it must be attached to a containing router.
++ * When that router is destroyed, the timer is automatically unscheduled.
++ */
++inline void
++Timer::initialize(Router *router)
++{
++ assert(!initialized());
++ _router = router;
++}
++
++/** @brief Initialize the timer.
++ *
++ * @param element identifies the containing router
++ *
++ * @sa initialize(Router *router)
++ */
++inline void
++Timer::initialize(Element *element)
++{
++ initialize(element->router());
++}
++
++/** @brief Schedule the timer to fire at @a when.
++ *
++ * @param when expiration time
++ *
++ * This element is a synonym for schedule_at(). */
++inline void
++Timer::reschedule_at(const Timestamp &when)
++{
++ schedule_at(when);
++}
++
++/** @brief Shedule the timer to fire immediately.
++ *
++ * Equivalent to schedule_at(Timestamp::now()). */
++inline void
++Timer::schedule_now()
++{
++ schedule_at(Timestamp::now());
++}
++
++/** @brief Schedule the timer to fire after @a delta_sec seconds.
++ *
++ * @param delta_sec interval until expiration time, in seconds
++ *
++ * @sa schedule_after, reschedule_after_sec */
++inline void
++Timer::schedule_after_sec(uint32_t delta_sec)
++{
++ schedule_after(Timestamp(delta_sec, 0));
++}
++
++/** @brief Schedule the timer to fire after @a delta_msec milliseconds.
++ *
++ * @param delta_msec interval until expiration time, in milliseconds
++ *
++ * @sa schedule_after, reschedule_after_msec */
++inline void
++Timer::schedule_after_msec(uint32_t delta_msec)
++{
++ schedule_after(Timestamp::make_msec(delta_msec));
++}
++
++/** @brief Schedule the timer to fire @a delta time after its previous expiry.
++ *
++ * @param delta interval until expiration time
++ *
++ * @sa schedule_after */
++inline void
++Timer::reschedule_after(const Timestamp &delta)
++{
++ schedule_at(_expiry + delta);
++}
++
++/** @brief Schedule the timer to fire @a delta_sec seconds after its previous
++ * expiry.
++ *
++ * @param delta_sec interval until expiration time, in seconds
++ *
++ * @sa schedule_after_sec */
++inline void
++Timer::reschedule_after_sec(uint32_t delta_sec)
++{
++ schedule_at(Timestamp(_expiry.sec() + delta_sec, _expiry.subsec()));
++}
++
++/** @brief Schedule the timer to fire @a delta_msec milliseconds after its
++ * previous expiry.
++ *
++ * @param delta_msec interval until expiration time, in milliseconds
++ *
++ * @sa schedule_after_msec */
++inline void
++Timer::reschedule_after_msec(uint32_t delta_msec)
++{
++ schedule_at(_expiry + Timestamp::make_msec(delta_msec));
++}
++
++/** @brief Schedule the timer to fire after @a delta_sec seconds (deprecated).
++ *
++ * @deprecated Use schedule_after_sec() instead. */
++inline void
++Timer::schedule_after_s(uint32_t delta_sec)
++{
++ schedule_after_sec(delta_sec);
++}
++
++/** @brief Schedule the timer to fire after @a delta_msec milliseconds (deprecated).
++ *
++ * @deprecated Use schedule_after_msec() instead. */
++inline void
++Timer::schedule_after_ms(uint32_t delta_msec)
++{
++ schedule_after_msec(delta_msec);
++}
++
++/** @brief Schedule the timer to fire @a delta_sec seconds after its previous
++ * expiry time (deprecated).
++ *
++ * @deprecated Use reschedule_after_sec() instead. */
++inline void
++Timer::reschedule_after_s(uint32_t delta_sec)
++{
++ reschedule_after_sec(delta_sec);
++}
++
++/** @brief Schedule the timer to fire @a delta_msec milliseconds after its
++ * previous expiry time (deprecated).
++ *
++ * @deprecated Use reschedule_after_msec() instead. */
++inline void
++Timer::reschedule_after_ms(uint32_t delta_msec)
++{
++ reschedule_after_msec(delta_msec);
++}
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/timestamp.hh click-1.6.0-27/inst/include/click/timestamp.hh
+--- click-1.6.0/inst/include/click/timestamp.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/timestamp.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,699 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/timestamp.cc" -*-
++#ifndef CLICK_TIMESTAMP_HH
++#define CLICK_TIMESTAMP_HH
++#include <click/glue.hh>
++CLICK_DECLS
++class String;
++#if !HAVE_NANOTIMESTAMP && SIZEOF_STRUCT_TIMEVAL == 8
++# define TIMESTAMP_PUNS_TIMEVAL 1
++#endif
++#if HAVE_STRUCT_TIMESPEC && HAVE_NANOTIMESTAMP && SIZEOF_STRUCT_TIMESPEC == 8
++# define TIMESTAMP_PUNS_TIMESPEC 1
++#endif
++#if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
++# include <math.h>
++#endif
++
++#if HAVE_NANOTIMESTAMP
++# define PRITIMESTAMP "%d.%09d"
++#else
++# define PRITIMESTAMP "%d.%06d"
++#endif
++
++class Timestamp { public:
++
++#if HAVE_NANOTIMESTAMP
++ enum {
++ NSUBSEC = 1000000000 /**< Number of subseconds in a second. Can be
++ 1000000 or 1000000000, depending on how
++ Click is compiled. */
++ };
++#else
++ enum {
++ NSUBSEC = 1000000
++ };
++#endif
++
++ inline Timestamp();
++ inline Timestamp(int32_t sec, uint32_t subsec);
++ inline Timestamp(const struct timeval &tv);
++#if HAVE_STRUCT_TIMESPEC
++ inline Timestamp(const struct timespec &ts);
++#endif
++#if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
++ inline Timestamp(double);
++#endif
++
++ typedef int32_t (Timestamp::*unspecified_bool_type)() const;
++ inline operator unspecified_bool_type() const;
++
++ inline int32_t sec() const;
++ inline uint32_t subsec() const;
++
++ inline uint32_t msec() const;
++ inline uint32_t usec() const;
++ inline uint32_t nsec() const;
++
++ inline int32_t msec1() const;
++ inline int32_t usec1() const;
++ inline int32_t nsec1() const;
++
++#if TIMESTAMP_PUNS_TIMEVAL
++ inline const struct timeval &timeval() const;
++#else
++ inline struct timeval timeval() const;
++#endif
++#if HAVE_STRUCT_TIMESPEC
++# if TIMESTAMP_PUNS_TIMESPEC
++ inline const struct timespec ×pec() const;
++# else
++ inline struct timespec timespec() const;
++# endif
++#endif
++#if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
++ inline double doubleval() const;
++#endif
++
++ static inline Timestamp make_msec(uint32_t msec);
++ static inline Timestamp make_usec(int32_t sec, uint32_t usec);
++ static inline Timestamp make_usec(uint32_t usec);
++ static inline Timestamp make_nsec(int32_t sec, uint32_t nsec);
++
++ static inline Timestamp epsilon();
++ static inline Timestamp now();
++
++ inline void set(int32_t sec, uint32_t subsec);
++ inline void set_sec(int32_t sec);
++ inline void set_subsec(uint32_t subsec);
++ inline void set_usec(int32_t sec, uint32_t usec);
++ inline void set_nsec(int32_t sec, uint32_t nsec);
++
++ inline void set_now();
++#if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
++ int set_timeval_ioctl(int fd, int ioctl_selector);
++#endif
++
++ void add_fix();
++ void sub_fix();
++
++ String unparse() const;
++
++ inline static uint32_t msec_to_subsec(uint32_t msec);
++ inline static uint32_t usec_to_subsec(uint32_t usec);
++ inline static uint32_t nsec_to_subsec(uint32_t nsec);
++ inline static uint32_t subsec_to_msec(uint32_t subsec);
++ inline static uint32_t subsec_to_usec(uint32_t subsec);
++ inline static uint32_t subsec_to_nsec(uint32_t subsec);
++
++ int32_t _sec;
++ int32_t _subsec;
++
++};
++
++
++/** @brief Convert milliseconds to subseconds.
++ @param msec number of milliseconds
++
++ Converts its parameter to a number of subseconds (that is, either
++ microseconds or nanoseconds, depending on configuration options and driver
++ choice).
++
++ @sa usec_to_subsec(), nsec_to_subsec(), subsec_to_msec(), subsec_to_usec(),
++ subsec_to_nsec() */
++inline uint32_t
++Timestamp::msec_to_subsec(uint32_t msec)
++{
++#if HAVE_NANOTIMESTAMP
++ return msec * 1000000;
++#else
++ return msec * 1000;
++#endif
++}
++
++/** @brief Convert microseconds to subseconds.
++ @param usec number of microseconds
++ @sa msec_to_subsec() */
++inline uint32_t
++Timestamp::usec_to_subsec(uint32_t usec)
++{
++#if HAVE_NANOTIMESTAMP
++ return usec * 1000;
++#else
++ return usec;
++#endif
++}
++
++/** @brief Convert nanoseconds to subseconds.
++ @param nsec number of nanoseconds
++ @sa msec_to_subsec() */
++inline uint32_t
++Timestamp::nsec_to_subsec(uint32_t nsec)
++{
++#if HAVE_NANOTIMESTAMP
++ return nsec;
++#else
++ return (nsec + 500) / 1000;
++#endif
++}
++
++/** @brief Convert subseconds to milliseconds.
++ @param subsec number of subseconds
++ @sa msec_to_subsec() */
++inline uint32_t
++Timestamp::subsec_to_msec(uint32_t subsec)
++{
++#if HAVE_NANOTIMESTAMP
++ return subsec / 1000000;
++#else
++ return subsec / 1000;
++#endif
++}
++
++/** @brief Convert subseconds to microseconds.
++ @param subsec number of subseconds
++ @sa msec_to_subsec() */
++inline uint32_t
++Timestamp::subsec_to_usec(uint32_t subsec)
++{
++#if HAVE_NANOTIMESTAMP
++ return subsec / 1000;
++#else
++ return subsec;
++#endif
++}
++
++/** @brief Convert subseconds to nanoseconds.
++ @param subsec number of subseconds
++ @sa msec_to_subsec() */
++inline uint32_t
++Timestamp::subsec_to_nsec(uint32_t subsec)
++{
++#if HAVE_NANOTIMESTAMP
++ return subsec;
++#else
++ return subsec * 1000;
++#endif
++}
++
++
++/** @brief Create a zero-valued Timestamp. */
++inline
++Timestamp::Timestamp()
++ : _sec(0), _subsec(0)
++{
++}
++
++/** @brief Create a Timestamp measuring @a sec seconds plus @a subsec subseconds.
++ @param sec number of seconds
++ @param subsec number of subseconds
++
++ The @a subsec parameter must be between 0 and NSUBSEC - 1; errors are not
++ necessarily checked. */
++inline
++Timestamp::Timestamp(int32_t sec, uint32_t subsec)
++ : _sec(sec), _subsec(subsec)
++{
++}
++
++/** @brief Create a Timestamp measuring @a tv.
++ @param tv timeval structure */
++inline
++Timestamp::Timestamp(const struct timeval& tv)
++ : _sec(tv.tv_sec), _subsec(usec_to_subsec(tv.tv_usec))
++{
++}
++
++#if HAVE_STRUCT_TIMESPEC
++/** @brief Create a Timestamp measuring @a ts.
++ @param ts timespec structure */
++inline
++Timestamp::Timestamp(const struct timespec& ts)
++ : _sec(ts.tv_sec), _subsec(nsec_to_subsec(ts.tv_nsec))
++{
++}
++#endif
++
++/** @brief Returns true iff this timestamp is not zero-valued. */
++inline
++Timestamp::operator unspecified_bool_type() const
++{
++ return _sec || _subsec ? &Timestamp::sec : 0;
++}
++
++/** @brief Sets this timestamp to the current time.
++
++ The current time is measured in seconds since January 1, 1970 GMT.
++ @sa now() */
++inline void
++Timestamp::set_now()
++{
++#if TIMESTAMP_PUNS_TIMEVAL
++ click_gettimeofday((struct timeval*) this);
++#else
++ struct timeval tv;
++ click_gettimeofday(&tv);
++ _sec = tv.tv_sec;
++ _subsec = usec_to_subsec(tv.tv_usec);
++#endif
++}
++
++/** @brief Return a timestamp representing the current time.
++
++ The current time is measured in seconds since January 1, 1970 GMT.
++ @sa set_now() */
++inline Timestamp
++Timestamp::now()
++{
++ Timestamp t;
++ t.set_now();
++ return t;
++}
++
++/** @brief Returns the smallest nonzero timestamp.
++
++ Same as Timestamp(0, 1). */
++inline Timestamp
++Timestamp::epsilon()
++{
++ return Timestamp(0, 1);
++}
++
++/** @brief Returns a timestamp representing an interval of @a msec
++ milliseconds.
++ @param msec number of milliseconds (may be greater than 1000) */
++inline Timestamp
++Timestamp::make_msec(uint32_t msec)
++{
++ return Timestamp(msec / 1000, msec_to_subsec(msec % 1000));
++}
++
++/** @brief Returns a timestamp representing @a sec seconds plus @a usec
++ microseconds.
++ @param sec number of seconds
++ @param usec number of microseconds (less than 1000000) */
++inline Timestamp
++Timestamp::make_usec(int32_t sec, uint32_t usec)
++{
++ return Timestamp(sec, usec_to_subsec(usec));
++}
++
++/** @brief Returns a timestamp representing an interval of @a usec
++ microseconds.
++ @param usec number of microseconds (may be greater than 1000000) */
++inline Timestamp
++Timestamp::make_usec(uint32_t usec)
++{
++ return Timestamp(usec / 1000000, usec_to_subsec(usec % 1000000));
++}
++
++/** @brief Returns a timestamp representing @a sec seconds plus @a nsec
++ nanoseconds.
++ @param sec number of seconds
++ @param nsec number of nanoseconds (less than 1000000000) */
++inline Timestamp
++Timestamp::make_nsec(int32_t sec, uint32_t nsec)
++{
++ return Timestamp(sec, nsec_to_subsec(nsec));
++}
++
++/** @brief Sets this timestamp's components.
++ @param sec number of seconds
++ @param subsec number of subseconds */
++inline void
++Timestamp::set(int32_t sec, uint32_t subsec)
++{
++ _sec = sec;
++ _subsec = subsec;
++}
++
++/** @brief Sets this timestamp's seconds component.
++ @param sec number of seconds
++
++ The subseconds component is left unchanged. */
++inline void
++Timestamp::set_sec(int32_t sec)
++{
++ _sec = sec;
++}
++
++/** @brief Sets this timestamp's subseconds component.
++ @param subsec number of subseconds
++
++ The seconds component is left unchanged. */
++inline void
++Timestamp::set_subsec(uint32_t subsec)
++{
++ _subsec = subsec;
++}
++
++/** @brief Sets this timestamp to a seconds-and-microseconds value.
++ @param sec number of seconds
++ @param usec number of microseconds (must be less than 1000000)
++ @sa make_usec() */
++inline void
++Timestamp::set_usec(int32_t sec, uint32_t usec)
++{
++ _sec = sec;
++ _subsec = usec_to_subsec(usec);
++}
++
++/** @brief Sets this timestamp to a seconds-and-nanoseconds value.
++ @param sec number of seconds
++ @param nsec number of nanoseconds (must be less than 1000000000)
++ @sa make_nsec() */
++inline void
++Timestamp::set_nsec(int32_t sec, uint32_t nsec)
++{
++ _sec = sec;
++ _subsec = nsec_to_subsec(nsec);
++}
++
++/** @brief Returns this timestamp's seconds component. */
++inline int32_t
++Timestamp::sec() const
++{
++ return _sec;
++}
++
++/** @brief Returns this timestamp's subseconds component. */
++inline uint32_t
++Timestamp::subsec() const
++{
++ return _subsec;
++}
++
++/** @brief Returns this timestamp's subseconds component, converted to
++ milliseconds. */
++inline uint32_t
++Timestamp::msec() const
++{
++ return subsec_to_msec(_subsec);
++}
++
++/** @brief Returns this timestamp's subseconds component, converted to
++ microseconds. */
++inline uint32_t
++Timestamp::usec() const
++{
++ return subsec_to_usec(_subsec);
++}
++
++/** @brief Returns this timestamp's subseconds component, converted to
++ nanoseconds. */
++inline uint32_t
++Timestamp::nsec() const
++{
++ return subsec_to_nsec(_subsec);
++}
++
++/** @brief Returns this timestamp's interval length, converted to
++ milliseconds.
++
++ Will overflow on intervals of more than 2147483.647 seconds. */
++inline int32_t
++Timestamp::msec1() const
++{
++ return _sec * 1000 + subsec_to_msec(_subsec);
++}
++
++/** @brief Returns this timestamp's interval length, converted to
++ microseconds.
++
++ Will overflow on intervals of more than 2147.483647 seconds. */
++inline int32_t
++Timestamp::usec1() const
++{
++ return _sec * 1000000 + subsec_to_usec(_subsec);
++}
++
++/** @brief Returns this timestamp's interval length, converted to
++ nanoseconds.
++
++ Will overflow on intervals of more than 2.147483647 seconds. */
++inline int32_t
++Timestamp::nsec1() const
++{
++ return _sec * 1000000000 + subsec_to_nsec(_subsec);
++}
++
++#if TIMESTAMP_PUNS_TIMEVAL
++inline const struct timeval &
++Timestamp::timeval() const
++{
++ return *(const struct timeval*) this;
++}
++#else
++/** @brief Returns a struct timeval with the same value as this timestamp.
++
++ If Timestamp and struct timeval have the same size and representation,
++ then this operation returns a "const struct timeval &" whose address is
++ the same as this Timestamp. */
++inline struct timeval
++Timestamp::timeval() const
++{
++ struct timeval tv;
++ tv.tv_sec = _sec;
++ tv.tv_usec = usec();
++ return tv;
++}
++#endif
++
++#if HAVE_STRUCT_TIMESPEC
++# if TIMESTAMP_PUNS_TIMESPEC
++inline const struct timespec &
++Timestamp::timespec() const
++{
++ return *(const struct timespec*) this;
++}
++# else
++/** @brief Returns a struct timespec with the same value as this timestamp.
++
++ If Timestamp and struct timespec have the same size and representation,
++ then this operation returns a "const struct timespec &" whose address is
++ the same as this Timestamp. */
++inline struct timespec
++Timestamp::timespec() const
++{
++ struct timespec tv;
++ tv.tv_sec = _sec;
++ tv.tv_nsec = nsec();
++ return tv;
++}
++# endif
++#endif
++
++/** @relates Timestamp
++ @brief Compares two timestamps for equality.
++
++ Returns true iff the two operands have the same seconds and subseconds
++ components. */
++inline bool
++operator==(const Timestamp &a, const Timestamp &b)
++{
++ return a.sec() == b.sec() && a.subsec() == b.subsec();
++}
++
++/** @relates Timestamp
++ @brief Compares two timestamps for inequality.
++
++ Returns true iff !(@a a == @a b). */
++inline bool
++operator!=(const Timestamp &a, const Timestamp &b)
++{
++ return !(a == b);
++}
++
++/** @relates Timestamp
++ @brief Compares two timestamps.
++
++ Returns true iff @a a represents a shorter interval than @a b, or
++ considered as absolute time, @a a happened before @a b. */
++inline bool
++operator<(const Timestamp &a, const Timestamp &b)
++{
++ return a.sec() < b.sec() || (a.sec() == b.sec() && a.subsec() < b.subsec());
++}
++
++/** @relates Timestamp
++ @brief Compares two timestamps.
++
++ Returns true iff @a a measures an interval no larger than @a b, or
++ considered as absolute time, @a a happened at or before @a b. */
++inline bool
++operator<=(const Timestamp &a, const Timestamp &b)
++{
++ return !(b < a);
++}
++
++/** @relates Timestamp
++ @brief Compares two timestamps.
++
++ Returns true iff @a a measures an interval no shorter than @a b, or
++ considered as absolute time, @a a happened at or after @a b. */
++inline bool
++operator>=(const Timestamp &a, const Timestamp &b)
++{
++ return !(a < b);
++}
++
++/** @relates Timestamp
++ @brief Compares two timestamps.
++
++ Returns true iff @a a measures a longer interval than @a b, or considered
++ as absolute time, @a a happened after @a b. */
++inline bool
++operator>(const Timestamp &a, const Timestamp &b)
++{
++ return b < a;
++}
++
++inline void
++Timestamp::add_fix()
++{
++ if (_subsec >= NSUBSEC)
++ _sec++, _subsec -= NSUBSEC;
++}
++
++inline void
++Timestamp::sub_fix()
++{
++ if (_subsec < 0)
++ _sec--, _subsec += NSUBSEC;
++}
++
++/** @brief Adds @a b to @a a.
++
++ Returns the result (the new value of @a a). */
++inline Timestamp &
++operator+=(Timestamp &a, const Timestamp &b)
++{
++ a._sec += b._sec;
++ a._subsec += b._subsec;
++ a.add_fix();
++ return a;
++}
++
++/** @brief Subtracts @a b from @a a.
++
++ Returns the result (the new value of @a a). */
++inline Timestamp &
++operator-=(Timestamp &a, const Timestamp &b)
++{
++ a._sec -= b._sec;
++ a._subsec -= b._subsec;
++ a.sub_fix();
++ return a;
++}
++
++/** @brief Adds the two operands and returns the result. */
++inline Timestamp
++operator+(Timestamp a, const Timestamp &b)
++{
++ a += b;
++ return a;
++}
++
++/** @brief Subtracts @a b from @a a and returns the result. */
++inline Timestamp
++operator-(Timestamp a, const Timestamp &b)
++{
++ a -= b;
++ return a;
++}
++
++/** @brief Negates @a a and returns the result. */
++inline Timestamp
++operator-(const Timestamp &a)
++{
++ if (a._subsec)
++ return Timestamp(-a._sec - 1, Timestamp::NSUBSEC - a._subsec);
++ else
++ return Timestamp(-a._sec, 0);
++}
++
++#if !CLICK_LINUXMODULE && !CLICK_BSDMODULE
++/** @brief Returns this timestamp's value, converted to a real number. */
++inline double
++Timestamp::doubleval() const
++{
++ return _sec + (_subsec / (double) NSUBSEC);
++}
++
++/** @brief Create a timestamp measuring @a d seconds. */
++inline
++Timestamp::Timestamp(double d)
++{
++ double dfloor = floor(d);
++ _sec = (int32_t) dfloor;
++ _subsec = (uint32_t) ((d - dfloor) * NSUBSEC + 0.5);
++ add_fix();
++}
++
++/** @brief Scales @a a by a factor of @a b and returns the result. */
++inline Timestamp
++operator*(const Timestamp &a, double b)
++{
++ return Timestamp(a.doubleval() * b);
++}
++
++inline Timestamp
++operator*(const Timestamp &a, int b)
++{
++ return Timestamp(a.doubleval() * b);
++}
++
++inline Timestamp
++operator*(const Timestamp &a, unsigned b)
++{
++ return Timestamp(a.doubleval() * b);
++}
++
++inline Timestamp
++operator*(double a, const Timestamp &b)
++{
++ return Timestamp(b.doubleval() * a);
++}
++
++inline Timestamp
++operator*(int a, const Timestamp &b)
++{
++ return Timestamp(b.doubleval() * a);
++}
++
++inline Timestamp
++operator*(unsigned a, const Timestamp &b)
++{
++ return Timestamp(b.doubleval() * a);
++}
++
++/** @brief Scales @a a down by a factor of @a b and returns the result. */
++inline Timestamp
++operator/(const Timestamp &a, double b)
++{
++ return Timestamp(a.doubleval() / b);
++}
++
++inline Timestamp
++operator/(const Timestamp &a, int b)
++{
++ return Timestamp(a.doubleval() / b);
++}
++
++inline Timestamp
++operator/(const Timestamp &a, unsigned b)
++{
++ return Timestamp(a.doubleval() / b);
++}
++
++/** @brief Divides @a a by @a b and returns the result. */
++inline double
++operator/(const Timestamp &a, const Timestamp &b)
++{
++ return a.doubleval() / b.doubleval();
++}
++# endif /* !CLICK_LINUXMODULE && !CLICK_BSDMODULE */
++
++StringAccum& operator<<(StringAccum&, const Timestamp&);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/userutils.hh click-1.6.0-27/inst/include/click/userutils.hh
+--- click-1.6.0/inst/include/click/userutils.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/userutils.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,51 @@
++// -*- c-basic-offset: 2; related-file-name: "../../lib/userutils.cc" -*-
++#ifndef CLICK_USERUTILS_HH
++#define CLICK_USERUTILS_HH
++#include <click/archive.hh>
++#include <stdio.h>
++CLICK_DECLS
++class ErrorHandler;
++
++bool glob_match(const String &string, const String &pattern);
++
++String percent_substitute(const String &string, int format1, ...);
++
++int click_strcmp(const String &a, const String &b);
++
++const char *filename_landmark(const char *, bool file_is_expr = false);
++
++String file_string(FILE *, ErrorHandler * = 0);
++String file_string(String, ErrorHandler * = 0);
++
++String unique_tmpnam(const String &, ErrorHandler * = 0);
++void remove_file_on_exit(const String &);
++bool path_allows_default_path(String path);
++String click_mktmpdir(ErrorHandler * = 0);
++
++const char *clickpath();
++void set_clickpath(const char *);
++
++String clickpath_find_file(const String& filename, const char *subdir,
++ String default_path, ErrorHandler * = 0);
++void clickpath_expand_path(const char* subdir, const String& default_path, Vector<String>&);
++
++void parse_tabbed_lines(const String &, Vector<String> *, ...);
++
++ArchiveElement init_archive_element(const String &, int);
++
++String shell_quote(const String &, bool quote_tilde = false);
++String shell_command_output_string(String command_line, const String &command_stdin, ErrorHandler *);
++
++bool compressed_data(const unsigned char *, int);
++FILE *open_uncompress_pipe(const String &filename, const unsigned char *, int, ErrorHandler *);
++
++int compressed_filename(const String &filename);
++FILE *open_compress_pipe(const String &filename, ErrorHandler *);
++
++#if HAVE_DYNAMIC_LINKING
++int clickdl_load_package(String, ErrorHandler *);
++void clickdl_load_requirement(String, const Vector<ArchiveElement> *archive, ErrorHandler *);
++#endif
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/variableenv.hh click-1.6.0-27/inst/include/click/variableenv.hh
+--- click-1.6.0/inst/include/click/variableenv.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/variableenv.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,49 @@
++// -*- c-basic-offset: 4; related-file-name: "../../lib/variableenv.cc" -*-
++#ifndef CLICK_VARIABLEENVIRONMENT_HH
++#define CLICK_VARIABLEENVIRONMENT_HH
++#include <click/string.hh>
++#include <click/vector.hh>
++CLICK_DECLS
++class StringAccum;
++
++class VariableExpander { public:
++
++ VariableExpander() { }
++ virtual ~VariableExpander() { }
++
++ virtual bool expand(const String &var, int vartype, int quote, StringAccum &) = 0;
++
++};
++
++class VariableEnvironment : public VariableExpander { public:
++
++ VariableEnvironment(VariableEnvironment *parent);
++
++ int depth() const { return _depth; }
++ int size() const { return _names.size(); }
++
++ const String &name(int i) const { return _names[i]; }
++ const Vector<String> &values() const { return _values; }
++ const String &value(int i) const { return _values[i]; }
++ const String &value(const String &name, bool &found) const;
++
++ void clear() { _names.clear(); _values.clear(); }
++
++ VariableEnvironment *parent_of(int depth);
++ bool define(const String &name, const String &value, bool override);
++ bool expand(const String &var, int vartype, int quote, StringAccum &);
++
++ private:
++
++ Vector<String> _names;
++ Vector<String> _values;
++ int _depth;
++ VariableEnvironment *_parent;
++
++};
++
++String cp_expand(const String &, VariableExpander &, bool expand_quote = false);
++String cp_expand_in_quotes(const String &, int quote);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/click/vector.cc click-1.6.0-27/inst/include/click/vector.cc
+--- click-1.6.0/inst/include/click/vector.cc 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/vector.cc 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,149 @@
++/*
++ * vector.{cc,hh} -- simple array template class
++ * Eddie Kohler
++ *
++ * Copyright (c) 1999-2000 Massachusetts Institute of Technology
++ * Copyright (c) 2006 Regents of the University of California
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file. These conditions include: you must
++ * preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding.
++ */
++
++#ifndef CLICK_VECTOR_CC
++#define CLICK_VECTOR_CC
++
++CLICK_ENDDECLS
++#include <click/glue.hh>
++#include <click/vector.hh>
++CLICK_DECLS
++
++template <class T>
++Vector<T>::Vector(const Vector<T> &o)
++ : _l(0), _n(0), _capacity(0)
++{
++ *this = o;
++}
++
++template <class T>
++Vector<T>::~Vector()
++{
++ for (size_type i = 0; i < _n; i++)
++ _l[i].~T();
++ delete[] (unsigned char *)_l;
++}
++
++template <class T> Vector<T> &
++Vector<T>::operator=(const Vector<T> &o)
++{
++ if (&o != this) {
++ for (size_type i = 0; i < _n; i++)
++ _l[i].~T();
++ _n = 0;
++ if (reserve(o._n)) {
++ _n = o._n;
++ for (size_type i = 0; i < _n; i++)
++ new(velt(i)) T(o._l[i]);
++ }
++ }
++ return *this;
++}
++
++template <class T> Vector<T> &
++Vector<T>::assign(size_type n, const T &e)
++{
++ resize(0, e);
++ resize(n, e);
++ return *this;
++}
++
++template <class T> typename Vector<T>::iterator
++Vector<T>::insert(iterator i, const T& e)
++{
++ assert(i >= begin() && i <= end());
++ size_type pos = i - begin();
++ if (_n < _capacity || reserve(RESERVE_GROW)) {
++ for (iterator j = end() - 1; j >= begin() + pos; j--) {
++ new((void*) (j+1)) T(*j);
++ j->~T();
++ }
++ new(velt(pos)) T(e);
++ _n++;
++ }
++ return begin() + pos;
++}
++
++template <class T> typename Vector<T>::iterator
++Vector<T>::erase(iterator a, iterator b)
++{
++ if (b > a) {
++ assert(a >= begin() && b <= end());
++ iterator i = a, j = b;
++ for (; j < end(); i++, j++) {
++ i->~T();
++ new((void*) i) T(*j);
++ }
++ for (; i < end(); i++)
++ i->~T();
++ _n -= b - a;
++ return a;
++ } else
++ return b;
++}
++
++template <class T> bool
++Vector<T>::reserve(size_type want)
++{
++ if (want < 0)
++ want = (_capacity > 0 ? _capacity * 2 : 4);
++ if (want <= _capacity)
++ return true;
++
++ T *new_l = (T *)new unsigned char[sizeof(T) * want];
++ if (!new_l)
++ return false;
++
++ for (size_type i = 0; i < _n; i++) {
++ new(velt(new_l, i)) T(_l[i]);
++ _l[i].~T();
++ }
++ delete[] (unsigned char *)_l;
++
++ _l = new_l;
++ _capacity = want;
++ return true;
++}
++
++template <class T> void
++Vector<T>::resize(size_type nn, const T &e)
++{
++ if (nn <= _capacity || reserve(nn)) {
++ for (size_type i = nn; i < _n; i++)
++ _l[i].~T();
++ for (size_type i = _n; i < nn; i++)
++ new(velt(i)) T(e);
++ _n = nn;
++ }
++}
++
++template <class T> void
++Vector<T>::swap(Vector<T> &o)
++{
++ T *l = _l;
++ size_type n = _n;
++ size_type cap = _capacity;
++ _l = o._l;
++ _n = o._n;
++ _capacity = o._capacity;
++ o._l = l;
++ o._n = n;
++ o._capacity = cap;
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/click/vector.hh click-1.6.0-27/inst/include/click/vector.hh
+--- click-1.6.0/inst/include/click/vector.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/click/vector.hh 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,284 @@
++#ifndef CLICK_VECTOR_HH
++#define CLICK_VECTOR_HH
++#include <click/algorithm.hh>
++CLICK_DECLS
++
++template <class T>
++class Vector { public:
++
++ typedef T value_type;
++ typedef T& reference;
++ typedef const T& const_reference;
++ typedef T* pointer;
++ typedef const T* const_pointer;
++
++ typedef int size_type;
++ enum { RESERVE_GROW = (size_type) -1 };
++
++ typedef T* iterator;
++ typedef const T* const_iterator;
++
++ explicit Vector() : _l(0), _n(0), _capacity(0) { }
++ explicit Vector(size_type n, const T &e) : _l(0), _n(0), _capacity(0) { resize(n, e); }
++ // template <class In> ...
++ Vector(const Vector<T> &);
++ ~Vector();
++
++ Vector<T>& operator=(const Vector<T>&);
++ Vector<T>& assign(size_type n, const T& e = T());
++ // template <class In> ...
++
++ // iterators
++ iterator begin() { return _l; }
++ const_iterator begin() const { return _l; }
++ iterator end() { return _l + _n; }
++ const_iterator end() const { return _l + _n; }
++
++ // capacity
++ size_type size() const { return _n; }
++ void resize(size_type nn, const T& e = T());
++ size_type capacity() const { return _capacity; }
++ bool empty() const { return _n == 0; }
++ bool reserve(size_type);
++
++ // element access
++ T& operator[](size_type i) { assert(i>=0 && i<_n); return _l[i]; }
++ const T& operator[](size_type i) const{ assert(i>=0 && i<_n); return _l[i]; }
++ T& at(size_type i) { return operator[](i); }
++ const T& at(size_type i) const { return operator[](i); }
++ T& front() { return operator[](0); }
++ const T& front() const { return operator[](0); }
++ T& back() { return operator[](_n - 1); }
++ const T& back() const { return operator[](_n - 1); }
++ T& at_u(size_type i) { return _l[i]; }
++ const T& at_u(size_type i) const { return _l[i]; }
++
++ // modifiers
++ inline void push_back(const T&);
++ inline void pop_back();
++ inline void push_front(const T&);
++ inline void pop_front();
++ iterator insert(iterator, const T&);
++ inline iterator erase(iterator);
++ iterator erase(iterator, iterator);
++ void swap(Vector<T> &);
++ void clear() { erase(begin(), end()); }
++
++ private:
++
++ T *_l;
++ size_type _n;
++ size_type _capacity;
++
++ void *velt(size_type i) const { return (void*)&_l[i]; }
++ static void *velt(T* l, size_type i) { return (void*)&l[i]; }
++
++};
++
++template <class T> inline void
++Vector<T>::push_back(const T& e)
++{
++ if (_n < _capacity || reserve(RESERVE_GROW)) {
++ new(velt(_n)) T(e);
++ _n++;
++ }
++}
++
++template <class T> inline void
++Vector<T>::pop_back()
++{
++ assert(_n > 0);
++ --_n;
++ _l[_n].~T();
++}
++
++template <class T> inline typename Vector<T>::iterator
++Vector<T>::erase(iterator i)
++{
++ return (i < end() ? erase(i, i + 1) : i);
++}
++
++template <class T> inline void
++Vector<T>::push_front(const T& e)
++{
++ insert(begin(), e);
++}
++
++template <class T> inline void
++Vector<T>::pop_front()
++{
++ erase(begin());
++}
++
++
++template <>
++class Vector<void*> { public:
++
++ typedef void* value_type;
++ typedef void*& reference;
++ typedef void* const& const_reference;
++ typedef void** pointer;
++ typedef void* const* const_pointer;
++
++ typedef int size_type;
++ enum { RESERVE_GROW = (size_type) -1 };
++
++ typedef void** iterator;
++ typedef void* const* const_iterator;
++
++ explicit Vector() : _l(0), _n(0), _capacity(0) { }
++ explicit Vector(size_type n, void* e) : _l(0), _n(0), _capacity(0) { resize(n, e); }
++ Vector(const Vector<void*> &);
++ ~Vector();
++
++ Vector<void*> &operator=(const Vector<void*> &);
++ Vector<void*> &assign(size_type n, void* e = 0);
++
++ // iterators
++ iterator begin() { return _l; }
++ const_iterator begin() const { return _l; }
++ iterator end() { return _l + _n; }
++ const_iterator end() const { return _l + _n; }
++
++ // capacity
++ size_type size() const { return _n; }
++ void resize(size_type nn, void* e = 0);
++ size_type capacity() const { return _capacity; }
++ bool empty() const { return _n == 0; }
++ bool reserve(size_type);
++
++ // element access
++ void*& operator[](size_type i) { assert(i>=0 && i<_n); return _l[i]; }
++ void* operator[](size_type i) const { assert(i>=0 && i<_n); return _l[i]; }
++ void*& at(size_type i) { return operator[](i); }
++ void* at(size_type i) const { return operator[](i); }
++ void*& front() { return operator[](0); }
++ void* front() const { return operator[](0); }
++ void*& back() { return operator[](_n - 1); }
++ void* back() const { return operator[](_n - 1); }
++ void*& at_u(size_type i) { return _l[i]; }
++ void* at_u(size_type i) const { return _l[i]; }
++
++ // modifiers
++ inline void push_back(void*);
++ inline void pop_back();
++ inline void push_front(void*);
++ inline void pop_front();
++ iterator insert(iterator, void*);
++ inline iterator erase(iterator);
++ iterator erase(iterator, iterator);
++ void swap(Vector<void*> &);
++ void clear() { _n = 0; }
++
++ private:
++
++ void **_l;
++ size_type _n;
++ size_type _capacity;
++
++};
++
++inline void
++Vector<void*>::push_back(void *e)
++{
++ if (_n < _capacity || reserve(RESERVE_GROW)) {
++ _l[_n] = e;
++ _n++;
++ }
++}
++
++inline void
++Vector<void*>::pop_back()
++{
++ assert(_n > 0);
++ --_n;
++}
++
++inline Vector<void*>::iterator
++Vector<void*>::erase(Vector<void*>::iterator e)
++{
++ return (e < end() ? erase(e, e + 1) : e);
++}
++
++inline void
++Vector<void*>::push_front(void *e)
++{
++ insert(begin(), e);
++}
++
++inline void
++Vector<void*>::pop_front()
++{
++ erase(begin());
++}
++
++
++template <class T>
++class Vector<T*>: private Vector<void*> {
++
++ typedef Vector<void*> Base;
++
++ public:
++
++ typedef T* value_type;
++ typedef T*& reference;
++ typedef T* const& const_reference;
++ typedef T** pointer;
++ typedef T* const* const_pointer;
++
++ typedef int size_type;
++ enum { RESERVE_GROW = Base::RESERVE_GROW };
++
++ typedef T** iterator;
++ typedef T* const* const_iterator;
++
++ explicit Vector() : Base() { }
++ explicit Vector(size_type n, T* e) : Base(n, (void *)e) { }
++ Vector(const Vector<T *> &o) : Base(o) { }
++ ~Vector() { }
++
++ Vector<T *> &operator=(const Vector<T *> &o)
++ { Base::operator=(o); return *this; }
++ Vector<T *> &assign(size_type n, T *e = 0)
++ { Base::assign(n, (void *)e); return *this; }
++
++ // iterators
++ const_iterator begin() const { return (const_iterator)(Base::begin()); }
++ iterator begin() { return (iterator)(Base::begin()); }
++ const_iterator end() const { return (const_iterator)(Base::end()); }
++ iterator end() { return (iterator)(Base::end()); }
++
++ // capacity
++ size_type size() const { return Base::size(); }
++ void resize(size_type n, T *e = 0) { Base::resize(n, (void *)e); }
++ size_type capacity() const { return Base::capacity(); }
++ bool empty() const { return Base::empty(); }
++ bool reserve(size_type n) { return Base::reserve(n); }
++
++ // element access
++ T*& operator[](size_type i) { return (T*&)(Base::at(i)); }
++ T* operator[](size_type i) const { return (T*)(Base::operator[](i)); }
++ T*& at(size_type i) { return (T*&)(Base::operator[](i)); }
++ T* at(size_type i) const { return (T*)(Base::at(i)); }
++ T*& front() { return (T*&)(Base::front()); }
++ T* front() const { return (T*)(Base::front()); }
++ T*& back() { return (T*&)(Base::back()); }
++ T* back() const { return (T*)(Base::back()); }
++ T*& at_u(size_type i) { return (T*&)(Base::at_u(i)); }
++ T* at_u(size_type i) const { return (T*)(Base::at_u(i)); }
++
++ // modifiers
++ void push_back(T* e) { Base::push_back((void*)e); }
++ void pop_back() { Base::pop_back(); }
++ void push_front(T *e) { Base::push_front((void*)e); }
++ void pop_front() { Base::pop_front(); }
++ iterator insert(iterator i, T* e) { return (iterator)Base::insert((void**)i, (void*)e); }
++ iterator erase(iterator i) { return (iterator)Base::erase((void**)i); }
++ iterator erase(iterator i, iterator j) { return (iterator)Base::erase((void**)i, (void**)j); }
++ void swap(Vector<T *> &o) { Base::swap(o); }
++ void clear() { Base::clear(); }
++
++};
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/dhcp.h click-1.6.0-27/inst/include/clicknet/dhcp.h
+--- click-1.6.0/inst/include/clicknet/dhcp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/dhcp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,130 @@
++#ifndef CLICKNET_DHCP_H
++#define CLICKNET_DHCP_H
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_dhcp {,
++ uint8_t op; /* message type */
++ uint8_t htype; /* hardware address type */
++ uint8_t hlen; /* hardware address length */
++ uint8_t hops; /* should be zero in client's message */
++ uint32_t xid; /* transaction id */
++ uint16_t secs; /* elapsed time in sec. from trying to boot */
++ uint16_t flags;
++ uint32_t ciaddr; /* (previously allocated) client IP address */
++ uint32_t yiaddr; /* 'your' client IP address */
++ uint32_t siaddr; /* should be zero in client's messages */
++ uint32_t giaddr; /* should be zero in client's messages */
++ uint8_t chaddr[16]; /* client's hardware address */
++ uint8_t sname[64]; /* server host name, null terminated string */
++ uint8_t file[128]; /* boot file name, null terminated string */
++ uint32_t magic; /* magic cookie */
++ uint8_t options[312]; /* message options */
++});
++
++
++#define ETH_10MB 1 /* htype */
++#define ETH_10MB_LEN 6 /* hlen */
++
++/* DHCP message OP code */
++#define DHCP_BOOTREQUEST 1
++#define DHCP_BOOTREPLY 2
++
++/* DHCP Client State*/
++enum dhcp_client_state {
++ DHCP_CLIENT_INIT_STATE = 1,
++ DHCP_CLIENT_SELECTING_STATE,
++ DHCP_CLIENT_REQUESTING_STATE,
++ DHCP_CLIENT_INIT_REBOOT,
++ DHCP_CLIENT_REBOOTING,
++ DHCP_CLIENT_BOUND,
++ DHCP_CLIENT_RENEWING,
++ DHCP_CLIENT_REBINDING
++};
++
++
++/* DHCP message type */
++#define DHCP_DISCOVER 1
++#define DHCP_OFFER 2
++#define DHCP_REQUEST 3
++#define DHCP_DECLINE 4
++#define DHCP_ACK 5
++#define DHCP_NACK 6
++#define DHCP_RELEASE 7
++#define DHCP_INFORM 8
++
++#define DHCP_MAGIC 0x63538263
++
++
++
++/* DHCP Option codes: */
++#define DHO_PAD 0
++#define DHO_SUBNET_MASK 1
++#define DHO_TIME_OFFSET 2
++#define DHO_ROUTERS 3
++#define DHO_TIME_SERVERS 4
++#define DHO_NAME_SERVERS 5
++#define DHO_DOMAIN_NAME_SERVERS 6
++#define DHO_LOG_SERVERS 7
++#define DHO_COOKIE_SERVERS 8
++#define DHO_LPR_SERVERS 9
++#define DHO_IMPRESS_SERVERS 10
++#define DHO_RESOURCE_LOCATION_SERVERS 11
++#define DHO_HOST_NAME 12
++#define DHO_BOOT_SIZE 13
++#define DHO_MERIT_DUMP 14
++#define DHO_DOMAIN_NAME 15
++#define DHO_SWAP_SERVER 16
++#define DHO_ROOT_PATH 17
++#define DHO_EXTENSIONS_PATH 18
++#define DHO_IP_FORWARDING 19
++#define DHO_NON_LOCAL_SOURCE_ROUTING 20
++#define DHO_POLICY_FILTER 21
++#define DHO_MAX_DGRAM_REASSEMBLY 22
++#define DHO_DEFAULT_IP_TTL 23
++#define DHO_PATH_MTU_AGING_TIMEOUT 24
++#define DHO_PATH_MTU_PLATEAU_TABLE 25
++#define DHO_INTERFACE_MTU 26
++#define DHO_ALL_SUBNETS_LOCAL 27
++#define DHO_BROADCAST_ADDRESS 28
++#define DHO_PERFORM_MASK_DISCOVERY 29
++#define DHO_MASK_SUPPLIER 30
++#define DHO_ROUTER_DISCOVERY 31
++#define DHO_ROUTER_SOLICITATION_ADDRESS 32
++#define DHO_STATIC_ROUTES 33
++#define DHO_TRAILER_ENCAPSULATION 34
++#define DHO_ARP_CACHE_TIMEOUT 35
++#define DHO_IEEE802_3_ENCAPSULATION 36
++#define DHO_DEFAULT_TCP_TTL 37
++#define DHO_TCP_KEEPALIVE_INTERVAL 38
++#define DHO_TCP_KEEPALIVE_GARBAGE 39
++#define DHO_NIS_DOMAIN 40
++#define DHO_NIS_SERVERS 41
++#define DHO_NTP_SERVERS 42
++#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
++#define DHO_NETBIOS_NAME_SERVERS 44
++#define DHO_NETBIOS_DD_SERVER 45
++#define DHO_NETBIOS_NODE_TYPE 46
++#define DHO_NETBIOS_SCOPE 47
++#define DHO_FONT_SERVERS 48
++#define DHO_X_DISPLAY_MANAGER 49
++#define DHO_DHCP_REQUESTED_ADDRESS 50
++#define DHO_DHCP_LEASE_TIME 51
++#define DHO_DHCP_OPTION_OVERLOAD 52
++#define DHO_DHCP_MESSAGE_TYPE 53
++#define DHO_DHCP_SERVER_IDENTIFIER 54
++#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
++#define DHO_DHCP_MESSAGE 56
++#define DHO_DHCP_MAX_MESSAGE_SIZE 57
++#define DHO_DHCP_RENEWAL_TIME 58
++#define DHO_DHCP_REBINDING_TIME 59
++#define DHO_VENDOR_CLASS_IDENTIFIER 60
++#define DHO_DHCP_CLIENT_IDENTIFIER 61
++#define DHO_NWIP_DOMAIN_NAME 62
++#define DHO_NWIP_SUBOPTIONS 63
++#define DHO_USER_CLASS 77
++#define DHO_FQDN 81
++#define DHO_DHCP_AGENT_OPTIONS 82
++#define DHO_SUBNET_SELECTION 118 /* RFC3011! */
++#define DHO_END 255
++
++#endif /* CLICKNET_DHCP_H */
+diff -Nurb click-1.6.0/inst/include/clicknet/ether.h click-1.6.0-27/inst/include/clicknet/ether.h
+--- click-1.6.0/inst/include/clicknet/ether.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/ether.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,118 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_ETHER_H
++#define CLICKNET_ETHER_H
++
++/*
++ * <clicknet/ether.h> -- Ethernet and ARP headers, based on one of the BSDs.
++ *
++ * Relevant RFCs include:
++ * RFC826 Ethernet Address Resolution Protocol: or, Converting Network
++ * Protocol Addresses to 48.bit Ethernet Address for Transmission
++ * on Ethernet Hardware
++ * RFC894 Standard for the transmission of IP datagrams over Ethernet
++ * networks
++ * Also see the relevant IEEE 802 standards.
++ */
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_ether {,
++ uint8_t ether_dhost[6]; /* 0-5 Ethernet destination address */
++ uint8_t ether_shost[6]; /* 6-11 Ethernet source address */
++ uint16_t ether_type; /* 12-13 Ethernet protocol */
++});
++
++#define ETHERTYPE_IP 0x0800
++#define ETHERTYPE_ARP 0x0806
++#define ETHERTYPE_TRAIL 0x1000
++#define ETHERTYPE_8021Q 0x8100
++#define ETHERTYPE_IP6 0x86DD
++#define ETHERTYPE_GRID 0x7fff /* wvlan_cs driver won't transmit frames with high bit of protocol number set */
++
++struct click_arp { /* Offsets relative to ARP (Ethernet) header */
++ uint16_t ar_hrd; /* 0-1 (14-15) hardware address format */
++#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
++#define ARPHRD_IEEE802 6 /* token ring */
++#define ARPHRD_ARCNET 7 /* Arcnet */
++#define ARPHRD_FRELAY 15 /* frame relay */
++#define ARPHRD_STRIP 23 /* Ricochet Starmode Radio */
++#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) */
++#define ARPHRD_80211 801 /* IEEE 802.11 (wifi) */
++ uint16_t ar_pro; /* 2-3 (16-17) protocol address format */
++ uint8_t ar_hln; /* 4 (18) hardware address length */
++ uint8_t ar_pln; /* 5 (19) protocol address length */
++ uint16_t ar_op; /* 6-7 (20-21) opcode (command) */
++#define ARPOP_REQUEST 1 /* ARP request */
++#define ARPOP_REPLY 2 /* ARP reply */
++#define ARPOP_REVREQUEST 3 /* reverse request: hw->proto */
++#define ARPOP_REVREPLY 4 /* reverse reply */
++#define ARPOP_INVREQUEST 8 /* peer identification req */
++#define ARPOP_INVREPLY 9 /* peer identification reply */
++};
++
++struct click_ether_arp {
++ struct click_arp ea_hdr; /* 0-7 (14-21) fixed-size ARP header */
++ uint8_t arp_sha[6]; /* 8-13 (22-27) sender hardware address */
++ uint8_t arp_spa[4]; /* 14-17 (28-31) sender protocol address */
++ uint8_t arp_tha[6]; /* 18-23 (32-37) target hardware address */
++ uint8_t arp_tpa[4]; /* 24-27 (38-41) target protocol address */
++};
++
++
++/* Ethernet with VLAN (802.1q) */
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_ether_vlan {,
++ uint8_t ether_dhost[6]; /* 0-5 Ethernet source address */
++ uint8_t ether_shost[6]; /* 6-11 Ethernet destination address */
++ uint16_t ether_vlan_proto; /* 12-13 == ETHERTYPE_8021Q */
++ uint16_t ether_vlan_tci; /* 14-15 tag control information */
++ uint16_t ether_vlan_encap_proto; /* 16-17 Ethernet protocol */
++});
++
++
++#define ND_SOL 0x0087 /* Neighborhood Solicitation Message Type */
++#define ND_ADV 0x0088 /* Neighborhood Advertisement Message Type */
++
++/* define structure of Neighborhood Solicitation Message */
++struct click_nd_sol {
++ uint8_t type;
++ uint8_t code;
++ uint16_t checksum;
++ uint32_t reserved;
++ uint8_t nd_tpa[16];
++ uint8_t option_type; /*option type: 1 (source link-layer add) */
++ uint8_t option_length; /*option length: 1 (in units of 8 octets) */
++ uint8_t nd_sha[6]; /*source link-layer address */
++};
++
++/* define structure of Neighborhood Advertisement Message -reply to multicast neighborhood solitation message */
++struct click_nd_adv {
++ uint8_t type;
++ uint8_t code;
++ uint16_t checksum;
++ uint8_t flags; /* bit 1: sender_is_router
++ bit 2: solicited
++ bit 3: override
++ all other bits should be zero */
++ uint8_t reserved[3];
++ uint8_t nd_tpa[16];
++ uint8_t option_type; /* option type: 2 (target link-layer add) */
++ uint8_t option_length; /* option length: 1 (in units of 8 octets) */
++ uint8_t nd_tha[6]; /* source link-layer address */
++};
++
++
++/* define structure of Neighborhood Advertisement Message - reply to unicast neighborhood solitation message */
++struct click_nd_adv2 {
++ uint8_t type;
++ uint8_t code;
++ uint16_t checksum;
++ uint8_t flags; /* bit 1: sender_is_router
++ bit 2: solicited
++ bit 3: override
++ all other bits should be zero */
++ uint8_t reserved[3];
++ uint8_t nd_tpa[16];
++};
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/fddi.h click-1.6.0-27/inst/include/clicknet/fddi.h
+--- click-1.6.0/inst/include/clicknet/fddi.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/fddi.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,47 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_FDDI_H
++#define CLICKNET_FDDI_H
++
++/*
++ * <clicknet/fddi.h> -- our own definitions of FDDI headers
++ * based on a file from Linux
++ */
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_fddi {,
++ uint8_t fc;
++ uint8_t daddr[6];
++ uint8_t saddr[6];
++});
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_fddi_8022_1 {,
++ struct click_fddi h;
++ uint8_t dsap;
++ uint8_t ssap;
++ uint8_t ctrl;
++});
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_fddi_8022_2 {,
++ struct click_fddi h;
++ uint8_t dsap;
++ uint8_t ssap;
++ uint8_t ctrl1;
++ uint8_t ctrl2;
++});
++
++CLICK_PACKED_STRUCTURE(
++struct click_fddi_snap {,
++ struct click_fddi h;
++ uint8_t dsap;
++ uint8_t ssap;
++ uint8_t ctrl;
++ uint8_t oui[3];
++ uint16_t ether_type;
++});
++
++#define FDDI_FC_LLC_ASYNC 0x50
++#define FDDI_FC_LLCMASK 0xF0 /* length/class/format bits */
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/icmp.h click-1.6.0-27/inst/include/clicknet/icmp.h
+--- click-1.6.0/inst/include/clicknet/icmp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/icmp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,124 @@
++/* -*- c-basic-offset: 4 -*- */
++#ifndef CLICKNET_ICMP_H
++#define CLICKNET_ICMP_H
++#include <clicknet/ip.h>
++
++/*
++ * <clicknet/icmp.h> -- ICMP packet definitions, based on FreeBSD.
++ *
++ * Relevant RFCs include:
++ * RFC792 Internet Control Message Protocol
++ * RFC1122 Requirements for Internet Hosts - Communication Layers
++ * RFC1123 Requirements for Internet Hosts - Application and Support
++ * RFC1812 Requirements for IP Version 4 Routers
++ */
++
++/* most icmp request types: ICMP_UNREACH, ICMP_SOURCEQUENCH, ICMP_TIMXCEED */
++struct click_icmp {
++ uint8_t icmp_type; /* 0 ICMP type (see below) */
++ uint8_t icmp_code; /* 1 ICMP code (see below) */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ uint32_t padding; /* 4-7 should be zero */
++ /* followed by original IP header and initial portion of data */
++};
++
++/* header for types with sequence numbers: ICMP_ECHO, ICMP_ECHOREPLY,
++ ICMP_INFOREQ, ICMP_INFOREQREPLY */
++struct click_icmp_sequenced {
++ uint8_t icmp_type; /* 0 ICMP type (see below) */
++ uint8_t icmp_code; /* 1 ICMP code (see below) */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ uint16_t icmp_identifier; /* 4-5 flow identifier */
++ uint16_t icmp_sequence; /* 6-7 sequence number in flow */
++};
++
++/* ICMP_PARAMPROB header */
++struct click_icmp_paramprob {
++ uint8_t icmp_type; /* 0 ICMP type (see below) */
++ uint8_t icmp_code; /* 1 ICMP code (see below) */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ uint8_t icmp_pointer; /* 4 parameter pointer */
++ uint8_t padding[3]; /* 5-7 should be zero */
++ /* followed by original IP header and initial portion of data */
++};
++
++/* Redirect header: ICMP_REDIRECT */
++struct click_icmp_redirect {
++ uint8_t icmp_type; /* 0 ICMP_REDIRECT (see below) */
++ uint8_t icmp_code; /* 1 ICMP code (see below) */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ struct in_addr icmp_gateway; /* 4-7 address of gateway */
++ /* followed by original IP header and initial portion of data */
++};
++
++/* Timestamp and TimestampReply header: ICMP_TSTAMP and ICMP_TSTAMPREPLY */
++struct click_icmp_tstamp {
++ uint8_t icmp_type; /* 0 ICMP type (see below) */
++ uint8_t icmp_code; /* 1 ICMP code (see below) */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ uint16_t icmp_identifier; /* 4-5 flow identifier */
++ uint16_t icmp_sequence; /* 6-7 sequence number in flow */
++ uint32_t icmp_originate; /* 8-11 originate timestamp */
++ uint32_t icmp_receive; /* 12-15 receive timestamp */
++ uint32_t icmp_transmit; /* 16-19 transmit timestamp */
++};
++
++/* Path MTU Discovery header: ICMP_UNREACH_NEEDFRAG */
++struct click_icmp_needfrag {
++ uint8_t icmp_type; /* 0 ICMP_UNREACH (see below) */
++ uint8_t icmp_code; /* 1 ICMP_UNREACH_NEEDFRAG */
++ uint16_t icmp_cksum; /* 2-3 checksum */
++ uint16_t padding; /* 4-5 should be zero */
++ uint16_t icmp_nextmtu; /* 6-7 Next-Hop MTU */
++ /* followed by original IP header and initial portion of data */
++};
++
++#define click_icmp_unreach click_icmp
++#define click_icmp_sourcequench click_icmp
++#define click_icmp_timxceed click_icmp
++#define click_icmp_echo click_icmp_sequenced
++
++
++/* ICMP type definitions and (indented) code definitions */
++#define ICMP_ECHOREPLY 0 /* echo reply */
++#define ICMP_UNREACH 3 /* dest unreachable, codes: */
++#define ICMP_UNREACH_NET 0 /* bad net */
++#define ICMP_UNREACH_HOST 1 /* bad host */
++#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
++#define ICMP_UNREACH_PORT 3 /* bad port */
++#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
++#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
++#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
++#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
++#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
++#define ICMP_UNREACH_NET_PROHIB 9 /* net prohibited access */
++#define ICMP_UNREACH_HOST_PROHIB 10 /* host prohibited access */
++#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
++#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
++#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */
++#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec violation */
++#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */
++#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
++#define ICMP_REDIRECT 5 /* shorter route, codes: */
++#define ICMP_REDIRECT_NET 0 /* for network */
++#define ICMP_REDIRECT_HOST 1 /* for host */
++#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
++#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
++#define ICMP_ECHO 8 /* echo service */
++#define ICMP_ROUTERADVERT 9 /* router advertisement */
++#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
++#define ICMP_TIMXCEED 11 /* time exceeded, code: */
++#define ICMP_TIMXCEED_TRANSIT 0 /* ttl==0 in transit */
++#define ICMP_TIMXCEED_REASSEMBLY 1 /* ttl==0 in reassembly */
++#define ICMP_PARAMPROB 12 /* ip header bad */
++#define ICMP_PARAMPROB_ERRATPTR 0 /* error at param ptr */
++#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
++#define ICMP_PARAMPROB_LENGTH 2 /* bad length */
++#define ICMP_TSTAMP 13 /* timestamp request */
++#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
++#define ICMP_IREQ 15 /* information request */
++#define ICMP_IREQREPLY 16 /* information reply */
++#define ICMP_MASKREQ 17 /* address mask request */
++#define ICMP_MASKREQREPLY 18 /* address mask reply */
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/icmp6.h click-1.6.0-27/inst/include/clicknet/icmp6.h
+--- click-1.6.0/inst/include/clicknet/icmp6.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/icmp6.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,114 @@
++/* -*- c-basic-offset: 4 -*- */
++#ifndef CLICKNET_ICMP6_H
++#define CLICKNET_ICMP6_H
++#include <clicknet/ip6.h>
++
++/*
++ * <clicknet/icmp6.h> -- our own definitions for ICMP6 packets
++ * Based on RFC 1885
++ */
++
++/* types for ICMP6 packets */
++#define ICMP6_UNREACH 1
++#define ICMP6_PKTTOOBIG 2
++#define ICMP6_TIMXCEED 3
++#define ICMP6_PARAMPROB 4
++
++#define ICMP6_ECHO 128
++#define ICMP6_ECHOREPLY 129
++#define ICMP6_MEMBERSHIPQUERY 130
++#define ICMP6_MEMBERSHIPREPORT 131
++#define ICMP6_MEMBERSHIPREDUCTION 132
++
++#define ICMP6_REDIRECT 137
++
++/* codes for spefic types of ICMP6 packets */
++/* ICMP6 Error Message - Type: 1 */
++#define ICMP6_UNREACH_NOROUTE 0
++#define ICMP6_UNREACH_ADMIN 1
++#define ICMP6_UNREACH_NOTNEIGHBOR 2
++#define ICMP6_UNREACH_ADDR 3
++#define ICMP6_UNREACH_NOPORT 4
++
++/* ICMP6 Time Exceeded Message - Type: 3 */
++#define ICMP6_TIMXCEED_TRANSIT 0
++#define ICMP6_TIMXCEED_REASSEMBLY 1
++
++/* ICMP6 Parameter Problem Message - Type: 4 */
++#define ICMP6_PARAMPROB_HEADER 0
++#define ICMP6_PARAMPROB_NEXTHEADER 1
++#define ICMP6_PARAMPROB_OPTION 2
++
++/* remove possible definitions for symbols */
++#undef icmp6_identifier
++#undef icmp6_sequence
++#undef icmp6_pointer
++#undef icmp6_maxdelay
++
++
++/* most ICMP6 request types */
++struct click_icmp6 {
++ uint8_t icmp6_type; /* one of the ICMP6_TYPE_*'s above */
++ uint8_t icmp6_code; /* one of the ICMP6_CODE_*'s above */
++ uint16_t icmp6_cksum; /* 16 1's comp csum */
++ uint32_t padding; /* should be zero */
++ /* followed by as much of invoking packet as will fit without the ICMPv6 packet exceeding 576 octets*/
++};
++
++/* packet too big header */
++struct click_icmp6_pkttoobig {
++ uint8_t icmp6_type; /* one of the ICMP6_TYPE_*'s above */
++ uint8_t icmp6_code; /* one of the ICMP6_CODE_*'s above */
++ uint16_t icmp6_cksum; /* 16 1's comp csum */
++ uint32_t icmp6_mtusize; /* maximum packet size */
++ /* followed by as much of invoking packet as will fit without the ICMPv6 packet exceeding 576 octets*/
++};
++
++/* parameter problem header */
++struct click_icmp6_paramprob {
++ uint8_t icmp6_type; /* one of the ICMP_TYPE_*'s above */
++ uint8_t icmp6_code; /* one of the ICMP6_CODE_*'s above */
++ uint16_t icmp6_cksum; /* 16 1's comp csum */
++ uint32_t icmp6_pointer; /* which octect in orig. IP6 pkt was a problem */
++ /* followed by as much of invoking packet as will fit without the ICMPv6 packet exceeding 576 octets*/
++};
++
++
++/* struct for things with sequence numbers - echo request & echo reply msgs*/
++struct click_icmp6_sequenced {
++ uint8_t icmp6_type; /* one of the ICMP6_TYPE_*'s above */
++ uint8_t icmp6_code; /* one of the ICMP6_CODE_*'s above */
++ uint16_t icmp6_cksum; /* 16 1's comp csum */
++ uint16_t icmp6_identifier;
++ uint16_t icmp6_sequence;
++ /* Followed by: */
++ /* Echo Request: zero or more octets of arbitary data */
++ /* Echo Reply: the data fromm the invoking Echo Request msg */
++};
++
++/* struct for group membership messages */
++struct click_icmp6_membership {
++ uint8_t icmp6_type; /* one of the ICMP6_TYPE_*'s above */
++ uint8_t icmp6_code; /* one of the ICMP6_CODE_*'s above */
++ uint16_t icmp6_cksum; /* 16 1's comp csum */
++ uint16_t icmp6_maxdelay; /* maximum response delay, in milliseconds */
++ uint16_t padding;
++ /* followed by multicast address */
++};
++
++/* struct for redirect messages */
++struct click_icmp6_redirect {
++ uint8_t icmp6_type;
++ uint8_t icmp6_code;
++ uint16_t icmp6_cksum;
++ uint32_t padding;
++ struct click_in6_addr icmp6_target;
++ struct click_in6_addr icmp6_dst;
++};
++
++/* different struct names for each type of packet */
++#define click_icmp6_unreach click_icmp6
++#define click_icmp6_timxceed click_icmp6
++#define click_icmp6_echo click_icmp6_sequenced
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/ip.h click-1.6.0-27/inst/include/clicknet/ip.h
+--- click-1.6.0/inst/include/clicknet/ip.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/ip.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,157 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_IP_H
++#define CLICKNET_IP_H
++/* get struct in_addr */
++#include <click/cxxprotect.h>
++CLICK_CXX_PROTECT
++#if CLICK_LINUXMODULE
++#include <linux/autoconf.h>
++# include <net/checksum.h>
++# include <linux/in.h>
++#else
++# include <sys/types.h>
++# include <netinet/in.h>
++#endif
++
++/*
++ * <clicknet/ip.h> -- IP header definitions, based on one of the BSDs.
++ *
++ * Relevant RFCs include:
++ * RFC791 Internet Protocol
++ * RFC3168 The Addition of Explicit Congestion Notification (ECN) to IP
++ */
++
++struct click_ip {
++#if CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
++ unsigned ip_v : 4; /* 0 version == 4 */
++ unsigned ip_hl : 4; /* header length */
++#elif CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++ unsigned ip_hl : 4; /* 0 header length */
++ unsigned ip_v : 4; /* version == 4 */
++#else
++# error "unknown byte order"
++#endif
++ uint8_t ip_tos; /* 1 type of service */
++#define IP_DSCPMASK 0xFC /* diffserv code point */
++#define IP_ECNMASK 0x03 /* ECN code point */
++#define IP_ECN_NOT_ECT 0x00 /* not ECN capable transport */
++#define IP_ECN_ECT1 0x01 /* ECN capable transport */
++#define IP_ECN_ECT2 0x02 /* ECN capable transport */
++#define IP_ECN_CE 0x03 /* ECN congestion exp'd */
++ uint16_t ip_len; /* 2-3 total length */
++ uint16_t ip_id; /* 4-5 identification */
++ uint16_t ip_off; /* 6-7 fragment offset field */
++#define IP_RF 0x8000 /* reserved fragment flag */
++#define IP_DF 0x4000 /* don't fragment flag */
++#define IP_MF 0x2000 /* more fragments flag */
++#define IP_OFFMASK 0X1FFF /* mask for fragmenting bits */
++ uint8_t ip_ttl; /* 8 time to live */
++ uint8_t ip_p; /* 9 protocol */
++ uint16_t ip_sum; /* 10-11 checksum */
++ struct in_addr ip_src; /* 12-15 source address */
++ struct in_addr ip_dst; /* 16-19 destination address */
++};
++
++/* ip_protocol */
++#define IP_PROTO_ICMP 1
++#define IP_PROTO_IGMP 2
++#define IP_PROTO_GGP 3
++#define IP_PROTO_IPIP 4
++#define IP_PROTO_ST 5
++#define IP_PROTO_TCP 6
++#define IP_PROTO_UCL 7
++#define IP_PROTO_EGP 8
++#define IP_PROTO_IGP 9
++#define IP_PROTO_BBN 10
++#define IP_PROTO_NVPII 11
++#define IP_PROTO_PUP 12
++#define IP_PROTO_ARGUS 13
++#define IP_PROTO_EMCON 14
++#define IP_PROTO_XNET 15
++#define IP_PROTO_CHAOS 16
++#define IP_PROTO_UDP 17
++#define IP_PROTO_MUX 18
++#define IP_PROTO_DCN 19
++#define IP_PROTO_HMP 20
++#define IP_PROTO_PRM 21
++#define IP_PROTO_XNS 22
++#define IP_PROTO_TRUNK1 23
++#define IP_PROTO_TRUNK2 24
++#define IP_PROTO_LEAF1 25
++#define IP_PROTO_LEAF2 26
++#define IP_PROTO_RDP 27
++#define IP_PROTO_IRTP 28
++#define IP_PROTO_ISOTP4 29
++#define IP_PROTO_NETBLT 30
++#define IP_PROTO_MFENSP 31
++#define IP_PROTO_MERIT 32
++#define IP_PROTO_DCCP 33
++#define IP_PROTO_ICMP6 58
++#define IP_PROTO_CFTP 62
++#define IP_PROTO_SATNET 64
++#define IP_PROTO_MITSUBNET 65
++#define IP_PROTO_RVD 66
++#define IP_PROTO_IPPC 67
++#define IP_PROTO_SATMON 69
++#define IP_PROTO_IPCV 71
++#define IP_PROTO_BRSATMON 76
++#define IP_PROTO_WBMON 78
++#define IP_PROTO_WBEXPAK 79
++#define IP_PROTO_SCTP 132
++
++#define IP_PROTO_NONE 257
++#define IP_PROTO_TRANSP 258
++#define IP_PROTO_TCP_OR_UDP 256
++#define IP_PROTO_PAYLOAD 259
++
++#define IPOPT_EOL 0 /* end of option list */
++#define IPOPT_NOP 1 /* no operation */
++#define IPOPT_RR 7 /* record packet route */
++#define IPOPT_TS 68 /* timestamp */
++#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
++#define IPOPT_LSRR 131 /* loose source route */
++#define IPOPT_SATID 136 /* satnet id */
++#define IPOPT_SSRR 137 /* strict source route */
++#define IPOPT_RA 148 /* router alert */
++
++#define IP_ISFRAG(iph) (((iph)->ip_off & htons(IP_MF | IP_OFFMASK)) != 0)
++#define IP_FIRSTFRAG(iph) (((iph)->ip_off & htons(IP_OFFMASK)) == 0)
++
++
++/* checksum functions */
++
++#if !CLICK_LINUXMODULE
++uint16_t click_in_cksum(const unsigned char *addr, int len);
++uint16_t click_in_cksum_pseudohdr_raw(uint32_t csum, uint32_t src, uint32_t dst, int proto, int packet_len);
++#else
++# define click_in_cksum(addr, len) \
++ ip_compute_csum((unsigned char *)(addr), (len))
++# define click_in_cksum_pseudohdr_raw(csum, src, dst, proto, transport_len) \
++ csum_tcpudp_magic((src), (dst), (transport_len), (proto), ~(csum) & 0xFFFF)
++#endif
++uint16_t click_in_cksum_pseudohdr_hard(uint32_t csum, const struct click_ip *iph, int packet_len);
++
++/* use if you're not sure whether there are source routing options */
++static inline uint16_t
++click_in_cksum_pseudohdr(uint32_t csum, const struct click_ip *iph,
++ int transport_len)
++{
++ if (iph->ip_hl == 5)
++ return click_in_cksum_pseudohdr_raw(csum, iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p, transport_len);
++ else
++ return click_in_cksum_pseudohdr_hard(csum, iph, transport_len);
++}
++
++static inline void
++click_update_in_cksum(uint16_t *csum, uint16_t old_hw, uint16_t new_hw)
++{
++ /* incrementally update IP checksum according to RFC1624:
++ new_sum = ~(~old_sum + ~old_halfword + new_halfword) */
++ uint32_t sum = (~*csum & 0xFFFF) + (~old_hw & 0xFFFF) + new_hw;
++ sum = (sum & 0xFFFF) + (sum >> 16);
++ *csum = ~(sum + (sum >> 16));
++}
++
++CLICK_CXX_UNPROTECT
++#include <click/cxxunprotect.h>
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/ip6.h click-1.6.0-27/inst/include/clicknet/ip6.h
+--- click-1.6.0/inst/include/clicknet/ip6.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/ip6.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,85 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_IP6_H
++#define CLICKNET_IP6_H
++#include <clicknet/ip.h>
++#undef s6_addr
++#undef s6_addr16
++#undef s6_addr32
++#undef s6_addr64
++
++/*
++ * <clicknet/ip6.h> -- our own definitions of IP6 headers
++ * based on RFC 2460
++ */
++
++/* IPv6 address , same as from /usr/include/netinet/in.h */
++struct click_in6_addr {
++ union {
++ uint8_t u6_addr8[16];
++ uint16_t u6_addr16[8];
++ uint32_t u6_addr32[4];
++#ifdef HAVE_INT64_TYPES
++ uint64_t u6_addr64[2];
++#endif
++ } in6_u;
++#define s6_addr in6_u.u6_addr8
++#define s6_addr16 in6_u.u6_addr16
++#define s6_addr32 in6_u.u6_addr32
++#define s6_addr64 in6_u.u6_addr64
++};
++
++struct click_ip6 {
++ union {
++ uint32_t ip6_un1_flow; /* 0-3 version, class, flow label */
++ struct {
++#if CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++ unsigned ip6_un2_tc : 4; /* 0 top of traffic class */
++ unsigned ip6_un2_v : 4; /* version == 6 */
++#elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
++ unsigned ip6_un2_v : 4; /* 0 version == 6 */
++ unsigned ip6_un2_tc : 4; /* top of traffic class */
++#else
++# error "unknown endianness!"
++#endif
++ uint8_t ip6_un2_flow[3];
++ } ip6_un2_vfc;
++ } ip6_flun;
++#define ip6_v ip6_flun.ip6_un2_vfc.ip6_un2_v
++#define ip6_tc ip6_flun.ip6_un2_vfc.ip6_un2_tc
++#define ip6_flow ip6_flun.ip6_un1_flow
++ uint16_t ip6_plen; /* 4-5 payload length */
++ uint8_t ip6_nxt; /* 6 next header */
++ uint8_t ip6_hlim; /* 7 hop limit */
++ struct click_in6_addr ip6_src; /* 8-23 source address */
++ struct click_in6_addr ip6_dst; /* 24-39 dest address */
++};
++
++#define IP6_FLOW_MASK 0x000FFFFFU
++#define IP6_FLOW_SHIFT 0
++#define IP6_CLASS_MASK 0x0FF00000U
++#define IP6_CLASS_SHIFT 20
++#define IP6_DSCP_MASK 0x0FC00000U
++#define IP6_DSCP_SHIFT 22
++#define IP6_V_MASK 0xF0000000U
++#define IP6_V_SHIFT 28
++
++CLICK_DECLS
++
++uint16_t in6_fast_cksum(const struct click_in6_addr *saddr,
++ const struct click_in6_addr *daddr,
++ uint16_t len,
++ uint8_t proto,
++ uint16_t ori_csum,
++ const unsigned char *addr,
++ uint16_t len2);
++
++uint16_t in6_cksum(const struct click_in6_addr *saddr,
++ const struct click_in6_addr *daddr,
++ uint16_t len,
++ uint8_t proto,
++ uint16_t ori_csum,
++ unsigned char *addr,
++ uint16_t len2);
++
++CLICK_ENDDECLS
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/llc.h click-1.6.0-27/inst/include/clicknet/llc.h
+--- click-1.6.0/inst/include/clicknet/llc.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/llc.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,153 @@
++/*
++ * <clicknet/llc.h> - contains the definitions for llc frames.
++ * It was originally taken from freebsd and modified for click use.
++ * John Bicket
++ */
++
++/*
++ * Copyright (c) 1988, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * @(#)if_llc.h 8.1 (Berkeley) 6/10/93
++ * $FreeBSD: src/sys/net/if_llc.h,v 1.7 1999/08/28 00:48:18 peter Exp $
++ */
++
++#ifndef CLICKNET_LLC_H
++#define CLICKNET_LLC_H
++
++/*
++ * IEEE 802.2 Link Level Control headers, for use in conjunction with
++ * 802.{3,4,5} media access control methods.
++ *
++ * Headers here do not use bit fields due to shortcomings in many
++ * compilers.
++ */
++
++struct click_llc {
++ uint8_t llc_dsap;
++ uint8_t llc_ssap;
++ union {
++ struct {
++ uint8_t control;
++ uint8_t format_id;
++ uint8_t _class;
++ uint8_t window_x2;
++ } type_u;
++ struct {
++ uint8_t num_snd_x2;
++ uint8_t num_rcv_x2;
++ } type_i;
++ struct {
++ uint8_t control;
++ uint8_t num_rcv_x2;
++ } type_s;
++ struct {
++ uint8_t control;
++ struct frmrinfo {
++ uint8_t rej_pdu_0;
++ uint8_t rej_pdu_1;
++ uint8_t frmr_control;
++ uint8_t frmr_control_ext;
++ uint8_t frmr_cause;
++ } frmrinfo;
++ } type_frmr;
++ struct {
++ uint8_t control;
++ uint8_t org_code[3];
++ uint16_t ether_type;
++ } type_snap;
++ struct {
++ uint8_t control;
++ uint8_t control_ext;
++ } type_raw;
++ } llc_un;
++};
++
++#define llc_control llc_un.type_u.control
++#define llc_control_ext llc_un.type_raw.control_ext
++#define llc_fid llc_un.type_u.format_id
++#define llc_class llc_un.type_u._class
++#define llc_window llc_un.type_u.window_x2
++#define llc_frmrinfo llc_un.type_frmr.frmrinfo
++#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0
++#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1
++#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control
++#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext
++#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext
++
++/*
++ * Don't use sizeof(struct llc_un) for LLC header sizes
++ */
++#define LLC_ISFRAMELEN 4
++#define LLC_UFRAMELEN 3
++#define LLC_FRMRLEN 7
++
++/*
++ * Unnumbered LLC format commands
++ */
++#define LLC_UI 0x3
++#define LLC_UI_P 0x13
++#define LLC_DISC 0x43
++#define LLC_DISC_P 0x53
++#define LLC_UA 0x63
++#define LLC_UA_P 0x73
++#define LLC_TEST 0xe3
++#define LLC_TEST_P 0xf3
++#define LLC_FRMR 0x87
++#define LLC_FRMR_P 0x97
++#define LLC_DM 0x0f
++#define LLC_DM_P 0x1f
++#define LLC_XID 0xaf
++#define LLC_XID_P 0xbf
++#define LLC_SABME 0x6f
++#define LLC_SABME_P 0x7f
++
++/*
++ * Supervisory LLC commands
++ */
++#define LLC_RR 0x01
++#define LLC_RNR 0x05
++#define LLC_REJ 0x09
++
++/*
++ * Info format - dummy only
++ */
++#define LLC_INFO 0x00
++
++/*
++ * ISO PDTR 10178 contains among others
++ */
++#define LLC_IP_LSAP 0x06
++#define LLC_X25_LSAP 0x7e
++#define LLC_SNAP_LSAP 0xaa
++#define LLC_ISO_LSAP 0xfe
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/ppp.h click-1.6.0-27/inst/include/clicknet/ppp.h
+--- click-1.6.0/inst/include/clicknet/ppp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/ppp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,69 @@
++#ifndef CLICKNET_PPP_H
++#define CLICKNET_PPP_H
++
++/*
++ * <clicknet/ppp.h> -- our own definition of the PPP header, borrowed from
++ * tcpdump
++ *
++ * Copyright 1989 by Carnegie Mellon.
++ *
++ * Permission to use, copy, modify, and distribute this program for any
++ * purpose and without fee is hereby granted, provided that this copyright
++ * and permission notice appear on all copies and supporting documentation,
++ * the name of Carnegie Mellon not be used in advertising or publicity
++ * pertaining to distribution of the program without specific prior
++ * permission, and notice be given in supporting documentation that copying
++ * and distribution is by permission of Carnegie Mellon and Stanford
++ * University. Carnegie Mellon makes no representations about the
++ * suitability of this software for any purpose. It is provided "as is"
++ * without express or implied warranty.
++ */
++
++#define PPP_ADDRESS 0xff /* The address byte value */
++#define PPP_CONTROL 0x03 /* The control byte value */
++
++/* Protocol numbers */
++#define PPP_IP 0x0021 /* Raw IP */
++#define PPP_OSI 0x0023 /* OSI Network Layer */
++#define PPP_NS 0x0025 /* Xerox NS IDP */
++#define PPP_DECNET 0x0027 /* DECnet Phase IV */
++#define PPP_APPLE 0x0029 /* Appletalk */
++#define PPP_IPX 0x002b /* Novell IPX */
++#define PPP_VJC 0x002d /* Van Jacobson Compressed TCP/IP */
++#define PPP_VJNC 0x002f /* Van Jacobson Uncompressed TCP/IP */
++#define PPP_BRPDU 0x0031 /* Bridging PDU */
++#define PPP_STII 0x0033 /* Stream Protocol (ST-II) */
++#define PPP_VINES 0x0035 /* Banyan Vines */
++#define PPP_IPV6 0x0057 /* IPv6 */
++#define PPP_COMP 0x00fd /* Compressed Datagram */
++
++#define PPP_HELLO 0x0201 /* 802.1d Hello Packets */
++#define PPP_LUXCOM 0x0231 /* Luxcom */
++#define PPP_SNS 0x0233 /* Sigma Network Systems */
++#define PPP_MPLS_UCAST 0x0281 /* rfc 3032 */
++#define PPP_MPLS_MCAST 0x0283 /* rfc 3022 */
++
++#define PPP_IPCP 0x8021 /* IP Control Protocol */
++#define PPP_OSICP 0x8023 /* OSI Network Layer Control Protocol */
++#define PPP_NSCP 0x8025 /* Xerox NS IDP Control Protocol */
++#define PPP_DECNETCP 0x8027 /* DECnet Control Protocol */
++#define PPP_APPLECP 0x8029 /* Appletalk Control Protocol */
++#define PPP_IPXCP 0x802b /* Novell IPX Control Protocol */
++#define PPP_STIICP 0x8033 /* Strean Protocol Control Protocol */
++#define PPP_VINESCP 0x8035 /* Banyan Vines Control Protocol */
++#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
++#define PPP_CCP 0x80fd /* Compress Control Protocol */
++#define PPP_MPLSCP 0x8281 /* rfc 3022 */
++
++#define PPP_LCP 0xc021 /* Link Control Protocol */
++#define PPP_PAP 0xc023 /* Password Authentication Protocol */
++#define PPP_LQM 0xc025 /* Link Quality Monitoring */
++#define PPP_SPAP 0xc027
++#define PPP_CHAP 0xc223 /* Challenge Handshake Authentication Protocol */
++#define PPP_BACP 0xc02b /* Bandwidth Allocation Control Protocol */
++#define PPP_BAP 0xc02d /* BAP */
++#define PPP_MP 0xc03d /* Multi-Link */
++#define PPP_SPAP_OLD 0xc123
++#define PPP_EAP 0xc227
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/radiotap.h click-1.6.0-27/inst/include/clicknet/radiotap.h
+--- click-1.6.0/inst/include/clicknet/radiotap.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/radiotap.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,243 @@
++/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
++/* $NetBSD: ieee80211_radiotap.h,v 1.10 2005/01/04 00:34:58 dyoung Exp $ */
++
++/*-
++ * Copyright (c) 2003, 2004 David Young. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of David Young may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
++ * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
++ * OF SUCH DAMAGE.
++ */
++#ifndef _NET_IF_IEEE80211RADIOTAP_H_
++#define _NET_IF_IEEE80211RADIOTAP_H_
++
++/* A generic radio capture format is desirable. There is one for
++ * Linux, but it is neither rigidly defined (there were not even
++ * units given for some fields) nor easily extensible.
++ *
++ * I suggest the following extensible radio capture format. It is
++ * based on a bitmap indicating which fields are present.
++ *
++ * I am trying to describe precisely what the application programmer
++ * should expect in the following, and for that reason I tell the
++ * units and origin of each measurement (where it applies), or else I
++ * use sufficiently weaselly language ("is a monotonically nondecreasing
++ * function of...") that I cannot set false expectations for lawyerly
++ * readers.
++ */
++#if defined(__KERNEL__) || defined(_KERNEL)
++#ifndef DLT_IEEE802_11_RADIO
++#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */
++#endif
++#endif /* defined(__KERNEL__) || defined(_KERNEL) */
++
++/* XXX tcpdump/libpcap do not tolerate variable-length headers,
++ * yet, so we pad every radiotap header to 64 bytes. Ugh.
++ */
++#define IEEE80211_RADIOTAP_HDRLEN 64
++
++/* The radio capture header precedes the 802.11 header. */
++struct ieee80211_radiotap_header {
++ u_int8_t it_version; /* Version 0. Only increases
++ * for drastic changes,
++ * introduction of compatible
++ * new fields does not count.
++ */
++ u_int8_t it_pad;
++ u_int16_t it_len; /* length of the whole
++ * header in bytes, including
++ * it_version, it_pad,
++ * it_len, and data fields.
++ */
++ u_int32_t it_present; /* A bitmap telling which
++ * fields are present. Set bit 31
++ * (0x80000000) to extend the
++ * bitmap by another 32 bits.
++ * Additional extensions are made
++ * by setting bit 31.
++ */
++} __attribute__((__packed__));
++
++/* Name Data type Units
++ * ---- --------- -----
++ *
++ * IEEE80211_RADIOTAP_TSFT u_int64_t microseconds
++ *
++ * Value in microseconds of the MAC's 64-bit 802.11 Time
++ * Synchronization Function timer when the first bit of the
++ * MPDU arrived at the MAC. For received frames, only.
++ *
++ * IEEE80211_RADIOTAP_CHANNEL 2 x u_int16_t MHz, bitmap
++ *
++ * Tx/Rx frequency in MHz, followed by flags (see below).
++ *
++ * IEEE80211_RADIOTAP_FHSS u_int16_t see below
++ *
++ * For frequency-hopping radios, the hop set (first byte)
++ * and pattern (second byte).
++ *
++ * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s
++ *
++ * Tx/Rx data rate
++ *
++ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
++ * one milliwatt (dBm)
++ *
++ * RF signal power at the antenna, decibel difference from
++ * one milliwatt.
++ *
++ * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
++ * one milliwatt (dBm)
++ *
++ * RF noise power at the antenna, decibel difference from one
++ * milliwatt.
++ *
++ * IEEE80211_RADIOTAP_DB_ANTSIGNAL u_int8_t decibel (dB)
++ *
++ * RF signal power at the antenna, decibel difference from an
++ * arbitrary, fixed reference.
++ *
++ * IEEE80211_RADIOTAP_DB_ANTNOISE u_int8_t decibel (dB)
++ *
++ * RF noise power at the antenna, decibel difference from an
++ * arbitrary, fixed reference point.
++ *
++ * IEEE80211_RADIOTAP_LOCK_QUALITY u_int16_t unitless
++ *
++ * Quality of Barker code lock. Unitless. Monotonically
++ * nondecreasing with "better" lock strength. Called "Signal
++ * Quality" in datasheets. (Is there a standard way to measure
++ * this?)
++ *
++ * IEEE80211_RADIOTAP_TX_ATTENUATION u_int16_t unitless
++ *
++ * Transmit power expressed as unitless distance from max
++ * power set at factory calibration. 0 is max power.
++ * Monotonically nondecreasing with lower power levels.
++ *
++ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t decibels (dB)
++ *
++ * Transmit power expressed as decibel distance from max power
++ * set at factory calibration. 0 is max power. Monotonically
++ * nondecreasing with lower power levels.
++ *
++ * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
++ * one milliwatt (dBm)
++ *
++ * Transmit power expressed as dBm (decibels from a 1 milliwatt
++ * reference). This is the absolute power level measured at
++ * the antenna port.
++ *
++ * IEEE80211_RADIOTAP_FLAGS u_int8_t bitmap
++ *
++ * Properties of transmitted and received frames. See flags
++ * defined below.
++ *
++ * IEEE80211_RADIOTAP_ANTENNA u_int8_t antenna index
++ *
++ * Unitless indication of the Rx/Tx antenna for this packet.
++ * The first antenna is antenna 0.
++ *
++ * IEEE80211_RADIOTAP_RX_FLAGS u_int16_t bitmap
++ *
++ * Properties of received frames. See flags defined below.
++ *
++ * IEEE80211_RADIOTAP_TX_FLAGS u_int16_t bitmap
++ *
++ * Properties of transmitted frames. See flags defined below.
++ *
++ * IEEE80211_RADIOTAP_RTS_RETRIES u_int8_t data
++ *
++ * Number of rts retries a transmitted frame used.
++ *
++ * IEEE80211_RADIOTAP_DATA_RETRIES u_int8_t data
++ *
++ * Number of unicast retries a transmitted frame used.
++ *
++ */
++enum ieee80211_radiotap_type {
++ IEEE80211_RADIOTAP_TSFT = 0,
++ IEEE80211_RADIOTAP_FLAGS = 1,
++ IEEE80211_RADIOTAP_RATE = 2,
++ IEEE80211_RADIOTAP_CHANNEL = 3,
++ IEEE80211_RADIOTAP_FHSS = 4,
++ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
++ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
++ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
++ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
++ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
++ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
++ IEEE80211_RADIOTAP_ANTENNA = 11,
++ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
++ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
++ IEEE80211_RADIOTAP_RX_FLAGS = 14,
++ IEEE80211_RADIOTAP_TX_FLAGS = 15,
++ IEEE80211_RADIOTAP_RTS_RETRIES = 16,
++ IEEE80211_RADIOTAP_DATA_RETRIES = 17,
++ IEEE80211_RADIOTAP_EXT = 31
++};
++
++#if !defined(__KERNEL__) && !defined(_KERNEL)
++/* Channel flags. */
++#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
++#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
++#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
++#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
++#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
++#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
++#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
++#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
++#endif /* !defined(__KERNEL__) && !defined(_KERNEL) */
++
++/* For IEEE80211_RADIOTAP_FLAGS */
++#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
++ * during CFP
++ */
++#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
++ * with short
++ * preamble
++ */
++#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
++ * with WEP encryption
++ */
++#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
++ * with fragmentation
++ */
++#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
++#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
++ * 802.11 header and payload
++ * (to 32-bit boundary)
++ */
++/* For IEEE80211_RADIOTAP_RX_FLAGS */
++#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
++
++/* For IEEE80211_RADIOTAP_TX_FLAGS */
++#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
++ * retries */
++#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
++#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
++
++
++
++#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */
+diff -Nurb click-1.6.0/inst/include/clicknet/rfc1483.h click-1.6.0-27/inst/include/clicknet/rfc1483.h
+--- click-1.6.0/inst/include/clicknet/rfc1483.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/rfc1483.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,20 @@
++/* -*- mode: c; c-basic-offset: 4 -*- */
++#ifndef CLICKNET_RFC1483_H
++#define CLICKNET_RFC1483_H
++
++/*
++ * <clicknet/rfc1483.h>
++ */
++
++struct click_rfc1483 {
++ uint8_t dsap;
++ uint8_t ssap;
++ uint8_t ui;
++ uint8_t orgcode[3];
++ uint16_t ether_type;
++};
++
++#define RFC1483_SNAP_IP_EXPECTED "\xAA\xAA\x03\x00\x00\x00"
++#define RFC1483_SNAP_IP_EXPECTED_LEN 6
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/tcp.h click-1.6.0-27/inst/include/clicknet/tcp.h
+--- click-1.6.0/inst/include/clicknet/tcp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/tcp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,78 @@
++/* -*- c-basic-offset: 4 -*- */
++#ifndef CLICKNET_TCP_H
++#define CLICKNET_TCP_H
++
++/*
++ * <clicknet/tcp.h> -- TCP header definitions, based on one of the BSDs.
++ *
++ * Relevant RFCs include:
++ * RFC793 Transmission Control Protocol
++ * RFC1323 TCP Extensions for High Performance
++ * RFC2018 TCP Selective Acknowledgement Options
++ * RFC2581 TCP Congestion Control
++ * RFC2883 An Extension to the Selective Acknowledgement (SACK) Option
++ * for TCP
++ * RFC3168 The Addition of Explicit Congestion Notification (ECN) to IP
++ * RFC3540 Robust Explicit Congestion Notification (ECN) Signaling with
++ * Nonces
++ * among many others. See "A Roadmap for TCP Specification Documents",
++ * currently an Internet-Draft.
++ */
++
++typedef uint32_t tcp_seq_t;
++
++struct click_tcp {
++ uint16_t th_sport; /* 0-1 source port */
++ uint16_t th_dport; /* 2-3 destination port */
++ tcp_seq_t th_seq; /* 4-7 sequence number */
++ tcp_seq_t th_ack; /* 8-11 acknowledgement number */
++#if CLICK_BYTE_ORDER == CLICK_LITTLE_ENDIAN
++ unsigned th_flags2 : 4; /* 12 more flags */
++ unsigned th_off : 4; /* data offset in words */
++#elif CLICK_BYTE_ORDER == CLICK_BIG_ENDIAN
++ unsigned th_off : 4; /* 12 data offset in words */
++ unsigned th_flags2 : 4; /* more flags */
++#else
++# error "unknown byte order"
++#endif
++#define TH_NS 0x01 /* in 'th_flags2' */
++ uint8_t th_flags; /* 13 flags */
++#define TH_FIN 0x01
++#define TH_SYN 0x02
++#define TH_RST 0x04
++#define TH_PUSH 0x08
++#define TH_ACK 0x10
++#define TH_URG 0x20
++#define TH_ECE 0x40
++#define TH_CWR 0x80
++ uint16_t th_win; /* 14-15 window */
++ uint16_t th_sum; /* 16-17 checksum */
++ uint16_t th_urp; /* 18-19 urgent pointer */
++};
++
++/*
++ * TCP sequence number comparisons
++ */
++
++#define SEQ_LT(x,y) ((int)((x)-(y)) < 0)
++#define SEQ_LEQ(x,y) ((int)((x)-(y)) <= 0)
++#define SEQ_GT(x,y) ((int)((x)-(y)) > 0)
++#define SEQ_GEQ(x,y) ((int)((x)-(y)) >= 0)
++
++/*
++ * TCP options
++ */
++
++#define TCPOPT_EOL 0
++#define TCPOPT_NOP 1
++#define TCPOPT_MAXSEG 2
++#define TCPOLEN_MAXSEG 4
++#define TCPOPT_WSCALE 3
++#define TCPOLEN_WSCALE 3
++#define TCPOPT_SACK_PERMITTED 4
++#define TCPOLEN_SACK_PERMITTED 2
++#define TCPOPT_SACK 5
++#define TCPOPT_TIMESTAMP 8
++#define TCPOLEN_TIMESTAMP 10
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/udp.h click-1.6.0-27/inst/include/clicknet/udp.h
+--- click-1.6.0/inst/include/clicknet/udp.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/udp.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,18 @@
++#ifndef CLICKNET_UDP_H
++#define CLICKNET_UDP_H
++
++/*
++ * <clicknet/udp.h> -- UDP header definitions, based on one of the BSDs.
++ *
++ * Relevant RFCs include:
++ * RFC768 User Datagram Protocol
++ */
++
++struct click_udp {
++ uint16_t uh_sport; /* 0-1 source port */
++ uint16_t uh_dport; /* 2-3 destination port */
++ uint16_t uh_ulen; /* 4-5 UDP length */
++ uint16_t uh_sum; /* 6-7 checksum */
++};
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicknet/wifi.h click-1.6.0-27/inst/include/clicknet/wifi.h
+--- click-1.6.0/inst/include/clicknet/wifi.h 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicknet/wifi.h 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,410 @@
++/*
++ * <clicknet/wifi.h> - contains the definitions for 802.11 frames.
++ * It was originally taken from freebsd and modified for click use.
++ * John Bicket
++ */
++
++/* $NetBSD: if_ieee80211.h,v 1.5 2000/07/21 04:47:40 onoe Exp $ */
++/* $FreeBSD: src/sys/net/if_ieee80211.h,v 1.3.2.3 2001/07/04 00:12:38 brooks Exp $ */
++
++#ifndef _CLICKNET_WIFI_H_
++#define _CLICKNET_WIFI_H_
++
++
++#define WIFI_EXTRA_MAGIC 0x7492001
++
++enum {
++ WIFI_EXTRA_TX = (1<<0), /* packet transmission */
++ WIFI_EXTRA_TX_FAIL = (1<<1), /* transmission failed */
++ WIFI_EXTRA_TX_USED_ALT_RATE = (1<<2), /* used alternate bitrate */
++ WIFI_EXTRA_RX_ERR = (1<<3), /* failed crc check */
++ WIFI_EXTRA_RX_MORE = (1<<4), /* first part of a fragmented skb */
++ WIFI_EXTRA_NO_SEQ = (1<<5),
++ WIFI_EXTRA_NO_TXF = (1<<6),
++ WIFI_EXTRA_DO_RTS_CTS = (1<<7),
++ WIFI_EXTRA_DO_CTS = (1<<8)
++};
++
++
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_wifi_extra {,
++ uint32_t magic;
++ uint32_t flags;
++
++ uint8_t rssi;
++ uint8_t silence;
++ uint8_t power;
++ uint8_t pad;
++
++ uint8_t rate; /* bitrate in Mbps*2 */
++ uint8_t rate1; /* bitrate in Mbps*2 */
++ uint8_t rate2; /* bitrate in Mbps*2 */
++ uint8_t rate3; /* bitrate in Mbps*2 */
++
++ uint8_t max_tries;
++ uint8_t max_tries1;
++ uint8_t max_tries2;
++ uint8_t max_tries3;
++
++ uint8_t virt_col;
++ uint8_t retries;
++ uint16_t len;
++});
++
++
++/*
++ * generic definitions for IEEE 802.11 frames
++ */
++#define WIFI_ADDR_LEN 6
++
++CLICK_SIZE_PACKED_STRUCTURE(
++struct click_wifi {,
++ uint8_t i_fc[2];
++ uint8_t i_dur[2];
++ uint8_t i_addr1[WIFI_ADDR_LEN];
++ uint8_t i_addr2[WIFI_ADDR_LEN];
++ uint8_t i_addr3[WIFI_ADDR_LEN];
++ uint8_t i_seq[2];
++});
++
++#define WIFI_FC0_VERSION_MASK 0x03
++#define WIFI_FC0_VERSION_0 0x00
++#define WIFI_FC0_TYPE_MASK 0x0c
++#define WIFI_FC0_TYPE_MGT 0x00
++#define WIFI_FC0_TYPE_CTL 0x04
++#define WIFI_FC0_TYPE_DATA 0x08
++
++#define WIFI_FC0_SUBTYPE_MASK 0xf0
++/* for TYPE_MGT */
++#define WIFI_FC0_SUBTYPE_ASSOC_REQ 0x00
++#define WIFI_FC0_SUBTYPE_ASSOC_RESP 0x10
++#define WIFI_FC0_SUBTYPE_REASSOC_REQ 0x20
++#define WIFI_FC0_SUBTYPE_REASSOC_RESP 0x30
++#define WIFI_FC0_SUBTYPE_PROBE_REQ 0x40
++#define WIFI_FC0_SUBTYPE_PROBE_RESP 0x50
++#define WIFI_FC0_SUBTYPE_BEACON 0x80
++#define WIFI_FC0_SUBTYPE_ATIM 0x90
++#define WIFI_FC0_SUBTYPE_DISASSOC 0xa0
++#define WIFI_FC0_SUBTYPE_AUTH 0xb0
++#define WIFI_FC0_SUBTYPE_DEAUTH 0xc0
++/* for TYPE_CTL */
++#define WIFI_FC0_SUBTYPE_PS_POLL 0xa0
++#define WIFI_FC0_SUBTYPE_RTS 0xb0
++#define WIFI_FC0_SUBTYPE_CTS 0xc0
++#define WIFI_FC0_SUBTYPE_ACK 0xd0
++#define WIFI_FC0_SUBTYPE_CF_END 0xe0
++#define WIFI_FC0_SUBTYPE_CF_END_ACK 0xf0
++/* for TYPE_DATA (bit combination) */
++#define WIFI_FC0_SUBTYPE_DATA 0x00
++#define WIFI_FC0_SUBTYPE_CF_ACK 0x10
++#define WIFI_FC0_SUBTYPE_CF_POLL 0x20
++#define WIFI_FC0_SUBTYPE_CF_ACPL 0x30
++#define WIFI_FC0_SUBTYPE_NODATA 0x40
++#define WIFI_FC0_SUBTYPE_CFACK 0x50
++#define WIFI_FC0_SUBTYPE_CFPOLL 0x60
++#define WIFI_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
++#define WIFI_FC0_SUBTYPE_QOS 0x80
++#define WIFI_FC0_SUBTYPE_QOS_NULL 0xc0
++
++
++#define WIFI_FC1_DIR_MASK 0x03
++#define WIFI_FC1_DIR_NODS 0x00 /* STA->STA */
++#define WIFI_FC1_DIR_TODS 0x01 /* STA->AP */
++#define WIFI_FC1_DIR_FROMDS 0x02 /* AP ->STA */
++#define WIFI_FC1_DIR_DSTODS 0x03 /* AP ->AP */
++
++#define WIFI_FC1_MORE_FRAG 0x04
++#define WIFI_FC1_RETRY 0x08
++#define WIFI_FC1_PWR_MGT 0x10
++#define WIFI_FC1_MORE_DATA 0x20
++#define WIFI_FC1_WEP 0x40
++#define WIFI_FC1_ORDER 0x80
++
++#define WIFI_NWID_LEN 32
++
++/*
++ * BEACON management packets
++ *
++ * octect timestamp[8]
++ * octect beacon interval[2]
++ * octect capability information[2]
++ * information element
++ * octect elemid
++ * octect length
++ * octect information[length]
++ */
++typedef uint8_t * wifi_mgt_beacon_t;
++
++#define WIFI_BEACON_INTERVAL(beacon) \
++ (beacon[8] + (beacon[9] << 8))
++#define WIFI_BEACON_CAPABILITY(beacon) \
++ (beacon[10] + (beacon[11] << 8))
++
++#define WIFI_CAPINFO_ESS 0x01
++#define WIFI_CAPINFO_IBSS 0x02
++#define WIFI_CAPINFO_CF_POLLABLE 0x04
++#define WIFI_CAPINFO_CF_POLLREQ 0x08
++#define WIFI_CAPINFO_PRIVACY 0x10
++
++
++
++#define WIFI_MAX_RETRIES 11
++
++#define WIFI_QOS_HAS_SEQ(wh) \
++ (((wh)->i_fc[0] & \
++ (WIFI_FC0_TYPE_MASK | WIFI_FC0_SUBTYPE_QOS)) == \
++ (WIFI_FC0_TYPE_DATA | WIFI_FC0_SUBTYPE_QOS))
++
++
++/*
++ * Management information elements
++ */
++struct wifi_information {
++ char ssid[WIFI_NWID_LEN+1];
++ struct rates {
++ uint8_t *p;
++ } rates;
++ struct fh {
++ uint16_t dwell;
++ uint8_t set;
++ uint8_t pattern;
++ uint8_t index;
++ } fh;
++ struct ds {
++ uint8_t channel;
++ } ds;
++ struct cf {
++ uint8_t count;
++ uint8_t period;
++ uint8_t maxdur[2];
++ uint8_t dur[2];
++ } cf;
++ struct tim {
++ uint8_t count;
++ uint8_t period;
++ uint8_t bitctl;
++ /* uint8_t pvt[251]; The driver never needs to use this */
++ } tim;
++ struct ibss {
++ uint16_t atim;
++ } ibss;
++ struct challenge {
++ uint8_t *p;
++ uint8_t len;
++ } challenge;
++};
++
++#define WIFI_RATES_MAXSIZE 15
++#define WIFI_NWID_MAXSIZE 32
++
++enum {
++ WIFI_ELEMID_SSID = 0,
++ WIFI_ELEMID_RATES = 1,
++ WIFI_ELEMID_FHPARMS = 2,
++ WIFI_ELEMID_DSPARMS = 3,
++ WIFI_ELEMID_CFPARMS = 4,
++ WIFI_ELEMID_TIM = 5,
++ WIFI_ELEMID_IBSSPARMS = 6,
++ WIFI_ELEMID_CHALLENGE = 16,
++ WIFI_ELEMID_ERP = 42,
++ WIFI_ELEMID_XRATES = 50,
++ WIFI_ELEMID_VENDOR = 221
++};
++/*
++ * AUTH management packets
++ *
++ * octect algo[2]
++ * octect seq[2]
++ * octect status[2]
++ * octect chal.id
++ * octect chal.length
++ * octect chal.text[253]
++ */
++typedef uint8_t * wifi_mgt_auth_t;
++
++#define WIFI_AUTH_ALGORITHM(auth) \
++ (auth[0] + (auth[1] << 8))
++#define WIFI_AUTH_TRANSACTION(auth) \
++ (auth[2] + (auth[3] << 8))
++#define WIFI_AUTH_STATUS(auth) \
++ (auth[4] + (auth[5] << 8))
++
++#define WIFI_AUTH_ALG_OPEN 0x0000
++#define WIFI_AUTH_ALG_SHARED 0x0001
++
++#define WIFI_AUTH_OPEN_REQUEST 1
++#define WIFI_AUTH_OPEN_RESPONSE 2
++
++#define WIFI_AUTH_SHARED_REQUEST 1
++#define WIFI_AUTH_SHARED_CHALLENGE 2
++#define WIFI_AUTH_SHARED_RESPONSE 3
++#define WIFI_AUTH_SHARED_PASS 4
++
++/*
++ * Reason codes
++ *
++ * Unlisted codes are reserved
++ */
++#define WIFI_REASON_UNSPECIFIED 1
++#define WIFI_REASON_AUTH_EXPIRE 2
++#define WIFI_REASON_AUTH_LEAVE 3
++#define WIFI_REASON_ASSOC_EXPIRE 4
++#define WIFI_REASON_ASSOC_TOOMANY 5
++#define WIFI_REASON_NOT_AUTHED 6
++#define WIFI_REASON_NOT_ASSOCED 7
++#define WIFI_REASON_ASSOC_LEAVE 8
++#define WIFI_REASON_ASSOC_NOT_AUTHED 9
++
++/*
++ * Status code
++ *
++ * Unlisted codes are reserved
++ */
++#define WIFI_STATUS_SUCCESS 0x0000
++#define WIFI_STATUS_UNSPECIFIED 1
++#define WIFI_STATUS_CAPINFO 10
++#define WIFI_STATUS_NOT_ASSOCED 11
++#define WIFI_STATUS_OTHER 12
++#define WIFI_STATUS_ALG 13
++#define WIFI_STATUS_SEQUENCE 14
++#define WIFI_STATUS_CHALLENGE 15
++#define WIFI_STATUS_TIMEOUT 16
++#define WIFI_STATUS_BASIC_RATES 18
++#define WIFI_STATUS_TOO_MANY_STATIONS 22
++#define WIFI_STATUS_RATES 23
++#define WIFI_STATUS_SHORTSLOT_REQUIRED 25
++
++
++#define WIFI_WEP_KEYLEN 5 /* 40bit */
++#define WIFI_WEP_IVLEN 3 /* 24bit */
++#define WIFI_WEP_KIDLEN 1 /* 1 octet */
++#define WIFI_WEP_CRCLEN 4 /* CRC-32 */
++#define WIFI_WEP_NKID 4 /* number of key ids */
++
++#define WIFI_WEP_HEADERSIZE (WIFI_WEP_IVLEN + WIFI_WEP_KIDLEN)
++
++
++#define WIFI_WEP_NOSUP -1
++#define WIFI_WEP_OFF 0
++#define WIFI_WEP_ON 1
++#define WIFI_WEP_MIXED 2
++
++#define WIFI_AUTH_NONE 0
++#define WIFI_AUTH_OPEN 1
++#define WIFI_AUTH_SHARED 2
++
++#define WIFI_POWERSAVE_NOSUP -1
++#define WIFI_POWERSAVE_OFF 0
++#define WIFI_POWERSAVE_CAM 1
++#define WIFI_POWERSAVE_PSP 2
++#define WIFI_POWERSAVE_PSP_CAM 3
++#define WIFI_POWERSAVE_ON WIFI_POWERSAVE_CAM
++
++#define WIFI_RATE_BASIC 0x80
++#define WIFI_RATE_VAL 0x7f
++
++#define WIFI_RATE_SIZE 0x08
++
++#define WIFI_SEQ_FRAG_MASK 0x000f
++#define WIFI_SEQ_FRAG_SHIFT 0
++#define WIFI_SEQ_SEQ_MASK 0xfff0
++#define WIFI_SEQ_SEQ_SHIFT 4
++
++
++/*
++ * 802.11 protocol crypto-related definitions.
++ */
++#define WIFI_KEYBUF_SIZE 16
++#define WIFI_MICBUF_SIZE (8+8) /* space for both tx+rx keys */
++
++
++#ifndef MAX
++#define MAX(a, b) ((a) > (b) ? (a) : (b))
++#endif
++#ifndef MIN
++#define MIN(a, b) ((a) < (b) ? (a) : (b))
++#endif
++
++
++
++/* ARPHRD_IEEE80211_PRISM uses a bloated version of Prism2 RX frame header
++ * (from linux-wlan-ng) */
++
++/*
++ * For packet capture, define the same physical layer packet header
++ * structure as used in the wlan-ng driver
++ */
++enum {
++ DIDmsg_lnxind_wlansniffrm = 0x00000044,
++ DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044,
++ DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044,
++ DIDmsg_lnxind_wlansniffrm_channel = 0x00030044,
++ DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044,
++ DIDmsg_lnxind_wlansniffrm_sq = 0x00050044,
++ DIDmsg_lnxind_wlansniffrm_signal = 0x00060044,
++ DIDmsg_lnxind_wlansniffrm_noise = 0x00070044,
++ DIDmsg_lnxind_wlansniffrm_rate = 0x00080044,
++ DIDmsg_lnxind_wlansniffrm_istx = 0x00090044,
++ DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044
++};
++enum {
++ P80211ENUM_msgitem_status_no_value = 0x00
++};
++enum {
++ P80211ENUM_truth_false = 0x00
++};
++
++
++typedef struct {
++ uint32_t did;
++ uint16_t status;
++ uint16_t len;
++ uint32_t data;
++} p80211item_uint32_t;
++
++typedef struct {
++ uint32_t msgcode;
++ uint32_t msglen;
++#define WLAN_DEVNAMELEN_MAX 16
++ uint8_t devname[WLAN_DEVNAMELEN_MAX];
++ p80211item_uint32_t hosttime;
++ p80211item_uint32_t mactime;
++ p80211item_uint32_t channel;
++ p80211item_uint32_t rssi;
++ p80211item_uint32_t sq;
++ p80211item_uint32_t signal;
++ p80211item_uint32_t noise;
++ p80211item_uint32_t rate;
++ p80211item_uint32_t istx;
++ p80211item_uint32_t frmlen;
++} wlan_ng_prism2_header;
++
++
++#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */
++#define LWNG_CAPHDR_VERSION 0x80211001
++
++#define WIFI_SLOT_B 20
++#define WIFI_DIFS_B 50
++#define WIFI_SIFS_B 10
++#define WIFI_ACK_B 304
++#define WIFI_PLCP_HEADER_LONG_B 192
++#define WIFI_PLCP_HEADER_SHORT_B 192
++
++#define WIFI_SLOT_A 9
++#define WIFI_DIFS_A 28
++#define WIFI_SIFS_A 9
++#define WIFI_ACK_A 30
++#define WIFI_PLCP_HEADER_A 20
++
++
++#define is_b_rate(b) ((b == 2) || (b == 4) || (b == 11) || (b == 22))
++
++#define WIFI_CW_MIN 31
++#define WIFI_CW_MAX 1023
++
++// 6-byte LLC header (last byte is terminating NUL)
++#define WIFI_LLC_HEADER ((const uint8_t *) "\xAA\xAA\x03\x00\x00")
++#define WIFI_LLC_HEADER_LEN 6
++
++#endif /* !_CLICKNET_WIFI_H_ */
+diff -Nurb click-1.6.0/inst/include/clicktool/eclasst.hh click-1.6.0-27/inst/include/clicktool/eclasst.hh
+--- click-1.6.0/inst/include/clicktool/eclasst.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/eclasst.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,177 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ECLASST_HH
++#define CLICK_ECLASST_HH
++#include <click/string.hh>
++#include <stddef.h>
++#include <click/vector.hh>
++#include <click/hashmap.hh>
++#include "etraits.hh"
++class ErrorHandler;
++class StringAccum;
++class RouterT;
++class ElementT;
++class VariableEnvironment;
++class ElementMap;
++class SynonymElementClassT;
++
++class ElementClassT { public:
++
++ ElementClassT(const String &);
++ virtual ~ElementClassT();
++
++ static void set_base_type_factory(ElementClassT *(*factory)(const String &));
++ static ElementClassT *base_type(const String &);
++ static ElementClassT *tunnel_type();
++
++ void use() { _use_count++; }
++ void unuse() { if (--_use_count <= 0) delete this; }
++
++ const String &name() const { return _name; }
++ const char *printable_name_c_str();
++ virtual String landmark() const { return String(); }
++
++ // 'primitive' means 'not tunnel, not compound, not synonym'.
++ virtual bool primitive() const { return true; }
++ bool tunnel() const { return this == tunnel_type(); }
++
++ const ElementTraits &traits() const;
++ virtual const ElementTraits *find_traits() const;
++
++ const String &port_count_code() const;
++ const String &processing_code() const;
++ const String &flow_code() const;
++ bool requires(const String &) const;
++ bool provides(const String &) const;
++ const String &package() const;
++ const String &documentation_name() const;
++ String documentation_url() const;
++
++ // where was this type declared?
++ virtual RouterT *declaration_scope() const;
++ virtual ElementClassT *overload_type() const;
++
++ virtual void collect_types(HashMap<ElementClassT *, int> &) const;
++ virtual void collect_overloads(Vector<ElementClassT *> &) const;
++
++ static ElementT *expand_element(ElementT *, RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++
++ virtual ElementClassT *resolve(int ninputs, int noutputs, Vector<String> &args, ErrorHandler *, const String &landmark);
++ virtual ElementT *complex_expand_element(ElementT *, const String &, Vector<String> &, RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++
++ enum UnparseKind { UNPARSE_NAMED, UNPARSE_ANONYMOUS, UNPARSE_OVERLOAD };
++ virtual void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *stop);
++ virtual String unparse_signature() const;
++ static String unparse_signature(const String &name, const Vector<String> *formal_types, int nargs, int ninputs, int noutputs);
++
++ virtual void *cast(const char *) { return 0; }
++ virtual SynonymElementClassT *cast_synonym() { return 0; }
++ virtual RouterT *cast_router() { return 0; }
++
++ private:
++
++ String _name;
++ int _use_count;
++
++ mutable int _traits_version;
++ mutable const ElementTraits *_traits;
++
++ static ElementClassT *the_tunnel_type;
++
++ ElementClassT(const ElementClassT &);
++ ElementClassT &operator=(const ElementClassT &);
++
++ ElementT *direct_expand_element(ElementT *, RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++
++};
++
++class SynonymElementClassT : public ElementClassT { public:
++
++ SynonymElementClassT(const String &, ElementClassT *, RouterT *);
++
++ ElementClassT *synonym_of() const { return _eclass; }
++
++ ElementClassT *resolve(int, int, Vector<String> &, ErrorHandler *, const String &);
++ ElementT *complex_expand_element(ElementT *, const String &, Vector<String> &, RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++
++ void collect_types(HashMap<ElementClassT *, int> &) const;
++ void collect_overloads(Vector<ElementClassT *> &) const;
++
++ void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *);
++
++ bool primitive() const { return false; }
++ const ElementTraits *find_traits() const;
++
++ RouterT *declaration_scope() const;
++ ElementClassT *overload_type() const { return _eclass; }
++
++ SynonymElementClassT *cast_synonym() { return this; }
++ RouterT *cast_router();
++
++ private:
++
++ ElementClassT *_eclass;
++ RouterT *_declaration_scope;
++
++};
++
++
++extern int32_t default_element_map_version;
++
++inline ElementClassT *
++ElementClassT::tunnel_type()
++{
++ assert(the_tunnel_type);
++ return the_tunnel_type;
++}
++
++inline const ElementTraits &
++ElementClassT::traits() const
++{
++ if (_traits_version != default_element_map_version) {
++ _traits_version = default_element_map_version;
++ _traits = find_traits();
++ }
++ return *_traits;
++}
++
++inline const String &
++ElementClassT::documentation_name() const
++{
++ return traits().documentation_name;
++}
++
++inline const String &
++ElementClassT::port_count_code() const
++{
++ return traits().port_count_code;
++}
++
++inline const String &
++ElementClassT::processing_code() const
++{
++ return traits().processing_code;
++}
++
++inline const String &
++ElementClassT::flow_code() const
++{
++ return traits().flow_code;
++}
++
++inline bool
++ElementClassT::requires(const String &req) const
++{
++ return traits().requires(req);
++}
++
++inline bool
++ElementClassT::provides(const String &req) const
++{
++ return traits().provides(req);
++}
++
++inline size_t hashcode(ElementClassT *e) {
++ return CLICK_NAME(hashcode)(static_cast<void *>(e));
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/elementmap.hh click-1.6.0-27/inst/include/clicktool/elementmap.hh
+--- click-1.6.0/inst/include/clicktool/elementmap.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/elementmap.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,181 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ELEMENTMAP_HH
++#define CLICK_ELEMENTMAP_HH
++#include "etraits.hh"
++
++class ElementMap { public:
++
++ ElementMap();
++ ElementMap(const String&, ErrorHandler* = 0);
++ ~ElementMap();
++
++ static ElementMap* default_map() { return the_element_map; }
++ static void push_default(ElementMap*);
++ static void pop_default();
++
++ void use() { _use_count++; }
++ void unuse() { _use_count--; }
++
++ int size() const { return _e.size(); }
++ bool empty() const { return _e.size() == 1; }
++
++ const Traits& traits(const String&) const;
++ const Traits& traits_at(int i) const { return _e[i]; }
++ bool has_traits(const String&) const;
++ int traits_index(const String&) const;
++
++ bool provides_global(const String&) const;
++
++ int definition_index(int i) const { return _e[i].def_index; }
++ const String& source_directory(const Traits&) const;
++ const String& package(const Traits&) const;
++ const String& package(const String&) const;
++ String documentation_url(const Traits&) const;
++
++ class TraitsIterator;
++ TraitsIterator begin_elements() const;
++
++ int add(const Traits&);
++ void remove_at(int);
++
++ void parse(const String& data, ErrorHandler* = 0);
++ void parse(const String& data, const String& package_name, ErrorHandler* = 0);
++ void parse_xml(const String& data, const String& package_name, ErrorHandler*);
++ bool parse_default_file(const String& default_path, ErrorHandler*);
++ bool parse_requirement_files(RouterT*, const String& default_path, ErrorHandler*, String* not_found = 0);
++ bool parse_all_files(RouterT*, const String& default_path, ErrorHandler*);
++ static void report_file_not_found(String default_path, bool found_default, ErrorHandler*);
++ String unparse(const String& package = String()) const;
++ String unparse_nonxml() const;
++
++ int check_completeness(const RouterT*, ErrorHandler*) const;
++ bool driver_indifferent(const RouterT*, int driver_mask = Driver::ALLMASK, ErrorHandler* = 0) const;
++ bool driver_compatible(const RouterT*, int driver, ErrorHandler* = 0) const;
++
++ int driver_mask() const { return _driver_mask; }
++ void set_driver(int d) { set_driver_mask(1 << d); }
++ void set_driver_mask(int);
++
++ private:
++
++ struct Globals {
++ String srcdir;
++ String compile_flags;
++ String package;
++ String dochref;
++ };
++
++ Vector<Traits> _e;
++ HashMap<String, int> _name_map;
++
++ Vector<Globals> _def;
++
++ int _use_count;
++ int _driver_mask;
++
++ int get_driver_mask(const String&);
++ int driver_elt_index(int) const;
++
++ void collect_indexes(const RouterT*, Vector<int>&, ErrorHandler*) const;
++
++ static ElementMap* the_element_map;
++ static void bump_version();
++ void incr_version() const;
++
++};
++
++extern int32_t default_element_map_version;
++
++
++class ElementMap::TraitsIterator { public:
++
++ TraitsIterator(const ElementMap*, bool elements_only);
++
++ operator bool() { return _index < _emap->size(); }
++ void operator++(int);
++
++ const ElementTraits& value() const { return _emap->traits_at(_index); }
++ int traits_index() const { return _index; }
++
++ private:
++
++ const ElementMap* _emap;
++ int _index;
++ bool _elements_only;
++
++};
++
++
++inline const Traits&
++ElementMap::traits(const String& name) const
++{
++ int i = _name_map[name];
++ if (!(_e[i].driver_mask & _driver_mask))
++ i = driver_elt_index(i);
++ return _e[i];
++}
++
++inline bool
++ElementMap::has_traits(const String& name) const
++{
++ int i = _name_map[name];
++ if (!(_e[i].driver_mask & _driver_mask) && i > 0)
++ i = driver_elt_index(i);
++ return i > 0;
++}
++
++inline int
++ElementMap::traits_index(const String& name) const
++{
++ int i = _name_map[name];
++ if (!(_e[i].driver_mask & _driver_mask) && i > 0)
++ i = driver_elt_index(i);
++ return i;
++}
++
++inline const String&
++ElementMap::source_directory(const ElementTraits& t) const
++{
++ return _def[t.def_index].srcdir;
++}
++
++inline const String&
++ElementMap::package(const ElementTraits& t) const
++{
++ return _def[t.def_index].package;
++}
++
++inline const String&
++ElementMap::package(const String& name) const
++{
++ return package(traits(name));
++}
++
++inline void
++ElementMap::bump_version()
++{
++ // ensure it stays positive
++ default_element_map_version =
++ (default_element_map_version + 1) & 0x7FFFFFFF;
++}
++
++inline void
++ElementMap::incr_version() const
++{
++ if (this == (const ElementMap *)the_element_map)
++ bump_version();
++}
++
++inline bool
++ElementMap::provides_global(const String& req) const
++{
++ return _e[0].provides(req);
++}
++
++inline ElementMap::TraitsIterator
++ElementMap::begin_elements() const
++{
++ return TraitsIterator(this, true);
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/elementt.hh click-1.6.0-27/inst/include/clicktool/elementt.hh
+--- click-1.6.0/inst/include/clicktool/elementt.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/elementt.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,208 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ELEMENTT_HH
++#define CLICK_ELEMENTT_HH
++#include "eclasst.hh"
++
++struct ElementT {
++
++ int flags;
++
++ ElementT();
++ ElementT(const String &, ElementClassT *, const String &, const String & = String());
++ ~ElementT();
++
++ RouterT *router() const { return _owner; }
++ int eindex() const { return _eindex; }
++
++ bool live() const { return _type; }
++ bool dead() const { return !_type; }
++ void kill();
++
++ const String &name() const { return _name; }
++ const char *name_c_str() const { return _name.c_str(); }
++ bool anonymous() const { return _name && _name[0] == ';'; }
++
++ ElementClassT *type() const { return _type; }
++ String type_name() const { return _type->name(); }
++ const char *type_name_c_str() const { return _type->printable_name_c_str(); }
++ void set_type(ElementClassT *);
++
++ const String &config() const { return _configuration; }
++ const String &configuration() const { return _configuration; }
++ void set_config(const String &s) { _configuration = s; }
++ void set_configuration(const String &s) { _configuration = s; }
++ String &config() { return _configuration; }
++ String &configuration() { return _configuration; }
++
++ const String &landmark() const { return _landmark; }
++ void set_landmark(const String &s) { _landmark = s; }
++ String &landmark() { return _landmark; }
++
++ bool tunnel() const { return _type==ElementClassT::tunnel_type(); }
++ inline bool tunnel_connected() const;
++ ElementT *tunnel_input() const { return _tunnel_input; }
++ ElementT *tunnel_output() const { return _tunnel_output; }
++
++ int ninputs() const { return _ninputs; }
++ int noutputs() const { return _noutputs; }
++
++ inline String declaration() const;
++
++ void *user_data() const { return _user_data; }
++ void set_user_data(void *v) { _user_data = v; }
++ void set_user_data(intptr_t v) { _user_data = (void *)v; }
++
++ static bool name_ok(const String &, bool allow_anon_names = false);
++ static void redeclaration_error(ErrorHandler *, const char *type, String name, const String &landmark, const String &old_landmark);
++
++ private:
++
++ int _eindex;
++ String _name;
++ ElementClassT *_type;
++ String _configuration;
++ String _landmark;
++ int _ninputs;
++ int _noutputs;
++ ElementT *_tunnel_input;
++ ElementT *_tunnel_output;
++ RouterT *_owner;
++ void *_user_data;
++
++ ElementT(const ElementT &);
++ ElementT &operator=(const ElementT &);
++
++ friend class RouterT;
++
++};
++
++struct PortT {
++
++ ElementT *element;
++ int port;
++
++ PortT() : element(0), port(-1) { }
++ PortT(ElementT *e, int p) : element(e), port(p) { }
++
++ bool live() const { return element != 0; }
++ bool dead() const { return element == 0; }
++ RouterT *router() const { return (element ? element->router() : 0); }
++
++ int eindex() const { return (element ? element->eindex() : -1); }
++
++ int index_in(const Vector<PortT> &, int start = 0) const;
++ int force_index_in(Vector<PortT> &, int start = 0) const;
++
++ String unparse_input() const;
++ String unparse_output() const;
++
++ static void sort(Vector<PortT> &);
++
++};
++
++class ConnectionT { public:
++
++ ConnectionT();
++ ConnectionT(const PortT &, const PortT &, const String & = String());
++ ConnectionT(const PortT &, const PortT &, const String &, int, int);
++
++ bool live() const { return _from.live(); }
++ bool dead() const { return _from.dead(); }
++ void kill() { _from.element = 0; }
++
++ const PortT &from() const { return _from; }
++ const PortT &to() const { return _to; }
++ ElementT *from_element() const { return _from.element; }
++ int from_eindex() const { return _from.eindex(); }
++ int from_port() const { return _from.port; }
++ ElementT *to_element() const { return _to.element; }
++ int to_eindex() const { return _to.eindex(); }
++ int to_port() const { return _to.port; }
++ const String &landmark() const { return _landmark; }
++
++ int next_from() const { return _next_from; }
++ int next_to() const { return _next_to; }
++
++ String unparse() const;
++
++ private:
++
++ PortT _from;
++ PortT _to;
++ String _landmark;
++ int _next_from;
++ int _next_to;
++
++ friend class RouterT;
++
++};
++
++
++inline void
++ElementT::kill()
++{
++ if (_type)
++ _type->unuse();
++ _type = 0;
++}
++
++inline void
++ElementT::set_type(ElementClassT *t)
++{
++ assert(t);
++ t->use();
++ if (_type)
++ _type->unuse();
++ _type = t;
++}
++
++inline String
++ElementT::declaration() const
++{
++ assert(_type);
++ return _name + " :: " + _type->name();
++}
++
++inline bool
++ElementT::tunnel_connected() const
++{
++ return _tunnel_input || _tunnel_output;
++}
++
++inline bool
++operator==(const PortT &h1, const PortT &h2)
++{
++ return h1.element == h2.element && h1.port == h2.port;
++}
++
++inline bool
++operator!=(const PortT &h1, const PortT &h2)
++{
++ return h1.element != h2.element || h1.port != h2.port;
++}
++
++inline bool
++operator<(const PortT &h1, const PortT &h2)
++{
++ return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port < h2.port);
++}
++
++inline bool
++operator>(const PortT &h1, const PortT &h2)
++{
++ return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port > h2.port);
++}
++
++inline bool
++operator<=(const PortT &h1, const PortT &h2)
++{
++ return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port <= h2.port);
++}
++
++inline bool
++operator>=(const PortT &h1, const PortT &h2)
++{
++ return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port >= h2.port);
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/etraits.hh click-1.6.0-27/inst/include/clicktool/etraits.hh
+--- click-1.6.0/inst/include/clicktool/etraits.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/etraits.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,85 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ETRAITS_HH
++#define CLICK_ETRAITS_HH
++#include <click/string.hh>
++
++struct Driver {
++ enum {
++ USERLEVEL = 0, LINUXMODULE = 1, BSDMODULE = 2, NSMODULE = 3,
++ ALLMASK = 0xF, COUNT = 4
++ };
++ static const char *name(int);
++ static const char *requirement(int);
++ static int driver(const String&);
++ static int driver_mask(const String&);
++};
++
++
++struct ElementTraits {
++
++ String name;
++ String cxx;
++ String documentation_name;
++ String header_file;
++ String source_file;
++ String port_count_code;
++ String processing_code;
++ String flow_code;
++ String flags;
++ String methods;
++ String requirements;
++ String provisions;
++ String libs;
++ int def_index;
++ int driver_mask;
++ int name_next;
++
++ ElementTraits();
++
++ static const ElementTraits &null_traits() { return the_null_traits; }
++
++ bool allows_driver(int d) const { return (driver_mask&(1<<d)) != 0; }
++
++ bool requires(const String &) const;
++ bool provides(const String &) const;
++ int flag_value(int) const;
++
++ String *component(int);
++ String *component(const String &);
++
++ void calculate_driver_mask();
++
++ enum {
++ D_NONE,
++ D_CLASS, D_CXX_CLASS, D_HEADER_FILE, D_PORT_COUNT, D_PROCESSING,
++ D_FLOW_CODE, D_FLAGS, D_METHODS, D_REQUIREMENTS, D_PROVISIONS, D_LIBS,
++ D_SOURCE_FILE, D_DOC_NAME,
++ D_FIRST_DEFAULT = D_CLASS, D_LAST_DEFAULT = D_LIBS
++ };
++ static int parse_component(const String &);
++ static ElementTraits make(int, ...);
++
++ private:
++
++ static ElementTraits the_null_traits;
++
++ friend class ElementMap;
++
++};
++
++typedef ElementTraits Traits;
++
++
++inline
++ElementTraits::ElementTraits()
++ : def_index(0), driver_mask(Driver::ALLMASK), name_next(0)
++{
++}
++
++inline String *
++ElementTraits::component(const String &s)
++{
++ return component(parse_component(s));
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/lexert.hh click-1.6.0-27/inst/include/clicktool/lexert.hh
+--- click-1.6.0/inst/include/clicktool/lexert.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/lexert.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,145 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_LEXERT_HH
++#define CLICK_LEXERT_HH
++#include <click/error.hh>
++#include <click/hashmap.hh>
++#include <stdio.h>
++class RouterT;
++class ElementClassT;
++class StringAccum;
++class LexerTInfo;
++class VariableEnvironment;
++
++enum {
++ lexEOF = 0,
++ lexIdent = 256,
++ lexVariable,
++ lexConfig,
++ lexArrow,
++ lex2Colon,
++ lex2Bar,
++ lex3Dot,
++ lexTunnel,
++ lexElementclass,
++ lexRequire,
++ lexDefine
++};
++
++class Lexeme { public:
++
++ Lexeme() : _kind(lexEOF) { }
++ Lexeme(int k, const String &s, const char *p) : _kind(k), _s(s), _pos(p) { }
++
++ int kind() const { return _kind; }
++ bool is(int k) const { return _kind == k; }
++ operator bool() const { return _kind != lexEOF; }
++
++ const String &string() const { return _s; }
++ String &string() { return _s; }
++
++ const char *pos1() const { return _pos; }
++ const char *pos2() const { return _pos + _s.length(); }
++
++ private:
++
++ int _kind;
++ String _s;
++ const char *_pos;
++
++};
++
++class LexerT { public:
++
++ LexerT(ErrorHandler *, bool ignore_line_directives);
++ virtual ~LexerT();
++
++ void reset(const String &data, const String &filename = String());
++ void clear();
++ void set_lexinfo(LexerTInfo *);
++ void ignore_line_directives(bool g) { _ignore_line_directives = g; }
++
++ String remaining_text() const;
++ void set_remaining_text(const String &);
++
++ const Lexeme &lex();
++ void unlex(const Lexeme &);
++ Lexeme lex_config();
++ String landmark() const;
++
++ bool yport(int &port, const char *&pos1, const char *&pos2);
++ bool yelement(int &element, bool comma_ok);
++ void ydeclaration(const Lexeme &first_element = Lexeme());
++ bool yconnection();
++ void ycompound_arguments(RouterT *);
++ void yelementclass(const char *pos1);
++ void ytunnel();
++ ElementClassT *ycompound(String, const char *decl_pos1, const char *name_pos1);
++ void yrequire();
++ void yvar();
++ bool ystatement(bool nested = false);
++
++ RouterT *router() const { return _router; }
++ RouterT *finish(const VariableEnvironment &global_scope);
++
++ protected:
++
++ // lexer
++ String _big_string;
++
++ const char *_data;
++ const char *_end;
++ const char *_pos;
++
++ String _filename;
++ String _original_filename;
++ unsigned _lineno;
++ bool _ignore_line_directives;
++
++ bool get_data();
++ const char *skip_line(const char *);
++ const char *skip_slash_star(const char *);
++ const char *skip_backslash_angle(const char *);
++ const char *skip_quote(const char *, char);
++ const char *process_line_directive(const char *);
++ Lexeme next_lexeme();
++ static String lexeme_string(int);
++
++ // parser
++ enum { TCIRCLE_SIZE = 8 };
++ Lexeme _tcircle[TCIRCLE_SIZE];
++ int _tpos;
++ int _tfull;
++
++ // router
++ RouterT *_router;
++
++ int _anonymous_offset;
++
++ // what names represent types? (builds up linearly)
++ HashMap<String, ElementClassT *> _base_type_map;
++
++ // errors
++ LexerTInfo *_lexinfo;
++ ErrorHandler *_errh;
++
++ void vlerror(const char *, const char *, const String &, const char *, va_list);
++ int lerror(const char *, const char *, const char *, ...);
++ int lerror(const Lexeme &, const char *, ...);
++ String anon_element_name(const String &) const;
++
++ bool expect(int, bool report_error = true);
++ const char *next_pos() const;
++
++ ElementClassT *element_type(const Lexeme &) const;
++ ElementClassT *force_element_type(const Lexeme &);
++ void ydefine(RouterT *, const String &name, const String &value, bool isformal, const Lexeme &, bool &scope_order_error);
++
++ LexerT(const LexerT &);
++ LexerT &operator=(const LexerT &);
++ int make_element(String, const Lexeme &, const char *decl_pos2, ElementClassT *, const String &, const String &);
++ int make_anon_element(const Lexeme &, const char *decl_pos2, ElementClassT *, const String &, const String &);
++ void connect(int f1, int p1, int p2, int f2);
++
++};
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/lexertinfo.hh click-1.6.0-27/inst/include/clicktool/lexertinfo.hh
+--- click-1.6.0/inst/include/clicktool/lexertinfo.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/lexertinfo.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,29 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_LEXERTINFO_HH
++#define CLICK_LEXERTINFO_HH
++#include "lexert.hh"
++class ElementT;
++class ElementClassT;
++
++class LexerTInfo { public:
++
++ LexerTInfo() { }
++ virtual ~LexerTInfo() { }
++
++ virtual void notify_comment(const char *pos1, const char *pos2);
++ virtual void notify_error(const String &message, const char *pos1, const char *pos2);
++ virtual void notify_line_directive(const char *pos1, const char *pos2);
++ virtual void notify_keyword(const String &keyword, const char *pos1, const char *pos2);
++ virtual void notify_config_string(const char *pos1, const char *pos2);
++ virtual void notify_class_declaration(ElementClassT *, bool anonymous,
++ const char *pos1, const char *name_pos1, const char *pos2);
++ virtual void notify_class_extension(ElementClassT *, const char *pos1, const char *pos2);
++ virtual void notify_class_reference(ElementClassT *, const char *pos1, const char *pos2);
++ virtual void notify_element_declaration(
++ ElementT *e, const char *pos1, const char *name_pos2, const char *decl_pos2);
++ virtual void notify_element_reference(
++ ElementT *e, const char *pos1, const char *pos2);
++
++};
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/processingt.hh click-1.6.0-27/inst/include/clicktool/processingt.hh
+--- click-1.6.0/inst/include/clicktool/processingt.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/processingt.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,187 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_PROCESSINGT_HH
++#define CLICK_PROCESSINGT_HH
++#include "routert.hh"
++class ElementMap;
++class Bitvector;
++
++class ProcessingT { public:
++
++ enum ProcessingCode { VAGNOSTIC = 0, VPUSH = 1, VPULL = 2 };
++ static const char processing_letters[];
++
++ ProcessingT();
++ ProcessingT(const RouterT *, ErrorHandler *);
++ ProcessingT(const RouterT *, ElementMap *, ErrorHandler *);
++ ProcessingT(const RouterT *, ElementMap *, bool flatten, ErrorHandler *);
++ int reset(const RouterT *, ElementMap *, bool flatten, ErrorHandler *);
++ void resolve_agnostics(); // change remaining AGNOSTICs to PUSH
++
++ int nelements() const { return _input_pidx.size() - 1; }
++ int ninput_pidx() const { return _input_pidx.back(); }
++ int noutput_pidx() const { return _output_pidx.back(); }
++
++ int input_pidx(const ConnectionT &) const;
++ int output_pidx(const ConnectionT &) const;
++ int input_pidx(const PortT &) const;
++ int output_pidx(const PortT &) const;
++ int input_pidx(int ei, int p = 0) const { return _input_pidx[ei]+p; }
++ int output_pidx(int ei, int p = 0) const { return _output_pidx[ei]+p; }
++ PortT input_port(int pidx) const;
++ PortT output_port(int pidx) const;
++
++ int input_processing(const PortT &) const;
++ int output_processing(const PortT &) const;
++ int input_processing(int ei, int p) const;
++ int output_processing(int ei, int p) const;
++ bool input_is_pull(int ei, int p) const;
++ bool output_is_push(int ei, int p) const;
++ const PortT &input_connection(int ei, int p) const;
++ const PortT &output_connection(int ei, int p) const;
++
++ bool same_processing(int, int) const;
++
++ String processing_code(const ElementT *) const;
++
++ static int forward_flow(const String &code, int input_port, int noutputs, Bitvector *, ErrorHandler * = 0);
++ static int forward_flow(const PortT &, Bitvector *, ErrorHandler * = 0);
++ static int backward_flow(const String &code, int output_port, int ninputs, Bitvector *, ErrorHandler * = 0);
++ static int backward_flow(const PortT &, Bitvector *, ErrorHandler * = 0);
++
++ void set_connected_inputs(const Bitvector &, Bitvector &) const;
++ void set_connected_outputs(const Bitvector &, Bitvector &) const;
++ void set_connected_inputs(const PortT &, Bitvector &) const;
++ void set_connected_outputs(const PortT &, Bitvector &) const;
++ void set_flowed_inputs(const Bitvector &, Bitvector &, ErrorHandler* = 0) const;
++ void set_flowed_outputs(const Bitvector &, Bitvector &, ErrorHandler* = 0) const;
++
++ void forward_reachable_inputs(Bitvector &, ErrorHandler * = 0) const;
++
++ String compound_processing_code() const;
++ String compound_flow_code(ErrorHandler * = 0) const;
++
++ private:
++
++ const RouterT *_router;
++
++ Vector<int> _input_pidx;
++ Vector<int> _output_pidx;
++ Vector<const ElementT *> _input_elt;
++ Vector<const ElementT *> _output_elt;
++ Vector<int> _input_processing;
++ Vector<int> _output_processing;
++ Vector<PortT> _connected_input;
++ Vector<PortT> _connected_output;
++
++ void create_pidx(ErrorHandler *);
++
++ void initial_processing_for(int, ErrorHandler *);
++ void initial_processing(ErrorHandler *);
++ void processing_error(const ConnectionT &, int, ErrorHandler *);
++ void check_processing(ErrorHandler *);
++ void check_connections(ErrorHandler *);
++
++};
++
++
++inline int
++ProcessingT::input_pidx(const PortT &h) const
++{
++ assert(h.router() == _router);
++ return input_pidx(h.eindex(), h.port);
++}
++
++inline int
++ProcessingT::output_pidx(const PortT &h) const
++{
++ assert(h.router() == _router);
++ return output_pidx(h.eindex(), h.port);
++}
++
++inline int
++ProcessingT::input_pidx(const ConnectionT &c) const
++{
++ return input_pidx(c.to());
++}
++
++inline int
++ProcessingT::output_pidx(const ConnectionT &c) const
++{
++ return output_pidx(c.from());
++}
++
++inline PortT
++ProcessingT::input_port(int pidx) const
++{
++ const ElementT *e = _input_elt[pidx];
++ return PortT(const_cast<ElementT *>(e), pidx - _input_pidx[e->eindex()]);
++}
++
++inline PortT
++ProcessingT::output_port(int pidx) const
++{
++ const ElementT *e = _output_elt[pidx];
++ return PortT(const_cast<ElementT *>(e), pidx - _output_pidx[e->eindex()]);
++}
++
++inline int
++ProcessingT::input_processing(const PortT &h) const
++{
++ return _input_processing[input_pidx(h)];
++}
++
++inline int
++ProcessingT::output_processing(const PortT &h) const
++{
++ return _output_processing[output_pidx(h)];
++}
++
++inline int
++ProcessingT::input_processing(int i, int p) const
++{
++ return _input_processing[input_pidx(i, p)];
++}
++
++inline int
++ProcessingT::output_processing(int i, int p) const
++{
++ return _output_processing[output_pidx(i, p)];
++}
++
++inline bool
++ProcessingT::input_is_pull(int i, int p) const
++{
++ return input_processing(i, p) == VPULL;
++}
++
++inline bool
++ProcessingT::output_is_push(int i, int p) const
++{
++ return output_processing(i, p) == VPUSH;
++}
++
++inline const PortT &
++ProcessingT::input_connection(int i, int p) const
++{
++ return _connected_input[input_pidx(i, p)];
++}
++
++inline const PortT &
++ProcessingT::output_connection(int i, int p) const
++{
++ return _connected_output[output_pidx(i, p)];
++}
++
++inline int
++ProcessingT::forward_flow(const PortT &p, Bitvector *bv, ErrorHandler *errh)
++{
++ return forward_flow(p.element->type()->flow_code(), p.port, p.element->noutputs(), bv, errh);
++}
++
++inline int
++ProcessingT::backward_flow(const PortT &p, Bitvector *bv, ErrorHandler *errh)
++{
++ return backward_flow(p.element->type()->flow_code(), p.port, p.element->ninputs(), bv, errh);
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/routert.hh click-1.6.0-27/inst/include/clicktool/routert.hh
+--- click-1.6.0/inst/include/clicktool/routert.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/routert.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,462 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_ROUTERT_HH
++#define CLICK_ROUTERT_HH
++#include "elementt.hh"
++#include "eclasst.hh"
++#include <click/error.hh>
++#include <click/hashmap.hh>
++#include <click/archive.hh>
++#include <click/variableenv.hh>
++typedef HashMap<String, int> StringMap;
++
++class RouterT : public ElementClassT { public:
++
++ RouterT();
++ RouterT(const String &name, const String &landmark, RouterT *declaration_scope = 0);
++ virtual ~RouterT();
++
++ // ELEMENTS
++ int nelements() const { return _elements.size(); }
++ int n_live_elements() const { return _n_live_elements; }
++
++ inline const ElementT *element(const String &) const;
++ inline ElementT *element(const String &);
++ int eindex(const String &s) const { return _element_name_map[s]; }
++
++ const ElementT *element(int i) const{ return _elements[i]; }
++ ElementT *element(int i) { return _elements[i]; }
++
++ class iterator;
++ class const_iterator;
++ class type_iterator;
++ class const_type_iterator;
++ inline iterator begin_elements();
++ inline const_iterator begin_elements() const;
++ inline type_iterator begin_elements(ElementClassT *);
++ inline const_type_iterator begin_elements(ElementClassT *) const;
++ inline iterator end_elements();
++ inline const_iterator end_elements() const;
++
++ bool elive(int i) const { return _elements[i]->live(); }
++ bool edead(int i) const { return _elements[i]->dead(); }
++ inline String ename(int) const;
++ inline ElementClassT *etype(int) const;
++ inline String etype_name(int) const;
++
++ ElementT *get_element(const String &name, ElementClassT *, const String &configuration, const String &landmark);
++ ElementT *add_anon_element(ElementClassT *, const String &configuration = String(), const String &landmark = String());
++ void change_ename(int, const String &);
++ void deanonymize_elements();
++ void free_element(ElementT *);
++ void free_dead_elements();
++
++ void set_new_eindex_collector(Vector<int> *v) { _new_eindex_collector=v; }
++
++ // TYPES
++ ElementClassT *locally_declared_type(const String &) const;
++ inline ElementClassT *declared_type(const String &) const;
++ void add_declared_type(ElementClassT *, bool anonymous);
++
++ void collect_types(HashMap<ElementClassT *, int> &) const;
++ void collect_locally_declared_types(Vector<ElementClassT *> &) const;
++ void collect_overloads(Vector<ElementClassT *> &) const;
++
++ // CONNECTIONS
++ int nconnections() const { return _conn.size(); }
++ const Vector<ConnectionT> &connections() const { return _conn; }
++ const ConnectionT &connection(int c) const { return _conn[c]; }
++ bool connection_live(int c) const { return _conn[c].live(); }
++
++ void add_tunnel(const String &, const String &, const String &, ErrorHandler *);
++
++ bool add_connection(const PortT &, const PortT &, const String &landmark = String());
++ inline bool add_connection(ElementT *, int, ElementT *, int, const String &landmark = String());
++ void kill_connection(int);
++ void kill_bad_connections();
++ void compact_connections();
++
++ inline bool has_connection(const PortT &, const PortT &) const;
++ int find_connection(const PortT &, const PortT &) const;
++ void change_connection_to(int, PortT);
++ void change_connection_from(int, PortT);
++ bool find_connection_from(const PortT &, PortT &) const;
++ void find_connections_from(const PortT &, Vector<PortT> &) const;
++ void find_connections_from(const PortT &, Vector<int> &) const;
++ void find_connections_to(const PortT &, Vector<PortT> &) const;
++ void find_connections_to(const PortT &, Vector<int> &) const;
++ void find_connection_vector_from(ElementT *, Vector<int> &) const;
++ void find_connection_vector_to(ElementT *, Vector<int> &) const;
++
++ bool insert_before(const PortT &, const PortT &);
++ bool insert_after(const PortT &, const PortT &);
++ inline bool insert_before(ElementT *, const PortT &);
++ inline bool insert_after(ElementT *, const PortT &);
++
++ // REQUIREMENTS
++ void add_requirement(const String &);
++ void remove_requirement(const String &);
++ const Vector<String> &requirements() const { return _requirements; }
++
++ // ARCHIVE
++ void add_archive(const ArchiveElement &);
++ int narchive() const { return _archive.size(); }
++ int archive_index(const String &s) const { return _archive_map[s]; }
++ const Vector<ArchiveElement> &archive() const{ return _archive; }
++ ArchiveElement &archive(int i) { return _archive[i]; }
++ const ArchiveElement &archive(int i) const { return _archive[i]; }
++ inline ArchiveElement &archive(const String &s);
++ inline const ArchiveElement &archive(const String &s) const;
++
++ void add_components_to(RouterT *, const String &prefix = String()) const;
++
++ // CHECKING, FLATTENING AND EXPANDING
++ void check() const;
++
++ void remove_duplicate_connections();
++ void remove_dead_elements(ErrorHandler * = 0);
++
++ void remove_compound_elements(ErrorHandler *, bool expand_vars);
++ void remove_tunnels(ErrorHandler * = 0);
++
++ void expand_into(RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++ void flatten(ErrorHandler *, bool expand_vars = false);
++
++ // UNPARSING
++ void unparse(StringAccum &, const String & = String()) const;
++ void unparse_requirements(StringAccum &, const String & = String()) const;
++ void unparse_defines(StringAccum &, const String & = String()) const;
++ void unparse_declarations(StringAccum &, const String & = String()) const;
++ void unparse_connections(StringAccum &, const String & = String()) const;
++ String configuration_string() const;
++
++ // COMPOUND ELEMENTS
++ String landmark() const { return _type_landmark; }
++ const ElementTraits *find_traits() const;
++
++ bool primitive() const { return false; }
++
++ int nformals() const { return _nformals; }
++ const VariableEnvironment &scope() const { return _scope; }
++ inline bool define(const String &name, const String &value, bool isformal);
++ inline void redefine(const VariableEnvironment &);
++ int ninputs() const { return _ninputs; }
++ int noutputs() const { return _noutputs; }
++
++ RouterT *declaration_scope() const { return _declaration_scope; }
++ ElementClassT *overload_type() const { return _overload_type; }
++ void set_overload_type(ElementClassT *);
++
++ int finish_type(ErrorHandler *);
++
++ ElementClassT *resolve(int, int, Vector<String> &, ErrorHandler *, const String &landmark);
++ ElementT *complex_expand_element(ElementT *, const String &, Vector<String> &, RouterT *, const String &prefix, VariableEnvironment &, ErrorHandler *);
++
++ String unparse_signature() const;
++ void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *);
++
++ RouterT *cast_router() { return this; }
++
++ private:
++
++ struct Pair {
++ int from;
++ int to;
++ Pair() : from(-1), to(-1) { }
++ Pair(int f, int t) : from(f), to(t) { }
++ };
++
++ struct ElementType {
++ ElementClassT * const type;
++ int scope_cookie;
++ int prev_name;
++ ElementType(ElementClassT *c, int sc, int pn) : type(c), scope_cookie(sc), prev_name(pn) { assert(type); type->use(); }
++ ElementType(const ElementType &o) : type(o.type), scope_cookie(o.scope_cookie), prev_name(o.prev_name) { type->use(); }
++ ~ElementType() { type->unuse(); }
++ const String &name() const { return type->name(); }
++ private:
++ ElementType &operator=(const ElementType &);
++ };
++
++ StringMap _element_name_map;
++ Vector<ElementT *> _elements;
++ ElementT *_free_element;
++ int _n_live_elements;
++ Vector<int> *_new_eindex_collector;
++
++ Vector<ConnectionT> _conn;
++ Vector<Pair> _first_conn;
++ int _free_conn;
++
++ StringMap _declared_type_map;
++ Vector<ElementType> _declared_types;
++
++ Vector<String> _requirements;
++
++ StringMap _archive_map;
++ Vector<ArchiveElement> _archive;
++
++ RouterT *_declaration_scope;
++ int _declaration_scope_cookie;
++ int _scope_cookie;
++
++ VariableEnvironment _scope;
++ int _nformals;
++ int _ninputs;
++ int _noutputs;
++ bool _scope_order_error : 1;
++ ElementClassT *_overload_type;
++ String _type_landmark;
++ mutable ElementTraits _traits;
++ bool _circularity_flag;
++
++ RouterT(const RouterT &);
++ RouterT &operator=(const RouterT &);
++
++ ElementClassT *declared_type(const String &, int scope_cookie) const;
++ void update_noutputs(int);
++ void update_ninputs(int);
++ ElementT *add_element(const ElementT &);
++ void assign_element_name(int);
++ void free_connection(int ci);
++ void unlink_connection_from(int ci);
++ void unlink_connection_to(int ci);
++ void expand_tunnel(Vector<PortT> *port_expansions, const Vector<PortT> &ports, bool is_output, int which, ErrorHandler *) const;
++ int assign_arguments(const Vector<String> &, Vector<String> *) const;
++
++ friend class RouterUnparserT;
++
++};
++
++class RouterT::const_iterator { public:
++ operator bool() const { return _e; }
++ int eindex() const { return _e->eindex(); }
++ void operator++(int) { if (_e) step(_e->router(), eindex()+1);}
++ void operator++() { (*this)++; }
++ operator const ElementT *() const { return _e; }
++ const ElementT *operator->() const { return _e; }
++ const ElementT &operator*() const { return *_e; }
++ private:
++ const ElementT *_e;
++ const_iterator() : _e(0) { }
++ const_iterator(const RouterT *r, int ei) { step(r, ei); }
++ void step(const RouterT *, int);
++ friend class RouterT;
++ friend class RouterT::iterator;
++};
++
++class RouterT::iterator : public RouterT::const_iterator { public:
++ operator ElementT *() const { return const_cast<ElementT *>(_e); }
++ ElementT *operator->() const { return const_cast<ElementT *>(_e); }
++ ElementT &operator*() const { return const_cast<ElementT &>(*_e); }
++ private:
++ iterator() : const_iterator() { }
++ iterator(RouterT *r, int ei) : const_iterator(r, ei) { }
++ friend class RouterT;
++};
++
++class RouterT::const_type_iterator { public:
++ operator bool() const { return _e; }
++ int eindex() const { return _e->eindex(); }
++ inline void operator++(int);
++ inline void operator++();
++ operator const ElementT *() const { return _e; }
++ const ElementT *operator->() const { return _e; }
++ const ElementT &operator*() const { return *_e; }
++ private:
++ const ElementT *_e;
++ const_type_iterator() : _e(0) { }
++ const_type_iterator(const RouterT *r, ElementClassT *t, int i) { step(r, t, i); }
++ void step(const RouterT *, ElementClassT *, int);
++ friend class RouterT;
++ friend class RouterT::type_iterator;
++};
++
++class RouterT::type_iterator : public RouterT::const_type_iterator { public:
++ operator ElementT *() const { return const_cast<ElementT *>(_e); }
++ ElementT *operator->() const { return const_cast<ElementT *>(_e); }
++ ElementT &operator*() const { return const_cast<ElementT &>(*_e); }
++ private:
++ type_iterator() : const_type_iterator() { }
++ type_iterator(RouterT *r, ElementClassT *t, int ei) : const_type_iterator(r, t, ei) { }
++ friend class RouterT;
++};
++
++
++inline RouterT::iterator
++RouterT::begin_elements()
++{
++ return iterator(this, 0);
++}
++
++inline RouterT::const_iterator
++RouterT::begin_elements() const
++{
++ return const_iterator(this, 0);
++}
++
++inline RouterT::type_iterator
++RouterT::begin_elements(ElementClassT *t)
++{
++ return type_iterator(this, t, 0);
++}
++
++inline RouterT::const_type_iterator
++RouterT::begin_elements(ElementClassT *t) const
++{
++ return const_type_iterator(this, t, 0);
++}
++
++inline RouterT::const_iterator
++RouterT::end_elements() const
++{
++ return const_iterator();
++}
++
++inline RouterT::iterator
++RouterT::end_elements()
++{
++ return iterator();
++}
++
++inline void
++RouterT::const_type_iterator::operator++(int)
++{
++ if (_e)
++ step(_e->router(), _e->type(), _e->eindex() + 1);
++}
++
++inline void
++RouterT::const_type_iterator::operator++()
++{
++ (*this)++;
++}
++
++inline const ElementT *
++RouterT::element(const String &s) const
++{
++ int i = _element_name_map[s];
++ return (i >= 0 ? _elements[i] : 0);
++}
++
++inline ElementT *
++RouterT::element(const String &s)
++{
++ int i = _element_name_map[s];
++ return (i >= 0 ? _elements[i] : 0);
++}
++
++inline String
++RouterT::ename(int e) const
++{
++ return _elements[e]->name();
++}
++
++inline ElementClassT *
++RouterT::etype(int e) const
++{
++ return _elements[e]->type();
++}
++
++inline String
++RouterT::etype_name(int e) const
++{
++ return _elements[e]->type()->name();
++}
++
++inline ElementClassT *
++RouterT::declared_type(const String &name) const
++{
++ return declared_type(name, 0x7FFFFFFF);
++}
++
++inline bool
++RouterT::add_connection(ElementT *from_elt, int from_port, ElementT *to_elt,
++ int to_port, const String &landmark)
++{
++ return add_connection(PortT(from_elt, from_port), PortT(to_elt, to_port), landmark);
++}
++
++inline bool
++RouterT::has_connection(const PortT &hfrom, const PortT &hto) const
++{
++ return find_connection(hfrom, hto) >= 0;
++}
++
++inline bool
++RouterT::insert_before(ElementT *e, const PortT &h)
++{
++ return insert_before(PortT(e, 0), h);
++}
++
++inline bool
++RouterT::insert_after(ElementT *e, const PortT &h)
++{
++ return insert_after(PortT(e, 0), h);
++}
++
++inline bool
++RouterT::define(const String &name, const String &value, bool isformal)
++{
++ assert(!isformal || _nformals == _scope.size());
++ bool retval = _scope.define(name, value, false);
++ if (isformal)
++ _nformals = _scope.size();
++ return retval;
++}
++
++inline void
++RouterT::redefine(const VariableEnvironment &ve)
++{
++ for (int i = 0; i < ve.size(); i++)
++ _scope.define(ve.name(i), ve.value(i), true);
++}
++
++inline ArchiveElement &
++RouterT::archive(const String &name)
++{
++ return _archive[_archive_map[name]];
++}
++
++inline const ArchiveElement &
++RouterT::archive(const String &name) const
++{
++ return _archive[_archive_map[name]];
++}
++
++inline bool
++operator==(const RouterT::const_iterator &i, const RouterT::const_iterator &j)
++{
++ return i.operator->() == j.operator->();
++}
++
++inline bool
++operator!=(const RouterT::const_iterator &i, const RouterT::const_iterator &j)
++{
++ return i.operator->() != j.operator->();
++}
++
++inline bool
++operator==(const RouterT::const_type_iterator &i, const RouterT::const_type_iterator &j)
++{
++ return i.operator->() == j.operator->();
++}
++
++inline bool
++operator!=(const RouterT::const_type_iterator &i, const RouterT::const_type_iterator &j)
++{
++ return i.operator->() != j.operator->();
++}
++
++inline bool
++operator==(const RouterT::const_type_iterator &i, const RouterT::const_iterator &j)
++{
++ return i.operator->() == j.operator->();
++}
++
++inline bool
++operator!=(const RouterT::const_type_iterator &i, const RouterT::const_iterator &j)
++{
++ return i.operator->() != j.operator->();
++}
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/runparse.hh click-1.6.0-27/inst/include/clicktool/runparse.hh
+--- click-1.6.0/inst/include/clicktool/runparse.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/runparse.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,31 @@
++// -*- c-basic-offset: 4 -*-
++#ifndef CLICK_RUNPARSE_HH
++#define CLICK_RUNPARSE_HH
++#include "routert.hh"
++#include <click/pair.hh>
++
++class RouterUnparserT { public:
++
++ RouterUnparserT(ErrorHandler *);
++
++ struct Pair {
++ ElementClassT *first;
++ ElementClassT *second;
++ Pair(ElementClassT *a, ElementClassT *b) : first(a), second(b) { }
++ };
++
++ private:
++
++ HashMap<int, int> _tuid_map;
++ Vector<ElementClassT *> _types;
++
++ enum { X_BAD = 0, X_UNK = 1, X_LT = 2, X_LEQ = 3, X_EQ = 4, X_GEQ = 5, X_GT = 6, X_NUM = 7 };
++ static int relation_negater[X_NUM];
++ static uint8_t relation_combiner[X_NUM][X_NUM];
++ HashMap<Pair<ElementClassT *, ElementClassT *>, int> _relation;
++
++ ErrorHandler *_errh;
++
++};
++
++#endif
+diff -Nurb click-1.6.0/inst/include/clicktool/toolutils.hh click-1.6.0-27/inst/include/clicktool/toolutils.hh
+--- click-1.6.0/inst/include/clicktool/toolutils.hh 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/include/clicktool/toolutils.hh 2009-02-05 10:20:38.000000000 -0500
+@@ -0,0 +1,18 @@
++#ifndef CLICK_TOOLUTILS_HH
++#define CLICK_TOOLUTILS_HH
++#include <click/userutils.hh>
++class RouterT;
++
++extern bool ignore_line_directives;
++int click_maybe_define(const char *arg, ErrorHandler *errh);
++RouterT *read_router_string(const String &text, const String &landmark, ErrorHandler *);
++RouterT *read_router_string(String text, const String &landmark, bool, RouterT *, ErrorHandler *);
++RouterT *read_router_file(const char *filename, ErrorHandler *);
++RouterT *read_router_file(const char *filename, bool empty_ok, ErrorHandler *);
++RouterT *read_router(const String &, bool is_expr, ErrorHandler *);
++void write_router_file(RouterT *, FILE *, ErrorHandler * = 0);
++int write_router_file(RouterT *, const char *, ErrorHandler * = 0);
++
++String xml_quote(const String &);
++
++#endif
+Files click-1.6.0/inst/lib/click.ko and click-1.6.0-27/inst/lib/click.ko differ
+Files click-1.6.0/inst/lib/libclick.a and click-1.6.0-27/inst/lib/libclick.a differ
+Files click-1.6.0/inst/lib/libclicktool.a and click-1.6.0-27/inst/lib/libclicktool.a differ
+Files click-1.6.0/inst/lib/proclikefs.ko and click-1.6.0-27/inst/lib/proclikefs.ko differ
+Files click-1.6.0/inst/sbin/click-install and click-1.6.0-27/inst/sbin/click-install differ
+Files click-1.6.0/inst/sbin/click-uninstall and click-1.6.0-27/inst/sbin/click-uninstall differ
+diff -Nurb click-1.6.0/inst/share/click/config.mk click-1.6.0-27/inst/share/click/config.mk
+--- click-1.6.0/inst/share/click/config.mk 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/config.mk 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,13 @@
++clickprefix=/d/click/click-1.6.0-27/inst
++clickbindir=/d/click/click-1.6.0-27/inst/bin
++clicksbindir=/d/click/click-1.6.0-27/inst/sbin
++clicklibdir=/d/click/click-1.6.0-27/inst/lib
++clickincludedir=/d/click/click-1.6.0-27/inst/include
++clickdatadir=/d/click/click-1.6.0-27/inst/share/click
++clicklinuxdir=/d/kernels/linux-2.6.27.10-clickport
++clicksrcdir=/d/click/click-1.6.0-27/inst/share/click/src
++CLICK_HAVE_USERLEVEL_DRIVER=1
++CLICK_HAVE_LINUXMODULE_DRIVER=1
++CLICK_HAVE_BSDMODULE_DRIVER=0
++CLICK_LINUXMODULE_2_6=1
++CLICK_GMAKE=make
+diff -Nurb click-1.6.0/inst/share/click/elementmap.xml click-1.6.0-27/inst/share/click/elementmap.xml
+--- click-1.6.0/inst/share/click/elementmap.xml 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/elementmap.xml 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,219 @@
++<?xml version="1.0" standalone="yes"?>
++<?xml-stylesheet type="application/xml" href="http://www.lcdf.org/click/xml/elementmap.xsl"?>
++<?xml-stylesheet type="application/xml" href="file:///d/click/click-1.6.0-27/etc/elementmap.xsl"?>
++<elementmap xmlns="http://www.lcdf.org/click/xml/" sourcedir="/d/click/click-1.6.0-27" src="file:///d/click/click-1.6.0-27" provides="i686 i386 i586 int64 linux linux_2_6 pcap" drivers="userlevel linuxmodule">
++<entry name="ARPFaker" cxxclass="ARPFaker" docname="ARPFaker" headerfile="elements/ethernet/arpfaker.hh" sourcefile="elements/ethernet/arpfaker.cc" portcount="0/1" processing="h/h" flowcode="x/x" />
++<entry name="ARPPrint" cxxclass="ARPPrint" docname="ARPPrint" headerfile="elements/ethernet/arpprint.hh" sourcefile="elements/ethernet/arpprint.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="ARPQuerier" cxxclass="ARPQuerier" docname="ARPQuerier" headerfile="elements/ethernet/arpquerier.hh" sourcefile="elements/ethernet/arpquerier.cc" portcount="2/1-2" processing="h/h" flowcode="xy/x" />
++<entry name="ARPResponder" cxxclass="ARPResponder" docname="ARPResponder" headerfile="elements/ethernet/arpresponder.hh" sourcefile="elements/ethernet/arpresponder.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="AdaptiveRED" cxxclass="AdaptiveRED" docname="AdaptiveRED" headerfile="elements/aqm/adaptivered.hh" sourcefile="elements/aqm/adaptivered.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" requires="RED" />
++<entry name="AddressInfo" cxxclass="AddressInfo" docname="AddressInfo" headerfile="<click/standard/addressinfo.hh>" sourcefile="elements/standard/addressinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="Align" cxxclass="Align" docname="Align" headerfile="elements/standard/align.hh" sourcefile="elements/standard/align.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="AlignmentInfo" cxxclass="AlignmentInfo" docname="AlignmentInfo" headerfile="<click/standard/alignmentinfo.hh>" sourcefile="elements/standard/alignmentinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="AverageCounter" cxxclass="AverageCounter" docname="AverageCounter" headerfile="elements/standard/averagecounter.hh" sourcefile="elements/standard/averagecounter.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="BandwidthMeter" cxxclass="BandwidthMeter" docname="BandwidthMeter" headerfile="elements/standard/bandwidthmeter.hh" sourcefile="elements/standard/bandwidthmeter.cc" portcount="1/2-" processing="h/h" flowcode="x/x" />
++<entry name="BandwidthRatedSplitter" cxxclass="BandwidthRatedSplitter" docname="BandwidthRatedSplitter" headerfile="elements/standard/bwratedsplitter.hh" sourcefile="elements/standard/bwratedsplitter.cc" portcount="1/2" processing="h/h" flowcode="x/x" requires="RatedSplitter" />
++<entry name="BandwidthRatedUnqueue" cxxclass="BandwidthRatedUnqueue" docname="BandwidthRatedUnqueue" headerfile="elements/standard/bwratedunqueue.hh" sourcefile="elements/standard/bwratedunqueue.cc" portcount="1/1" processing="l/h" flowcode="x/x" requires="RatedUnqueue" />
++<entry name="BandwidthShaper" cxxclass="BandwidthShaper" docname="BandwidthShaper" headerfile="elements/standard/bandwidthshaper.hh" sourcefile="elements/standard/bandwidthshaper.cc" portcount="1/1" processing="l/l" flowcode="x/x" requires="Shaper" />
++<entry name="BpfyFilter" cxxclass="BpfyFilter" headerfile="elements/ip/crapfilter3.hh" sourcefile="elements/ip/crapfilter3.cc" portcount="1/1-2" processing="h/h" flowcode="x/x" />
++<entry name="Burster" cxxclass="Burster" docname="Burster" headerfile="elements/standard/burster.hh" sourcefile="elements/standard/burster.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="CPUQueue" cxxclass="CPUQueue" docname="CPUQueue" headerfile="elements/linuxmodule/cpuqueue.hh" sourcefile="elements/linuxmodule/cpuqueue.cc" portcount="1/1-" processing="h/l" flowcode="x/x" requires="linuxmodule" />
++<entry name="CPUSwitch" cxxclass="CPUSwitch" docname="CPUSwitch" headerfile="elements/linuxmodule/cpuswitch.hh" sourcefile="elements/linuxmodule/cpuswitch.cc" portcount="1/1-" processing="h/h" flowcode="x/x" requires="linuxmodule" />
++<entry name="ChangeUID" cxxclass="ChangeUID" docname="ChangeUID" headerfile="elements/userlevel/changeuid.hh" sourcefile="elements/userlevel/changeuid.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="ChatterSocket" cxxclass="ChatterSocket" docname="ChatterSocket" headerfile="elements/userlevel/chattersocket.hh" sourcefile="elements/userlevel/chattersocket.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="CheckARPHeader" cxxclass="CheckARPHeader" docname="CheckARPHeader" headerfile="elements/ethernet/checkarpheader.hh" sourcefile="elements/ethernet/checkarpheader.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CheckCRC32" cxxclass="CheckCRC32" docname="CheckCRC32" headerfile="elements/standard/checkcrc32.hh" sourcefile="elements/standard/checkcrc32.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="CheckICMPHeader" cxxclass="CheckICMPHeader" docname="CheckICMPHeader" headerfile="elements/icmp/checkicmpheader.hh" sourcefile="elements/icmp/checkicmpheader.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CheckIPHeader" cxxclass="CheckIPHeader" docname="CheckIPHeader" headerfile="elements/ip/checkipheader.hh" sourcefile="elements/ip/checkipheader.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" flags="A" methods="static_initialize static_cleanup" />
++<entry name="CheckIPHeader2" cxxclass="CheckIPHeader2" docname="CheckIPHeader2" headerfile="elements/ip/checkipheader2.hh" sourcefile="elements/ip/checkipheader2.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" flags="A" requires="CheckIPHeader" />
++<entry name="CheckLength" cxxclass="CheckLength" docname="CheckLength" headerfile="elements/standard/checklength.hh" sourcefile="elements/standard/checklength.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CheckPaint" cxxclass="CheckPaint" docname="CheckPaint" headerfile="elements/standard/checkpaint.hh" sourcefile="elements/standard/checkpaint.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CheckTCPHeader" cxxclass="CheckTCPHeader" docname="CheckTCPHeader" headerfile="elements/tcpudp/checktcpheader.hh" sourcefile="elements/tcpudp/checktcpheader.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CheckUDPHeader" cxxclass="CheckUDPHeader" docname="CheckUDPHeader" headerfile="elements/tcpudp/checkudpheader.hh" sourcefile="elements/tcpudp/checkudpheader.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="CiscyFilter" cxxclass="CiscyFilter" headerfile="elements/ip/crapfilter2.hh" sourcefile="elements/ip/crapfilter2.cc" portcount="1/1-2" processing="h/h" flowcode="x/x" />
++<entry name="Classifier" cxxclass="Classifier" docname="Classifier" headerfile="elements/standard/classifier.hh" sourcefile="elements/standard/classifier.cc" portcount="1/-" processing="h/h" flowcode="x/x" flags="A" requires="AlignmentInfo" />
++<entry name="CompareBlock" cxxclass="CompareBlock" docname="CompareBlock" headerfile="elements/standard/compblock.hh" sourcefile="elements/standard/compblock.cc" portcount="1/2" processing="a/a" flowcode="x/x" />
++<entry name="ControlSocket" cxxclass="ControlSocket" docname="ControlSocket" headerfile="elements/userlevel/controlsocket.hh" sourcefile="elements/userlevel/controlsocket.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="Counter" cxxclass="Counter" docname="Counter" headerfile="elements/standard/counter.hh" sourcefile="elements/standard/counter.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="CrapFilter" cxxclass="CrapFilter" headerfile="elements/ip/crapfilter.hh" sourcefile="elements/ip/crapfilter.cc" portcount="1/1-2" processing="h/h" flowcode="x/x" />
++<entry name="CycleCountAccum" cxxclass="CycleCountAccum" docname="CycleCountAccum" headerfile="elements/linuxmodule/cyclecountaccum.hh" sourcefile="elements/linuxmodule/cyclecountaccum.cc" portcount="1/1" processing="a/a" flowcode="x/x" requires="linuxmodule int64" />
++<entry name="DRRSched" cxxclass="DRRSched" docname="DRRSched" headerfile="elements/standard/drr.hh" sourcefile="elements/standard/drr.cc" portcount="-/1" processing="l/l" flowcode="x/x" />
++<entry name="DecIPTTL" cxxclass="DecIPTTL" docname="DecIPTTL" headerfile="elements/ip/decipttl.hh" sourcefile="elements/ip/decipttl.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="DelayShaper" cxxclass="DelayShaper" docname="DelayShaper" headerfile="elements/standard/delayshaper.hh" sourcefile="elements/standard/delayshaper.cc" portcount="1/1" processing="l/l" flowcode="x/x" />
++<entry name="DelayUnqueue" cxxclass="DelayUnqueue" docname="DelayUnqueue" headerfile="elements/standard/delayunqueue.hh" sourcefile="elements/standard/delayunqueue.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="DevirtualizeInfo" cxxclass="DevirtualizeInfo" headerfile="elements/standard/devirtualizeinfo.hh" sourcefile="elements/standard/devirtualizeinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="DirectIPLookup" cxxclass="DirectIPLookup" docname="DirectIPLookup" headerfile="elements/ip/directiplookup.hh" sourcefile="elements/ip/directiplookup.cc" portcount="1/-" processing="h/h" requires="IPRouteTable userlevel|bsdmodule" />
++<entry name="Discard" cxxclass="Discard" docname="Discard" headerfile="elements/standard/discard.hh" sourcefile="elements/standard/discard.cc" portcount="1/0" processing="a/a" flowcode="x/x" />
++<entry name="DiscardNoFree" cxxclass="DiscardNoFree" docname="DiscardNoFree" headerfile="elements/standard/discardnofree.hh" sourcefile="elements/standard/discardnofree.cc" portcount="1/0" processing="a/a" flowcode="x/x" />
++<entry name="DriverManager" cxxclass="DriverManager" docname="DriverManager" headerfile="elements/standard/drivermanager.hh" sourcefile="elements/standard/drivermanager.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="Script" />
++<entry name="DropBroadcasts" cxxclass="DropBroadcasts" docname="DropBroadcasts" headerfile="elements/standard/dropbroadcasts.hh" sourcefile="elements/standard/dropbroadcasts.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="DynamicUDPIPEncap" cxxclass="DynamicUDPIPEncap" docname="DynamicUDPIPEncap" headerfile="elements/tcpudp/dynudpipencap.hh" sourcefile="elements/tcpudp/dynudpipencap.cc" portcount="1/1" processing="a/a" flowcode="x/x" flags="A" />
++<entry name="EnsureEther" cxxclass="EnsureEther" docname="EnsureEther" headerfile="elements/ethernet/ensureether.hh" sourcefile="elements/ethernet/ensureether.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Error" cxxclass="ErrorElement" docname="Error" headerfile="<click/standard/errorelement.hh>" sourcefile="elements/standard/errorelement.cc" portcount="-/-" processing="a/a" flowcode="x/y" />
++<entry name="EtherEncap" cxxclass="EtherEncap" docname="EtherEncap" headerfile="elements/ethernet/etherencap.hh" sourcefile="elements/ethernet/etherencap.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="EtherMirror" cxxclass="EtherMirror" docname="EtherMirror" headerfile="elements/ethernet/ethermirror.hh" sourcefile="elements/ethernet/ethermirror.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="FTPPortMapper" cxxclass="FTPPortMapper" docname="FTPPortMapper" headerfile="elements/app/ftpportmapper.hh" sourcefile="elements/app/ftpportmapper.cc" portcount="1/1" processing="a/a" flowcode="x/x" requires="TCPRewriter" />
++<entry name="FastTCPFlows" cxxclass="FastTCPFlows" docname="FastTCPFlows" headerfile="elements/linuxmodule/fasttcpflows.hh" sourcefile="elements/linuxmodule/fasttcpflows.cc" portcount="0/1" processing="l/l" flowcode="x/x" requires="linuxmodule" />
++<entry name="FastUDPFlows" cxxclass="FastUDPFlows" docname="FastUDPFlows" headerfile="elements/linuxmodule/fastudpflows.hh" sourcefile="elements/linuxmodule/fastudpflows.cc" portcount="0/1" processing="l/l" flowcode="x/x" requires="linuxmodule" />
++<entry name="FastUDPSource" cxxclass="FastUDPSource" docname="FastUDPSource" headerfile="elements/linuxmodule/fastudpsrc.hh" sourcefile="elements/linuxmodule/fastudpsrc.cc" portcount="0/1" processing="l/l" flowcode="x/x" requires="linuxmodule" />
++<entry name="FixIPSrc" cxxclass="FixIPSrc" docname="FixIPSrc" headerfile="elements/ip/fixipsrc.hh" sourcefile="elements/ip/fixipsrc.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="FromDevice" cxxclass="FromDevice" docname="FromDevice" headerfile="elements/linuxmodule/fromdevice.hh" sourcefile="elements/linuxmodule/fromdevice.cc" portcount="0/1" processing="h/h" methods="static_initialize static_cleanup" requires="AnyDevice linuxmodule" />
++<entry name="FromDevice" cxxclass="FromDevice" docname="FromDevice.u" headerfile="elements/userlevel/fromdevice.hh" sourcefile="elements/userlevel/fromdevice.cc" portcount="0/1" processing="h/h" flowcode="x/x" requires="userlevel FakePcap" />
++<entry name="FromDump" cxxclass="FromDump" docname="FromDump" headerfile="elements/userlevel/fromdump.hh" sourcefile="elements/userlevel/fromdump.cc" portcount="0/1-2" processing="a/ah" flowcode="x/x" requires="userlevel|ns FakePcap FromFile" />
++<entry name="FromHost" cxxclass="FromHost" docname="FromHost" headerfile="elements/linuxmodule/fromhost.hh" sourcefile="elements/linuxmodule/fromhost.cc" portcount="0/1" processing="h/h" methods="static_initialize" requires="AnyDevice linuxmodule" />
++<entry name="FromHost" cxxclass="FromHost" docname="FromHost.u" headerfile="elements/userlevel/fromhost.hh" sourcefile="elements/userlevel/fromhost.cc" portcount="0/1" processing="h/h" flowcode="x/x" requires="userlevel linux" />
++<entry name="FromRawSocket" cxxclass="FromRawSocket" docname="FromRawSocket" headerfile="elements/userlevel/fromrawsocket.hh" sourcefile="elements/userlevel/fromrawsocket.cc" portcount="0-1/0-1" processing="h/h" flowcode="x/y" requires="RawSocket" />
++<entry name="FromSocket" cxxclass="FromSocket" docname="FromSocket" headerfile="elements/userlevel/fromsocket.hh" sourcefile="elements/userlevel/fromsocket.cc" portcount="0-1/0-1" processing="h/h" flowcode="x/y" requires="Socket" />
++<entry name="FrontDropQueue" cxxclass="FrontDropQueue" docname="FrontDropQueue" headerfile="elements/standard/frontdropqueue.hh" sourcefile="elements/standard/frontdropqueue.cc" portcount="1/1" processing="h/l" flowcode="x/x" requires="NotifierQueue" />
++<entry name="FullNoteQueue" cxxclass="FullNoteQueue" docname="Queue" headerfile="elements/standard/fullnotequeue.hh" sourcefile="elements/standard/fullnotequeue.cc" portcount="1/1" processing="h/l" flowcode="x/x" requires="NotifierQueue" />
++<entry name="GetIPAddress" cxxclass="GetIPAddress" docname="GetIPAddress" headerfile="elements/ip/getipaddress.hh" sourcefile="elements/ip/getipaddress.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="HashSwitch" cxxclass="HashSwitch" docname="HashSwitch" headerfile="elements/standard/hashswitch.hh" sourcefile="elements/standard/hashswitch.cc" portcount="1/1-" processing="h/h" flowcode="x/x" />
++<entry name="HostEtherFilter" cxxclass="HostEtherFilter" docname="HostEtherFilter" headerfile="elements/ethernet/hostetherfilter.hh" sourcefile="elements/ethernet/hostetherfilter.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="ICMPError" cxxclass="ICMPError" docname="ICMPError" headerfile="elements/icmp/icmperror.hh" sourcefile="elements/icmp/icmperror.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="ICMPPingEncap" cxxclass="ICMPPingEncap" docname="ICMPPingEncap" headerfile="elements/icmp/icmppingencap.hh" sourcefile="elements/icmp/icmppingencap.cc" portcount="1/1" processing="a/a" flowcode="x/x" flags="A" />
++<entry name="ICMPPingResponder" cxxclass="ICMPPingResponder" docname="ICMPPingResponder" headerfile="elements/icmp/icmppingresponder.hh" sourcefile="elements/icmp/icmppingresponder.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="ICMPPingRewriter" cxxclass="ICMPPingRewriter" docname="ICMPPingRewriter" headerfile="elements/icmp/icmppingrewriter.hh" sourcefile="elements/icmp/icmppingrewriter.cc" portcount="1-2/1-2" processing="h/h" flowcode="x/x" />
++<entry name="ICMPPingSource" cxxclass="ICMPPingSource" docname="ICMPPingSource" headerfile="elements/icmp/icmpsendpings.hh" sourcefile="elements/icmp/icmpsendpings.cc" portcount="0-1/1" processing="h/a" flowcode="x/x" />
++<entry name="ICMPRewriter" cxxclass="ICMPRewriter" docname="ICMPRewriter" headerfile="elements/icmp/icmprewriter.hh" sourcefile="elements/icmp/icmprewriter.cc" portcount="1/1-2" processing="a/a" flowcode="x/x" requires="IPRw ICMPPingRewriter" />
++<entry name="ICMPSendPings" cxxclass="ICMPPingSource" docname="ICMPPingSource" headerfile="elements/icmp/icmpsendpings.hh" sourcefile="elements/icmp/icmpsendpings.cc" portcount="0-1/1" processing="h/a" flowcode="x/x" />
++<entry name="IPAddrPairRewriter" cxxclass="IPAddrPairRewriter" docname="IPAddrPairRewriter" headerfile="elements/ip/ipaddrpairrewriter.hh" sourcefile="elements/ip/ipaddrpairrewriter.cc" portcount="1-/1-256" processing="h/h" requires="IPRw IPRewriterPatterns" />
++<entry name="IPAddrRewriter" cxxclass="IPAddrRewriter" docname="IPAddrRewriter" headerfile="elements/ip/ipaddrrewriter.hh" sourcefile="elements/ip/ipaddrrewriter.cc" portcount="1-/1-256" processing="h/h" requires="IPRw IPRewriterPatterns" />
++<entry name="IPClassifier" cxxclass="IPClassifier" docname="IPClassifier" headerfile="elements/ip/ipclassifier.hh" sourcefile="elements/ip/ipclassifier.cc" portcount="1/-" processing="h/h" flowcode="x/x" flags="" requires="IPFilter" />
++<entry name="IPEncap" cxxclass="IPEncap" docname="IPEncap" headerfile="elements/ip/ipencap.hh" sourcefile="elements/ip/ipencap.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="IPFieldInfo" cxxclass="IPFieldInfo" headerfile="elements/ip/ipfieldinfo.hh" sourcefile="elements/ip/ipfieldinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" methods="static_initialize static_cleanup" />
++<entry name="IPFilter" cxxclass="IPFilter" docname="IPFilter" headerfile="elements/ip/ipfilter.hh" sourcefile="elements/ip/ipfilter.cc" portcount="1/-" processing="h/h" flowcode="x/x" flags="" methods="static_initialize static_cleanup" requires="Classifier" />
++<entry name="IPFragmenter" cxxclass="IPFragmenter" docname="IPFragmenter" headerfile="elements/ip/ipfragmenter.hh" sourcefile="elements/ip/ipfragmenter.cc" portcount="1/1-2" processing="h/h" flowcode="x/x" />
++<entry name="IPGWOptions" cxxclass="IPGWOptions" docname="IPGWOptions" headerfile="elements/ip/ipgwoptions.hh" sourcefile="elements/ip/ipgwoptions.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="IPInputCombo" cxxclass="IPInputCombo" docname="IPInputCombo" headerfile="elements/ip/ipinputcombo.hh" sourcefile="elements/ip/ipinputcombo.cc" portcount="1/1" processing="a/a" flowcode="x/x" flags="A" requires="CheckIPHeader" />
++<entry name="IPMirror" cxxclass="IPMirror" docname="IPMirror" headerfile="elements/ip/ipmirror.hh" sourcefile="elements/ip/ipmirror.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="IPNameInfo" cxxclass="IPNameInfo" docname="IPNameInfo" headerfile="elements/ip/ipnameinfo.hh" sourcefile="elements/ip/ipnameinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" methods="static_initialize static_cleanup" />
++<entry name="IPOutputCombo" cxxclass="IPOutputCombo" docname="IPOutputCombo" headerfile="elements/ip/ipoutputcombo.hh" sourcefile="elements/ip/ipoutputcombo.cc" portcount="1/5" processing="h/h" flowcode="x/x" />
++<entry name="IPPrint" cxxclass="IPPrint" docname="IPPrint" headerfile="elements/ip/ipprint.hh" sourcefile="elements/ip/ipprint.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="IPRateMonitor" cxxclass="IPRateMonitor" docname="IPRateMonitor" headerfile="elements/ip/ipratemon.hh" sourcefile="elements/ip/ipratemon.cc" portcount="1-2/1-2" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="IPReassembler" cxxclass="IPReassembler" docname="IPReassembler" headerfile="elements/ip/ipreassembler.hh" sourcefile="elements/ip/ipreassembler.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="IPRewriter" cxxclass="IPRewriter" docname="IPRewriter" headerfile="elements/tcpudp/iprewriter.hh" sourcefile="elements/tcpudp/iprewriter.cc" portcount="1-/1-256" processing="h/h" requires="IPRw IPRewriterPatterns" />
++<entry name="IPRewriterPatterns" cxxclass="IPRewriterPatterns" docname="IPRewriterPatterns" headerfile="elements/ip/iprwpatterns.hh" sourcefile="elements/ip/iprwpatterns.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="IPRw" />
++<entry name="Idle" cxxclass="Idle" docname="Idle" headerfile="elements/standard/idle.hh" sourcefile="elements/standard/idle.cc" portcount="-/-" processing="a/a" flowcode="x/y" flags="S0" />
++<entry name="InfiniteSource" cxxclass="InfiniteSource" docname="InfiniteSource" headerfile="elements/standard/infinitesource.hh" sourcefile="elements/standard/infinitesource.cc" portcount="0/1" processing="a/a" flowcode="x/x" flags="S1" />
++<entry name="KernelFilter" cxxclass="KernelFilter" docname="KernelFilter" headerfile="elements/userlevel/kernelfilter.hh" sourcefile="elements/userlevel/kernelfilter.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="KernelHandlerProxy" cxxclass="KernelHandlerProxy" docname="KernelHandlerProxy" headerfile="elements/userlevel/khandlerproxy.hh" sourcefile="elements/userlevel/khandlerproxy.cc" requires="userlevel HandlerProxy" />
++<entry name="KernelTap" cxxclass="KernelTap" docname="KernelTap" headerfile="elements/userlevel/kerneltap.hh" sourcefile="elements/userlevel/kerneltap.cc" portcount="0-1/1-2" processing="a/h" flowcode="x/y" flags="S3" requires="userlevel KernelTun" />
++<entry name="KernelTun" cxxclass="KernelTun" docname="KernelTun" headerfile="elements/userlevel/kerneltun.hh" sourcefile="elements/userlevel/kerneltun.cc" portcount="0-1/1-2" processing="a/h" flowcode="x/y" flags="S3" requires="userlevel FakePcap" />
++<entry name="LinearIPLookup" cxxclass="LinearIPLookup" docname="LinearIPLookup" headerfile="elements/ip/lineariplookup.hh" sourcefile="elements/ip/lineariplookup.cc" portcount="1/-" processing="h/h" requires="IPRouteTable" />
++<entry name="LinkUnqueue" cxxclass="LinkUnqueue" docname="LinkUnqueue" headerfile="elements/standard/linkunqueue.hh" sourcefile="elements/standard/linkunqueue.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="LinuxIPLookup" cxxclass="LinuxIPLookup" docname="LinuxIPLookup" headerfile="elements/ip/lookupiproutelinux.hh" sourcefile="elements/ip/lookupiproutelinux.cc" portcount="1/1-" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="LookupIPRouteMP" cxxclass="LookupIPRouteMP" docname="LookupIPRouteMP" headerfile="elements/ip/lookupiproutemp.hh" sourcefile="elements/ip/lookupiproutemp.cc" portcount="1/-" processing="a/a" flowcode="x/x" requires="linuxmodule" />
++<entry name="MSQueue" cxxclass="MSQueue" docname="MSQueue" headerfile="elements/standard/msqueue.hh" sourcefile="elements/standard/msqueue.cc" portcount="1/1" processing="h/l" flowcode="x/x" />
++<entry name="MarkIPCE" cxxclass="MarkIPCE" docname="MarkIPCE" headerfile="elements/ip/markipce.hh" sourcefile="elements/ip/markipce.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="MarkIPHeader" cxxclass="MarkIPHeader" docname="MarkIPHeader" headerfile="elements/ip/markipheader.hh" sourcefile="elements/ip/markipheader.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Message" cxxclass="MessageElement" docname="Message" headerfile="elements/standard/messageelement.hh" sourcefile="elements/standard/messageelement.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="Meter" cxxclass="Meter" docname="Meter" headerfile="elements/standard/meter.hh" sourcefile="elements/standard/meter.cc" portcount="1/2-" processing="h/h" flowcode="x/x" requires="BandwidthMeter" />
++<entry name="MixedQueue" cxxclass="MixedQueue" docname="MixedQueue" headerfile="elements/standard/mixedqueue.hh" sourcefile="elements/standard/mixedqueue.cc" portcount="2/1" processing="h/l" flowcode="x/x" requires="NotifierQueue" />
++<entry name="NotifierQueue" cxxclass="NotifierQueue" docname="NotifierQueue" headerfile="elements/standard/notifierqueue.hh" sourcefile="elements/standard/notifierqueue.cc" portcount="1/1" processing="h/l" flowcode="x/x" requires="SimpleQueue" />
++<entry name="Null" cxxclass="NullElement" docname="Null" headerfile="elements/standard/nullelement.hh" sourcefile="elements/standard/nullelement.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null1" cxxclass="Null1" docname="Null1" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null2" cxxclass="Null2" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null3" cxxclass="Null3" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null4" cxxclass="Null4" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null5" cxxclass="Null5" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null6" cxxclass="Null6" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null7" cxxclass="Null7" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Null8" cxxclass="Null8" headerfile="elements/standard/nulls.hh" sourcefile="elements/standard/nulls.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Paint" cxxclass="Paint" docname="Paint" headerfile="elements/standard/paint.hh" sourcefile="elements/standard/paint.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="PaintSwitch" cxxclass="PaintSwitch" docname="PaintSwitch" headerfile="elements/standard/paintswitch.hh" sourcefile="elements/standard/paintswitch.cc" portcount="1/-" processing="h/h" flowcode="x/x" />
++<entry name="PaintTee" cxxclass="PaintTee" docname="PaintTee" headerfile="elements/standard/painttee.hh" sourcefile="elements/standard/painttee.cc" portcount="1/2" processing="a/ah" flowcode="x/x" />
++<entry name="PerfCountAccum" cxxclass="PerfCountAccum" docname="PerfCountAccum" headerfile="elements/linuxmodule/perfcountaccum.hh" sourcefile="elements/linuxmodule/perfcountaccum.cc" portcount="1/1" processing="a/a" requires="linuxmodule i586 int64 PerfCountUser" />
++<entry name="PerfCountInfo" cxxclass="PerfCountInfo" docname="PerfCountInfo" headerfile="elements/linuxmodule/perfcountinfo.hh" sourcefile="elements/linuxmodule/perfcountinfo.cc" requires="linuxmodule PerfCountUser" />
++<entry name="PokeHandlers" cxxclass="PokeHandlers" docname="PokeHandlers" headerfile="elements/standard/pokehandlers.hh" sourcefile="elements/standard/pokehandlers.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="PollDevice" cxxclass="PollDevice" docname="PollDevice" headerfile="elements/linuxmodule/polldevice.hh" sourcefile="elements/linuxmodule/polldevice.cc" portcount="0/1" processing="h/h" methods="static_initialize static_cleanup" requires="AnyDevice linuxmodule" />
++<entry name="PortInfo" cxxclass="PortInfo" docname="PortInfo" headerfile="<click/standard/portinfo.hh>" sourcefile="elements/standard/portinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="Print" cxxclass="Print" docname="Print" headerfile="elements/standard/print.hh" sourcefile="elements/standard/print.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="PrioSched" cxxclass="PrioSched" docname="PrioSched" headerfile="elements/standard/priosched.hh" sourcefile="elements/standard/priosched.cc" portcount="-/1" processing="l/l" flowcode="x/x" />
++<entry name="ProgressBar" cxxclass="ProgressBar" docname="ProgressBar" headerfile="elements/userlevel/progressbar.hh" sourcefile="elements/userlevel/progressbar.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="userlevel" />
++<entry name="PullNull" cxxclass="PullNullElement" headerfile="elements/standard/nullelement.hh" sourcefile="elements/standard/nullelement.cc" portcount="1/1" processing="l/l" flowcode="x/x" />
++<entry name="PullSwitch" cxxclass="PullSwitch" docname="PullSwitch" headerfile="elements/standard/pullswitch.hh" sourcefile="elements/standard/pullswitch.cc" portcount="-/1" processing="l/l" flowcode="x/x" />
++<entry name="PullTee" cxxclass="PullTee" docname="PullTee" headerfile="elements/standard/tee.hh" sourcefile="elements/standard/tee.cc" portcount="1/1-" processing="l/lh" flowcode="x/x" />
++<entry name="PushNull" cxxclass="PushNullElement" headerfile="elements/standard/nullelement.hh" sourcefile="elements/standard/nullelement.cc" portcount="1/1" processing="h/h" flowcode="x/x" />
++<entry name="Queue" cxxclass="FullNoteQueue" docname="Queue" headerfile="elements/standard/fullnotequeue.hh" sourcefile="elements/standard/fullnotequeue.cc" portcount="1/1" processing="h/l" flowcode="x/x" requires="NotifierQueue" />
++<entry name="QuitWatcher" cxxclass="QuitWatcher" docname="QuitWatcher" headerfile="elements/standard/quitwatcher.hh" sourcefile="elements/standard/quitwatcher.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="RED" cxxclass="RED" docname="RED" headerfile="elements/aqm/red.hh" sourcefile="elements/aqm/red.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" requires="int64" />
++<entry name="RFC2507Comp" cxxclass="RFC2507c" docname="RFC2507Comp" headerfile="elements/ip/rfc2507c.hh" sourcefile="elements/ip/rfc2507c.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="RFC2507Decomp" cxxclass="RFC2507d" docname="RFC2507Decomp" headerfile="elements/ip/rfc2507d.hh" sourcefile="elements/ip/rfc2507d.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="RIPSend" cxxclass="RIPSend" docname="RIPSend" headerfile="elements/ip/ripsend.hh" sourcefile="elements/ip/ripsend.cc" portcount="0/1" processing="h/h" flowcode="x/x" />
++<entry name="RadixIPLookup" cxxclass="RadixIPLookup" docname="RadixIPLookup" headerfile="elements/ip/radixiplookup.hh" sourcefile="elements/ip/radixiplookup.cc" portcount="1/-" processing="h/h" requires="IPRouteTable" />
++<entry name="RandomBitErrors" cxxclass="RandomBitErrors" docname="RandomBitErrors" headerfile="elements/standard/randomerror.hh" sourcefile="elements/standard/randomerror.cc" portcount="1/1" processing="a/a" flowcode="x/x" requires="int64" />
++<entry name="RandomSample" cxxclass="RandomSample" docname="RandomSample" headerfile="elements/standard/randomsample.hh" sourcefile="elements/standard/randomsample.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="RandomSource" cxxclass="RandomSource" docname="RandomSource" headerfile="elements/standard/randomsource.hh" sourcefile="elements/standard/randomsource.cc" portcount="0/1" processing="a/a" flowcode="x/x" />
++<entry name="RandomSwitch" cxxclass="RandomSwitch" docname="RandomSwitch" headerfile="elements/standard/randomswitch.hh" sourcefile="elements/standard/randomswitch.cc" portcount="1/1-" processing="h/h" flowcode="x/x" />
++<entry name="RangeIPLookup" cxxclass="RangeIPLookup" docname="RangeIPLookup" headerfile="elements/ip/rangeiplookup.hh" sourcefile="elements/ip/rangeiplookup.cc" portcount="1/-" processing="h/h" requires="DirectIPLookup" />
++<entry name="RatedSource" cxxclass="RatedSource" docname="RatedSource" headerfile="elements/standard/ratedsource.hh" sourcefile="elements/standard/ratedsource.cc" portcount="0/1" processing="a/a" flowcode="x/x" />
++<entry name="RatedSplitter" cxxclass="RatedSplitter" docname="RatedSplitter" headerfile="elements/standard/ratedsplitter.hh" sourcefile="elements/standard/ratedsplitter.cc" portcount="1/2" processing="h/h" flowcode="x/x" />
++<entry name="RatedUnqueue" cxxclass="RatedUnqueue" docname="RatedUnqueue" headerfile="elements/standard/ratedunqueue.hh" sourcefile="elements/standard/ratedunqueue.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="RawSocket" cxxclass="RawSocket" docname="RawSocket" headerfile="elements/userlevel/rawsocket.hh" sourcefile="elements/userlevel/rawsocket.cc" portcount="0-1/0-1" processing="l/h" flowcode="x/y" requires="userlevel linux" />
++<entry name="RoundRobinIPMapper" cxxclass="RoundRobinIPMapper" docname="RoundRobinIPMapper" headerfile="elements/ip/rripmapper.hh" sourcefile="elements/ip/rripmapper.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="IPRw" />
++<entry name="RoundRobinSched" cxxclass="RRSched" docname="RoundRobinSched" headerfile="elements/standard/rrsched.hh" sourcefile="elements/standard/rrsched.cc" portcount="-/1" processing="l/l" flowcode="x/x" />
++<entry name="RoundRobinSwitch" cxxclass="RoundRobinSwitch" docname="RoundRobinSwitch" headerfile="elements/standard/rrswitch.hh" sourcefile="elements/standard/rrswitch.cc" portcount="1/1-" processing="h/h" flowcode="x/x" />
++<entry name="RoundTripCycleCount" cxxclass="RTCycles" docname="RoundTripCycleCount" headerfile="elements/linuxmodule/rtcycles.hh" sourcefile="elements/linuxmodule/rtcycles.cc" portcount="1/1" processing="a/a" flowcode="x/x" requires="linuxmodule int64" />
++<entry name="ScheduleInfo" cxxclass="ScheduleInfo" docname="ScheduleInfo" headerfile="<click/standard/scheduleinfo.hh>" sourcefile="elements/standard/scheduleinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="ScheduleLinux" cxxclass="ScheduleLinux" docname="ScheduleLinux" headerfile="elements/linuxmodule/schedulelinux.hh" sourcefile="elements/linuxmodule/schedulelinux.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="linuxmodule" />
++<entry name="Script" cxxclass="Script" docname="Script" headerfile="elements/standard/script.hh" sourcefile="elements/standard/script.cc" portcount="0/0" processing="a/a" flowcode="x/x" methods="static_initialize static_cleanup" />
++<entry name="SetAnnoByte" cxxclass="SetAnnoByte" docname="SetAnnoByte" headerfile="elements/standard/setannobyte.hh" sourcefile="elements/standard/setannobyte.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetCRC32" cxxclass="SetCRC32" docname="SetCRC32" headerfile="elements/standard/setcrc32.hh" sourcefile="elements/standard/setcrc32.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetCycleCount" cxxclass="SetCycleCount" docname="SetCycleCount" headerfile="elements/linuxmodule/setcyclecount.hh" sourcefile="elements/linuxmodule/setcyclecount.cc" portcount="1/1" processing="a/a" flowcode="x/x" requires="linuxmodule int64" />
++<entry name="SetIPAddress" cxxclass="SetIPAddress" docname="SetIPAddress" headerfile="elements/ip/setipaddress.hh" sourcefile="elements/ip/setipaddress.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetIPChecksum" cxxclass="SetIPChecksum" docname="SetIPChecksum" headerfile="elements/ip/setipchecksum.hh" sourcefile="elements/ip/setipchecksum.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetIPDSCP" cxxclass="SetIPDSCP" docname="SetIPDSCP" headerfile="elements/ip/setipdscp.hh" sourcefile="elements/ip/setipdscp.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetPacketType" cxxclass="SetPacketType" docname="SetPacketType" headerfile="elements/standard/setpackettype.hh" sourcefile="elements/standard/setpackettype.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetPerfCount" cxxclass="SetPerfCount" docname="SetPerfCount" headerfile="elements/linuxmodule/setperfcount.hh" sourcefile="elements/linuxmodule/setperfcount.cc" portcount="1/1" processing="a/a" requires="linuxmodule i586 int64 PerfCountUser" />
++<entry name="SetRandIPAddress" cxxclass="SetRandIPAddress" docname="SetRandIPAddress" headerfile="elements/ip/setrandipaddress.hh" sourcefile="elements/ip/setrandipaddress.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetTCPChecksum" cxxclass="SetTCPChecksum" docname="SetTCPChecksum" headerfile="elements/tcpudp/settcpchecksum.hh" sourcefile="elements/tcpudp/settcpchecksum.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetTimestamp" cxxclass="SetTimestamp" docname="SetTimestamp" headerfile="elements/standard/settimestamp.hh" sourcefile="elements/standard/settimestamp.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="SetUDPChecksum" cxxclass="SetUDPChecksum" docname="SetUDPChecksum" headerfile="elements/tcpudp/setudpchecksum.hh" sourcefile="elements/tcpudp/setudpchecksum.cc" portcount="1/1-2" processing="a/ah" flowcode="x/x" />
++<entry name="Shaper" cxxclass="Shaper" docname="Shaper" headerfile="elements/standard/shaper.hh" sourcefile="elements/standard/shaper.cc" portcount="1/1" processing="l/l" flowcode="x/x" />
++<entry name="SimpleQueue" cxxclass="SimpleQueue" docname="SimpleQueue" headerfile="elements/standard/simplequeue.hh" sourcefile="elements/standard/simplequeue.cc" portcount="1/1" processing="h/l" flowcode="x/x" provides="Storage" />
++<entry name="Socket" cxxclass="Socket" docname="Socket" headerfile="elements/userlevel/socket.hh" sourcefile="elements/userlevel/socket.cc" portcount="0-1/0-1" processing="a/h" flowcode="x/y" requires="userlevel IPRouteTable" />
++<entry name="SortedIPLookup" cxxclass="SortedIPLookup" docname="SortedIPLookup" headerfile="elements/ip/sortediplookup.hh" sourcefile="elements/ip/sortediplookup.cc" portcount="1/-" processing="h/h" requires="LinearIPLookup" />
++<entry name="SourceIPHashMapper" cxxclass="SourceIPHashMapper" docname="SourceIPHashMapper" headerfile="elements/ip/siphmapper.hh" sourcefile="elements/ip/siphmapper.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="IPRw" />
++<entry name="SpinlockAcquire" cxxclass="SpinlockAcquire" docname="SpinlockAcquire" headerfile="elements/standard/spinlockacquire.hh" sourcefile="elements/standard/spinlockacquire.cc" portcount="-/-" processing="a/a" flowcode="x/x" />
++<entry name="SpinlockInfo" cxxclass="SpinlockInfo" docname="SpinlockInfo" headerfile="elements/standard/spinlockinfo.hh" sourcefile="elements/standard/spinlockinfo.cc" portcount="0/0" processing="a/a" flowcode="x/x" />
++<entry name="SpinlockRelease" cxxclass="SpinlockRelease" docname="SpinlockRelease" headerfile="elements/standard/spinlockrelease.hh" sourcefile="elements/standard/spinlockrelease.cc" portcount="-/-" processing="a/a" flowcode="x/x" />
++<entry name="StaticIPLookup" cxxclass="StaticIPLookup" docname="StaticIPLookup" headerfile="elements/ip/lookupiproute.hh" sourcefile="elements/ip/lookupiproute.cc" portcount="1/-" processing="h/h" requires="LinearIPLookup" />
++<entry name="StaticPullSwitch" cxxclass="StaticPullSwitch" docname="StaticPullSwitch" headerfile="elements/standard/staticpullswitch.hh" sourcefile="elements/standard/staticpullswitch.cc" portcount="-/1" processing="l/l" flowcode="x/x" />
++<entry name="StaticSwitch" cxxclass="StaticSwitch" docname="StaticSwitch" headerfile="elements/standard/staticswitch.hh" sourcefile="elements/standard/staticswitch.cc" portcount="1/-" processing="h/h" flowcode="x/x" />
++<entry name="StaticThreadSched" cxxclass="StaticThreadSched" docname="StaticThreadSched" headerfile="elements/linuxmodule/staticthreadsched.hh" sourcefile="elements/linuxmodule/staticthreadsched.cc" portcount="0/0" processing="a/a" flowcode="x/x" requires="linuxmodule" />
++<entry name="StoreData" cxxclass="StoreData" docname="StoreData" headerfile="elements/standard/storedata.hh" sourcefile="elements/standard/storedata.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="StoreIPAddress" cxxclass="StoreIPAddress" docname="StoreIPAddress" headerfile="elements/ip/storeipaddress.hh" sourcefile="elements/ip/storeipaddress.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="StrideSched" cxxclass="StrideSched" docname="StrideSched" headerfile="elements/standard/stridesched.hh" sourcefile="elements/standard/stridesched.cc" portcount="1-/1" processing="l/l" flowcode="x/x" />
++<entry name="StrideSwitch" cxxclass="StrideSwitch" docname="StrideSwitch" headerfile="elements/standard/strideswitch.hh" sourcefile="elements/standard/strideswitch.cc" portcount="1/1-" processing="h/h" flowcode="x/x" requires="StrideSched" />
++<entry name="Strip" cxxclass="Strip" docname="Strip" headerfile="elements/standard/strip.hh" sourcefile="elements/standard/strip.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="StripIPHeader" cxxclass="StripIPHeader" docname="StripIPHeader" headerfile="elements/ip/stripipheader.hh" sourcefile="elements/ip/stripipheader.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="StripToNetworkHeader" cxxclass="StripToNetworkHeader" docname="StripToNetworkHeader" headerfile="elements/standard/striptonet.hh" sourcefile="elements/standard/striptonet.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="Suppressor" cxxclass="Suppressor" docname="Suppressor" headerfile="elements/standard/suppressor.hh" sourcefile="elements/standard/suppressor.cc" portcount="-/=" processing="a/a" flowcode="#/#" />
++<entry name="Switch" cxxclass="Switch" docname="Switch" headerfile="elements/standard/switch.hh" sourcefile="elements/standard/switch.cc" portcount="1/-" processing="h/h" flowcode="x/x" />
++<entry name="TCPRewriter" cxxclass="TCPRewriter" docname="TCPRewriter" headerfile="elements/tcpudp/tcprewriter.hh" sourcefile="elements/tcpudp/tcprewriter.cc" portcount="1-/1-256" processing="h/h" requires="IPRw IPRewriterPatterns" />
++<entry name="Tee" cxxclass="Tee" docname="Tee" headerfile="elements/standard/tee.hh" sourcefile="elements/standard/tee.cc" portcount="1/1-" processing="h/h" flowcode="x/x" />
++<entry name="TimedSink" cxxclass="TimedSink" docname="TimedSink" headerfile="elements/standard/timedsink.hh" sourcefile="elements/standard/timedsink.cc" portcount="1/0" processing="l/l" flowcode="x/x" />
++<entry name="TimedSource" cxxclass="TimedSource" docname="TimedSource" headerfile="elements/standard/timedsource.hh" sourcefile="elements/standard/timedsource.cc" portcount="0/1" processing="h/h" flowcode="x/x" />
++<entry name="ToDevice" cxxclass="ToDevice" docname="ToDevice" headerfile="elements/linuxmodule/todevice.hh" sourcefile="elements/linuxmodule/todevice.cc" portcount="1/0" processing="l/l" methods="static_initialize static_cleanup" requires="AnyDevice linuxmodule" />
++<entry name="ToDevice" cxxclass="ToDevice" docname="ToDevice.u" headerfile="elements/userlevel/todevice.hh" sourcefile="elements/userlevel/todevice.cc" portcount="1/0-2" processing="l/h" flowcode="x/x" flags="S2" requires="FromDevice userlevel" />
++<entry name="ToDump" cxxclass="ToDump" docname="ToDump" headerfile="elements/userlevel/todump.hh" sourcefile="elements/userlevel/todump.cc" portcount="1/0-1" processing="a/a" flowcode="x/x" flags="S2" requires="userlevel|ns FakePcap" />
++<entry name="ToHost" cxxclass="ToHost" docname="ToHost" headerfile="elements/linuxmodule/tohost.hh" sourcefile="elements/linuxmodule/tohost.cc" portcount="1/0" processing="h/h" flags="S2" methods="static_initialize static_cleanup" requires="linuxmodule AnyDevice" />
++<entry name="ToHost" cxxclass="ToHost" docname="ToHost.u" headerfile="elements/userlevel/tohost.hh" sourcefile="elements/userlevel/tohost.cc" portcount="1/0" processing="h/h" flowcode="x/x" requires="userlevel FromHost" />
++<entry name="ToHostSniffers" cxxclass="ToHostSniffers" docname="ToHostSniffers" headerfile="elements/linuxmodule/tohostsniffers.hh" sourcefile="elements/linuxmodule/tohostsniffers.cc" portcount="1/0" processing="h/h" flowcode="x/x" requires="linuxmodule ToHost" />
++<entry name="ToRawSocket" cxxclass="ToRawSocket" docname="ToRawSocket" headerfile="elements/userlevel/torawsocket.hh" sourcefile="elements/userlevel/torawsocket.cc" portcount="0-1/0-1" processing="l/l" flowcode="x/y" requires="RawSocket" />
++<entry name="ToSocket" cxxclass="ToSocket" docname="ToSocket" headerfile="elements/userlevel/tosocket.hh" sourcefile="elements/userlevel/tosocket.cc" portcount="0-1/0-1" processing="l/l" flowcode="x/y" requires="Socket" />
++<entry name="Truncate" cxxclass="Truncate" docname="Truncate" headerfile="elements/standard/truncate.hh" sourcefile="elements/standard/truncate.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="UDPIPEncap" cxxclass="UDPIPEncap" docname="UDPIPEncap" headerfile="elements/tcpudp/udpipencap.hh" sourcefile="elements/tcpudp/udpipencap.cc" portcount="1/1" processing="a/a" flowcode="x/x" flags="A" />
++<entry name="UMLSwitch" cxxclass="UMLSwitch" docname="UMLSwitch" headerfile="elements/userlevel/umlswitch.hh" sourcefile="elements/userlevel/umlswitch.cc" portcount="0-1/0-1" processing="l/h" flowcode="x/y" requires="Socket" />
++<entry name="Unqueue" cxxclass="Unqueue" docname="Unqueue" headerfile="elements/standard/unqueue.hh" sourcefile="elements/standard/unqueue.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="Unqueue2" cxxclass="Unqueue2" docname="Unqueue2" headerfile="elements/standard/unqueue2.hh" sourcefile="elements/standard/unqueue2.cc" portcount="1/1" processing="l/h" flowcode="x/x" />
++<entry name="Unstrip" cxxclass="Unstrip" docname="Unstrip" headerfile="elements/standard/unstrip.hh" sourcefile="elements/standard/unstrip.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry name="UnstripIPHeader" cxxclass="UnstripIPHeader" docname="UnstripIPHeader" headerfile="elements/ip/unstripipheader.hh" sourcefile="elements/ip/unstripipheader.cc" portcount="1/1" processing="a/a" flowcode="x/x" />
++<entry headerfile="elements/linuxmodule/anydevice.hh" sourcefile="elements/linuxmodule/anydevice.cc" requires="linuxmodule" provides="AnyDevice" />
++<entry headerfile="elements/userlevel/fakepcap.hh" sourcefile="elements/userlevel/fakepcap.cc" requires="userlevel|ns" provides="FakePcap" />
++<entry headerfile="elements/userlevel/fromfile.hh" sourcefile="elements/userlevel/fromfile.cc" requires="userlevel|ns FakePcap" provides="FromFile" />
++<entry headerfile="elements/userlevel/handlerproxy.hh" sourcefile="elements/userlevel/handlerproxy.cc" requires="userlevel" provides="HandlerProxy" />
++<entry docname="IPRouteTable" headerfile="elements/ip/iproutetable.hh" sourcefile="elements/ip/iproutetable.cc" provides="IPRouteTable" />
++<entry headerfile="elements/ip/iprw.hh" sourcefile="elements/ip/iprw.cc" provides="IPRw" />
++<entry headerfile="elements/linuxmodule/perfcountuser.hh" sourcefile="elements/linuxmodule/perfcountuser.cc" requires="linuxmodule i586" provides="PerfCountUser" />
++</elementmap>
+diff -Nurb click-1.6.0/inst/share/click/mkinstalldirs click-1.6.0-27/inst/share/click/mkinstalldirs
+--- click-1.6.0/inst/share/click/mkinstalldirs 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/mkinstalldirs 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,158 @@
++#! /bin/sh
++# mkinstalldirs --- make directory hierarchy
++
++scriptversion=2005-06-29.22
++
++# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
++# Created: 1993-05-16
++# Public domain.
++#
++# This file is maintained in Automake, please report
++# bugs to <bug-automake@gnu.org> or send patches to
++# <automake-patches@gnu.org>.
++
++errstatus=0
++dirmode=
++
++usage="\
++Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
++
++Create each directory DIR (with mode MODE, if specified), including all
++leading file name components.
++
++Report bugs to <bug-automake@gnu.org>."
++
++# process command line arguments
++while test $# -gt 0 ; do
++ case $1 in
++ -h | --help | --h*) # -h for help
++ echo "$usage"
++ exit $?
++ ;;
++ -m) # -m PERM arg
++ shift
++ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
++ dirmode=$1
++ shift
++ ;;
++ --version)
++ echo "$0 $scriptversion"
++ exit $?
++ ;;
++ --) # stop option processing
++ shift
++ break
++ ;;
++ -*) # unknown option
++ echo "$usage" 1>&2
++ exit 1
++ ;;
++ *) # first non-opt arg
++ break
++ ;;
++ esac
++done
++
++for file
++do
++ if test -d "$file"; then
++ shift
++ else
++ break
++ fi
++done
++
++case $# in
++ 0) exit 0 ;;
++esac
++
++# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
++# mkdir -p a/c at the same time, both will detect that a is missing,
++# one will create a, then the other will try to create a and die with
++# a "File exists" error. This is a problem when calling mkinstalldirs
++# from a parallel make. We use --version in the probe to restrict
++# ourselves to GNU mkdir, which is thread-safe.
++case $dirmode in
++ '')
++ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
++ echo "mkdir -p -- $*"
++ exec mkdir -p -- "$@"
++ else
++ # On NextStep and OpenStep, the `mkdir' command does not
++ # recognize any option. It will interpret all options as
++ # directories to create, and then abort because `.' already
++ # exists.
++ test -d ./-p && rmdir ./-p
++ test -d ./--version && rmdir ./--version
++ fi
++ ;;
++ *)
++ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
++ test ! -d ./--version; then
++ echo "mkdir -m $dirmode -p -- $*"
++ exec mkdir -m "$dirmode" -p -- "$@"
++ else
++ # Clean up after NextStep and OpenStep mkdir.
++ for d in ./-m ./-p ./--version "./$dirmode";
++ do
++ test -d $d && rmdir $d
++ done
++ fi
++ ;;
++esac
++
++for file
++do
++ case $file in
++ /*) pathcomp=/ ;;
++ *) pathcomp= ;;
++ esac
++ oIFS=$IFS
++ IFS=/
++ set fnord $file
++ shift
++ IFS=$oIFS
++
++ for d
++ do
++ test "x$d" = x && continue
++
++ pathcomp=$pathcomp$d
++ case $pathcomp in
++ -*) pathcomp=./$pathcomp ;;
++ esac
++
++ if test ! -d "$pathcomp"; then
++ echo "mkdir $pathcomp"
++
++ mkdir "$pathcomp" || lasterr=$?
++
++ if test ! -d "$pathcomp"; then
++ errstatus=$lasterr
++ else
++ if test ! -z "$dirmode"; then
++ echo "chmod $dirmode $pathcomp"
++ lasterr=
++ chmod "$dirmode" "$pathcomp" || lasterr=$?
++
++ if test ! -z "$lasterr"; then
++ errstatus=$lasterr
++ fi
++ fi
++ fi
++ fi
++
++ pathcomp=$pathcomp/
++ done
++done
++
++exit $errstatus
++
++# Local Variables:
++# mode: shell-script
++# sh-indentation: 2
++# eval: (add-hook 'write-file-hooks 'time-stamp)
++# time-stamp-start: "scriptversion="
++# time-stamp-format: "%:y-%02m-%02d.%02H"
++# time-stamp-end: "$"
++# End:
+diff -Nurb click-1.6.0/inst/share/click/pkg-Makefile click-1.6.0-27/inst/share/click/pkg-Makefile
+--- click-1.6.0/inst/share/click/pkg-Makefile 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/pkg-Makefile 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,112 @@
++# pkg-Makefile -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2006 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++VPATH ?= .:$(top_srcdir)/$(subdir):$(top_srcdir)
++
++include $(clickdatadir)/pkg-config.mk
++
++ifeq ($(CLICK_PACKAGE_MAKING),userlevel)
++include $(clickdatadir)/pkg-userlevel.mk
++endif
++
++ifeq ($(CLICK_PACKAGE_MAKING),linuxmodule)
++include $(clickdatadir)/pkg-linuxmodule.mk
++endif
++
++ifeq ($(CLICK_PACKAGE_MAKING),bsdmodule)
++include $(clickdatadir)/pkg-bsdmodule.mk
++endif
++
++ifeq ($(CLICK_PACKAGE_MAKING),)
++
++INSTALL ?= $(CLICKINSTALL)
++INSTALL_DATA ?= $(CLICKINSTALL) -m 644
++mkinstalldirs ?= $(clickdatadir)/mkinstalldirs
++
++CLICK_BUILDTOOL = $(clickbindir)/click-buildtool
++CLICK_ELEM2PACKAGE = $(CLICK_BUILDTOOL) elem2package $(ELEM2PACKAGE_INCLUDES)
++
++# set TARGETS, etc. based on MAKE_UPACKAGE, MAKE_KPACKAGE, and MAKE_BPACKAGE
++ifeq ($(MAKE_UPACKAGE),1)
++TARGETS += $(package).uo
++DRIVERS += userlevel
++endif
++ifeq ($(MAKE_KPACKAGE),1)
++TARGETS += $(package).ko
++DRIVERS += linuxmodule
++endif
++ifeq ($(MAKE_BPACKAGE),1)
++TARGETS += $(package).bo
++DRIVERS += bsdmodule
++endif
++
++all: $(TARGETS)
++
++$(package).uo: Makefile always
++ $(MAKE) CLICK_PACKAGE_MAKING=userlevel $(package).uo
++
++$(package).ko: Makefile always
++ $(MAKE) CLICK_PACKAGE_MAKING=linuxmodule $(package).ko
++
++ifneq ($(wildcard $(srcdir)/Makefile.in),)
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++ cd $(top_builddir) \
++ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
++endif
++
++ifneq ($(wildcard $(top_srcdir)/configure.ac),)
++$(top_builddir)/config.status: $(top_srcdir)/configure
++ cd $(top_builddir) && ./config.status --recheck
++$(top_srcdir)/configure: $(top_srcdir)/configure.ac
++ cd $(top_srcdir) && autoconf
++endif
++
++elemlist:
++ for i in $(DRIVERS); do $(MAKE) CLICK_PACKAGE_MAKING=$$i elemlist; done
++
++elementmap-$(package).xml: $(clickbindir)/click-mkelemmap always
++ r="$(DRIVERS) $(package)"; echo $(srcdir) | $(CLICK_BUILDTOOL) findelem -r "$$r" -P | $(clickbindir)/click-mkelemmap -r "$(package)" -t "$(DRIVERS)" -s `cd $(srcdir) && pwd` > elementmap-$(package).xml
++
++install: install-obj install-man elementmap-$(package).xml always
++ $(mkinstalldirs) $(DESTDIR)$(clickdatadir)
++ $(INSTALL_DATA) elementmap-$(package).xml $(DESTDIR)$(clickdatadir)/elementmap-$(package).xml
++install-obj: $(TARGETS) always
++ $(mkinstalldirs) $(DESTDIR)$(libdir)
++ for i in $(TARGETS); do $(INSTALL_DATA) $$i $(DESTDIR)$(libdir)/$$i; done
++install-man: always elementmap-$(package).xml
++ $(mkinstalldirs) $(DESTDIR)$(mandir)
++ $(mkinstalldirs) $(DESTDIR)$(mandir)/mann
++ $(clickbindir)/click-elem2man -L -d $(DESTDIR)$(mandir)/mann -P $(package) -e $(clickdatadir)/elementmap.xml elementmap-$(package).xml
++
++uninstall: uninstall-obj uninstall-man always
++ /bin/rm -f $(DESTDIR)$(clickdatadir)/elementmap-$(package).xml
++uninstall-obj: always
++ for i in $(TARGETS); do /bin/rm -f $(DESTDIR)$(libdir)/$$i; done
++uninstall-man: always elementmap-$(package).xml
++ $(clickbindir)/click-elem2man -L -d $(DESTDIR)$(mandir)/mann -P $(package) -e $(clickdatadir)/elementmap.xml -u elementmap-$(package).xml
++
++clean: always
++ @for i in $(DRIVERS); do make CLICK_PACKAGE_MAKING=$$i clean; done
++ -rm -f elementmap-$(package).xml conftest.*
++distclean: clean
++ -rm -f Makefile config.h config.status config.cache config.log
++
++always:
++ @:
++
++.PHONY: all always clean distclean elemlist \
++ install install-obj install-man uninstall uninstall-obj uninstall-man
++
++endif
+diff -Nurb click-1.6.0/inst/share/click/pkg-config.mk click-1.6.0-27/inst/share/click/pkg-config.mk
+--- click-1.6.0/inst/share/click/pkg-config.mk 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/pkg-config.mk 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,43 @@
++# pkg-config.mk -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2006 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++CLICKCC = gcc -W -Wall
++CLICKCPP = gcc -W -Wall -E
++CLICKCXX = g++ -W -Wall
++CLICKCXXCPP = g++ -W -Wall -E
++
++CLICKAR_CREATE = ar cru
++CLICKRANLIB = ranlib
++CLICKSTRIP = strip
++
++CLICKKERNEL_CC = gcc -w -W -Wall
++CLICKKERNEL_CXX = g++ -w -W -Wall -fno-exceptions -fno-rtti -D__SMP__
++
++CLICKCPPFLAGS =
++CLICKCFLAGS = -g -O2
++CLICKCFLAGS_NDEBUG = -O2
++CLICKCXXFLAGS = -g -O2
++CLICKCXXFLAGS_NDEBUG = -O2
++CLICKDEPCFLAGS = -MD
++
++CLICKDEFS = -DHAVE_CONFIG_H
++CLICKINCLUDES = -I$(clickincludedir) -I$(clicksrcdir)
++CLICKLDFLAGS =
++CLICKLDMODULEFLAGS = -shared
++
++CLICKAUTOCONF = autoconf
++CLICKGMAKE = make
++CLICKINSTALL = /usr/bin/install -c
++
+diff -Nurb click-1.6.0/inst/share/click/pkg-linuxmodule-26.mk click-1.6.0-27/inst/share/click/pkg-linuxmodule-26.mk
+--- click-1.6.0/inst/share/click/pkg-linuxmodule-26.mk 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/pkg-linuxmodule-26.mk 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,92 @@
++# pkg-linuxmodule-26.mk -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2006-2007 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++CLICKBUILD = linux26module
++
++CLICKCPPFLAGS += -DCLICK_LINUXMODULE
++CLICKINCLUDES := -I$(clickincludedir) -I$(clicksrcdir) -I$(clicklinuxdir)/include
++
++LINUXCFLAGS = $(shell echo "$(CPPFLAGS) $(CFLAGS)" | sed \
++ -e s,-fno-unit-at-a-time,, -e s,-Wstrict-prototypes,, \
++ -e s,-Wdeclaration-after-statement,, \
++ -e s,-Wno-pointer-sign,, -e s,-fno-common,,)
++
++CXXFLAGS ?= $(CLICKCXXFLAGS_NDEBUG)
++DEPCFLAGS ?= -Wp,-MD,$(depfile)
++
++DEFS ?= $(CLICKDEFS)
++INCLUDES ?= $(CLICKINCLUDES)
++
++CXXCOMPILE = $(CLICKKERNEL_CXX) $(LINUXCFLAGS) $(CLICKCPPFLAGS) \
++ $(CLICKCFLAGS_NDEBUG) $(CXXFLAGS) $(PACKAGE_CXXFLAGS) \
++ $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++COMPILE = $(CLICKKERNEL_CC) $(LINUXCFLAGS) $(CLICKCPPFLAGS) \
++ $(CLICKCFLAGS_NDEBUG) $(PACKAGE_CFLAGS) \
++ $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++
++packagesrcdir ?= $(srcdir)
++PACKAGE_OBJS ?= kpackage.ko
++
++CLICK_BUILDTOOL ?= $(clickbindir)/click-buildtool
++CLICK_ELEM2PACKAGE ?= $(CLICK_BUILDTOOL) elem2package $(ELEM2PACKAGE_INCLUDES)
++
++quiet_cmd_cxxcompile = CXX $(quiet_modtag) $(subst $(obj)/,,$@)
++cmd_cxxcompile = $(CXXCOMPILE) -c -o $@ $<
++
++quiet_cmd_ccompile = CC $(quiet_modtag) $(subst $(obj)/,,$@)
++cmd_ccompile = $(COMPILE) -c -o $@ $<
++
++EXTRA_CFLAGS += $(CLICKCPPFLAGS) $(CLICKCFLAGS_NDEBUG) $(CLICKDEFS) $(CLICKINCLUDES)
++
++ifneq ($(KBUILD_EXTMOD),)
++ifeq ($(srcdir),.)
++top_srcdir := $(src)/..
++srcdir := $(src)
++else
++ifneq ($(patsubst /%,/,$(srcdir)),/)
++top_srcdir := $(obj)/$(top_srcdir)
++srcdir := $(obj)/$(srcdir)
++endif
++top_builddir := $(obj)/$(top_builddir)
++builddir := $(obj)
++endif
++
++-include $(obj)/kelements.mk
++
++$(package)-objs := $(ELEMENT_OBJS) $(PACKAGE_OBJS) kversion.ko
++endif
++
++obj-m += $(package).o
++
++$(obj)/kelements.conf: $(CLICK_BUILDTOOL)
++ echo $(packagesrcdir) | $(CLICK_BUILDTOOL) findelem -r linuxmodule -r $(package) -P $(CLICKFINDELEMFLAGS) > $(obj)/kelements.conf
++$(obj)/kelements.mk: $(obj)/kelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_BUILDTOOL) elem2make -t linuxmodule < $(obj)/kelements.conf > $(obj)/kelements.mk
++$(obj)/kpackage.ko: $(obj)/kpackage.cc
++ $(call if_changed_dep,cxxcompile)
++$(obj)/kpackage.cc: $(obj)/kelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_ELEM2PACKAGE) $(package) < $(obj)/kelements.conf > $(obj)/kpackage.cc
++ @rm -f $(obj)/kpackage.kd
++$(obj)/kversion.ko: $(obj)/kversion.c
++ $(call if_changed_dep,ccompile)
++$(obj)/kversion.c: $(CLICK_BUILDTOOL)
++ $(CLICK_BUILDTOOL) kversion $(KVERSIONFLAGS) > $(obj)/kversion.c
++
++DEPFILES := $(wildcard *.kd)
++ifneq ($(DEPFILES),)
++include $(DEPFILES)
++endif
++
++.PHONY: clean elemlist
+diff -Nurb click-1.6.0/inst/share/click/pkg-linuxmodule.mk click-1.6.0-27/inst/share/click/pkg-linuxmodule.mk
+--- click-1.6.0/inst/share/click/pkg-linuxmodule.mk 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/pkg-linuxmodule.mk 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,115 @@
++# pkg-linuxmodule.mk -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2006 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++CLICKBUILD = linuxmodule
++
++CC ?= $(CLICKKERNEL_CC)
++CPP ?= $(CLICKCPP)
++CXX ?= $(CLICKKERNEL_CXX)
++CXXCPP ?= $(CLICKCXXCPP)
++AR_CREATE ?= $(CLICKAR_CREATE)
++RANLIB ?= $(CLICKRANLIB)
++STRIP ?= $(CLICKSTRIP)
++
++CPPFLAGS ?= $(CLICKCPPFLAGS) -DCLICK_LINUXMODULE
++CFLAGS ?= $(CLICKCFLAGS_NDEBUG)
++CXXFLAGS ?= $(CLICKCXXFLAGS_NDEBUG)
++DEPCFLAGS ?= $(CLICKDEPCFLAGS)
++
++DEFS ?= $(CLICKDEFS)
++INCLUDES ?= -I$(clickincludedir) -I$(clicksrcdir) -I$(clicklinuxdir)/include
++LDFLAGS ?= $(CLICKLDFLAGS)
++
++packagesrcdir ?= $(srcdir)
++PACKAGE_OBJS ?= kpackage.ko
++
++CLICK_BUILDTOOL ?= $(clickbindir)/click-buildtool
++CLICK_ELEM2PACKAGE ?= $(CLICK_BUILDTOOL) elem2package $(ELEM2PACKAGE_INCLUDES)
++
++ifneq ($(CLICK_LINUXMODULE_2_6),1)
++
++CXXCOMPILE = $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(PACKAGE_CXXFLAGS) $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++CXXLD = $(CXX)
++CXXLINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@
++COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(PACKAGE_CFLAGS) $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++CCLD = $(CC)
++LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@
++FIXDEP = @-sed 's/\.o:/\.ko:/' < $*.d > $*.kd; /bin/rm -f $*.d
++
++ifeq ($(V),1)
++ccompile = $(COMPILE) $(1)
++cxxcompile = $(CXXCOMPILE) $(1)
++else
++ccompile = @/bin/echo ' ' $(2) $< && $(COMPILE) $(1)
++cxxcompile = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(1)
++endif
++
++.SUFFIXES:
++.SUFFIXES: .c .cc .ko .kii
++
++.c.ko:
++ $(call ccompile,-c $< -o $@,CC)
++ $(FIXDEP)
++.cc.ko:
++ $(call cxxcompile,-c $< -o $@,CXX)
++ $(FIXDEP)
++.cc.kii:
++ $(call cxxcompile,-E $< > $@,CXXCPP)
++
++ifneq ($(MAKECMDGOALS),clean)
++-include kelements.mk
++endif
++
++OBJS = $(ELEMENT_OBJS) $(PACKAGE_OBJS) kversion.ko
++
++endif
++
++ifeq ($(CLICK_LINUXMODULE_2_6),1)
++# Jump through hoops to avoid missing symbol warnings
++$(package).ko: Makefile Kbuild always
++ { ( $(MAKE) -C $(clicklinuxdir) M=$(shell pwd) CLICK_PACKAGE_MAKING=linuxmodule-26 modules 2>&1 1>&3; echo $$? > .$(package).ko.status ) | grep -v '^\*\*\* Warning:.*undefined' 1>&2; } 3>&1; v=`cat .$(package).ko.status`; rm .$(package).ko.status; exit $$v
++Kbuild: $(CLICK_BUILDTOOL)
++ echo 'include $$(obj)/Makefile' > Kbuild
++ $(CLICK_BUILDTOOL) kbuild >> Kbuild
++else
++$(package).ko: $(clickdatadir)/pkg-linuxmodule.mk $(OBJS)
++ $(LD) -r -o $(package).ko $(OBJS)
++ $(STRIP) -g $(package).ko
++endif
++
++elemlist kelements.conf: $(CLICK_BUILDTOOL)
++ echo $(packagesrcdir) | $(CLICK_BUILDTOOL) findelem -r linuxmodule -r $(package) -P $(CLICKFINDELEMFLAGS) > kelements.conf
++kelements.mk: kelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_BUILDTOOL) elem2make -t linuxmodule < kelements.conf > kelements.mk
++kpackage.cc: kelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_ELEM2PACKAGE) $(package) < kelements.conf > kpackage.cc
++ @rm -f kpackage.kd
++kversion.c: $(CLICK_BUILDTOOL)
++ $(CLICK_BUILDTOOL) kversion $(KVERSIONFLAGS) > kversion.c
++
++DEPFILES := $(wildcard *.kd)
++ifneq ($(DEPFILES),)
++include $(DEPFILES)
++endif
++
++always:
++ @:
++clean:
++ -rm -f $(package).ko .$(package).ko.status
++ -rm -f *.kd *.ko kelements.conf kelements.mk kpackage.cc kversion.c Kbuild
++ -rm -f .*.o.cmd .*.ko.cmd $(package).mod.c $(package).mod.o $(package).o
++ -rm -rf .tmp_versions
++
++.PHONY: clean elemlist always
+diff -Nurb click-1.6.0/inst/share/click/pkg-userlevel.mk click-1.6.0-27/inst/share/click/pkg-userlevel.mk
+--- click-1.6.0/inst/share/click/pkg-userlevel.mk 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/pkg-userlevel.mk 2009-02-05 10:20:41.000000000 -0500
+@@ -0,0 +1,96 @@
++# pkg-userlevel.mk -- build tools for Click
++# Eddie Kohler
++#
++# Copyright (c) 2006-2007 Regents of the University of California
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++CLICKBUILD = userlevel
++
++CC ?= $(CLICKCC)
++CPP ?= $(CLICKCPP)
++CXX ?= $(CLICKCXX)
++CXXCPP ?= $(CLICKCXXCPP)
++AR_CREATE ?= $(CLICKAR_CREATE)
++RANLIB ?= $(CLICKRANLIB)
++STRIP ?= $(CLICKSTRIP)
++
++CPPFLAGS ?= $(CLICKCPPFLAGS) -DCLICK_USERLEVEL
++CFLAGS ?= $(CLICKCFLAGS) -fPIC
++CXXFLAGS ?= $(CLICKCXXFLAGS) -fPIC
++DEPCFLAGS ?= $(CLICKDEPCFLAGS)
++
++DEFS ?= $(CLICKDEFS)
++INCLUDES ?= $(CLICKINCLUDES)
++LDFLAGS ?= $(CLICKLDMODULEFLAGS)
++
++packagesrcdir ?= $(srcdir)
++PACKAGE_OBJS ?= upackage.uo
++
++CLICK_BUILDTOOL ?= $(clickbindir)/click-buildtool
++CLICK_ELEM2PACKAGE ?= $(CLICK_BUILDTOOL) elem2package $(ELEM2PACKAGE_INCLUDES)
++STRIP_UPACKAGE ?= true
++
++CXXCOMPILE = $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(PACKAGE_CXXFLAGS) $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++CXXLD = $(CXX)
++CXXLINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@
++COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(PACKAGE_CFLAGS) $(DEFS) $(INCLUDES) $(DEPCFLAGS)
++CCLD = $(CC)
++LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@
++FIXDEP = @-sed 's/\.o:/\.uo:/' < $*.d > $*.ud; /bin/rm -f $*.d
++
++ifeq ($(V),1)
++ccompile = $(COMPILE) $(1)
++cxxcompile = $(CXXCOMPILE) $(1)
++else
++ccompile = @/bin/echo ' ' $(2) $< && $(COMPILE) $(1)
++cxxcompile = @/bin/echo ' ' $(2) $< && $(CXXCOMPILE) $(1)
++endif
++
++.SUFFIXES:
++.SUFFIXES: .c .cc .uo .uii
++
++.c.uo:
++ $(call ccompile,-c $< -o $@,CC)
++ $(FIXDEP)
++.cc.uo:
++ $(call cxxcompile,-c $< -o $@,CXX)
++ $(FIXDEP)
++.cc.uii:
++ $(call cxxcompile,-E $< > $@,CXXCPP)
++
++ifneq ($(MAKECMDGOALS),clean)
++-include uelements.mk
++endif
++
++OBJS = $(ELEMENT_OBJS) $(PACKAGE_OBJS)
++
++$(package).uo: $(clickdatadir)/pkg-userlevel.mk $(OBJS)
++ $(CXXLINK) -o $(package).uo $(OBJS) $(ELEMENT_LIBS)
++ $(STRIP_UPACKAGE) $(package).uo
++
++elemlist uelements.conf: $(CLICK_BUILDTOOL)
++ echo $(packagesrcdir) | $(CLICK_BUILDTOOL) findelem -r userlevel -r $(package) -P $(CLICKFINDELEMFLAGS) > uelements.conf
++uelements.mk: uelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_BUILDTOOL) elem2make -t userlevel < uelements.conf > uelements.mk
++upackage.cc: uelements.conf $(CLICK_BUILDTOOL)
++ $(CLICK_ELEM2PACKAGE) $(package) < uelements.conf > upackage.cc
++ @rm -f upackage.ud
++
++DEPFILES := $(wildcard *.ud)
++ifneq ($(DEPFILES),)
++include $(DEPFILES)
++endif
++
++clean:
++ -rm -f *.ud *.uo uelements.conf uelements.mk upackage.cc $(package).uo
++
++.PHONY: clean elemlist
+diff -Nurb click-1.6.0/inst/share/click/srcdir click-1.6.0-27/inst/share/click/srcdir
+--- click-1.6.0/inst/share/click/srcdir 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/click/srcdir 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1 @@
++/d/click/click-1.6.0-27
+diff -Nurb click-1.6.0/inst/share/info/click.info click-1.6.0-27/inst/share/info/click.info
+--- click-1.6.0/inst/share/info/click.info 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/info/click.info 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,2656 @@
++This is click.info, produced by makeinfo version 4.8 from
++../../doc/click.texi.
++
++INFO-DIR-SECTION Click modular router
++START-INFO-DIR-ENTRY
++* Click: (click). The Click modular router programming manual.
++END-INFO-DIR-ENTRY
++
++\1f
++File: click.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir)
++
++Click
++*****
++
++This document describes the Click modular router's programming
++interface. Read this if you're interested in writing new elements for
++Click. You shouldn't need to read it if you are just building routers
++that use existing elements.
++
++ Most of Click's programming interface documentation is now stored in
++the source code as structured comments. The formatted documentation is
++on the Web: <http://www.read.cs.ucla.edu/click/doxygen>
++
++* Menu:
++
++* Overview::
++* Helper Classes::
++* Packets::
++* Tasks::
++* Timers::
++* Notification::
++* Coding Standards::
++* Index:: Index.
++
++ --- The Detailed Node Listing ---
++
++Overview
++
++* Packet Transfer::
++
++Helper Classes
++
++* ErrorHandler::
++
++ErrorHandler
++
++* ErrorHandler Initialization::
++* Reporting Errors::
++* Error Format Strings::
++* Counting Errors::
++* Basic ErrorHandlers::
++* Error Veneers::
++* Writing ErrorHandlers::
++
++Packets
++
++* Packet Structure and Contents::
++* Packet Creation::
++* Packets and sk_buffs::
++* Packet Sharing::
++* Packet Buffer Manipulation::
++* Annotations::
++* Packet Out-of-Memory::
++* Handlers::
++
++Annotations
++
++* Header Annotations::
++* User Annotations::
++* Specific User Annotations::
++* Other Annotations::
++* Annotations In General::
++
++Other Annotations
++
++* Destination Address Annotation::
++* Timestamp Annotation::
++* Device Annotation::
++* Packet Type Annotation::
++* Performance Counter Annotation::
++
++Handlers
++
++* Read and Write Handler Overview::
++* Adding Handlers::
++* Default Handlers::
++* Accessing Handlers Internally::
++* LLRPC Overview::
++
++Accessing Handlers Internally
++
++* Handler Objects::
++* Handlers By Name or Index::
++
++Tasks
++
++* Task Initialization::
++* Scheduling Tasks::
++* Tickets::
++* Task Thread Choice::
++* Task Status::
++* Task Handlers::
++* Task Cleanup::
++
++Timers
++
++* Timer Initialization::
++* Scheduling Timers::
++* Timer Status Methods::
++* Timer Cleanup::
++
++Coding Standards
++
++* Upper and lower case names::
++* Common name patterns::
++
++\1f
++File: click.info, Node: Overview, Next: Helper Classes, Prev: Top, Up: Top
++
++1 Overview
++**********
++
++* Menu:
++
++* Packet Transfer::
++
++\1f
++File: click.info, Node: Packet Transfer, Prev: Overview, Up: Overview
++
++1.1 Packet Transfer
++===================
++
++\1f
++File: click.info, Node: Helper Classes, Next: Packets, Prev: Overview, Up: Top
++
++2 Helper Classes
++****************
++
++* Menu:
++
++* ErrorHandler::
++
++\1f
++File: click.info, Node: ErrorHandler, Prev: Helper Classes, Up: Helper Classes
++
++2.1 ErrorHandler
++================
++
++All Click error messages are passed to an instance of the
++`ErrorHandler' class. `ErrorHandler' separates the generation of error
++messages from the particular way those messages should be printed. It
++also makes it easy to automatically decorate errors with context
++information.
++
++ Most Click users must know how to report errors to an
++`ErrorHandler', and how `ErrorHandler's count the messages they
++receive. This section also describes how to decorate error messages
++with error veneers, and how to write new `ErrorHandler's.
++
++ `ErrorHandler' and its important subclasses are defined in
++`<click/error.hh>'.
++
++* Menu:
++
++* ErrorHandler Initialization::
++* Reporting Errors::
++* Error Format Strings::
++* Counting Errors::
++* Basic ErrorHandlers::
++* Error Veneers::
++* Writing ErrorHandlers::
++
++\1f
++File: click.info, Node: ErrorHandler Initialization, Next: Reporting Errors, Prev: ErrorHandler, Up: ErrorHandler
++
++2.1.1 Class Initialization
++--------------------------
++
++The `ErrorHandler' class maintains some global state that must be
++initialized by calling `static_initialize' at the beginning of the
++program, and may be freed by calling `static_cleanup' when execution is
++complete.
++
++ -- Static Method on ErrorHandler: void static_initialize (ErrorHandler
++ *DEFAULT_ERRH)
++ Call this function exactly once, at the beginning of the program,
++ before any error messages are reported to any `ErrorHandler'. It
++ is OK to create arbitrary `ErrorHandler' objects before calling
++ this method, however. The DEFAULT_ERRH argument becomes the default
++ `ErrorHandler'; see *Note Basic ErrorHandlers::.
++
++ -- Static Method on ErrorHandler: void static_cleanup ()
++ Call this function exactly once, just before the program exits.
++ Destroys the default and silent `ErrorHandler's and cleans up other
++ `ErrorHandler'-related memory. It is an error to call any
++ `ErrorHandler' method after calling `static_cleanup'.
++
++\1f
++File: click.info, Node: Reporting Errors, Next: Error Format Strings, Prev: ErrorHandler Initialization, Up: ErrorHandler
++
++2.1.2 Reporting Errors
++----------------------
++
++`ErrorHandler''s basic error reporting methods take a format string,
++which may use `printf'-like `%' escape sequences, and additional
++arguments as required by the format string. *Note Error Format
++Strings::, for more details on the format string. The five methods
++differ in the seriousness of the error they report.
++
++ -- Method on ErrorHandler: void debug (const char *FORMAT, ...)
++ -- Method on ErrorHandler: void message (const char *FORMAT, ...)
++ -- Method on ErrorHandler: int warning (const char *FORMAT, ...)
++ -- Method on ErrorHandler: int error (const char *FORMAT, ...)
++ -- Method on ErrorHandler: int fatal (const char *FORMAT, ...)
++ Report the error described by FORMAT and any additional arguments.
++ The methods are listed by increasing seriousness. Use `debug' for
++ debugging messages that should not be printed in a production
++ environment; `message' for explanatory messages that do not
++ indicate errors; `warning' for warnings (this function prepends the
++ string `warning: ' to every line of the error message); `error'
++ for errors; and `fatal' for errors so serious that they should
++ halt the execution of the program. The three functions that
++ indicate errors, `warning', `error', and `fatal', always return
++ `-EINVAL'. In some environments, `fatal' will actually exit the
++ program with exit code 1.
++
++ Each of these methods has an analogue that additionally takes a
++"landmark": a string representing where the error took place. A typical
++landmark contains a file name and line number, separated by a
++colon--`foo.click:31', for example.
++
++ -- Method on ErrorHandler: void ldebug (const String &LANDMARK, const
++ char *FORMAT, ...)
++ -- Method on ErrorHandler: void lmessage (const String &LANDMARK,
++ const char *FORMAT, ...)
++ -- Method on ErrorHandler: int lwarning (const String &LANDMARK, const
++ char *FORMAT, ...)
++ -- Method on ErrorHandler: int lerror (const String &LANDMARK, const
++ char *FORMAT, ...)
++ -- Method on ErrorHandler: int lfatal (const String &LANDMARK, const
++ char *FORMAT, ...)
++ Report the error described by FORMAT and any additional arguments.
++ The error took place at LANDMARK. Most `ErrorHandler's will simply
++ prepend `LANDMARK: ' to each line of the error message.
++
++ These methods are all implemented as wrappers around the `verror'
++function. This function takes a landmark, a format string, a `va_list'
++packaging up any additional arguments, and a "seriousness value", which
++encodes how serious the error was. The `Seriousness' enumerated type,
++which is defined in the `ErrorHandler' class, represents seriousness
++values. There are five constants, corresponding to the five
++error-reporting methods:
++
++`ERR_DEBUG'
++ Corresponds to `debug' and `ldebug'.
++
++`ERR_MESSAGE'
++ Corresponds to `message' and `lmessage'.
++
++`ERR_WARNING'
++ Corresponds to `warning' and `lwarning'.
++
++`ERR_ERROR'
++ Corresponds to `error' and `lerror'.
++
++`ERR_FATAL'
++ Corresponds to `fatal' and `lfatal'.
++
++ -- Method on ErrorHandler: int verror (Seriousness SERIOUSNESS, const
++ String &LANDMARK, const char *FORMAT, va_list VAL)
++ Report the error described by FORMAT and VAL. The error took place
++ at LANDMARK, if LANDMARK is nonempty. The SERIOUSNESS value is one
++ of the five constants described above. Always returns `-EINVAL'.
++
++\1f
++File: click.info, Node: Error Format Strings, Next: Counting Errors, Prev: Reporting Errors, Up: ErrorHandler
++
++2.1.3 Format Strings
++--------------------
++
++`ErrorHandler''s format strings closely follow C's standard `printf'
++format strings. Most characters in the format string are printed
++verbatim. The `%' character introduces a "conversion", which prints
++data read from the remaining arguments. The format string may contain
++newlines `\n', but it need not end with a newline; `ErrorHandler' will
++add a final newline if one does not exist.
++
++ Each conversion, or formatting escape, follows this pattern:
++
++ * First, the `%' character introduces each conversion.
++
++ * Next comes zero or more "flag characters";
++
++ * then an optional "field width";
++
++ * then an optional "precision";
++
++ * then an optional "length modifier";
++
++ * and finally, the mandatory "conversion specifier", which is
++ usually a single character, but may be a name enclosed in braces.
++
++We discuss each of these is turn.
++
++ Any conversion may be modified by zero or more of these flag
++characters.
++
++`#'
++ The value should be converted to an "alternate form". For `o'
++ conversions, the first character of the output string is made `0',
++ by prepending a `0' if there was not one already. For `x' and `X'
++ conversions, nonzero values have `0x' or `0X' prepended,
++ respectively.
++
++`0'
++ The value should be zero padded. For `d', `i', `u', `o', `x', and
++ `X' conversions, the converted value is padded on the left with
++ `0' characters rather than spaces.
++
++`-'
++ The value should be left-justified within the field width.
++
++` ' (a space)
++ Leave a blank before a nonnegative number produced by a signed
++ conversion.
++
++`+'
++ Print a `+' character before a nonnegative number produced by a
++ signed conversion.
++
++
++ The optional "field width", a decimal digit string, forces the
++conversion to use a minimum number of characters. The result of a
++conversion is padded on the left with space characters to reach the
++minimum field width, unless one of the `0' or `-' flags was supplied.
++
++ The optional "precision" is a decimal digit string preceded by a
++period `.'. For `d', `i', `u', `o', `x', and `X' conversions, the
++precision specifies the minimum number of digits that must appear;
++results with fewer digits are padded on the left with `0' characters.
++For the `s' conversion, the precision specifies the maximum number of
++characters that can be printed. For `e', `f', `E', and `F' conversions,
++it specifies the number of digits to appear after the radix character;
++for `g' and `G' conversions, the number of significant digits.
++
++ If either the field width or precision is specified as a star `*',
++`ErrorHandler' reads the next argument as an integer and uses that
++instead.
++
++ Length modifiers affect the argument type read by the conversion.
++There are three modifiers:
++
++`h'
++ The next argument is a `short' or `unsigned short'. Affects the
++ `d', `i', `u', `o', `x', and `X' conversions.
++
++`l'
++ The next argument is a `long' or `unsigned long'. Affects the `d',
++ `i', `u', `o', `x', and `X' conversions.
++
++`ll'
++ The next argument is a `long long' or `unsigned long long'.
++ Affects the `d', `i', `u', `o', `x', and `X' conversions.
++
++ Finally, these are the conversions themselves.
++
++`s'
++ Print the `const char *' argument, treated as a C string.
++
++`c'
++ The `int' argument is treated as a character constant. Printable
++ ASCII characters (values between 32 and 126) are printed verbatim.
++ Characters `\n', `\t', `\r', and `\0' use those C escape
++ representations. Other characters use the representation `\%03o'.
++
++`d', `i'
++ The argument is an `int'; print its decimal representation.
++
++`u'
++ The argument is an `unsigned int'; print its decimal
++ representation.
++
++`o'
++ The argument is an `unsigned int'; print its octal representation.
++
++`x', `X'
++ The argument is an `unsigned int'; print its hexadecimal
++ representation. The `%x' conversion uses lowercase letters; `%X'
++ uses uppercase letters.
++
++`e', `f', `g', `E', `F', `G'
++ The argument is a `double'; print its representation as if by
++ `printf' (user-level drivers only).
++
++`p'
++ The `void *' argument is cast to `unsigned long' and printed as by
++ `%#lx'.
++
++`%'
++ Print a literal `%' character.
++
++`{element}'
++ The argument is an `Element *'. Print that element's declaration.
++
++
++ Note that `ErrorHandler' does not support the `n' conversion.
++
++\1f
++File: click.info, Node: Counting Errors, Next: Basic ErrorHandlers, Prev: Error Format Strings, Up: ErrorHandler
++
++2.1.4 Counting Errors
++---------------------
++
++`ErrorHandler' objects count the number of errors and warnings they
++have received and make those values available to the user.
++
++ -- Method on ErrorHandler: virtual int nwarnings () const
++ -- Method on ErrorHandler: virtual int nerrors () const
++ Returns the number of warnings or errors received by this
++ `ErrorHandler' so far.
++
++ -- Method on ErrorHandler: virtual void reset_counts ()
++ Resets the `nwarnings' and `nerrors' counters to zero.
++
++ These counters are typically used to determine whether an error has
++taken place in some complex piece of code. For example:
++
++ int before_nerrors = errh->nerrors();
++ // ... complex code that may report errors to `errh' ...
++ if (errh->nerrors() != before_nerrors) {
++ // an error has taken place
++ }
++
++\1f
++File: click.info, Node: Basic ErrorHandlers, Next: Error Veneers, Prev: Counting Errors, Up: ErrorHandler
++
++2.1.5 Basic `ErrorHandler's
++---------------------------
++
++Every Click error message eventually reaches some "basic"
++`ErrorHandler', which generally prints the messages it receives. The
++user-level driver's basic `ErrorHandler' prints error messages to
++standard error, while in the Linux kernel module, the basic
++`ErrorHandler' logs messages to the syslog and stores them for access
++via `/click/errors'.
++
++ Two basic `ErrorHandlers' are always accessible via static methods:
++the "default `ErrorHandler'", returned by `default_handler' and set by
++`set_default_handler'; and the "silent `ErrorHandler'", returned by
++`silent_handler', which ignores any error messages it receives.
++
++ -- Static Method on ErrorHandler: ErrorHandler * default_handler ()
++ Returns the default `ErrorHandler'.
++
++ -- Static Method on ErrorHandler: void set_default_handler
++ (ErrorHandler *errh)
++ Sets the default `ErrorHandler' to ERRH. The `static_initialize'
++ method also sets the default `ErrorHandler'; see *Note
++ ErrorHandler Initialization::.
++
++ -- Static Method on ErrorHandler: ErrorHandler * silent_handler ()
++ Returns the silent `ErrorHandler'. This handler ignores any error
++ messages it receives. It maintains correct `nwarnings' and
++ `nerrors' counts, however.
++
++ `FileErrorHandler', a kind of basic `ErrorHandler', is available in
++any user-level program. It prints every message it receives to some
++file, usually standard error. It can also prepend an optional context
++string to every line of every error message.
++
++ -- Constructor on FileErrorHandler: FileErrorHandler (FILE *F,
++ const String &PREFIX = "")
++ Constructs a `FileErrorHandler' that prints error messages to file
++ F. If PREFIX is nonempty, then every line of every error message
++ is prepended by PREFIX.
++
++\1f
++File: click.info, Node: Error Veneers, Next: Writing ErrorHandlers, Prev: Basic ErrorHandlers, Up: ErrorHandler
++
++2.1.6 Error Veneers
++-------------------
++
++"Error veneers" wrap around basic `ErrorHandler' objects and change how
++error text is generated. An error veneer generally changes each error
++message's text in some way, perhaps by adding a context message or some
++indentation. It then passes the altered text to the basic
++`ErrorHandler' for printing. Error veneers can be easily nested.
++
++ The first argument to each error veneer constructor is a pointer to
++another `ErrorHandler' object. The veneer will pass altered error text
++to this handler, the "base handler", for further processing and
++printing. It also delegates `nwarnings()' and `nerrors()' calls to the
++base handler.
++
++ Click comes with three error veneers: one for adding context, one for
++prepending text to every line, and one for supplying missing landmarks.
++It is easy to write others; see *Note Writing ErrorHandlers::, for
++details.
++
++ -- Constructor on ContextErrorHandler: ContextErrorHandler
++ (ErrorHandler *BASE_ERRH, const String &CONTEXT,
++ const String &INDENT = " ")
++ Constructs a `ContextErrorHandler' with BASE_ERRH as base.
++
++ The first time this handler receives an error message, it will
++ precede the message with the CONTEXT string--generally more
++ detailed information about where the error has occurred. Every
++ line in every received error message is prepended with INDENT, two
++ spaces by default, to set off the message from its context.
++
++ -- Constructor on PrefixErrorHandler: PrefixErrorHandler
++ (ErrorHandler *BASE_ERRH, const String &PREFIX)
++ Constructs a `PrefixErrorHandler' with BASE_ERRH as base.
++
++ This handler precedes every line of every error message with
++ PREFIX.
++
++ -- Constructor on LandmarkErrorHandler: LandmarkErrorHandler
++ (ErrorHandler *BASE_ERRH, const String &LANDMARK)
++ Constructs a `LandmarkErrorHandler' with BASE_ERRH as base.
++
++ This handler supplies LANDMARK in place of any blank landmark
++ passed to it. This will cause the base handler to include LANDMARK
++ in its error message.
++
++ To demonstrate these veneers in practice, we'll use the following
++function, which prints two error messages:
++
++ void f(ErrorHandler *errh) {
++ errh->error("First line\nSecond line");
++ errh->lwarning("here", "Third line");
++ }
++
++ A simple `FileErrorHandler' shows the base case.
++
++ FileErrorHandler errh1(stderr);
++ f(&errh1);
++ -| First line
++ -| Second line
++ -| here: warning: Third line
++
++ The simplest error veneer, `PrefixErrorHandler', just prepends text
++to every line.
++
++ PrefixErrorHandler errh2(&errh1, "prefix - ");
++ f(&errh2);
++ -| prefix - First line
++ -| prefix - Second line
++ -| prefix - here: warning: Third line
++
++ `ContextErrorHandler' supplies a line of context before the first
++error message, and indents all messages except the context.
++
++ ContextErrorHandler errh3(&errh1, "This was called from ...", "** ");
++ f(&errh3);
++ -| This was called from ...
++ -| ** First line
++ -| ** Second line
++ -| here: ** warning: Third line
++
++Note that the indentation `** ' is printed after the landmark. This
++often looks better than the alternative.
++
++ Of course, an error veneer can take another error veneer as its "base
++handler", leading to cumulative effects.
++
++ ContextErrorHandler errh4(&errh2, "This was called from ...", "** ");
++ f(&errh4);
++ -| prefix - This was called from ...
++ -| prefix - ** First line
++ -| prefix - ** Second line
++ -| prefix - here: ** warning: Third line
++
++\1f
++File: click.info, Node: Writing ErrorHandlers, Prev: Error Veneers, Up: ErrorHandler
++
++2.1.7 Writing `ErrorHandler's
++-----------------------------
++
++`ErrorHandler' constructs an error message using three virtual
++functions. The first, `make_text', parses a format string and argument
++list into a single `String'. This is passed to the second function,
++`decorate_text', which may transform the string. The final function,
++`handle_text', prints the resulting error message. This structure
++makes `ErrorHandler' easy to extend. To write a new basic
++`ErrorHandler', you will need to override just `handle_text' and the
++counting functions (`nwarnings', `nerrors', and `reset_counts'). The
++`ErrorVeneer' helper class, described below, lets you override just
++`decorate_text' when writing an error veneer.
++
++ -- Method on ErrorHandler: virtual String make_text (Seriousness S,
++ const char *FORMAT, va_list VAL)
++ Parses the format string FORMAT with arguments from VAL, returning
++ the results as a STRING object.
++
++ The default implementation processes the formatting escapes
++ described above (*note Error Format Strings::). It also prepends
++ every line of the error message with `warning: ' if S equals
++ `ERR_WARNING'.
++
++ -- Method on ErrorHandler: virtual String decorate_text (Seriousness
++ S, const String &PREFIX, const String &LANDMARK, const String
++ &TEXT)
++ Decorates the error message TEXT as appropriate and returns the
++ result. At minimum, every line of the result should be prepended by
++ PREFIX and, if it is nonempty, the landmark string LANDMARK.
++
++ The default implementation creates lines like this:
++
++ PREFIXLANDMARK: TEXT (if LANDMARK is nonempty)
++ PREFIXTEXT (if LANDMARK is empty)
++
++ Any spaces and/or a final colon are stripped from the end of
++ LANDMARK. Special landmarks, which begin and end with a backslash
++ `\', are ignored.
++
++ -- Method on ErrorHandler: virtual void handle_text
++ (Seriousness S, const String &TEXT)
++ This method is responsible for printing or otherwise informing the
++ user about the error message TEXT. If S equals `ERR_FATAL', the
++ method should exit the program or perform some other drastic
++ action. It should also maintain the `nwarnings()' and `nerrors()'
++ counters. In most cases, it should ensure that the last character
++ in TEXT is a newline.
++
++ This method has no default implementation.
++
++ The `ErrorVeneer' class, a subclass of `ErrorHandler', supplies
++default implementations for these functions that ease the construction
++of new error veneers. `ErrorVeneer''s single instance variable,
++`ErrorHandler *_errh', is the base handler. `ErrorVeneer' overrides
++all the relevant virtual functions--`nwarnings', `nerrors',
++`reset_counts', `make_text', `decorate_text', and `handle_text'. Its
++versions simply delegate to the corresponding methods on `_errh'. An
++error veneer designer will generally subclass `ErrorVeneer' rather than
++`ErrorHandler'; then she will override only the methods she cares about
++(usually `decorate_text'), relying on `ErrorVeneer''s default
++implementations for the rest.
++
++ -- Constructor on ErrorVeneer: ErrorVeneer (ErrorHandler *BASE_ERRH)
++ Constructs an `ErrorVeneer' helper class with BASE_ERRH as its
++ base error handler. This constructor simply sets `_errh =
++ base_errh'.
++
++\1f
++File: click.info, Node: Packets, Next: Tasks, Prev: Helper Classes, Up: Top
++
++3 Packets
++*********
++
++The `Packet' class represents Click packets. The single `Packet'
++interface has multiple implementations, one per driver. Inside the
++Linux kernel driver, a `Packet' object is equivalent to a Linux
++`sk_buff' structure; most `Packet' methods are inline functions that
++expand to `sk_buff' calls. The user-level driver, however, uses a
++purpose-built `Packet' implementation.
++
++ Click packets separate header information from data. The `Packet *'
++pointer points to a header structure, which holds pointers to the
++actual packet data and a set of "annotations". Packet data may be
++shared by two or more packet headers. Packet headers, however, should
++never be shared.
++
++ Packets come in two flavors, `Packet' and `WritablePacket'. A
++`Packet' object represents a packet header whose data might be shared
++with other packets. Because of this potential sharing, `Packet' data is
++read-only, and its methods return `const' pointers to data. A
++`WritablePacket' object, in contrast, represents a packet header whose
++data is known not to be shared. Its methods return non-`const'
++pointers. The `uniqueify' method turns a `Packet' into a
++`WritablePacket', possibly by making a copy of the packet's data.
++`WritablePacket' is a subclass of `Packet', so you can turn a
++`WritablePacket' into a `Packet' implicitly.
++
++ The `Packet' and `WritablePacket' classes are defined in
++`<click/packet.hh>'.
++
++* Menu:
++
++* Packet Structure and Contents::
++* Packet Creation::
++* Packets and sk_buffs::
++* Packet Sharing::
++* Packet Buffer Manipulation::
++* Annotations::
++* Packet Out-of-Memory::
++* Handlers::
++
++\1f
++File: click.info, Node: Packet Structure and Contents, Next: Packet Creation, Prev: Packets, Up: Packets
++
++3.1 Structure and Contents
++==========================
++
++Packet data is stored in a single flat array of bytes. There is no
++support for linked chains a` la BSD `mbuf'. The actual packet data is
++embedded inside a buffer that may be much larger, leaving unused spaces
++called "headroom" and "tailroom" before and after the data proper.
++Therefore, tasks like prepending a header need not always reallocate
++memory. If the headroom is big enough, prepending space for a new
++header just requires bumping a pointer.
++
++ This diagram shows how a typical packet is laid out, with the
++relevant `Packet' methods' names.
++
++ data
++ |<- headroom ->|<----- length ----->|<- tailroom ->|
++ | | | |
++ +==============+====================+==============+
++ |XXXXXXXXXXXXXX| PACKET CONTENTS... |XXXXXXXXXXXXXX|
++ +==============+====================+==============+
++ | |
++ |<---------------- buffer_length ----------------->|
++ buffer_data
++
++
++ And here are those methods' descriptions.
++
++ -- Method on Packet: const unsigned char * data () const
++ Returns a pointer to the packet data proper.
++
++ -- Method on Packet: unsigned length () const
++ Returns the length of the packet data proper.
++
++ -- Method on Packet: const unsigned char * buffer_data () const
++ Returns a pointer to the buffer that contains the packet data.
++
++ -- Method on Packet: unsigned headroom () const
++ -- Method on Packet: unsigned tailroom () const
++ -- Method on Packet: unsigned buffer_length () const
++ Returns the length of the headroom area, the tailroom area, and the
++ whole buffer, respectively.
++
++ -- Method on WritablePacket: unsigned char * data () const
++ -- Method on WritablePacket: unsigned char * buffer_data () const
++ These `WritablePacket' methods are identical to `Packet''s `data'
++ and `buffer_data' methods except for their non-`const' return type.
++
++ Two invariants relate these methods' values:
++
++ buffer_length() = headroom() + length() + tailroom()
++ data() = buffer_data() + headroom()
++
++\1f
++File: click.info, Node: Packet Creation, Next: Packets and sk_buffs, Prev: Packet Structure and Contents, Up: Packets
++
++3.2 Creation and Destruction
++============================
++
++Packets are created with the `Packet::make' static methods, and
++destroyed with the `Packet::kill' method. (The `Packet' and
++`WritablePacket' classes have private constructors and destructors; you
++cannot create or destroy packets with `new' or `delete'.)
++
++3.2.1 `Packet::make'
++--------------------
++
++The `make' methods always take the length of the packet data; some of
++them take the packet contents and the headroom and tailroom lengths as
++well. (The contents of any headroom and tailroom areas are always
++undefined.) Most of them return a `WritablePacket *', since new packets
++are not shared.
++
++ The `Packet' class defines two constants related to packet creation,
++`DEFAULT_HEADROOM' and `MIN_BUFFER_LENGTH'. Those `make' methods that
++do not take an explicit headroom parameter use `DEFAULT_HEADROOM'
++instead. Furthermore, no `make' method will create a packet with buffer
++length less than `MIN_BUFFER_LENGTH'. If the sum of a packet's
++headroom and length is less than this, the packet buffer is given extra
++tailroom to bump the buffer length up to `MIN_BUFFER_LENGTH'. These
++constants have the values `DEFAULT_HEADROOM' = 28 and
++`MIN_BUFFER_LENGTH' = 64.
++
++ -- Static Method on Packet: WritablePacket * make (unsigned LEN)
++ Returns a new packet containing LEN bytes of undefined data.
++
++ -- Static Method on Packet: WritablePacket * make
++ (const char *DATA, unsigned LEN)
++ -- Static Method on Packet: WritablePacket * make
++ (const unsigned char *DATA, unsigned LEN)
++ Returns a new packet whose contents equal the first LEN bytes of
++ DATA. DATA may be a null pointer, in which case the packet
++ contains LEN bytes of undefined data.
++
++ -- Static Method on Packet: WritablePacket * make (unsigned HEADROOM,
++ const unsigned char *DATA, unsigned LEN, unsigned TAILROOM)
++ Returns a new packet containing HEADROOM bytes of headroom, LEN
++ bytes of contents, and at least TAILROOM bytes of tailroom. The
++ packet contents will equal the first LEN bytes of DATA unless DATA
++ is a null pointer, in which case the contents are undefined.
++
++ The following `make' method is only available in the user-level
++driver.
++
++ -- Static Method on Packet: WritablePacket * make
++ (unsigned char *DATA, unsigned LEN,
++ void (*DESTRUCTOR)(unsigned char *, size_t))
++ Returns a new packet that uses DATA as a buffer. That is, the new
++ packet will have the following characteristics:
++
++ `buffer_data' DATA
++ `buffer_length' LEN
++ `headroom' 0
++ `length' LEN
++ `tailroom' 0
++
++ When the resulting packet is destroyed, the function DESTRUCTOR
++ will be called with DATA and LEN as arguments. DESTRUCTOR may be
++ a null pointer, in which case `Packet' calls `delete[] DATA'
++ instead.
++
++ This method lets a user-level element manage packet memory itself,
++ rather than relying on `Packet'.
++
++*Note Packets and sk_buffs::, for a `make' method only available in the
++Linux kernel driver.
++
++3.2.2 `Packet::kill'
++--------------------
++
++To destroy a `Packet', simply call its `kill' method.
++
++ -- Method on Packet: void kill ()
++ Frees this packet. If this packet contained the last reference to
++ its data buffer, then frees the data buffer as well.
++
++\1f
++File: click.info, Node: Packets and sk_buffs, Next: Packet Sharing, Prev: Packet Creation, Up: Packets
++
++3.3 `Packet's and `sk_buff's
++============================
++
++In the Linux kernel driver, `Packet' objects are equivalent to `struct
++sk_buff's. This avoids indirection overhead and makes it cheap to pass
++packets back and forth between Linux and Click. The `Packet' operations
++described in this section are mostly inline functions that expand to
++conventional `sk_buff' calls like `skb_clone()'.
++
++ Click `Packet' `sk_buff's should always have `skb->users' equal to
++1. That is, the `sk_buff' headers should not be shared, although the
++data buffers they point to may be shared.
++
++ The `make', `skb', and `steal_skb' methods described in this section
++convert `Packet's to `sk_buff's and vice versa.
++
++ -- Static Method on Packet: Packet * make (struct sk_buff *SKB)
++ Returns a new packet equivalent to the `sk_buff' SKB. All of SKB's
++ data pointers and annotations are left unchanged. This method
++ generally does nothing, since `Packet's and `sk_buff's are
++ equivalent in the Linux kernel. However, if `SKB->users' field is
++ bigger than 1, the method will return a clone of SKB. This method
++ returns a `Packet *', not a `WritablePacket *', because the SKB
++ argument might share data with some other `sk_buff'.
++
++ Do not use or manipulate SKB after passing it to this method,
++ since Click and the `Packet' implementation now own SKB.
++
++ -- Method on Packet: struct sk_buff * skb ()
++ -- Method on Packet: const struct sk_buff * skb () const
++ Returns the `sk_buff' corresponding to this packet. Use this method
++ to examine the `sk_buff' version of a `Packet'.
++
++ Do not pass the result to a function that might free it or
++ increment its `users' field; use `steal_skb' for that.
++
++ -- Method on Packet: struct sk_buff * steal_skb ()
++ Returns the `sk_buff' corresponding to this packet. Use this
++ method to permanently change a `Packet' into an `sk_buff'--for
++ example, to create an `sk_buff' you'd like to send to Linux.
++
++ Do not use or manipulate a `Packet' after calling its `steal_skb'
++ method, since Linux now owns the resulting `sk_buff'.
++
++\1f
++File: click.info, Node: Packet Sharing, Next: Packet Buffer Manipulation, Prev: Packets and sk_buffs, Up: Packets
++
++3.4 Sharing--`clone' and `uniqueify'
++====================================
++
++The `clone' method creates a new packet header that shares data with an
++existing packet. The `uniqueify' method, in contrast, ensures that a
++packet's data is not shared by anyone, perhaps by making a copy of the
++data.
++
++ -- Method on Packet: Packet * clone ()
++ Creates and returns a new packet header that shares this packet's
++ data. The new packet's annotations are copied from this packet's
++ annotations.
++
++ The result may be a null pointer if there was not enough memory to
++ make a new packet header.
++
++ -- Method on Packet: WritablePacket * uniqueify ()
++ Ensures that this packet does not share data with any other
++ packet. This may involve copying the packet data, and perhaps
++ creating a new packet header, but if this packet is already
++ unshared, no real work is required. Returns a `WritablePacket *'
++ because the new packet is unshared.
++
++ Do not use, manipulate, or free a `Packet' after calling its
++ `uniqueify' method. Manipulate the returned `WritablePacket *'
++ instead.
++
++ The result may be a null pointer if there was not enough memory to
++ make a required data copy. In this case, the old packet is freed.
++
++ -- Method on Packet: bool shared () const
++ Returns true if and only if this packet shares data with some other
++ packet.
++
++\1f
++File: click.info, Node: Packet Buffer Manipulation, Next: Annotations, Prev: Packet Sharing, Up: Packets
++
++3.5 Buffer Manipulation--`push', `pull', `put', and `take'
++==========================================================
++
++The `push', `pull', `put', and `take' methods manipulate a packet's
++contents by adding or removing space from its headroom or tailroom.
++Given a packet, use `push' to add space to its beginning, `pull' to
++remove space from its beginning, `put' to add space to its end, and
++`take' to remove space from its end. The methods that add space, `push'
++and `put', uniqueify the relevant packet as a side effect. This ensures
++that the packet's data is unshared so you can immediately manipulate
++the added space.
++
++ -- Method on Packet: WritablePacket * push (unsigned AMT)
++ Adds AMT bytes of space to the beginning of the packet's data and
++ returns the resulting packet. The new space is uninitialized. The
++ result will not share data with any other packet; thus, it is a
++ `WritablePacket *'. If this packet is unshared and its headroom is
++ bigger than AMT, then this operation is cheap, amounting to a bit
++ of pointer arithmetic. Otherwise, it requires copying the packet
++ data and possibly creating a new packet header.
++
++ Do not use, manipulate, or free a `Packet' after calling its
++ `push' method. Manipulate the returned `WritablePacket *' instead.
++
++ The result may be a null pointer if there was not enough memory to
++ make a required new packet. In this case, the old packet is freed.
++
++ -- Method on Packet: void pull (unsigned AMT)
++ Removes AMT bytes of space from the beginning of the packet's
++ data. AMT must be less than or equal to the packet's `length()'.
++ This operation is always cheap, amounting to a bit of pointer
++ arithmetic.
++
++ -- Method on Packet: WritablePacket * put (unsigned AMT)
++ Adds AMT bytes of space to the end of the packet's data and
++ returns the resulting packet. The new space is uninitialized. The
++ result will not share data with any other packet; thus, it is a
++ `WritablePacket *'. If this packet is unshared and its tailroom is
++ bigger than AMT, then this operation is cheap, amounting to a bit
++ of pointer arithmetic. Otherwise, it requires copying the packet
++ data and possibly creating a new packet header.
++
++ Do not use, manipulate, or free a `Packet' after calling its `put'
++ method. Manipulate the returned `WritablePacket *' instead.
++
++ The result may be a null pointer if there was not enough memory to
++ make a required new packet. In this case, the old packet is freed.
++
++ -- Method on Packet: void take (unsigned AMT)
++ Removes AMT bytes of space from the end of the packet's data. AMT
++ must be less than or equal to the packet's `length()'. This
++ operation is always cheap, amounting to a bit of pointer
++ arithmetic.
++
++ The `push' and `put' methods have "nonunique" variants,
++`nonunique_push' and `nonunique_put', which do not have the side effect
++of uniqueifying their resulting packet. These methods are rarely used.
++
++ -- Method on Packet: Packet * nonunique_push (unsigned AMT)
++ Adds AMT bytes of space to the beginning of the packet's data and
++ returns the resulting packet. The new space is uninitialized. The
++ result may share data with other packets. If this packet's
++ headroom is bigger than AMT, then this operation is cheap,
++ amounting to a bit of pointer arithmetic. Otherwise, it requires
++ copying the packet data and possibly creating a new packet header.
++
++ Do not use, manipulate, or free a `Packet' after calling its
++ `nonunique_push' method. Manipulate the returned `Packet *'
++ instead.
++
++ The result may be a null pointer if there was not enough memory to
++ make a required new packet. In this case, the old packet is freed.
++
++ -- Method on Packet: Packet * nonunique_put (unsigned AMT)
++ Adds AMT bytes of space to the end of the packet's data, returning
++ the resulting packet. The new space is uninitialized. The result
++ may share data with other packets. If this packet's tailroom is
++ bigger than AMT, then this operation is cheap, amounting to a bit
++ of pointer arithmetic. Otherwise, it requires copying the packet
++ data and possibly creating a new packet header.
++
++ Do not use, manipulate, or free a `Packet' after calling its
++ `nonunique_put' method. Manipulate the returned `Packet *' instead.
++
++ The result may be a null pointer if there was not enough memory to
++ make a required new packet. In this case, the old packet is freed.
++
++\1f
++File: click.info, Node: Annotations, Next: Packet Out-of-Memory, Prev: Packet Buffer Manipulation, Up: Packets
++
++3.6 Annotations
++===============
++
++Each packet header has space for a number of "annotations", extra
++information about the packet that is not contained in its data. Click
++supports "header annotations", which indicate where in the packet a
++network header, such as an IP header, is located; "user annotations",
++whose semantics are left undefined by Click--different elements can
++treat them in different ways; and other specialized annotations, such
++as the "timestamp annotation", the "destination IP address annotation",
++and so forth.
++
++ New packets begin with all annotations cleared: numeric annotations
++are zero, pointer annotations are null pointers. `clone', `uniqueify',
++and their equivalents always copy each of the original packet's
++annotations in the appropriate way. (For example, the new header
++annotations will point into the new data, if a data copy was made.)
++
++* Menu:
++
++* Header Annotations::
++* User Annotations::
++* Specific User Annotations::
++* Other Annotations::
++* Annotations In General::
++
++\1f
++File: click.info, Node: Header Annotations, Next: User Annotations, Prev: Annotations, Up: Annotations
++
++3.6.1 Header Annotations
++------------------------
++
++Many packets contain a network header of some kind, such as an IP
++header. This header may be located anywhere in the packet depending on
++how the packet was encapsulated. Furthermore, the data encapsulated by
++that network header may be located anywhere after the network header,
++given the presence of options. With the "network header annotation" and
++the "transport header annotation", one element can determine where a
++network header is and how long it is, then store this information for
++other elements to use. For example, the `CheckIPHeader' element sets
++the header annotations on packets it receives. Elements like
++`SetIPDSCP' then require a non-null IP header annotation on their input
++packets.
++
++ The header annotations on new packets are each set to a null pointer.
++
++ -- Method on Packet: const unsigned char * network_header () const
++ -- Method on WritablePacket: unsigned char * network_header () const
++ Returns the network header annotation. The resulting pointer is
++ read-only on `Packet's and read/write on `WritablePacket's.
++
++ -- Method on Packet: const unsigned char * transport_header () const
++ -- Method on WritablePacket: unsigned char * transport_header () const
++ Returns the transport header annotation. The resulting pointer is
++ read-only on `Packet's and read/write on `WritablePacket's.
++
++ -- Method on Packet: int network_header_offset () const
++ Returns the offset from `data()' to `network_header()'. The result
++ might be negative, since the `data' pointer may have been advanced
++ past the network header annotation with the `pull' method.
++
++ -- Method on Packet: int network_header_length () const
++ Returns the network header's length. This equals
++ `transport_header()' - `network_header()'.
++
++ -- Method on Packet: unsigned transport_header_offset () const
++ Returns the offset from `data()' to `transport_header()'. The
++ result might be negative, since the `data' pointer may have been
++ advanced past the transport header annotation with the `pull'
++ method.
++
++ Several invariants relate these methods' values whenever the header
++annotations are non-null:
++
++ `buffer_data()' <= `network_header()' <= `transport_header()'
++ <= `buffer_data()' + `buffer_length()'
++ `network_header_offset()' = `network_header()' - `data()'
++ `transport_header_offset()' = `transport_header()' - `data()'
++ `network_header_length()' = `transport_header()' - `network_header()'
++
++
++ Set the network and transport header annotations simultaneously with
++the `set_network_header' method.
++
++ -- Method on Packet: void set_network_header
++ (const unsigned char *HEADER, unsigned LEN)
++ Sets the network header annotation to HEADER, which must lie
++ between `buffer_data()' and `buffer_data()' + `buffer_length()'.
++ The network header is LEN bytes long, so `network_header_length()'
++ will equal LEN and `transport_header()' will equal HEADER + LEN.
++
++3.6.1.1 Typed Header Annotations
++................................
++
++For convenience, `Packet' provides methods for accessing and setting
++the network header annotation as an IP or IPv6 header. These methods
++use the same annotations as the generic `network_header' methods; they
++are just typed differently.
++
++ -- Method on Packet: const click_ip * ip_header () const
++ -- Method on WritablePacket: click_ip * ip_header () const
++ -- Method on Packet: const click_ip6 * ip6_header () const
++ -- Method on WritablePacket: click_ip6 * ip6_header () const
++ Returns `network_header()' as a pointer to an IP or IPv6 header
++ structure.
++
++ -- Method on Packet: int ip_header_offset () const
++ -- Method on Packet: unsigned ip_header_length () const
++ -- Method on Packet: int ip6_header_offset () const
++ -- Method on Packet: unsigned ip6_header_length () const
++ Equivalent to `network_header_offset()' and
++ `network_header_length()'.
++
++ -- Method on Packet: void set_ip_header (const click_ip *HEADER,
++ unsigned LEN)
++ -- Method on Packet: void set_ip6_header (const click_ip6 *HEADER,
++ unsigned LEN)
++ Equivalent to `set_network_header(HEADER, LEN)'.
++
++ -- Method on Packet: void set_ip6_header (const click_ip6 *HEADER)
++ Equivalent to `set_ip6_header(HEADER, 40)'.
++
++ -- Method on Packet: const click_tcp * tcp_header () const
++ -- Method on WritablePacket: click_tcp * tcp_header () const
++ -- Method on Packet: const click_udp * udp_header () const
++ -- Method on WritablePacket: click_udp * udp_header () const
++ Returns `transport_header()' as a pointer to a TCP or UDP header
++ structure.
++
++\1f
++File: click.info, Node: User Annotations, Next: Specific User Annotations, Prev: Header Annotations, Up: Annotations
++
++3.6.2 User Annotations
++----------------------
++
++Each packet header has a "user annotation area", space reserved for
++arbitrary annotations. Different methods access this space as an array
++of bytes, integers, or unsigned integers. The `Packet' class does not
++assign semantics to any particular byte in the user annotation area.
++Instead, macros in `<click/packet_anno.hh>' provide names for
++particular bytes. Some of these names have overlapping byte ranges; the
++user must take care not to define a configuration whose elements use an
++annotation byte on a packet for different purposes. The next section
++describes the macros in Click's default `<click/packet_anno.hh>'.
++
++ These constants define the size of the annotation area.
++
++`Packet::USER_ANNO_SIZE'
++ The size of the annotation area in bytes.
++
++`Packet::USER_ANNO_US_SIZE'
++ The size of the annotation area in `unsigned short's.
++
++`Packet::USER_ANNO_S_SIZE'
++ The size of the annotation area in `short's.
++
++`Packet::USER_ANNO_U_SIZE'
++ The size of the annotation area in `unsigned int's.
++
++`Packet::USER_ANNO_I_SIZE'
++ The size of the annotation area in `int's.
++
++Currently, `USER_ANNO_SIZE' is 24, `USER_ANNO_U_SIZE' and
++`USER_ANNO_I_SIZE' are both 6, and `USER_ANNO_US_SIZE' and
++`USER_ANNO_S_SIZE' are both 12.
++
++ The user annotation area may be accessed as an array of bytes, an
++array of `unsigned int's, or an array of `int's. The elements of these
++arrays are numbered from 0 to K - 1, where K is the appropriate `SIZE'
++constant.
++
++ -- Method on Packet: unsigned char user_anno_c (int I) const
++ Returns the Ith byte in the user annotation area. I must be
++ between 0 and `USER_ANNO_SIZE' - 1.
++
++ -- Method on Packet: unsigned user_anno_u (int I)
++ -- Method on Packet: int user_anno_i (int I)
++ Returns the Ith `unsigned int' or `int' in the user annotation
++ area. I must be between 0 and `USER_ANNO_U_SIZE' - 1. The Ith
++ `unsigned int' or `int' annotation occupies bytes 4I through 4I +
++ 3 of the user annotation area.
++
++ -- Method on Packet: void set_user_anno_c (int I, unsigned char VALUE)
++ -- Method on Packet: void set_user_anno_u (int I, unsigned VALUE)
++ -- Method on Packet: void set_user_anno_i (int I, int VALUE)
++ Sets the Ith byte, `unsigned int', or `int' user annotation to
++ VALUE.
++
++ -- Method on Packet: unsigned * all_user_anno_u ()
++ Returns a pointer to the user annotation area, treated as an array
++ of `unsigned int's.
++
++\1f
++File: click.info, Node: Specific User Annotations, Next: Other Annotations, Prev: User Annotations, Up: Annotations
++
++3.6.3 Specific User Annotations
++-------------------------------
++
++The `<click/packet_anno.hh>' header file defines macros for accessing a
++packet's user annotation area by name. These macros follow some simple
++guidelines. Each user annotation is given a name like `PAINT' or
++`FIX_IP_SRC'. Then, two macros are written for each annotation,
++`NAME_ANNO' and `SET_NAME_ANNO'.
++
++ -- Macro: NAME_ANNO (const Packet *P)
++ Returns the value of P's NAME annotation.
++
++ -- Macro: SET_NAME_ANNO (Packet *P, VALUE)
++ Sets P's NAME annotation to VALUE.
++
++For example, here are the definitions of `PAINT_ANNO' and
++`SET_PAINT_ANNO' from Click's default `<click/packet_anno.hh>'.
++
++ #define PAINT_ANNO(p) ((p)->user_anno_c(0))
++ #define SET_PAINT_ANNO(p, v) ((p)->set_user_anno_c(0, (v)))
++
++
++ This table lists the annotations declared in Click's default
++`<click/packet_anno.hh>'.
++
++Annotation name Type Bytes Some relevant elements
++`PAINT' `unsigned char' 0 `Paint', `CheckPaint', `PaintTee'
++`ICMP_PARAM_PROB' `unsigned char' 1 `IPGWOptions', `ICMPError'
++`FIX_IP_SRC' `unsigned char' 3 `ICMPError', `FixIPSrc'
++`FWD_RATE' `int' 4-7 `IPRateMonitor'
++`REV_RATE' `int' 8-11 `IPRateMonitor'
++
++\1f
++File: click.info, Node: Other Annotations, Next: Annotations In General, Prev: Specific User Annotations, Up: Annotations
++
++3.6.4 Other Annotations
++-----------------------
++
++Packet headers have space for four other particular annotations, and
++special methods for accessing them. These annotations do not overlap the
++user annotation area. There are annotations that hold a destination IP
++address, a timestamp, the device on which the packet arrived, a packet
++type constant, and, in the Linux kernel module, a performance counter
++value.
++
++* Menu:
++
++* Destination Address Annotation::
++* Timestamp Annotation::
++* Device Annotation::
++* Packet Type Annotation::
++* Performance Counter Annotation::
++
++\1f
++File: click.info, Node: Destination Address Annotation, Next: Timestamp Annotation, Prev: Other Annotations, Up: Other Annotations
++
++3.6.4.1 Destination Address
++...........................
++
++The destination address annotation stores the IP or IPv6 address of the
++next hop towards the packet's destination. Elements check and manipulate
++this address, rather than the IP header's destination address, since the
++next-hop address often differs from the final destination. The
++destination IP address and IPv6 address are different annotations, but
++they overlap; you may set only one at a time.
++
++ -- Method on Packet: IPAddress dst_ip_anno () const
++ Returns this packet's destination IP address annotation.
++
++ -- Method on Packet: const IP6Address & dst_ip6_anno () const
++ Returns a reference to this packet's destination IPv6 address
++ annotation.
++
++ -- Method on Packet: void set_dst_ip_anno (IPAddress VALUE)
++ -- Method on Packet: void set_dst_ip6_anno (const IP6Address &VALUE)
++ Sets this packet's destination IP or IPv6 address annotation to
++ VALUE.
++
++ The destination IP address annotation is set by the `GetIPAddress'
++and `SetIPAddress' elements, manipulated by `LookupIPRoute' and its
++cousins, and used by `ARPQuerier'. It defaults to zero.
++
++\1f
++File: click.info, Node: Timestamp Annotation, Next: Device Annotation, Prev: Destination Address Annotation, Up: Other Annotations
++
++3.6.4.2 Timestamp
++.................
++
++The timestamp annotation generally indicates when a packet was received.
++
++ -- Method on Packet: const struct timeval & timestamp_anno () const
++ -- Method on Packet: struct timeval & timestamp_anno ()
++ Returns a reference to this packet's timestamp annotation.
++
++ -- Method on Packet: void set_timestamp_anno
++ (const struct timeval &VALUE)
++ Sets this packet's timestamp annotation to VALUE.
++
++ -- Method on Packet: void set_timestamp_anno (int SEC, int USEC)
++ Sets this packet's timestamp annotation to SEC and USEC.
++ Equivalent to `struct timeval tv; tv.tv_sec = SEC; tv.tv_usec =
++ USEC; set_timestamp_anno(tv)'.
++
++ Linux device drivers set this annotation, so packets emitted by
++`FromDevice' and `PollDevice' in the Linux kernel driver have the
++annotation set. Packet sources like `InfiniteSource' and `RatedSource'
++also set the annotation, as does `FromDump' in the user-level driver.
++Debugging elements like `Print' generally take a keyword argument that
++makes them print packet timestamps.
++
++ The timestamp annotation defaults to zero.
++
++\1f
++File: click.info, Node: Device Annotation, Next: Packet Type Annotation, Prev: Timestamp Annotation, Up: Other Annotations
++
++3.6.4.3 Device
++..............
++
++In the Linux kernel, packets received from some device are annotated
++with a pointer to the relevant `struct net_device' object. (In versions
++of the kernel prior to 2.3, this type was called `struct device'.) The
++`Packet' class provides access to this annotation. The annotation has
++type `net_device *'; Click defines `net_device' as a synonym for
++`struct device' in kernel versions 2.2 and prior.
++
++ -- Method on Packet: net_device * device_anno () const
++ Returns this packet's device annotation.
++
++ -- Method on Packet: void set_device_anno (net_device *VALUE)
++ Sets this packet's device annotation to VALUE.
++
++In the user-level driver, `device_anno' always returns 0, and
++`set_device_anno' does nothing.
++
++ The `ARPResponder' element sets this annotation on every generated
++response to the value of the annotation on the relevant query. Because
++of this, those responses can be safely forwarded to Linux: Linux's
++ARP-response code requires a correct device annotation.
++
++ The device annotation defaults to a null pointer.
++
++\1f
++File: click.info, Node: Packet Type Annotation, Next: Performance Counter Annotation, Prev: Device Annotation, Up: Other Annotations
++
++3.6.4.4 Packet Type
++...................
++
++The packet type annotation specifies how a packet was received. Its
++value is one of the following constants, which are defined in the
++`Packet::PacketType' enumeration.
++
++`HOST'
++ The packet was sent to this host.
++
++`BROADCAST'
++ The packet was sent to a link-level broadcast address.
++
++`MULTICAST'
++ The packet was sent to a link-level multicast address.
++
++`OTHERHOST'
++ The packet was sent to a different host, but received anyway. The
++ relevant device is probably in promiscuous mode.
++
++`OUTGOING'
++ The packet was generated at this host and is being sent to another
++ host.
++
++`LOOPBACK', `FASTROUTE'
++ See the Linux kernel documentation. These values correspond to
++ `PACKET_LOOPBACK' and `PACKET_FASTROUTE', which are defined in
++ `<linux/if_packet.h>'.
++
++ -- Method on Packet: Packet::PacketType packet_type_anno () const
++ Returns this packet's packet type annotation.
++
++ -- Method on Packet: void set_packet_type_anno
++ (Packet::PacketType VALUE)
++ Sets this packet's packet type annotation to VALUE.
++
++ In the Linux kernel, device drivers set the packet type annotation
++for the packets they receive. Thus, the `FromDevice' and `PollDevice'
++elements generate packets with correct packet type annotations. The
++user-level driver's `FromDevice' also sets the packet type annotation.
++The `ICMPError' and `DropBroadcasts' elements use the annotation's
++value.
++
++ The packet type annotation defaults to `Packet::HOST'.
++
++\1f
++File: click.info, Node: Performance Counter Annotation, Prev: Packet Type Annotation, Up: Other Annotations
++
++3.6.4.5 Performance Counter
++...........................
++
++This annotation is available only in the Linux kernel driver. Its value
++is an `unsigned long long' that generally corresponds to some
++performance counter value.
++
++ -- Method on Packet: unsigned long long perfctr_anno () const
++ Returns this packet's performance counter annotation.
++
++ -- Method on Packet: void set_perfctr_anno (unsigned long long VALUE)
++ Sets this packet's performance counter annotation to VALUE.
++
++ The `SetCycleCount', `SetPerfCount', `CycleCountAccum', and
++`PerfCountAccum' elements manipulate this annotation. Its default value
++is zero.
++
++\1f
++File: click.info, Node: Annotations In General, Prev: Other Annotations, Up: Annotations
++
++3.6.5 Annotations In General
++----------------------------
++
++`Packet' provides methods for clearing a packet's annotations, and for
++copying all of a packet's annotations from another packet.
++
++ -- Method on Packet: void clear_annotations ()
++ Clears all of this packet's annotations to their default state,
++ which is generally zero.
++
++ -- Method on Packet: void copy_annotations (const Packet *P)
++ Copies all of P's annotations into this packet except for its
++ header annotations. (This packet's current header annotations are
++ left unchanged.)
++
++\1f
++File: click.info, Node: Packet Out-of-Memory, Next: Handlers, Prev: Annotations, Up: Packets
++
++3.7 Out-of-Memory Conditions
++============================
++
++Any method that potentially allocates memory for a `Packet' may fail
++due to an out-of-memory condition. The complete list of these methods
++follows:
++
++ * `make' variants
++
++ * `clone'
++
++ * `uniqueify'
++
++ * `push'
++
++ * `put'
++
++ * `nonunique_push'
++
++ * `nonunique_put'
++
++These methods always return a null pointer on out-of-memory. Methods
++that manipulate existing packets--`uniqueify', `push', `put',
++`nonunique_push', and `nonunique_put'--additionally free any existing
++packet before returning a null pointer. You should always check the
++results of these methods to see if you have run out of memory.
++
++\1f
++File: click.info, Node: Handlers, Prev: Packet Out-of-Memory, Up: Packets
++
++3.8 Handlers
++============
++
++"Handlers" are access points through which users can interact with
++elements in a running Click router, or with the router as a whole.
++"Read" and "write handlers" behave like files in a file system, while
++"LLRPCs" provide a remote procedure call interface.
++
++* Menu:
++
++* Read and Write Handler Overview::
++* Adding Handlers::
++* Default Handlers::
++* Accessing Handlers Internally::
++* LLRPC Overview::
++
++\1f
++File: click.info, Node: Read and Write Handler Overview, Next: Adding Handlers, Prev: Handlers, Up: Handlers
++
++3.8.1 Read and Write Handler Overview
++-------------------------------------
++
++Read and write handlers appear to the user like files in a file system,
++or alternatively, like a limited RPC mechanism that uses ASCII strings
++for data transfer. To the element programmer, a read handler is simply a
++function that takes an element and returns a String; a write handler is
++a function that takes an element and a String and returns an error code.
++
++ -- Function Type: String (*ReadHandler) (Element *ELEMENT, void *THUNK)
++ Read handler functions have this type. When the user accesses a
++ read handler on an element, Click calls some `ReadHandler' function
++ and passes the element as an argument. The THUNK argument contains
++ callback data specified when the handler was added. The function's
++ String return value is passed back to the user.
++
++ -- Function Type: int (*WriteHandler) (const String &DATA,
++ Element *ELEMENT, void *THUNK, ErrorHandler *ERRH)
++ Write handler functions have this type. When the user accesses some
++ element write handler by passing in a string, Click calls some
++ `WriteHandler' function and passes the data and the relevant
++ element as arguments. The THUNK argument contains callback data
++ specified when the handler was added. The return value is an error
++ code: zero when there are no errors, and the negative of some
++ `errno' value when there is an error. More detailed information
++ about any errors should be reported to the ERRH argument.
++
++ Each handler has an ASCII "name". Handler names must be unique
++within each element; for example, there can be at most one `x' read
++handler in a given element. A given name can be shared by a read handler
++and a write handler, however. Such a handler pair is colloquially called
++a "read/write handler", although its two components need not have
++anything to do with one another.
++
++ There is currently no way to pass data to a read handler or return
++data from a write handler. Use LLRPCs if you need a more RPC-like
++read-write interface.
++
++ Note that read and write handler functions are regular functions, not
++virtual functions. Often, therefore, handler functions are defined as
++private static member functions in the relevant element class.
++
++ Read and write handlers need not use ASCII-formatted data. Most
++existing handlers do format their data in ASCII, however, and use
++`cp_uncomment' to ignore leading and trailing whitespace and comments.
++You may want to do the same for consistency's sake.
++
++ Be careful when writing handlers that modify element state, or read
++state that packet processing can modify. On an SMP machine, a handler
++may be called on one processor while packets are passing through the
++router on another processor. Furthermore, multiple read handlers and
++safe LLRPCs (*note LLRPC Overview::) may be active simultaneously on
++different processors. Write handlers are serialized with respect to
++other handlers and LLRPCs (but not packet processing). That is, no other
++handler or LLRPC will proceed while a write handler is active.
++
++\1f
++File: click.info, Node: Adding Handlers, Next: Default Handlers, Prev: Read and Write Handler Overview, Up: Handlers
++
++3.8.2 Adding Handlers
++---------------------
++
++Use `Element''s `add_read_handler' and `add_write_handler' methods to
++add handlers for an element. You will generally call these methods only
++from within your element's `add_handlers' method, although nothing
++prevents you from adding handlers at any time.
++
++ -- Method on Element: void add_read_handler (const String &NAME,
++ ReadHandler FUNC, void *THUNK)
++ Adds a read handler named NAME for this element. When the handler
++ is accessed, FUNC will be called with `this' and THUNK as
++ parameters.
++
++ -- Method on Element: void add_write_handler (const String &NAME,
++ WriteHandler FUNC, void *THUNK)
++ Adds a write handler named NAME for this element. When the handler
++ is accessed, FUNC will be called with the relevant data, `this',
++ THUNK, and an `ErrorHandler' as parameters.
++
++ To create a read/write handler, call `add_read_handler' and
++`add_write_handler' and supply the same handler name.
++
++ These methods simply forward their requests to static
++`add_read_handler' and `add_write_handler' methods on the `Router'
++class. Call those methods directly to add handlers to other elements,
++or to add global handlers.
++
++ -- Static Method on Router: void add_read_handler
++ (const Element *ELEMENT, const String &NAME,
++ ReadHandler FUNC, void *THUNK)
++ -- Static Method on Router: void add_write_handler
++ (const Element *ELEMENT, const String &NAME,
++ WriteHandler FUNC, void *THUNK)
++ Adds a read or write handler for ELEMENT, or a global read or
++ write handler if ELEMENT is null. The handler is named NAME.
++
++ The `change_handler_flags' method lets you change a handler's flags
++word (*note Handler Objects::).
++
++ -- Static Method on Router: void change_handler_flags
++ (Element *ELEMENT, const String &NAME, uint32_t CLEAR_FLAGS,
++ uint32_t SET_FLAGS)
++ Changes the flags for ELEMENT's NAME handler, or the global NAME
++ handler if ELEMENT is null. The flags are changed by first
++ clearing the bits set in CLEAR_FLAGS, then setting the bits set in
++ SET_FLAGS. This method fails and returns -1 when the specified
++ handler does not exist; otherwise, it returns 0.
++
++\1f
++File: click.info, Node: Default Handlers, Next: Accessing Handlers Internally, Prev: Adding Handlers, Up: Handlers
++
++3.8.3 Default Read and Write Handlers
++-------------------------------------
++
++Every element automatically provides five handlers, `class', `name',
++`config', `ports', and `handlers'. There is no need to add these
++handlers yourself. The default handlers behave as follows:
++
++`class'
++ Returns the element's class name, as returned by `class_name()',
++ followed by a newline. Example result: "ARPQueriern".
++
++`name'
++ Returns the element's name, as returned by `id()', followed by a
++ newline. Example result: "arpq_0n".
++
++`config'
++ Returns the element's configuration string. If the configuration
++ string does not end in newline, the hander appends a newline
++ itself. Example result: "18.26.7.1, 00:00:C0:4F:71:EFn".
++
++ If `can_live_reconfigure' returns true, `config' is also a write
++ handler, and writing to it reconfigures the element.
++
++`ports'
++ Returns a multi-line string describing the element's ports and
++ what they are connected to. The string has the form
++
++ M input[s]
++ ... M input port descriptions, one per line ...
++ N output[s]
++ ... N output port descriptions, one per line ...
++
++ Each port description lists the port's processing type, a dash,
++ and then a comma-separated list of all the ports to which this
++ port is connected. The processing type is either `push' or
++ `pull'; formerly agnostic ports are indicated by a trailing tilde
++ (`push~' or `pull~'). Example result:
++
++ 1 input
++ push~ - Strip@2 [0]
++ 2 outputs
++ push~ - [0] GetIPAddress@4
++ push - [0] Print@7
++
++ If Click was compiled with statistics collection enabled, the dash
++ on each line is replaced by a packet count.
++
++`handlers'
++ Returns a string listing the element's visible handlers, one per
++ line. Each line contains the handler name, a tab, and then either
++ `r', `w', or `rw', depending on whether the handler is read-only,
++ write-only, or read/write. Example result for an `InfiniteSource'
++ element, which has many handlers:
++
++ scheduled r
++ tickets r
++ reset w
++ count r
++ active rw
++ burstsize rw
++ limit rw
++ data rw
++ handlers r
++ ports r
++ config rw
++ name r
++ class r
++
++\1f
++File: click.info, Node: Accessing Handlers Internally, Next: LLRPC Overview, Prev: Default Handlers, Up: Handlers
++
++3.8.4 Accessing Handlers Internally
++-----------------------------------
++
++Element handlers are stored in the relevant `Router' as objects of type
++`Router::Handler'. (This design allows handler objects to be shared
++between elements when possible.) Handlers are often referred to by
++index; indexes between 0 and `Router::FIRST_GLOBAL_HANDLER - 1' refer
++to element handlers, while indexes above `Router::FIRST_GLOBAL_HANDLER'
++refer to global handlers. Indexes less than 0 are used for error
++returns, such as nonexistent handlers. `Router' methods translate
++between handler indexes and `Router::Handler' objects, and find
++handlers or handler indexes given handler names.
++
++* Menu:
++
++* Handler Objects::
++* Handlers By Name or Index::
++
++\1f
++File: click.info, Node: Handler Objects, Next: Handlers By Name or Index, Prev: Accessing Handlers Internally, Up: Accessing Handlers Internally
++
++3.8.4.1 The Router::Handler Type
++................................
++
++The `Router::Handler' type allows you to check a handler's properties
++and call the handler. All of its methods are `const'; you must go
++through `Router' to change a handler's properties. `Router::Handler'
++objects do not contain element references, since they are shared among
++elements. That means you can't easily find the element (if any) to
++which a particular `Router::Handler' is attached.
++
++ -- Method on Router::Handler: const String & name () const
++ Returns the handler's name.
++
++ -- Method on Router::Handler: uint32_t flags () const
++ Returns the handler's flags as an integer. The lower bits of the
++ flags word are reserved for the system, and four bits are reserved
++ for drivers, but the upper bits (at least 16) are left
++ uninterpreted, and may be used by elements. The first user flag
++ bit is called `Router::Handler::USER_FLAG_0'; its position in the
++ word equals `Router::Handler::USER_FLAG_SHIFT'. To change a
++ handler's flags, use the `Router::change_handler_flags' method
++ (*note Changing Handler Flags::).
++
++ -- Method on Router::Handler: bool readable () const
++ Returns true iff this handler is readable.
++
++ -- Method on Router::Handler: bool read_visible () const
++ Returns true iff this handler is readable, and that read handler
++ should be externally visible. Drivers and the ControlSocket
++ element use `read_visible' rather than `readable' when deciding
++ whether to tell the user that a read handler exists. Inter-element
++ communication within the router, however, may use `readable'
++ rather than `read_visible'.
++
++ -- Method on Router::Handler: bool writable () const
++ -- Method on Router::Handler: bool write_visible () const
++ The analogous methods for write handlers.
++
++ -- Method on Router::Handler: bool visible () const
++ Equivalent to `read_visible() || write_visible()'.
++
++ -- Method on Router::Handler: String unparse_name (Element *ELEMENT)
++ const
++ Returns the handler's name, including its attached element's name
++ if ELEMENT is non-null. For example, calling `unparse_name' on
++ element `e''s `foo' handler would return `e.foo', while calling it
++ on a global `bar' handler would return `bar'.
++
++ -- Static Method on Router::Handler: String unparse_name
++ (Element *ELEMENT, const String &NAME)
++ Returns a string representing ELEMENT's hypothetical NAME handler,
++ or the global NAME handler if ELEMENT is null.
++
++ -- Method on Router::Handler: String call_read (Element *ELEMENT) const
++ Calls this read handler on ELEMENT and returns the result. Do not
++ use this method unless you know the handler is `readable()'.
++
++ -- Method on Router::Handler: int call_write (const String &DATA,
++ Element *ELEMENT, ErrorHandler *ERRH) const
++ Calls this write handler on ELEMENT, passing it DATA and ERRH, and
++ returns the result. Do not use this method unless you know the
++ handler is `writable()'.
++
++\1f
++File: click.info, Node: Handlers By Name or Index, Prev: Handler Objects, Up: Accessing Handlers Internally
++
++3.8.4.2 Handlers By Name or Index
++.................................
++
++These `Router' methods locate handlers by name, returning either a
++pointer to a handler object or a handler index. The methods are static
++to allow access to global handlers outside the context of a running
++router.
++
++ -- Static Method on Router: const Router::Handler * handler
++ (const Element *ELEMENT, const String &NAME)
++ Returns a pointer to the handler object for ELEMENT's handler
++ named NAME, or null if no such handler exists. ELEMENT may be
++ null, in which case the method looks for a global handler named
++ NAME.
++
++ *Caution*: Handler pointers returned by `Router::handler' and
++ similar methods should be treated as transient, since they may
++ become invalid when new handlers are added.
++
++ -- Static Method on Router: int hindex (const Element *ELEMENT,
++ const String &NAME)
++ Like `Router::handler', above, but returns an integer handler
++ index for the named handler, or a negative number if no such
++ handler exists. All valid handler indexes are nonnegative.
++
++ -- Static Method on Router: const Router::Handler * handler
++ (const Router *ROUTER, int HINDEX)
++ Returns ROUTER's handler object corresponding to HINDEX, or a null
++ pointer if HINDEX is invalid with respect to ROUTER. There are
++ three possibilities: (1) HINDEX coresponds to a valid global
++ handler, which is returned. In this case, ROUTER need not be
++ valid. (2) HINDEX corresponds to a valid local handler in class
++ ROUTER, which is returned. (3) Otherwise, a null pointer is
++ returned.
++
++ -- Static Method on Router: const Router::Handler * handler
++ (const Element *ELEMENT, int HINDEX)
++ Convenience function equivalent to `handler(ELEMENT->router(),
++ HINDEX)'. Note that HINDEX need not refer to one of ELEMENT's
++ handlers.
++
++ -- Method on Router: const Router::Handler * handler (int HINDEX) const
++ Convenience function equivalent to `handler(this, HINDEX)'.
++
++ Finally, the `element_hindexes' static method returns all the
++handler indices that apply to a given element.
++
++ -- Static Method on Router: void element_hindexes
++ (const Element *ELEMENT, Vector<int> &RESULTS)
++ Appends to RESULTS all the handler indexes for ELEMENT's handlers,
++ or all global handlers if ELEMENT is null.
++
++\1f
++File: click.info, Node: LLRPC Overview, Prev: Accessing Handlers Internally, Up: Handlers
++
++3.8.5 LLRPC Overview
++--------------------
++
++\1f
++File: click.info, Node: Tasks, Next: Timers, Prev: Packets, Up: Top
++
++4 Tasks
++*******
++
++Click schedules a router's CPU or CPUs with one or more "task queues".
++These queues are simply lists of "tasks", which represent functions
++that would like access to the CPU. Tasks are generally associated with
++elements. When scheduled, most tasks call some element's `run_task'
++method.
++
++ Click tasks are represented by `Task' objects. An element that would
++like special access to a router's CPU should include and initialize a
++`Task' instance variable.
++
++ Tasks are generally called very frequently, up to tens of thousands
++of times per second. For infrequent events, it is far more efficient to
++use timers than to use tasks; see *Note Timers::.
++
++ Executing a task should not take a long time. The Click driver loop
++is not currently adaptive, so very long tasks can inappropriately delay
++timers and other periodic events. We may address this problem in a
++future release, but for now, keep tasks short.
++
++ See the Doxygen documentation on class `Task' for more information.
++
++ The `Task' class is defined in the `<click/task.hh>' header file.
++
++* Menu:
++
++* Task Initialization::
++* Scheduling Tasks::
++* Tickets::
++* Task Thread Choice::
++* Task Status::
++* Task Handlers::
++* Task Cleanup::
++
++\1f
++File: click.info, Node: Task Initialization, Next: Scheduling Tasks, Prev: Tasks, Up: Tasks
++
++4.1 Task Initialization
++=======================
++
++Task initialization is a two-step process. First, when a `Task' object
++is constructed, you must supply information about the function that it
++should call when it is scheduled. Second, when the router is
++initialized, you must initialize the task by supplying it with the
++relevant router. (You must initialize the task even if it will not be
++scheduled right away.)
++
++ `Task' has two constructors. One of them asks the task to call an
++element's `run_task' method when scheduled; the other asks it to call
++an arbitrary function pointer.
++
++ -- Constructor on Task: Task (Element *E)
++ When this task is scheduled, call `E->run_task()'.
++
++ -- Constructor on Task: Task (TaskHook HOOK, void *THUNK)
++ When this task is scheduled, call `HOOK(this, THUNK)'. The HOOK
++ argument is a function pointer with type `void (*)(Task *, void
++ *)'.
++
++ The `Task::initialize' method places the task on a router-wide list
++of `Task's, associates the task with a particular task queue, and,
++optionally, schedules it. Typically, an element's `initialize' method
++calls `Task::initialize'.
++
++ -- Method on Task: void initialize (Router *R, bool SCHEDULED)
++ -- Method on Task: void initialize (Element *E, bool SCHEDULED)
++ Attaches the task to the router object R (or `E->router()').
++ Additionally sets the task's tickets to a default value, and
++ schedules the task if SCHEDULED is true.
++
++ Many elements call `ScheduleInfo::initialize_task' instead of
++calling `Task::initialize' directly. This method queries any
++`ScheduleInfo' elements in the configuration to determine the task's
++scheduling parameters, sets those parameters, and calls
++`Task::initialize' to schedule the task. The
++`ScheduleInfo::initialize_task' method is defined in the
++`<click/standard/scheduleinfo.hh>' header file.
++
++ -- Static Method on ScheduleInfo: void initialize_task (Element *E,
++ Task *TASK, bool SCHEDULE, ErrorHandler *ERRH)
++ Sets TASK's scheduling parameters as specified by any
++ `ScheduleInfo' elements in the router configuration. The element E
++ is used to find the correct router, and provides the relevant name
++ for parameter lookup--the user supplies parameters to
++ `ScheduleInfo' by element name. If SCHEDULE is true, also
++ schedules TASK on `E->router()''s task queue. Reports any errors
++ to ERRH.
++
++ -- Static Method on ScheduleInfo: void initialize_task (Element *E,
++ Task *TASK, ErrorHandler *ERRH)
++ A synonym for `initialize_task(E, TASK, true, ERRH)'.
++
++ -- Static Method on ScheduleInfo: void join_scheduler (Element *E,
++ Task *TASK, ErrorHandler *ERRH)
++ A synonym for `initialize_task(E, TASK, true, ERRH)'.
++
++ The `initialize_task' method is generally called like this:
++
++ int
++ SomeElement::initialize(ErrorHandler *errh)
++ {
++ ScheduleInfo::initialize_task(this, &_task, errh);
++ }
++
++Here, `_task', a `Task' object, is one of `SomeElement''s instance
++variables.
++
++\1f
++File: click.info, Node: Scheduling Tasks, Next: Tickets, Prev: Task Initialization, Up: Tasks
++
++4.2 Scheduling Tasks
++====================
++
++The user may take a task off its task queue with the `unschedule'
++method, and place it back onto its task queue with the `reschedule'
++method. As tasks move to the head of the task queue, they are
++unscheduled and their callbacks are called. Within these callback
++functions, the user will typically call `fast_reschedule', which is
++like `reschedule' without the locking overhead.
++
++ -- Method on Task: void unschedule ()
++ Unschedules the task by removing it from its task queue. Does
++ nothing if if the task is currently unscheduled, or if it was
++ never initialized. When this function returns, the task will not
++ be scheduled.
++
++ -- Method on Task: void reschedule ()
++ Reschedules the task by placing it on its task queue. If the task
++ is already scheduled, then this method does nothing.
++
++ All three functions lock the task queue before manipulating it. This
++avoids corruption when there are multiple processors executing
++simultaneously. If `reschedule' cannot immediately lock a task
++queue--perhaps because it is being used on another processor--then they
++register a task request, which will be executed in the near future. In
++contrast, the `unschedule' function will wait until it can lock the
++task queue.
++
++ Sometimes unscheduling a task is not enough: you don't want the task
++to run, even if someone else (an upstream queue, for example) were to
++reschedule it. The `strong_unschedule' method both unschedules the task
++and shifts the task to the quiescent thread, which never runs. Thus, a
++`strong_unschedule'd task will not run until someone calls
++`strong_reschedule', which reschedules the task on its original
++preferred thread.
++
++ -- Method on Task: void strong_unschedule ()
++ Unschedules the task by removing it from its task queue and
++ shifting it to the quiescent thread. Does nothing if if the task
++ is currently unscheduled, or if it was never initialized. When
++ this function returns, the task will not be scheduled.
++
++ -- Method on Task: void strong_reschedule ()
++ Reschedules the task by placing it on the task queue corresponding
++ to its thread preference. The task will not be scheduled
++ immediately upon return, but it will become scheduled
++ soon--`strong_reschedule' uses a task request to avoid locking.
++
++ The `fast_reschedule' method avoids locking overhead in the common
++case that a task must be rescheduled from within its callback.
++
++ -- Method on Task: void fast_reschedule ()
++ Reschedules the task by placing it on its preferred task queue.
++ This method avoids locking overhead, so it is faster than
++ `reschedule'.
++
++ *Caution*: You may call a `Task''s `fast_reschedule' method
++ only from within its callback function. For instance, if an
++ element has a task, `_task', that calls the element's
++ `run_task' method when scheduled, and if `run_task' is called
++ only by that task's callback, then that element's `run_task'
++ method should call `_task.fast_reschedule()' instead of
++ `_task.reschedule()'.
++
++ The `fast_unschedule' method is to `unschedule' as `fast_reschedule'
++is to `reschedule'. It is rarely used, since tasks are automatically
++unscheduled before they are run.
++
++ -- Method on Task: void fast_unschedule ()
++ Unschedules the task by removing it from its task queue. Does
++ nothing if if the task is currently unscheduled, or if it was
++ never initialized. This method avoids locking overhead, so it is
++ faster than `unschedule'.
++
++ *Caution*: You may call a `Task''s `fast_unschedule' method
++ only from within its callback function.
++
++\1f
++File: click.info, Node: Tickets, Next: Task Thread Choice, Prev: Scheduling Tasks, Up: Tasks
++
++4.3 Tickets
++===========
++
++Click tasks are scheduled using the flexible, lightweight stride
++scheduling algorithm.(1) This algorithm assigns each task a parameter
++called its "tickets". A task with twice as many tickets as usual is
++scheduled twice as frequently.
++
++ `Task's have methods for querying, setting, and adjusting their
++tickets.
++
++ -- Method on Task: int tickets () const
++ Returns this task's tickets. This number will be at least 1 and no
++ more than `Task::MAX_TICKETS', which equals 32768.
++
++ -- Method on Task: void set_tickets (int T)
++ Sets this task's tickets to T. The T parameter should lie between
++ 1 and `Task::MAX_TICKETS', inclusive; numbers outside this range
++ are constrained to the nearest valid value.
++
++ -- Method on Task: void adj_tickets (int DELTA)
++ Equivalent to `set_tickets(tickets() + DELTA)'.
++
++ ---------- Footnotes ----------
++
++ (1) For more information, see MIT Laboratory for Computer Science
++Technical Memo MIT/LCS/TM-528, `Stride scheduling: deterministic
++proportional-share resource management', by Carl A. Waldspurger and
++William E. Weihl, June 1995.
++
++\1f
++File: click.info, Node: Task Thread Choice, Next: Task Status, Prev: Tickets, Up: Tasks
++
++4.4 Choosing a Thread
++=====================
++
++Each task belongs to some task queue, which generally corresponds to a
++thread of control. Single-threaded Click has one active thread, and
++therefore one task queue, but multithreaded Click can have an arbitrary
++number of threads. Either Click has a special thread, the "quiescent
++thread", numbered -1; tasks belonging to the quiescent thread never
++run, whether or not they are scheduled. Every task starts out belonging
++to the first thread, thread 0. The `change_thread' method moves a task
++to another thread.
++
++ -- Method on Task: void change_thread (int THREAD_ID)
++ Move this task to thread THREAD_ID, which should be a number
++ between -1 and the relevant `Router''s `nthreads()'.
++
++ The task is scheduled on the new task queue if and only if it was
++ scheduled on the old task queue.
++
++ Like `reschedule', `change_thread' must lock the task queue before
++manipulating it. (Unlike those methods, `change_thread' must lock two
++task queues, the old and the new.) If `change_thread' cannot lock a
++task queue, then it registers a task request that will be executed in
++the near future. This implies that a task may remain on the same
++thread, or become unscheduled, for some time after `change_thread' is
++called.
++
++\1f
++File: click.info, Node: Task Status, Next: Task Handlers, Prev: Task Thread Choice, Up: Tasks
++
++4.5 Task Status Methods
++=======================
++
++These methods let a user check various properties of a task--for
++instance, whether it is initialized or scheduled.
++
++ -- Method on Task: bool initialized () const
++ Returns true iff the task has been initialized--that is, if it is
++ associated with some router.
++
++ -- Method on Task: bool scheduled () const
++ Returns true iff the task is currently scheduled on some task
++ queue.
++
++ -- Method on Task: RouterThread * scheduled_list () const
++ Returns the task queue with which this task is associated. Even
++ unscheduled tasks are associated with some task queue; this is the
++ task queue on which the task will be placed if `reschedule' is
++ called.
++
++ -- Method on Task: TaskHook hook () const
++ Returns the callback function that is called when the task is
++ scheduled. If the task is associated with some element, this
++ method returns a null pointer.
++
++ -- Method on Task: void * thunk () const
++ Returns the extra data passed to the callback function when the
++ task is scheduled.
++
++ -- Method on Task: Element * element () const
++ If the task is associated with some element, this method returns
++ that element. Otherwise, returns a null pointer.
++
++\1f
++File: click.info, Node: Task Handlers, Next: Task Cleanup, Prev: Task Status, Up: Tasks
++
++4.6 Task Handlers
++=================
++
++By convention, elements with tasks should provide handlers that access
++task properties. The `Element::add_task_handlers' method automatically
++adds these handlers for a given `Task' object.
++
++ -- Method on Element: void add_task_handlers (Task *TASK,
++ const String &PREFIX = String())
++ Adds task handlers for TASK to this element. The string PREFIX is
++ prepended to every handler name.
++
++ This method adds at least the following handlers:
++
++`scheduled'
++ Returns a Boolean value saying whether the task is currently
++ scheduled on some task queue. Example result: "truen".
++
++`tickets'
++ Returns or sets the task's currently allocated tickets. This
++ handler is only available if Click was compiled to support stride
++ scheduling. Example result: "1024n".
++
++`thread_preference'
++ Returns the task's thread preference. This handler is only
++ available on multithreaded Click. Example result: "2n".
++
++\1f
++File: click.info, Node: Task Cleanup, Prev: Task Handlers, Up: Tasks
++
++4.7 Task Cleanup
++================
++
++You generally don't need to worry about destroying `Task' objects: they
++are automatically unscheduled and removed when the `Router' is
++destroyed. This only works if the `Task' objects have the same lifetime
++as the `Router', however. This includes the normal case, when `Task's
++are element instance variables. If you create and destroy `Task'
++objects as the router runs, however, you will need to call the
++following method before deleting the `Task'.
++
++ -- Method on Task: void cleanup ()
++ Cleans up the `Task' object.
++
++\1f
++File: click.info, Node: Timers, Next: Notification, Prev: Tasks, Up: Top
++
++5 Timers
++********
++
++Click "timers", like Click tasks, represent callback functions that the
++driver calls when appropriate. Unlike tasks, however, you schedule
++timers to go off at a specified time. Timers are intended for more
++infrequent and/or slower tasks.
++
++ As with `Task', most `Timer' objects are declared as instance
++variables of elements and scheduled when needed.
++
++ Timers may be scheduled with microsecond precision, but on current
++hardware, only millisecond precision is likely to be achievable.
++
++ The `Timer' class is defined in the `<click/timer.hh>' header file.
++
++* Menu:
++
++* Timer Initialization::
++* Scheduling Timers::
++* Timer Status Methods::
++* Timer Cleanup::
++
++\1f
++File: click.info, Node: Timer Initialization, Next: Scheduling Timers, Prev: Timers, Up: Timers
++
++5.1 Timer Initialization
++========================
++
++Timer initialization resembles task initialization. When the timer is
++constructed, you must supply it with information about its callback
++function. Later, after the router is initialized, you must initialize
++and, optionally, schedule it.
++
++ -- Constructor on Timer: Timer (Element *E)
++ When this timer goes off, call `E->run_timer()'.
++
++ -- Constructor on Timer: Timer (Task *T)
++ When this timer goes off, call `T->reschedule()'.
++
++ -- Constructor on Timer: Timer (TimerHook HOOK, void *THUNK)
++ When this timer goes off, call `HOOK(this, THUNK)'. The HOOK
++ argument is a function pointer with type `void (*)(Timer *, void
++ *)'.
++
++ -- Method on Timer: void initialize (Router *R)
++ -- Method on Timer: void initialize (Element *E)
++ Attaches the timer to the router object R (or `E->router()').
++
++ Typically, an element's `initialize' method calls
++`Timer::initialize', and possibly one of the `schedule' functions
++described below.
++
++\1f
++File: click.info, Node: Scheduling Timers, Next: Timer Status Methods, Prev: Timer Initialization, Up: Timers
++
++5.2 Scheduling Timers
++=====================
++
++A variety of methods schedule timers to go off at specified times. The
++basic method is `schedule_at', which schedules the timer for a
++specified time. Subsidiary methods schedule the timer relative to the
++current time (the `schedule_after' methods), or relative to the last
++time the timer was scheduled to run (the `reschedule_after' methods).
++Finally, `unschedule' unschedules the timer.
++
++ All `schedule' and `reschedule' functions first unschedule the timer
++if it was already scheduled.
++
++ The `reschedule' methods are particularly useful for timers that
++should occur periodically. For example, this callback function will
++cause its timer to go off at 20-second intervals:
++
++ void timer_callback(Timer *t, void *) {
++ t->reschedule_after_s(20);
++ }
++
++ -- Method on Timer: void schedule_at (const struct timeval &WHEN)
++ Schedule the timer to go off at WHEN. You must have initialized
++ the timer earlier.
++
++ -- Method on Timer: void schedule_now ()
++ Schedule the timer to go off as soon as possible.
++
++ -- Method on Timer: void schedule_after (const struct timeval &DELAY)
++ Schedule the timer to go off DELAY after the current time.
++
++ -- Method on Timer: void schedule_after_s (uint32_t DELAY)
++ Schedule the timer to go off DELAY seconds after the current time.
++
++ -- Method on Timer: void schedule_after_ms (uint32_t DELAY)
++ Schedule the timer to go off DELAY milliseconds after the current
++ time.
++
++ -- Method on Timer: void reschedule_after (const struct timeval &DELAY)
++ Schedule the timer to go off DELAY after it was last scheduled to
++ go off. If the timer was never previously scheduled, this method
++ will schedule the timer for some arbitrary time.
++
++ -- Method on Timer: void reschedule_after_s (uint32_t DELAY)
++ Schedule the timer to go off DELAY seconds after it was last
++ scheduled to go off.
++
++ -- Method on Timer: void reschedule_after_ms (uint32_t DELAY)
++ Schedule the timer to go off DELAY milliseconds after it was last
++ scheduled to go off.
++
++ -- Method on Timer: void unschedule ()
++ Unschedules the timer, if it was scheduled.
++
++\1f
++File: click.info, Node: Timer Status Methods, Next: Timer Cleanup, Prev: Scheduling Timers, Up: Timers
++
++5.3 Timer Status Methods
++========================
++
++These methods return information about a timer, including when it is
++scheduled to expire.
++
++ -- Method on Timer: bool initialized () const
++ Returns true iff the timer has been initialized with a call to
++ `initialize()'. Uninitialized timers must not be scheduled.
++
++ -- Method on Timer: bool scheduled () const
++ Returns true iff the timer is scheduled to expire some time in the
++ future.
++
++ -- Method on Timer: const struct timeval & expiry () const
++ Returns the time that the timer is set to expire. If the timer has
++ never been scheduled, the value is garbage. If the timer was
++ scheduled but is not scheduled currently, the value is most
++ recently set expiry time.
++
++\1f
++File: click.info, Node: Timer Cleanup, Prev: Timer Status Methods, Up: Timers
++
++5.4 Timer Cleanup
++=================
++
++You don't need to worry about cleaning up `Timer' objects. They are
++automatically unscheduled and removed when the `Router' is destroyed,
++and deleting a `Timer' automatically removes it from any relevant
++lists. The following function is nevertheless provided for consistency
++with `Task's, which do need to be cleaned up in certain circumstances
++(*note Task Cleanup::).
++
++ -- Method on Timer: void cleanup ()
++ Cleans up the `Timer' object.
++
++\1f
++File: click.info, Node: Notification, Next: Coding Standards, Prev: Timers, Up: Top
++
++6 Notification
++**************
++
++\1f
++File: click.info, Node: Coding Standards, Next: Index, Prev: Notification, Up: Top
++
++7 Coding Standards
++******************
++
++* Menu:
++
++* Upper and lower case names::
++* Common name patterns::
++
++\1f
++File: click.info, Node: Upper and lower case names, Next: Common name patterns, Prev: Coding Standards, Up: Coding Standards
++
++7.1 Upper and Lower Case in Names
++=================================
++
++Keep to the following consistent scheme for choosing between upper and
++lower case when naming variables, types, and functions.
++
++*Classes*
++ Use mixed case with an initial capital letter and no underscores:
++ `LookupIPRoute'.
++
++*Methods*
++ Use all lower case with underscores separating words:
++ `negation_is_simple'.
++
++*Constants*
++ Use all upper case with underscores separating words:
++ `TYPE_ICMP_TYPE'.
++
++*Instance variables*
++ Begin with an underscore, then use all lower case with underscores
++ separating words: `_length'.
++
++*Regular variables*
++ Use all lower case with underscores separating words: `i',
++ `the_handler'.
++
++*Class variables*
++ These variables are declared as `static' in the class header. Name
++ them like regular variables: `nelements_allocated'.
++
++*Functions*
++ Name them like methods: `quicksort_hook'.
++
++*Other types*
++ This includes typedefs and enumerated types. Name them like
++ classes: `CpVaParseCmd', `ConfigurePhase'.
++
++ There are exceptions to these guidelines. In particular:
++
++ * Instance variables in C structs--that is, classes with few methods
++ whose instance variables are mostly public--may be named like
++ regular variables, without a preceding underscore. The same goes
++ for the components of unions.
++
++ * Classes that act like simple types, such as `uatomic32_t', take
++ names similar to the types they replace (in this case `uint32_t').
++
++\1f
++File: click.info, Node: Common name patterns, Prev: Upper and lower case names, Up: Coding Standards
++
++7.2 Common Name Patterns
++========================
++
++ * Many instance variables have associated "getter methods" that
++ return their values, and/or "setter methods" that change their
++ values. For an instance variable named `_x', the getter method
++ should be named `x()' and the setter method should be named
++ `set_x()'.
++
++ * A variable or method which counts something is often named
++ `nOBJECTs'--for instance, `_nwarnings', `ninputs()', `_npackets'.
++
++ * Use a bare `0' for a null pointer, except where some ambiguity
++ might arise (for example, where an incorrect overloading might be
++ selected).
++
++\1f
++File: click.info, Node: Index, Prev: Coding Standards, Up: Top
++
++Index
++*****
++
++\0\b[index\0\b]
++* Menu:
++
++* (*ReadHandler): Read and Write Handler Overview.
++ (line 13)
++* (*WriteHandler): Read and Write Handler Overview.
++ (line 21)
++* add_read_handler on Element: Adding Handlers. (line 13)
++* add_read_handler on Router: Adding Handlers. (line 34)
++* add_task_handlers on Element: Task Handlers. (line 12)
++* add_write_handler on Element: Adding Handlers. (line 19)
++* add_write_handler on Router: Adding Handlers. (line 37)
++* adj_tickets on Task: Tickets. (line 24)
++* all_user_anno_u on Packet: User Annotations. (line 60)
++* buffer_data on Packet: Packet Structure and Contents.
++ (line 37)
++* buffer_data on WritablePacket: Packet Structure and Contents.
++ (line 47)
++* buffer_length on Packet: Packet Structure and Contents.
++ (line 42)
++* call_read on Router::Handler: Handler Objects. (line 57)
++* call_write on Router::Handler: Handler Objects. (line 62)
++* change_handler_flags on Router: Adding Handlers. (line 46)
++* change_thread on Task: Task Thread Choice. (line 16)
++* cleanup on Task: Task Cleanup. (line 15)
++* cleanup on Timer: Timer Cleanup. (line 14)
++* clear_annotations on Packet: Annotations In General.
++ (line 10)
++* clone on Packet: Packet Sharing. (line 12)
++* ContextErrorHandler on ContextErrorHandler: Error Veneers. (line 26)
++* copy_annotations on Packet: Annotations In General.
++ (line 14)
++* data on Packet: Packet Structure and Contents.
++ (line 31)
++* data on WritablePacket: Packet Structure and Contents.
++ (line 46)
++* debug on ErrorHandler: Reporting Errors. (line 13)
++* decorate_text on ErrorHandler: Writing ErrorHandlers.
++ (line 30)
++* default ErrorHandler: Basic ErrorHandlers. (line 13)
++* default_handler on ErrorHandler: Basic ErrorHandlers. (line 19)
++* device_anno on Packet: Device Annotation. (line 14)
++* dst_ip6_anno on Packet: Destination Address Annotation.
++ (line 17)
++* dst_ip_anno on Packet: Destination Address Annotation.
++ (line 14)
++* element on Task: Task Status. (line 33)
++* element_hindexes on Router: Handlers By Name or Index.
++ (line 52)
++* error on ErrorHandler: Reporting Errors. (line 16)
++* ErrorHandler, default: Basic ErrorHandlers. (line 13)
++* ErrorVeneer: Writing ErrorHandlers.
++ (line 54)
++* ErrorVeneer on ErrorVeneer: Writing ErrorHandlers.
++ (line 67)
++* expiry on Timer: Timer Status Methods.
++ (line 18)
++* fast_reschedule on Task: Scheduling Tasks. (line 55)
++* fast_unschedule on Task: Scheduling Tasks. (line 72)
++* fatal on ErrorHandler: Reporting Errors. (line 17)
++* FileErrorHandler on FileErrorHandler: Basic ErrorHandlers. (line 39)
++* flags on Router::Handler: Handler Objects. (line 17)
++* handle_text on ErrorHandler: Writing ErrorHandlers.
++ (line 45)
++* handler on Router: Handlers By Name or Index.
++ (line 13)
++* headroom on Packet: Packet Structure and Contents.
++ (line 40)
++* hindex on Router: Handlers By Name or Index.
++ (line 24)
++* hook on Task: Task Status. (line 24)
++* initialize on Task: Task Initialization. (line 31)
++* initialize on Timer: Timer Initialization.
++ (line 23)
++* initialize_task on ScheduleInfo: Task Initialization. (line 46)
++* initialized on Task: Task Status. (line 10)
++* initialized on Timer: Timer Status Methods.
++ (line 10)
++* ip6_header on Packet: Header Annotations. (line 76)
++* ip6_header on WritablePacket: Header Annotations. (line 77)
++* ip6_header_length on Packet: Header Annotations. (line 84)
++* ip6_header_offset on Packet: Header Annotations. (line 83)
++* ip_header on Packet: Header Annotations. (line 74)
++* ip_header on WritablePacket: Header Annotations. (line 75)
++* ip_header_length on Packet: Header Annotations. (line 82)
++* ip_header_offset on Packet: Header Annotations. (line 81)
++* join_scheduler on ScheduleInfo: Task Initialization. (line 60)
++* kill on Packet: Packet Creation. (line 80)
++* LandmarkErrorHandler on LandmarkErrorHandler: Error Veneers.
++ (line 43)
++* ldebug on ErrorHandler: Reporting Errors. (line 36)
++* length on Packet: Packet Structure and Contents.
++ (line 34)
++* lerror on ErrorHandler: Reporting Errors. (line 42)
++* lfatal on ErrorHandler: Reporting Errors. (line 44)
++* lmessage on ErrorHandler: Reporting Errors. (line 38)
++* lwarning on ErrorHandler: Reporting Errors. (line 40)
++* make on Packet <1>: Packets and sk_buffs.
++ (line 20)
++* make on Packet: Packet Creation. (line 31)
++* make_text on ErrorHandler: Writing ErrorHandlers.
++ (line 19)
++* message on ErrorHandler: Reporting Errors. (line 14)
++* name on Router::Handler: Handler Objects. (line 14)
++* NAME_ANNO: Specific User Annotations.
++ (line 13)
++* nerrors on ErrorHandler: Counting Errors. (line 11)
++* network_header on Packet: Header Annotations. (line 21)
++* network_header on WritablePacket: Header Annotations. (line 22)
++* network_header_length on Packet: Header Annotations. (line 36)
++* network_header_offset on Packet: Header Annotations. (line 31)
++* nonunique_push on Packet: Packet Buffer Manipulation.
++ (line 62)
++* nonunique_put on Packet: Packet Buffer Manipulation.
++ (line 77)
++* nwarnings on ErrorHandler: Counting Errors. (line 10)
++* packet_type_anno on Packet: Packet Type Annotation.
++ (line 33)
++* perfctr_anno on Packet: Performance Counter Annotation.
++ (line 11)
++* PrefixErrorHandler on PrefixErrorHandler: Error Veneers. (line 36)
++* pull on Packet: Packet Buffer Manipulation.
++ (line 31)
++* push on Packet: Packet Buffer Manipulation.
++ (line 16)
++* put on Packet: Packet Buffer Manipulation.
++ (line 37)
++* read_visible on Router::Handler: Handler Objects. (line 30)
++* readable on Router::Handler: Handler Objects. (line 27)
++* reschedule on Task: Scheduling Tasks. (line 20)
++* reschedule_after on Timer: Scheduling Timers. (line 42)
++* reschedule_after_ms on Timer: Scheduling Timers. (line 51)
++* reschedule_after_s on Timer: Scheduling Timers. (line 47)
++* reset_counts on ErrorHandler: Counting Errors. (line 15)
++* schedule_after on Timer: Scheduling Timers. (line 32)
++* schedule_after_ms on Timer: Scheduling Timers. (line 38)
++* schedule_after_s on Timer: Scheduling Timers. (line 35)
++* schedule_at on Timer: Scheduling Timers. (line 25)
++* schedule_now on Timer: Scheduling Timers. (line 29)
++* scheduled on Task: Task Status. (line 14)
++* scheduled on Timer: Timer Status Methods.
++ (line 14)
++* scheduled_list on Task: Task Status. (line 18)
++* set_default_handler on ErrorHandler: Basic ErrorHandlers. (line 23)
++* set_device_anno on Packet: Device Annotation. (line 17)
++* set_dst_ip6_anno on Packet: Destination Address Annotation.
++ (line 22)
++* set_dst_ip_anno on Packet: Destination Address Annotation.
++ (line 21)
++* set_ip6_header on Packet: Header Annotations. (line 91)
++* set_ip_header on Packet: Header Annotations. (line 89)
++* SET_NAME_ANNO: Specific User Annotations.
++ (line 16)
++* set_network_header on Packet: Header Annotations. (line 60)
++* set_packet_type_anno on Packet: Packet Type Annotation.
++ (line 37)
++* set_perfctr_anno on Packet: Performance Counter Annotation.
++ (line 14)
++* set_tickets on Task: Tickets. (line 19)
++* set_timestamp_anno on Packet: Timestamp Annotation.
++ (line 14)
++* set_user_anno_c on Packet: User Annotations. (line 54)
++* set_user_anno_i on Packet: User Annotations. (line 56)
++* set_user_anno_u on Packet: User Annotations. (line 55)
++* shared on Packet: Packet Sharing. (line 34)
++* silent_handler on ErrorHandler: Basic ErrorHandlers. (line 28)
++* skb on Packet: Packets and sk_buffs.
++ (line 32)
++* static_cleanup on ErrorHandler: ErrorHandler Initialization.
++ (line 20)
++* static_initialize on ErrorHandler: ErrorHandler Initialization.
++ (line 13)
++* steal_skb on Packet: Packets and sk_buffs.
++ (line 40)
++* strong_reschedule on Task: Scheduling Tasks. (line 46)
++* strong_unschedule on Task: Scheduling Tasks. (line 40)
++* tailroom on Packet: Packet Structure and Contents.
++ (line 41)
++* take on Packet: Packet Buffer Manipulation.
++ (line 52)
++* Task on Task: Task Initialization. (line 18)
++* tcp_header on Packet: Header Annotations. (line 97)
++* tcp_header on WritablePacket: Header Annotations. (line 98)
++* thunk on Task: Task Status. (line 29)
++* tickets on Task: Tickets. (line 15)
++* Timer on Timer: Timer Initialization.
++ (line 12)
++* timestamp_anno on Packet: Timestamp Annotation.
++ (line 9)
++* transport_header on Packet: Header Annotations. (line 26)
++* transport_header on WritablePacket: Header Annotations. (line 27)
++* transport_header_offset on Packet: Header Annotations. (line 40)
++* udp_header on Packet: Header Annotations. (line 99)
++* udp_header on WritablePacket: Header Annotations. (line 100)
++* uniqueify on Packet: Packet Sharing. (line 20)
++* unparse_name on Router::Handler: Handler Objects. (line 46)
++* unschedule on Task: Scheduling Tasks. (line 14)
++* unschedule on Timer: Scheduling Timers. (line 55)
++* user_anno_c on Packet: User Annotations. (line 43)
++* user_anno_i on Packet: User Annotations. (line 48)
++* user_anno_u on Packet: User Annotations. (line 47)
++* verror on ErrorHandler: Reporting Errors. (line 73)
++* visible on Router::Handler: Handler Objects. (line 42)
++* warning on ErrorHandler: Reporting Errors. (line 15)
++* writable on Router::Handler: Handler Objects. (line 38)
++* write_visible on Router::Handler: Handler Objects. (line 39)
++
++
++\1f
++Tag Table:
++Node: Top\7f233
++Node: Overview\7f2218
++Node: Packet Transfer\7f2353
++Node: Helper Classes\7f2470
++Node: ErrorHandler\7f2618
++Node: ErrorHandler Initialization\7f3523
++Node: Reporting Errors\7f4673
++Node: Error Format Strings\7f8229
++Node: Counting Errors\7f12734
++Node: Basic ErrorHandlers\7f13677
++Node: Error Veneers\7f15602
++Node: Writing ErrorHandlers\7f19343
++Node: Packets\7f22748
++Node: Packet Structure and Contents\7f24424
++Node: Packet Creation\7f26727
++Node: Packets and sk_buffs\7f30171
++Node: Packet Sharing\7f32385
++Node: Packet Buffer Manipulation\7f33889
++Node: Annotations\7f38510
++Node: Header Annotations\7f39633
++Node: User Annotations\7f44362
++Node: Specific User Annotations\7f46926
++Node: Other Annotations\7f48352
++Node: Destination Address Annotation\7f49046
++Node: Timestamp Annotation\7f50312
++Node: Device Annotation\7f51557
++Node: Packet Type Annotation\7f52750
++Node: Performance Counter Annotation\7f54390
++Node: Annotations In General\7f55128
++Node: Packet Out-of-Memory\7f55784
++Node: Handlers\7f56549
++Node: Read and Write Handler Overview\7f57053
++Node: Adding Handlers\7f60246
++Ref: Changing Handler Flags\7f62106
++Node: Default Handlers\7f62591
++Node: Accessing Handlers Internally\7f65097
++Node: Handler Objects\7f65946
++Node: Handlers By Name or Index\7f69116
++Node: LLRPC Overview\7f71591
++Node: Tasks\7f71730
++Node: Task Initialization\7f73013
++Node: Scheduling Tasks\7f76105
++Node: Tickets\7f79882
++Ref: Tickets-Footnote-1\7f80864
++Node: Task Thread Choice\7f81096
++Node: Task Status\7f82460
++Node: Task Handlers\7f83806
++Node: Task Cleanup\7f84870
++Node: Timers\7f85502
++Node: Timer Initialization\7f86263
++Node: Scheduling Timers\7f87370
++Node: Timer Status Methods\7f89646
++Node: Timer Cleanup\7f90505
++Node: Notification\7f91069
++Node: Coding Standards\7f91191
++Node: Upper and lower case names\7f91386
++Node: Common name patterns\7f93028
++Node: Index\7f93763
++\1f
++End Tag Table
+diff -Nurb click-1.6.0/inst/share/info/dir click-1.6.0-27/inst/share/info/dir
+--- click-1.6.0/inst/share/info/dir 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/info/dir 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,18 @@
++This is the file .../info/dir, which contains the
++topmost node of the Info hierarchy, called (dir)Top.
++The first time you invoke Info you start off looking at this node.
++\1f
++File: dir, Node: Top This is the top of the INFO tree
++
++ This (the Directory node) gives a menu of major topics.
++ Typing "q" exits, "?" lists all Info commands, "d" returns here,
++ "h" gives a primer for first-timers,
++ "mEmacs<Return>" visits the Emacs manual, etc.
++
++ In Emacs, you can click mouse button 2 on a menu item or cross reference
++ to select it.
++
++* Menu:
++
++Click modular router
++* Click: (click). The Click modular router programming manual.
+diff -Nurb click-1.6.0/inst/share/man/man1/click-align.1 click-1.6.0-27/inst/share/man/man1/click-align.1
+--- click-1.6.0/inst/share/man/man1/click-align.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-align.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,129 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-ALIGN 1 "27/Nov/1999" "Version \*V"
++.SH NAME
++click-align \- adds required Align elements to a Click configuration
++'
++.SH SYNOPSIS
++.B click-align
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click-align
++tool makes Click router configurations usable on machines that don't
++support unaligned accesses. It reads a router configuration file in the
++.M click 5
++language, adds any required
++.M Align n
++elements, and writes the new configuration to the standard output.
++.PP
++Several Click elements, such as
++.M CheckIPHeader n
++and
++.M ToLinux n ,
++have alignment requirements. The CheckIPHeader element, for example,
++expects that the packet begins with an IP header, and that this IP header
++is four-byte-aligned. Normally, Click does not guarantee this: elements
++cannot know how input packets will be aligned. The
++.B click-align
++tool first analyzes the router configuration, then inserts
++.M Align n
++elements as required to ensure that packets will be properly aligned. It
++also adds an
++.M AlignmentInfo n
++element so elements can figure out what packet alignment they can expect.
++.PP
++The list of alignment requirements is currently built in to the
++.B click-align
++tool and cannot be changed except by recompilation.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-align
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.PD 0
++.TP
++.BI \-\-expr " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to transform.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 5 ,
++.M Align n ,
++.M AlignmentInfo n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-combine.1 click-1.6.0-27/inst/share/man/man1/click-combine.1
+--- click-1.6.0/inst/share/man/man1/click-combine.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-combine.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,182 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0.5
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-COMBINE 1 "27/Apr/2000" "Version \*V"
++.SH NAME
++click-combine \- combines two or more Click configurations into one
++'
++.SH SYNOPSIS
++.B click-combine
++.RI \%[ options ]
++\%\fIname\fR=\fIfile\fR ... \e
++.br
++\% \fIname1\fR.\fIelement1\fR=\fIname2\fR.\fIelement2\fR ...
++'
++.SH DESCRIPTION
++The
++.B click-combine
++tool combines two or more Click router configurations into a single
++configuration representing the network. For example, say there is a
++point-to-point link from router A's eth0 interface to router B's eth1
++interface. Then in the combined configuration, A's ToDevice(eth0) element
++and B's PollDevice(eth1) element will be replaced with a new RouterLink
++element; packets will flow from A to B via the RouterLink element. You can
++edit the combined configuration with tools, which are effectively able to
++consider the whole network. For example, they can check cross-router
++properties or perform cross-router optimizations. Use the
++.M click-uncombine 1
++tool to extract a component router configuration from the combination.
++.PP
++Component routers are identified by name. This name must be a legal Click
++identifier (see
++.M click 5 )
++that does not contain a slash. To add a router component named
++.I N
++whose configuration is in the file
++.IR f ,
++supply the option
++.RI ` N = f '.
++You will generally supply at least two such options.
++.PP
++A link says that packets leaving one router via one element will arrive at
++another router via another element. The routers are specified by component
++name, and the elements can be specified by element name or by device name.
++To connect the
++.I e1
++element from router component
++.I A
++to the
++.I e2
++element from router component
++.IR B ,
++supply the option
++.RI ` A . e1 = B . e2 '.
++If
++.I e1
++is a
++.M ToDevice n
++element, then you can use its device name argument instead of its name.
++Similarly, if
++.I e2
++is a
++.M PollDevice n
++or
++.M FromDevice n
++element, you can use its device name argument instead of its name.
++.PP
++Link options are one-way, so if there is a duplex connection, you will need
++to give two arguments: `A.eth0=B.eth1 B.eth1=A.eth0', for example. You can
++also support more than two routers sharing a link; for example,
++`A.eth0=B.eth1 A.eth0=C.eth2'.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-combine
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BR \-o ", " \-\-output " \fIfile"
++.PD 0
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BR \-n ", " \-\-name " \fIname"
++The next router component will be named
++.IR name .
++This option and the
++.BR \-\-file
++provide an alternative to the
++.IR name = file
++syntax.
++'
++.Sp
++.TP
++.BR \-f ", " \-\-file " \fIfile"
++Read a router configuration from
++.IR file .
++Together with the
++.BR \-\-name
++option, the
++.B \-\-file
++and
++.B \-\-expression
++options provide an alternative to the
++.IR name = file
++syntax.
++'
++.Sp
++.TP
++.BR \-e ", " \-\-expression " \fIexpr"
++Use
++.IR expr ,
++a string in the Click language, as the next router configuration.
++'
++.Sp
++.TP
++.BR \-l ", " \-\-link " \fIcomponent1\fR.\fIelement1\fR=\fIcomponent2\fR.\fIelement2"
++Add a link specification as described above.
++'
++.Sp
++.TP
++.BR \-c ", " \-\-config
++Output new configuration only (not an archive with extra information).
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click-uncombine 1 ,
++.M click-xform 1 ,
++.M click 5 ,
++.M PollDevice n ,
++.M FromDevice n ,
++.M ToDevice n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-devirtualize.1 click-1.6.0-27/inst/share/man/man1/click-devirtualize.1
+--- click-1.6.0/inst/share/man/man1/click-devirtualize.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-devirtualize.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,190 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0.3
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-DEVIRTUALIZE 1 "31/Mar/2000" "Version \*V"
++.SH NAME
++click-devirtualize \- removes virtual function calls from a Click configuration
++'
++.SH SYNOPSIS
++.B click-devirtualize
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click-devirtualize
++tool speeds up a Click configuration by removing virtual function calls
++from its elements. It reads a router configuration file in the
++.M click 5
++language and creates specialized C++ source code for each element. The
++virtual function calls in this specialized C++ code are replaced with
++direct function calls to other elements in the configuration.
++.PP
++After creating the source code,
++.B click-devirtualize
++will optionally compile it into dynamically loadable packages. The elements
++in the input configuration are changed to use new, specially generated
++element classes, and the resulting configuration, plus source code and any
++compiled packages, are combined into an archive and written to the standard
++output. You can install such an archive into the
++.M click.o 8
++Linux kernel module with
++.M click-install 1 :
++.Sp
++.nf
++ % click-devirtualize -k CONFIGURATION | click-install
++.fi
++.Sp
++The
++.M click 1
++user level driver can read the archives directly.
++.PP
++The
++.B click-devirtualize
++transformation can be reversed with the
++.B \-\-reverse
++option.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-devirtualize
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP 5
++.BI \-e " expr"
++.PD 0
++.TP
++.BI \-\-expr " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to transform.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BR \-l ", " \-\-linuxmodule
++Generate a dynamically loadable package for the
++.M click.o 8
++Linux kernel module.
++'
++.Sp
++.TP
++.BR \-u ", " \-\-userlevel
++Generate a dynamically loadable package for the
++.M click 1
++user-level driver.
++'
++.Sp
++.TP 5
++.BR \-s ", " \-\-source
++Output only the specialized element class source code.
++'
++.Sp
++.TP 5
++.BR \-c ", " \-\-config
++Output only the new configuration (the one that includes specialized
++elements).
++'
++.Sp
++.TP 5
++.BR \-r ", " \-\-reverse
++Reverse the tranformation. That is, change any existing devirtualized
++element classes into the equivalent normal elements.
++'
++.Sp
++.TP
++.BI \-n " class"
++.TP
++.BI \-\-no\-devirtualize " class"
++Do not devirtualize elements whose element class is
++.IR class .
++Such elements will continue using normal source code.
++'
++.Sp
++.TP
++.BI \-i " file"
++.TP
++.BI \-\-instructions " file"
++Read devirtualization instructions from
++.IR file .
++This file can contain any number of lines. Comments start with `#';
++non-blank, non-comment lines should have devirtualization directives. There
++is currently one directive: "noclass
++.IR "class1 class2" "..."""
++is equivalent to several `\-\-no\-devirtualize
++.IR class "i'"
++options.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click-install 1 ,
++.M click 5 ,
++.M click.o 8
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-fastclassifier.1 click-1.6.0-27/inst/share/man/man1/click-fastclassifier.1
+--- click-1.6.0/inst/share/man/man1/click-fastclassifier.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-fastclassifier.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,194 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0.3
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-FASTCLASSIFIER 1 "9/Feb/2000" "Version \*V"
++.SH NAME
++click-fastclassifier \- specializes Classifier code in a Click configuration
++'
++.SH SYNOPSIS
++.B click-fastclassifier
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click-fastclassifier
++tool speeds up a Click configuration by creating fast versions of all its
++.M Classifier n ,
++.M IPClassifier n ,
++and
++.M IPFilter n
++elements. It reads a router configuration file in the
++.M click 5
++language and creates specialized C++ source code for each Classifier-like
++element. A Classifier is expanded into a series of if statements; for
++example, the expansion of `Classifier(0/80, -)' contains something like
++this function:
++.PP
++.nf
++inline void
++FastClassifier_a_ac::length_unchecked_push(Packet *p)
++{
++ const unsigned *data = (const unsigned *)(p->data() - 0);
++ step_0:
++ if ((data[0] & 255U) == 128U) {
++ output(0).push(p);
++ return;
++ }
++ output(1).push(p);
++ return;
++}
++.fi
++.PP
++After creating the source code,
++.B click-fastclassifier
++will optionally compile it into dynamically loadable packages. The
++Classifier elements in the input configuration are changed to use new
++FastClassifier elements, and the resulting configuration, plus source code
++and any compiled packages, are combined into an archive and written to the
++standard output. You can install such an archive into the
++.M click.o 8
++Linux kernel module with
++.M click-install 1 :
++.Sp
++.nf
++ % click-fastclassifier -k CONFIGURATION | click-install
++.fi
++.Sp
++The
++.M click 1
++user level driver can read the archives directly.
++.PP
++The
++.B click-fastclassifier
++transformation can be reversed with the
++.B \-\-reverse
++option.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-fastclassifier
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP 5
++.BI \-e " expr"
++.PD 0
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to transform.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BR \-k ", " \-\-kernel
++Generate a dynamically loadable package for the
++.M click.o 8
++Linux kernel module.
++'
++.Sp
++.TP
++.BR \-u ", " \-\-user
++Generate a dynamically loadable package for the
++.M click 1
++user-level driver.
++'
++.Sp
++.TP 5
++.BR \-s ", " \-\-source
++Output only the source code for the FastClassifier elements.
++'
++.Sp
++.TP 5
++.BR \-c ", " \-\-config
++Output only the new configuration (the one that includes FastClassifiers).
++'
++.Sp
++.TP 5
++.BR \-r ", " \-\-reverse
++Reverse the tranformation. That is, remove any existing FastClassifier
++elements and replace them with equivalent Classifiers.
++'
++.Sp
++.TP 5
++.BR \-q ", " \-\-quiet
++Compile code quietly (without echoing commands or top-level warnings).
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click-devirtualize 1 ,
++.M click-install 1 ,
++.M click 5 ,
++.M click.o 8 ,
++.M Classifier n ,
++.M IPClassifier n ,
++.M IPFilter n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-flatten.1 click-1.6.0-27/inst/share/man/man1/click-flatten.1
+--- click-1.6.0/inst/share/man/man1/click-flatten.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-flatten.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,133 @@
++.\" -*- mode: nroff -*-
++.ds V 1.5.0
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-FLATTEN 1 "21/May/2001" "Version \*V"
++.SH NAME
++click-flatten \- removes compound elements from a Click configuration
++'
++.SH SYNOPSIS
++.B click-flatten
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click-flatten
++tool flattens a Click router configuration, compiling all its compound
++elements away, and writes the resulting configuration to the standard
++output. It can also output information about the file.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-flatten
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BR \-c ", " \-\-classes
++.PD 0
++Output an alphabetical list of the element classes used by the flattened
++router file, one per line, instead of the usual configuration.
++'
++.Sp
++.TP 5
++.BR \-n ", " \-\-elements
++Output an alphabetical list of the element names in the flattened router
++file, one per line, instead of the usual configuration.
++'
++.Sp
++.TP 5
++.BR \-d ", " \-\-declaration
++Output the element declarations in the flattened router file, one per line,
++instead of the usual configuration.
++'
++.Sp
++.TP 5
++.BR \-f ", " \-\-file " \fIfile"
++Read the router configuration to flatten from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP 5
++.BR \-e ", " \-\-expression " \fIexpr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to flatten.
++'
++.Sp
++.TP
++.BR \-\-config
++Output flattened configuration only -- if the input was an archive, ignore
++other archive elements.
++'
++.Sp
++.TP
++.BR \-\-expand\-vars
++Expand global variables. By default,
++.B click-flatten
++does not expand global variables into configuration strings, allowing later
++operations, such as
++.BR click-install ,
++to override their values.
++'
++.Sp
++.TP
++.BR \-o ", " \-\-output " \fIfile"
++Write the flattened router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 5 ,
++.M click-check 1 ,
++.M click-xform 1
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-install.1 click-1.6.0-27/inst/share/man/man1/click-install.1
+--- click-1.6.0/inst/share/man/man1/click-install.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-install.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,237 @@
++.\" -*- mode: nroff -*-
++.ds V 1.2
++.ds D 27/Apr/2000
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-INSTALL 1 "\*D" "Version \*V"
++.SH NAME
++click-install \- installs a Click configuration into the kernel module driver
++'
++.SH SYNOPSIS
++.B click-install
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++.B Click-install
++is a convenience program that installs a Click router configuration
++into the current Linux kernel. It reads a router configuration file in the
++.M click 5
++language, installs the
++.M click.o 8
++kernel module if necessary, compiles and/or installs any dynamically
++loadable packages required by the router configuration, installs the router
++configuration itself by writing it to /click/config, and uninstalls
++any unused packages. It reports any errors to standard error, including
++errors reported by the Click module, and returns a zero (true) exit status
++if and only if the configuration was successfully installed.
++'
++.SH "OPTIONS"
++'
++Arguments such as "NAME=value" set configuration parameters, overriding any
++existing settings. Thus, "echo \%'Message($MSG)' | \fBclick\-install\fR
++MSG=Hi" will cause the kernel module to print "Hi".
++.PP
++If any filename argument is a single dash "-",
++.B click-install
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration.
++'
++.Sp
++.TP 5
++.BR \-h ", " \-\-hotswap
++Hot-swap install the new configuration. If you supply this option, the new
++configuration will only be installed if it initializes correctly. If it
++fails, the old configuration will continue to route packets without
++interruption. Furthermore, state from the old configuration\*Esuch as
++packets contained in
++.M Queue n
++elements\*Ewill be swapped into the new configuration under certain
++conditions. See under
++.B /click/hotconfig
++in
++.M click.o 8
++for details.
++'
++.Sp
++.TP 5
++.BR \-u ", " \-\-uninstall
++Uninstall and reinstall the Click kernel module.
++.B \-\-hotswap
++and
++.B \-\-uninstall
++are mutually exclusive.
++'
++.Sp
++.TP 5
++.BR \-t ", " "\-\-threads=\fIN\fP"
++The Click kernel module will run
++.I N
++threads per router. Click must have been build with
++\f(CW\-\-enable\-multithread\fR. This option only matters when
++.B click-install
++installs a Click kernel module. The thread count on an installed kernel
++module cannot be changed. (The
++.B \-\-uninstall
++option is useful here.)
++'
++.Sp
++.TP 5
++.BR \-n ", " "\-\-priority=\fIN\fP"
++Set the Click kernel thread's priority to
++.IR N .
++Lower numbers have higher priority. A typical range for priority values is
++-20 (highest) to +19 (lowest). If you do not give a
++.B \-\-priority
++option, then the current priority is left unchanged.
++'
++.Sp
++.TP 5
++.BR \-G ", " "\-\-greedy"
++The Click kernel module will claim an entire CPU, not allowing any other
++process to run. This option only matters when
++.B click-install
++installs a Click kernel module; the greediness of an installed kernel
++module cannot be changed. (The
++.B \-\-uninstall
++option is useful here.)
++'
++.Sp
++.TP 5
++.BR \-p ", " "\-\-private"
++Make the /click directory hierarchy readable only by the owning user, which
++is usually root. Generally, files under /click are writable only by the
++owner, but readable by everyone. Works only when simultaneously loading a
++Click kernel module; see
++.BR \-\-uninstall .
++'
++.Sp
++.TP 5
++.BR \-U ", " "\-\-user=\fIUSER\fR[:\fIGROUP\fR]"
++Set the user ID and group ID of the /click directory hierarchy to
++.I USER
++and group
++.IR GROUP .
++By default
++.IR USER " and " GROUP
++are both root. Works only when simultaneously loading a
++Click kernel module; see
++.BR \-\-uninstall .
++'
++.Sp
++.TP 5
++.BR \-\-\cpu =\fIN
++Sets the Click thread to preferentially run on CPU
++.IR N .
++If Click is running
++.I K
++threads, they are run preferentially on CPUs
++.I N
++up to, but not including,
++.I N
+++
++.IR K .
++Thread affinities are ignored if they refer to unavailable CPUs. Works
++only when simultaneously loading a Click kernel module; see
++.BR \-\-uninstall .
++'
++.Sp
++.TP 5
++.BR \-m ", " \-\-map
++(Linux 2.4 only) If a Click kernel module is installed, write its load map
++to standard output. This can make it easier to debug kernel panics.
++'
++.Sp
++.TP 5
++.BR \-V ", " \-\-verbose
++Print information about each step in the install process, including the
++filenames of any installed modules.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "EXIT STATUS"
++.B Click-install
++exits with one of the following return values:
++.TP 5
++.B 0
++The configuration was successfully installed.
++.TP
++.B 1
++Some error prevented
++.B click-install
++from attempting to install the configuration. For example, perhaps the
++configuration could not be parsed, or the kernel module could not be
++loaded.
++.TP
++.B 2
++The configuration was installed, but the kernel module reports that it
++could not be initialized.
++.PD
++'
++.SH "SEE ALSO"
++.M click-uninstall 1 ,
++.M click 5 ,
++.M click.o 8
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-mkmindriver.1 click-1.6.0-27/inst/share/man/man1/click-mkmindriver.1
+--- click-1.6.0/inst/share/man/man1/click-mkmindriver.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-mkmindriver.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,196 @@
++.\" -*- mode: nroff -*-
++.ds V 1.2.0
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-MKMINDRIVER 1 "28/Apr/2001" "Version \*V"
++.SH NAME
++click-mkmindriver \- generates a build environment for a minimal Click driver
++'
++.SH SYNOPSIS
++.B click-mkmindriver
++.RI "-p " packagename
++.RI \%[ options "] \e"
++.RI \%[ param = value " ...]"
++.br
++.RI "\% [" router\-files... ]
++'
++.SH DESCRIPTION
++The
++.B click-mkmindriver
++tool generates a build environment for a minimal Click driver\*Ethat is, a
++driver containing only the elements necessary to run the configurations in
++the
++.IR router\-files .
++You must supply a name for the driver,
++.IR packagename .
++Running
++.RI "`make MINDRIVER=" packagename "'"
++will create either a user-level driver named
++.RI "`" packagename "click',"
++or a Linux kernel module named
++.RI "`" packagename "click.o'."
++Run
++.B click-mkmindriver
++from the respective Click build directory, or supply a relevant
++.B \-\-directory
++option.
++.PP
++Sometimes one element depends weakly on another, especially for parsing.
++For instance, the
++.M IPEncap n
++element can take advantage of protocol names supplied by the
++.M IPNameInfo n
++class; if IPNameInfo is not available, IPEncap will still work, it just
++won't be able to parse protocol names.
++.B Click-mkmindriver
++does not include weakly dependent elements automatically, so you must
++supply them explicitly with
++.B \-E
++options if you want them. Common examples include IPNameInfo and
++IPFieldInfo. If a configuration fails to parse, try including these
++elements.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-mkmindriver
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-p " packagename"
++.PD 0
++.TP
++.BI \-\-package " packagename"
++Specifies the package name.
++'
++.Sp
++.TP
++.BI \-f " file"
++.TP
++.BI \-\-file " file"
++Read a router configuration from
++.IR file .
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as a router configuration.
++'
++.Sp
++.TP
++.BR \-a ", " \-\-all
++Include every primitive element class, even those in compound elements that
++are not themselves used, in the following router configurations. This is
++useful to add support for
++.M click-xform 1 ,
++for example.
++'
++.Sp
++.TP
++.BR \-l ", " \-\-linuxmodule
++Output a build environment for a Linux kernel module driver.
++'
++.Sp
++.TP
++.BR \-u ", " \-\-userlevel
++Output a build environment for a user-level driver. This is the default.
++'
++.Sp
++.TP
++.BI \-d " dir"
++.TP
++.BI \-\-directory " dir"
++Write output file `elements_\fIpackagename\fR.conf' to the directory
++.IR dir .
++This directory must already contain a normal build environment for the
++Click Linux module or user-level driver. (The driver required depends on
++the
++.B \-k
++and
++.B \-u
++options.) The default directory is `.'.
++'
++'
++.Sp
++.TP
++.BI \-E " elts"
++.TP
++.BI \-\-elements " elts"
++Include the element classes
++.IR elts ,
++a space-separated list of element class names.
++.B Click-mkmindriver
++will also read a router configuration, but see
++.B \-\-no\-file
++below.
++'
++.Sp
++.TP
++.BR \-\-no\-extras
++Do not add optional, but useful, element classes by default. Currently,
++these classes are
++.M Align n
++and
++.M IPNameInfo n ". "
++If a configuration or option explicitly requires one of these classes, it
++will of course be included.
++'
++.Sp
++.TP
++.BR \-V ", " \-\-verbose
++Print verbose progress information to standard error.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click.o 8
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.read.cs.ucla.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-pretty.1 click-1.6.0-27/inst/share/man/man1/click-pretty.1
+--- click-1.6.0/inst/share/man/man1/click-pretty.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-pretty.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,591 @@
++.\" -*- mode: nroff -*-
++.ds V 1.5.0
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-PRETTY 1 "4/Jan/2002" "Version \*V"
++.SH NAME
++click-pretty \- pretty-prints a Click configuration in HTML
++'
++.SH SYNOPSIS
++.B click-pretty
++.RI \%[ options ", " param = value " ...]"
++.RI \%[ routerfile ]
++.RI "> " output\fR.html
++.br
++.B click-pretty
++.B \-\-dot
++.RI \%[...]
++.RI \%[ routerfile \]
++.RB "| " "dot \fR\-Tpng"
++.RI "> " output\fR.png
++'
++.SH DESCRIPTION
++The
++.B click-pretty
++tool pretty-prints Click configurations into HTML files, including syntax
++highlighting and optional indexes; or, optionally, it can output a graph
++definition suitable for passing to
++.M dot 1 .
++.B Click-pretty
++reads a router configuration and, optionally, an HTML-like template file,
++replaces special tags in the template with HTML code derived from the
++configuration, and writes the result to the standard output.
++'
++.SH "HTML TEMPLATES"
++.BR Click-pretty 's
++HTML output is based on a template file that contains special HTML-like
++tags. These tags, which start with a tilde "~", control
++.BR click-pretty 's
++operation.
++'
++.SS "The config Tag"
++'
++.PP
++The
++.B <~config>
++tag expands to a pretty-printed version of the router configuration.
++Various features in the configuration are highlighted with HTML
++.B <span class=xxx>
++tags; the class differs from feature to feature, so you can affect the
++output with CSS. The classes are:
++.PP
++.TP 10
++.B c-cmt
++.PD 0
++Comments.
++.TP
++.B c-kw
++Keywords.
++.TP
++.B c-cfg
++Configuration strings.
++.TP
++.B c-cd
++Element class declarations.
++.TP
++.B c-ed
++Element declarations.
++.TP
++.B c-err
++Configuration errors.
++.PD
++.PP
++Other features of the output include:
++.TP 3
++\(bu
++'
++Anchors marking element declarations and element class declarations. For
++example, the tag
++.BR "<a name='e-X'>"
++encloses the declaration of an element named
++.BR X .
++'
++.TP
++\(bu
++'
++A
++.B span title
++attribute encloses every element reference, giving that element's
++declaration. Thus, a user can find out what class an element has by
++hovering their mouse over a reference to it.
++'
++.TP
++\(bu
++'
++Similarly,
++.BR "span title" s
++explain configuration errors in more detail.
++'
++.TP
++\(bu
++'
++Element class names are linked to element class declarations, for compound
++elements, or, optionally, to Web documentation, for primitive element
++classes. See the
++.B \-u
++option, below.
++'
++.SS "The elements Tag"
++'
++.PP
++The
++.B "<~elements>"
++tag expands to an alphabetical list of the elements and/or element classes
++used in the router configuration. The
++.B entry
++attribute determines how elements are rendered;
++.B typeentry
++does the same for classes. Inside these attributes, subtags like
++.BR <~name> ,
++.BR <~type> ,
++and
++.BR <~inputs>
++expand to information about the relevant element or type. For example, this
++.B <~elements>
++tag expands to a comma-separated list of the configuration's elements:
++.Es
++<~elements entry="<~name>" sep=", ">
++.Ee
++This one expands to an unordered list of declarations, with element names
++and type names linked to relevant declarations in the configuration:
++.Es
++<ul>
++<~elements entry="<li><~name link> :: <~type link></li>">
++</ul>
++.Ee
++'
++.SS "elements Tag Attributes"
++.TP 5
++.BR entry =\fItext
++Sets the text used for each element in the configuration. If this attribute
++is absent, the
++.B <~element>
++tag's expansion will not mention elements.
++'
++.TP 5
++.BR typeentry =\fItext
++Sets the text used for each element type used by the configuration. If this
++attribute is absent, the
++.B <~element>
++tag's expansion will not mention element types.
++'
++.TP 5
++.BR sep =\fItext
++Sets the text used to separate entries in the expansion.
++'
++.TP 5
++.BR column =\fIwhich\fR/\fIcount
++If present,
++.I count
++should be a number greater than 1, and
++.I which
++should be between 1 and
++.IR count .
++The
++.B <~element>
++tag is expanded, then broken into
++.I count
++columns at entry boundaries. Only the
++.IR which th
++column is printed.
++'
++.TP 5
++.BR configlink =\fItext
++See the
++.B <~configlink>
++subtag below.
++'
++.TP 5
++.BR typeref =\fItext
++See the
++.B <~typerefs>
++subtag below.
++'
++.TP 5
++.BR inputentry "=\fItext\fR, " noinputentry "=\fItext\fR"
++See the
++.B <~inputs>
++subtag below.
++'
++.TP 5
++.BR outputentry "=\fItext\fR, " nooutputentry "=\fItext\fR"
++See the
++.B <~outputs>
++subtag below.
++'
++.TP 5
++.BR inputconnection "=\fItext\fR, " noinputconnection "=\fItext\fR"
++See the
++.B <~inputconnections>
++subtag below.
++'
++.TP 5
++.BR outputconnection "=\fItext\fR, " nooutputconnection "=\fItext\fR"
++See the
++.B <~outputconnections>
++subtag below.
++'
++.PD
++'
++.SS "Subtags"
++.PP
++These subtags apply only within
++.B <~elements>
++entries and type entries.
++'
++.TP 5
++.BR "<~name [link" "=\fIlink\fR" "]>"
++Expands to the current element's name. When the
++.B link
++attribute is present, the name is contained in a link pointing at the
++declaration site within the router configuration or, when
++.I link
++equals "type", the element class's Web documentation.
++'
++.TP 5
++.BR "<~type [link]>"
++Expands to the current element type's name, or the current element's
++type-name. When the
++.B link
++attribute is present, the name is contained in a link pointing at the
++the element class's Web documentation.
++'
++.TP 5
++.BR "<~config [limit" "=\fIlimit" "] [parens]>"
++Elements only. Expands to the current element's configuration string. The
++result contains at most \fIlimit\fR characters; if the configuration string
++was longer,
++.B click-pretty
++prints its first \fIlimit\fR characters, followed by an ellipsis. If
++.B parens
++was supplied, non-empty configuration strings are enclosed in parentheses.
++'
++.TP 5
++.BR "<~configlink [text" "=\fItext" "]>"
++Elements only. Expands to a link to the element's declaration in the router
++configuration. The
++.B text
++attribute gives the link text; it defaults to the
++.B <~elements>
++tag's
++.B configlink
++attribute.
++'
++.TP 5
++.BR "<~typerefs [entry" "=\fItext" "] [sep" "=\fIsep" "]>"
++Expands to an alphabetical list of elements in the configuration that have
++the current element type, separated by \fIsep\fR. The
++.B entry
++attribute specifies how to render each element; it defaults to the
++.B <~elements>
++tag's
++.B typeref
++attribute.
++'
++.TP 5
++.BR "<~ninputs [english]>"
++Elements only. Expands to the current element's number of input ports. If
++.B english
++was supplied, either "input" or "inputs" follows the number.
++'
++.TP 5
++.BR "<~outputs [english]>"
++Elements only. Expands to the current element's number of output ports. If
++.B english
++was supplied, either "input" or "inputs" follows the number.
++'
++.TP 5
++.BR "<~inputs [entry" "=\fItext" "] [noentry" "=\fItext" "] [sep" "=\fIsep" "]>"
++Elements only. Expands to a list of the element's input ports. The
++.B entry
++attribute specifies how to render each port; it defaults to the
++.B <~elements>
++tag's
++.B inputentry
++attribute. If the element has no input ports, the
++.B noentry
++attribute is used instead, which defaults to the
++.B <~elements>
++tag's
++.B noinputentry
++attribute.
++'
++.TP 5
++.BR "<~outputs [entry" "=\fItext" "] [noentry" "=\fItext" "] [sep" "=\fIsep" "]>"
++Elements only. Expands to a list of the element's output ports. The
++.B entry
++attribute specifies how to render each port; it defaults to the
++.B <~elements>
++tag's
++.B outputentry
++attribute. If the element has no output ports, the
++.B noentry
++attribute is used instead, which defaults to the
++.B <~elements>
++tag's
++.B nooutputentry
++attribute.
++.PD
++'
++.TP 5
++.BR "<~if test" "=\fItext" " [then" "=\fItext" "] [else" "=\fItext" "] [eq" "=\fItext" "]"
++.PD 0
++.TP
++.BR " [ne" "=\fItext" "] [gt" "=\fItext" "] [lt" "=\fItext" "] [ge" "=\fItext" "] [le" "=\fItext" "]>"
++.PD
++Silently expands the
++.B test
++attribute, then makes a comparison. If that comparison is true, expands the
++.B then
++attribute; otherwise, expands the
++.B else
++attribute. The comparison depends on which of the other attributes is
++present. When
++.B eq
++is supplied, the comparison is true if
++.BR test 's
++expansion equals
++.BR eq 's
++expansion.
++.B ne
++checks for inequality.
++The
++.BR gt ,
++.BR lt ,
++.BR ge ,
++and
++.BR le
++attributes compare strings (or integers) in alphabetical (or numeric)
++sorting order. A
++.B gt
++comparison is true when
++.BR test 's
++expansion is greater than
++.BR gt 's
++expansion; similarly,
++.B lt
++checks for less than,
++.B ge
++for greater-than-or-equal-to, and
++.B le
++for less-than-or-equal-to. If none of these attributes are present, the
++test is true if
++.B test
++expands to a nonempty string.
++'
++.SS "Port-Specific Subtags"
++These subtags apply only within
++.B <~inputs>
++and
++.B <~outputs>
++entries.
++'
++.TP 5
++.BR "<~port>"
++Expands to the current port number.
++'
++.TP 5
++.BR "<~processing>"
++Expands to the current port's processing value: either "push", "pull", or
++(rarely) "agnostic".
++'
++.TP 5
++.BR "<~inputconnections [entry" "=\fItext" "] [noentry" "=\fItext" "] [sep" "=\fIsep\fR" "]>"
++Expands to a list of the output ports to which this input port is
++connected. List entries are separated by \fIsep\fR. The
++.B entry
++attribute specifies how to render each port; it defaults to the
++.B <~elements>
++tag's
++.B inputconnection
++attribute. If the port is not connected to anything, the
++.B noentry
++attribute is used instead, which defaults to the
++.B <~elements>
++tag's
++.B noinputconnection
++attribute.
++'
++.TP 5
++.BR "<~outputconnections [entry" "=\fItext" "] [noentry" "=\fItext" "] [sep" "=\fIsep\fR" "]>"
++Expands to a list of the input ports to which this output port is
++connected. List entries are separated by \fIsep\fR. The
++.B entry
++attribute specifies how to render each port; it defaults to the
++.B <~elements>
++tag's
++.B outputconnection
++attribute. If the port is not connected to anything, the
++.B noentry
++attribute is used instead, which defaults to the
++.B <~elements>
++tag's
++.B nooutputconnection
++attribute.
++.PD
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-align
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write HTML output to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BI \-t " file"
++.TP
++.BI \-\-template " file"
++Use
++.I file
++as the HTML template file. If no template is specified,
++.B click-pretty
++will use a built-in default.
++'
++.Sp
++.TP
++.BI \-d "name\fR=\fItext"
++.TP
++.BI \-\-define " name\fR=\fItext"
++Defines a new tag named
++.IR name .
++Occurrences of
++.BI <~ name >
++in the template will be replaced with the expansion of
++.IR text .
++'
++.Sp
++.TP
++.BR \-\-userlevel
++.TP
++.BR \-k ", " \-\-linuxmodule
++.TP
++.BR \-b ", " \-\-bsdmodule
++Specifies the driver for which the configuration was designed. This is
++necessary to discover whether ports are push or pull. Usually, you don't
++have to give any of these options;
++.B click-pretty
++will figure out the right answer by looking at the configuration.
++'
++.Sp
++.TP
++.BI \-u " url"
++.TP
++.BI \-\-class\-docs " url"
++Web documentation for primitive element classes is available at
++.IR url .
++The
++.I url
++may contain a single "%s", which is replaced with the element class's
++documentation name. (This is the same as its regular name, unless
++.B =title
++was specified in the documentation comment.) URLs specified in elementmap
++files with $webdoc take precedence over
++.BR \-u .
++'
++.Sp
++.TP
++.BI \-\-package\-docs " package\fR=\fIurl"
++Web documentation for primitive element classes in package
++.I package
++is available at
++.IR url .
++The
++.I url
++may contain a single "%s", which is replaced with the element class's
++documentation name. URLs specified in elementmap files take precedence over
++.BR \-\-package\-docs .
++'
++.Sp
++.TP
++.BI \-\-write\-template
++Output the template unmodified. This is useful for getting a look at the
++built-in default.
++'
++.Sp
++.TP
++.BI \-\-dot
++Rather than generating HTML, generate a graph definition suitable for input
++to the
++.M dot 1
++program (part of the
++.B graphviz
++suite originally from Bell Labs). Using
++.BR \-\-dot ,
++you can automatically generate a PNG or PostScript graphic showing a
++picture of the Click configuration, as in "\fBclick-pretty\fR router.click
++| \fBdot\fR \-Tpng >routerpicture.png".
++'
++.Sp
++.TP
++.BI \-C " path"
++.TP
++.BI \-\-clickpath " path"
++Use
++.I path
++for CLICKPATH.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH FILES
++.TP 5
++.B CLICKDIR/share/click/elementmap
++.B Click-pretty
++uses elementmap files to determine whether ports are push or pull. You can
++also add `$webdoc URL' lines to elementmap files;
++.B click-pretty
++will use that URL for element classes described in that elementmap. As with
++the
++.B \-u
++option, a $webdoc URL can contain `%s', which is replaced with the element
++class name.
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
+diff -Nurb click-1.6.0/inst/share/man/man1/click-uncombine.1 click-1.6.0-27/inst/share/man/man1/click-uncombine.1
+--- click-1.6.0/inst/share/man/man1/click-uncombine.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-uncombine.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,107 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0.5
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-UNCOMBINE 1 "27/Apr/2000" "Version \*V"
++.SH NAME
++click-uncombine \- separates a component from a combined Click configuration
++'
++.SH SYNOPSIS
++.B click-uncombine
++.RI \%[ param = value " ...]"
++.RI \%[ options ]
++.RI \%[ router\-file " [" \fIcomponent\fR ]]
++'
++.SH DESCRIPTION
++The
++.B click-uncombine
++tool reads a combined router configuration created by
++.M click-combine 1
++and outputs one of its components. The chosen component is specified by its
++name, as originally specified to
++.M click-combine 1 .
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-uncombine
++will use the standard input or output instead, as appropriate. You can give
++one or two non-option arguments; the first is the router file and the
++second, the component name.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the combined router configuration from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-n " name"
++.TP
++.BI \-\-name " name"
++Output the router component named
++.IR name .
++'
++.Sp
++.TP 5
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click-combine 1 ,
++.M click 5
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-undead.1 click-1.6.0-27/inst/share/man/man1/click-undead.1
+--- click-1.6.0/inst/share/man/man1/click-undead.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-undead.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,203 @@
++.\" -*- mode: nroff -*-
++.ds V 1.1
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-UNDEAD 1 "28/Aug/2000" "Version \*V"
++.SH NAME
++click-undead \- removes dead code from a Click configuration
++'
++.SH SYNOPSIS
++.B click-undead
++.RI \%[ param = value " ...]"
++.RI \%[ options ]
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click-undead
++tool speeds up some Click configurations by removing dead code. This
++includes:
++.IP "\(bu" 3
++Any
++.M Null n ,
++.M StaticSwitch n ,
++and
++.M StaticPullSwitch n
++elements.
++.IP "\(bu" 3
++Any elements not reachable from both a
++.I source element
++and a
++.IR "sink element" .
++Click packet source elements include
++.M FromDevice n
++and
++.M InfiniteSource n ;
++packet sink elements include
++.M ToDump n ,
++.M ToDevice n ,
++and
++.M Discard n
++(when it is used as a pull element).
++.IP "\(bu" 3
++Dead ports on scheduler elements
++.RM ( RoundRobinSched n ,
++.M PrioSched n ,
++.M StrideSched n ,
++and so on) are removed. These are ports that no packet could ever enter.
++.IP "\(bu" 3
++Scheduler elements that have only one attached input are redundant, so they
++are removed.
++.IP "\(bu" 3
++Dead ports on tee elements
++.RM ( Tee n ,
++.M PullTee n )
++are removed. These are ports with no packet sink downstream.
++.IP "\(bu" 3
++Tee elements that have only one attached output are redundant, so they are
++removed.
++.PP
++.B click-undead
++will not remove any information elements. Connections to removed elements
++are rerouted appropriately.
++.PP
++For example,
++.B click-undead
++will transform this configuration,
++.Sp
++.nf
++ Idle -> Counter -> td1 :: ToDump(a);
++ InfiniteSource -> ss :: StaticSwitch(1);
++ ss[0] -> ToDump(c);
++ ss[1] -> Queue -> rr :: RoundRobinSched;
++ Idle -> [1]rr;
++ rr -> td2 :: ToDump(b);
++.fi
++.Sp
++into this configuration:
++.Sp
++.nf
++ InfiniteSource -> Queue -> td2 :: ToDump(b);
++.fi
++.Sp
++Note that the resulting configuration is not guaranteed to have the same
++semantics as the input configuration. Here, for example, the result
++configuration does not truncate the files `a' and `c'.
++.PP
++The resulting configuration is written to the standard output.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-undead
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to transform.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BR \-k ", " \-\-kernel
++Check the configuration only for the
++.M click.o 8
++Linux kernel module driver.
++'
++.Sp
++.TP
++.BR \-u ", " \-\-user
++Check the configuration only for the
++.M click 1
++user-level driver.
++'
++.Sp
++.TP 5
++.BR \-c ", " \-\-config
++Output only the new configuration, not any archived packages.
++'
++.Sp
++.TP 5
++.BR \-V ", " \-\-verbose
++Print debugging information about the transformation\*Efor example, which
++elements are chosen as sources and sinks.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click-install 1 ,
++.M click 5 ,
++.M click.o 8 ,
++.M Discard n ,
++.M FromDevice n ,
++.M InfiniteSource n ,
++.M ToDump n ,
++.M ToDevice n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-uninstall.1 click-1.6.0-27/inst/share/man/man1/click-uninstall.1
+--- click-1.6.0/inst/share/man/man1/click-uninstall.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-uninstall.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,73 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-UNINSTALL 1 "9/Feb/2000" "Version \*V"
++.SH NAME
++click-uninstall \- uninstalls the Click kernel module
++'
++.SH SYNOPSIS
++.B click-uninstall
++.I \%[options]
++'
++.SH DESCRIPTION
++.B Click-uninstall
++is a convenience program that uninstalls Click from the current Linux
++kernel. It uninstalls the currently running configuration, any dynamically
++loadable Click packages, and the
++.M click.o 8
++kernel module itself.
++'
++.SH "OPTIONS"
++'
++.TP 5
++.BI \-\-help
++.PD 0
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "SEE ALSO"
++.M click-install 1 ,
++.M click 5 ,
++.M click.o 8
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click-xform.1 click-1.6.0-27/inst/share/man/man1/click-xform.1
+--- click-1.6.0/inst/share/man/man1/click-xform.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click-xform.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,310 @@
++.\" -*- mode: nroff -*-
++.ds V 1.0.3
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK-XFORM 1 "31/Mar/2000" "Version \*V"
++.SH NAME
++click-xform \- pattern-based Click configuration optimizer
++'
++.SH SYNOPSIS
++.B click-xform
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file " [" pattern\-files ...]]
++'
++.SH DESCRIPTION
++The
++.B click-xform
++tool is a Click router configuration optimizer. It reads files giving Click
++configuration patterns and their replacements, and a router configuration
++file. Then it replaces pattern matches in the configuration until none
++remain and writes the new configuration to the standard output.
++.PP
++Pattern files use the Click language (see
++.M click 5 ).
++They contain pairs of `elementclass' definitions, where each pair consists
++of one pattern text and one replacement text. The replacement for a pattern
++named
++.RI ` X '
++must be named
++.RI ` X _Replacement'.
++This example pattern file replaces all Queues with Queue-Shaper
++combinations:
++.Rs
++.nf
++elementclass QueuePattern {
++ input -> Queue -> output;
++}
++elementclass QueuePattern_Replacement {
++ input -> Queue -> Shaper(200) -> output;
++}
++.fi
++.Re
++.PP
++A pattern text can contain an arbitrary number of elements, and an
++arbitrary number of input and output ports. Basically, a pattern matches a
++fragment of a router configuration when they have the same number of
++elements; their element classes match; all of the pattern's connections are
++duplicated in the fragment; and any connections into or out of the fragment
++correspond to connections to or from the pattern's input and output ports.
++The formal definition of matching is given below.
++.PP
++Any configuration strings in the pattern must match the configuration
++strings in the configuration subset. The pattern can use variables, which
++look like `$[letters, numbers and underscores]', to match a set of
++configuration strings; except for variables, the strings must match
++verbatim. A variable matches a single configuration argument. The same
++variable can be used multiple times in a pattern; if so, then it must match
++the same text on each occurrence. If a variable is used in the
++replacement's configuration strings, then when a replacement is made, the
++text that matched in the pattern will be inserted instead. For example,
++applying this pattern
++.Rs
++.nf
++elementclass Meters {
++ input -> Meter($a)
++ -> Shaper($b) -> output;
++}
++elementclass Meters_Replacement {
++ input -> Meter($b)
++ -> SlowShaper($a) -> output;
++}
++.fi
++.Re
++to this configuration
++.Rs
++.nf
++\&... -> Meter(1000) -> Shaper(2000) -> ...
++.fi
++.Re
++will create this result:
++.Rs
++.nf
++\&... -> Meter(2000) -> SlowShaper(1000) -> ...
++.fi
++.Re
++.PP
++The optimizer will not apply the same pattern to a configuration subset
++twice in succession. Specifically, every replacement element is marked with
++the pattern that generated it; a pattern will not match a configuration
++fragment if every element in that fragment came from that pattern. Thus, a
++pattern like the QueuePattern above won't cause an infinite loop. You can
++still cause an infinite loop, if you'd like, by having two patterns that
++match the same text:
++.Rs
++.nf
++elementclass Evil1 {
++ input -> Queue -> output;
++}
++elementclass Evil1_Replacement {
++ input -> Queue -> output;
++}
++elementclass Evil2 {
++ input -> Queue -> output;
++}
++elementclass Evil2_Replacement {
++ input -> Queue -> output;
++}
++.fi
++.Re
++This collection of patterns will make the optimizer run forever on any
++configuration that has a Queue.
++.PP
++The
++.B click-xform
++transformation can be reversed with the
++.B \-\-reverse
++option.
++'
++.SH "OPTIONS"
++'
++If any filename argument is a single dash "-",
++.B click-xform
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-p " file"
++.PD 0
++.TP
++.BI \-\-patterns " file"
++Read patterns and replacements from
++.IR file .
++You can give any number of these options.
++'
++.Sp
++.TP
++.BI \-f " file"
++.TP
++.BI \-\-file " file"
++Read the router configuration to transform from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration to transform.
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write the output router configuration to
++.IR file .
++The default is the standard output.
++'
++.Sp
++.TP
++.BR \-r ", " \-\-reverse
++Apply the patterns in reverse. That is, replace occurrences of the
++replacement texts with the corresponding pattern texts.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "FORMAL DEFINITION OF MATCHING"
++'
++A pattern
++.I P
++matches a subset
++.I S
++of the configuration's elements if the following conditions hold:
++.TP 4
++\(bu
++There is a one-to-one mapping
++.I map
++from
++.I P
++to
++.I S
++that respects element classes (that is, if an element
++.IR p " in " P
++has class
++.IR K ,
++then
++.RI map( p ") also has class " K ).
++.TP 4
++\(bu
++The configuration strings match, possibly by using a consistent variable
++assignment.
++.TP 4
++\(bu
++For every connection
++.RI ` p1 " [" x "] -> [" y "] " p2 '
++in the pattern
++.IR P ,
++there exists a connection
++.RI `map( p1 ") [" x "] -> [" y "] map(" p2 )'
++in the configuration subset
++.IR S .
++.TP 4
++\(bu
++For every connection
++.RI ` c1 " [" x "] -> [" y "] " c2 '
++in the configuration, one of four conditions hold:
++.RS
++.TP 3
++\(bu
++The connection is wholly outside the subset
++.IR S .
++(That is,
++.IR c1 " is not in " S
++and
++.IR c2 " is not in " S .)
++.TP 3
++\(bu
++The connection is inside the subset, and corresponds to a connection in the
++pattern. (That is,
++.IR c1 " is in " S ,
++.IR c2 " is in " S ,
++and
++.I P
++has a connection
++.RI "`map-1(" c1 ") [" x "] -> [" y "] map-1(" c2 ")'.)"
++.TP 3
++\(bu
++The connection goes into the subset, and corresponds to an input port in
++the pattern. (That is,
++.IR c1 " is not in " S
++but
++.IR c2 " is in " S ,
++and there exists an input port number
++.I i
++so that
++.I P
++has a connection
++.RI "`input [" i "] -> [" y "] map-1(" c2 ")',"
++and for every connection in the pattern
++.RI "`input [" i "] -> [" z "] " q ',
++there is a connection in the configuration
++.RI ` c1 " [" x "] -> [" z "] map(" q ")'.)"
++.TP 3
++\(bu
++The connection goes out of the subset, and corresponds to an output port in
++the pattern. (That is,
++.IR c1 " is in " S
++but
++.IR c2 " is not in " S ,
++and there exists an output port number
++.I o
++so that
++.I P
++has a connection
++.RI "`map-1(" c1 ") [" x "] -> [" o "] output',"
++and for every connection in the pattern
++.RI ` q " [" z "] -> [" o "] output',"
++there is a connection in the configuration
++.RI "`map(" q ") [" z "] -> [" y "] " c2 "'.)"
++.RE
++'
++.SH "SEE ALSO"
++.M click 5
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/click.1 click-1.6.0-27/inst/share/man/man1/click.1
+--- click-1.6.0/inst/share/man/man1/click.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/click.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,259 @@
++.\" -*- mode: nroff -*-
++.ds V 1.3
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK 1 "26/Mar/2003" "Version \*V"
++.SH NAME
++click \- Click user-level driver
++'
++.SH SYNOPSIS
++.B click
++.RI \%[ options ]
++.RI \%[ param = value " ...]"
++.RI \%[ router\-file ]
++'
++.SH DESCRIPTION
++The
++.B click
++driver executes a Click modular router specification in a user-level
++program. It reads a router configuration file, sets up the router according
++to that file, and generally continues until interrupted. The router
++configuration is written in the Click language (see
++.M click 5 ),
++and can contain dynamically loadable code, which
++.B click
++will link against before installing the configuration.
++.PP
++The
++.B click
++program can read and write packets from the network using Berkeley Packet
++Filters\*Esee
++.M FromDevice.u n
++and
++.M ToDevice.u n .
++It can also read and write BPF dump files, such as those created by
++.M tcpdump 1 "\*Esee"
++.M FromDump n
++and
++.M ToDump n .
++The
++.M InfiniteSource n
++element, and others like it, may be useful for testing configurations
++without affecting the network.
++'
++.SH "OPTIONS"
++'
++Arguments such as "NAME=value" set configuration parameters, overriding any
++existing settings. Thus, "echo \%'Message($MSG)' | \fBclick\fR MSG=Hi" will
++print "Hi".
++.PP
++If any filename argument is a single dash "-",
++.B click
++will use the standard input or output instead, as appropriate.
++'
++.TP 5
++.BI \-f " file"
++.PD 0
++.TP
++.BI \-\-file " file"
++Read the router configuration from
++.IR file .
++The default is the standard input.
++'
++.Sp
++.TP
++.BI \-e " expr"
++.TP
++.BI \-\-expression " expr"
++Use
++.IR expr ,
++a string in the Click language, as the router configuration.
++'
++.Sp
++.TP
++.BI \-p " port"
++.TP
++.BI \-\-port " port"
++Open a
++.M ControlSocket n
++connection listening on TCP port
++.IR port .
++ControlSockets allow users to connect to the router and call its read and
++write handlers remotely.
++'
++.Sp
++.TP
++.BI \-u " file"
++.TP
++.BI \-\-unix\-socket " file"
++Open a
++.M ControlSocket n
++connection listening on a Unix socket, on file
++.IR file .
++'
++.Sp
++.TP
++.BR \-R ", " \-\-allow\-reconfigure
++Provide a "hotconfig" handler, which allows remote
++.M ControlSocket n
++users, and elements within the router, to reconfigure the router
++dynamically. See
++.M click.o 8 's
++"/click/hotconfig" section for more information on hot-swapping.
++'
++.Sp
++.TP
++.BI \-h " \fR[\fPelement\fR.]\fPhandler"
++.TP
++.BI \-\-handler " \fR[\fPelement\fR.]\fPhandler"
++After running the driver, call
++.IR element 's
++read handler named
++.IR handler ,
++or the global read handler named
++.IR handler ,
++and print the result to standard output. Each element has several generic
++handlers\*Efor example,
++.BR config
++returns the element's configuration string and
++.BR class
++returns the element's class name. Some elements have additional handlers;
++.M Counter n ,
++for example, has
++.BR count " and " rate
++handlers that return the number of packets arrived and the recent arrival
++rate in packets per second. See
++.M click.o 8
++for more information on generic handlers, and the element documentation for
++more information on element-specific handlers.
++.Sp
++.I element
++may be a pattern that uses the shell's globbing syntax (*, ?, and
++[...]). In this case,
++.B click
++will run each
++.I handler
++whose element's name matches the pattern.
++.I element
++may also be an element class or interface name, such as "Queue" or "Storage";
++.B click
++will run each
++.I handler
++whose element has that class or interface.
++'
++.Sp
++.TP
++.BI \-x " \fR[\fPelement\fR.]\fPhandler"
++.TP
++.BI \-\-exit-handler " \fR[\fPelement\fR.]\fPhandler"
++After running the driver, call
++.IR element 's
++read handler named
++.IR handler ,
++or the global read handler named
++.IR handler ,
++and use the result as the
++.B click
++process exit value. The handler should return an integer, which is used directly, or a boolean (true means 0, false means 1).
++'
++.Sp
++.TP
++.BI \-o " file"
++.TP
++.BI \-\-output " file"
++Write a flattened version of the router configuration to
++.IR file .
++The flattening process removes all compound elements and additional archive
++members.
++'
++.Sp
++.TP 5
++.BR \-q ", " \-\-quit
++Do not run the driver. This option can be used to check a configuration for
++errors, or to check handler results (with the
++.B \-\-handler
++option) without running the configuration.
++'
++.Sp
++.TP 5
++.BR \-t ", " \-\-time
++Print the time it took to run the driver.
++'
++.Sp
++.TP 5
++.BR \-w ", " \-\-no\-warnings
++Do not print any warning messages.
++'
++.Sp
++.TP
++.BI \-C " path"
++.TP
++.BI \-\-clickpath " path"
++Use
++.I path
++for CLICKPATH.
++'
++.Sp
++.TP 5
++.BI \-\-help
++Print usage information and exit.
++'
++.Sp
++.TP
++.BI \-\-version
++Print the version number and some quickie warranty information and exit.
++'
++.PD
++'
++.SH "BUGS"
++If you get an unaligned access error, try running your configuration
++through
++.M click-align 1
++first.
++'
++.SH "SEE ALSO"
++.M click-align 1 ,
++.M click 5 ,
++.M click.o 8 ,
++.M ControlSocket n ,
++.M FromDevice.u n ,
++.M ToDevice.u n ,
++.M FromDump n ,
++.M ToDump n ,
++.M tcpdump 1 ,
++.M InfiniteSource n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man1/testie.1 click-1.6.0-27/inst/share/man/man1/testie.1
+--- click-1.6.0/inst/share/man/man1/testie.1 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man1/testie.1 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,309 @@
++.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
++.\"
++.\" Standard preamble:
++.\" ========================================================================
++.de Sh \" Subsection heading
++.br
++.if t .Sp
++.ne 5
++.PP
++\fB\\$1\fR
++.PP
++..
++.de Sp \" Vertical space (when we can't use .PP)
++.if t .sp .5v
++.if n .sp
++..
++.de Vb \" Begin verbatim text
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve \" End verbatim text
++.ft R
++.fi
++..
++.\" Set up some character translations and predefined strings. \*(-- will
++.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
++.\" double quote, and \*(R" will give a right double quote. | will give a
++.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
++.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
++.\" expand to `' in nroff, nothing in troff, for use with C<>.
++.tr \(*W-|\(bv\*(Tr
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.ie n \{\
++. ds -- \(*W-
++. ds PI pi
++. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
++. ds L" ""
++. ds R" ""
++. ds C` ""
++. ds C' ""
++'br\}
++.el\{\
++. ds -- \|\(em\|
++. ds PI \(*p
++. ds L" ``
++. ds R" ''
++'br\}
++.\"
++.\" If the F register is turned on, we'll generate index entries on stderr for
++.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
++.\" entries marked with X<> in POD. Of course, you'll have to process the
++.\" output yourself in some meaningful fashion.
++.if \nF \{\
++. de IX
++. tm Index:\\$1\t\\n%\t"\\$2"
++..
++. nr % 0
++. rr F
++.\}
++.\"
++.\" For nroff, turn off justification. Always turn off hyphenation; it makes
++.\" way too many mistakes in technical documents.
++.hy 0
++.if n .na
++.\"
++.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
++.\" Fear. Run. Save yourself. No user-serviceable parts.
++. \" fudge factors for nroff and troff
++.if n \{\
++. ds #H 0
++. ds #V .8m
++. ds #F .3m
++. ds #[ \f1
++. ds #] \fP
++.\}
++.if t \{\
++. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++. ds #V .6m
++. ds #F 0
++. ds #[ \&
++. ds #] \&
++.\}
++. \" simple accents for nroff and troff
++.if n \{\
++. ds ' \&
++. ds ` \&
++. ds ^ \&
++. ds , \&
++. ds ~ ~
++. ds /
++.\}
++.if t \{\
++. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.\}
++. \" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++. \" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++. \" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++. ds : e
++. ds 8 ss
++. ds o a
++. ds d- d\h'-1'\(ga
++. ds D- D\h'-1'\(hy
++. ds th \o'bp'
++. ds Th \o'LP'
++. ds ae ae
++. ds Ae AE
++.\}
++.rm #[ #] #H #V #F C
++.\" ========================================================================
++.\"
++.IX Title "TESTIE 1"
++.TH TESTIE 1 "" "perl v5.8.8" ""
++.SH "NAME"
++testie \- simple test harness
++.SH "SYNOPSIS"
++.IX Header "SYNOPSIS"
++.Vb 1
++\& testie [OPTIONS] [FILE]...
++.Ve
++.SH "DESCRIPTION"
++.IX Header "DESCRIPTION"
++Testie is a simple test harness. Each testie test file incorporates a shell
++script to be run and, optionally, input and expected output files for that
++script. Testie runs the script; the test fails if any of the script
++commands fail, or if the script generates unexpected output.
++.PP
++To run testie, pass it one or more test filenames. It will print useful
++error messages for failed tests. Alternatively, give it directory names;
++the directories are recursively searched for '\fI*.testie\fR' files.
++.PP
++Return status is 0 if all tests succeed, 1 if any test fails, and 2 if a
++test fails due to an internal error. Tests whose \f(CW%require\fR prerequisites
++fail do not affect the return status, except that if all tests'
++prerequisites fail, the return status is 1 instead of 0.
++.SH "OPTIONS"
++.IX Header "OPTIONS"
++.IP "\fI\s-1VARIABLE\s0\fR=\fI\s-1VALUE\s0\fR" 8
++.IX Item "VARIABLE=VALUE"
++Provide a setting for \fI\s-1VARIABLE\s0\fR. Occurrences in the script of
++\&'\f(CW$VARIABLE\fR' or '\f(CW\*(C`${VARIABLE}\*(C'\fR' will be replaced by \fI\s-1VALUE\s0\fR. Note that
++this is not an environment variable setting. Variable references to unset
++variables are left unchanged.
++.IP "\-V, \-\-verbose" 8
++.IX Item "-V, --verbose"
++Print information to standard error about successful tests as well as
++unsuccessful tests.
++.IP "\-VV, \-\-superverbose" 8
++.IX Item "-VV, --superverbose"
++Like \-\-verbose, but use a slightly different format, and additionally print
++every test's \f(CW%desc\fR section before the test results.
++.IP "\-v, \-\-version" 8
++.IX Item "-v, --version"
++Print version number information and exit.
++.IP "\-\-help" 8
++.IX Item "--help"
++Print help information and exit.
++.IP "\-\-preserve\-temporaries" 8
++.IX Item "--preserve-temporaries"
++Preserve the temporary directory created for the test.
++.IP "\-s, \-\-show \s-1FILE\s0" 8
++.IX Item "-s, --show FILE"
++Echo the contents of \s-1FILE\s0 on completion. \s-1FILE\s0 should be one of the
++filenames specified by \f(CW%file\fR or \f(CW%expect\fR*, or 'stdout' or 'stderr'.
++.IP "\-e, \-\-expand" 8
++.IX Item "-e, --expand"
++Don't run the given test; instead, expand its files into the current
++directory. The script is stored in a file called '+script+'.
++.SH "FILE FORMAT"
++.IX Header "FILE FORMAT"
++Testie test files consist of several sections, each introduced by a line
++starting with %. There must be, at least, a \f(CW%script\fR section.
++.PP
++The \f(CW%file\fR and \f(CW%expect\fR* sections define input and/or output files by
++name. Testie runs its script in a private directory in \fI/tmp\fR; any files
++mentioned in \f(CW%file\fR or \f(CW%expect\fR* are placed in that directory.
++.IP "%script" 8
++.IX Item "%script"
++The shell script (in sh syntax) that controls the test. Testie will run
++each command in sequence. Every command in the script must succeed, with
++exit status 0, or the test will fail. The script's inputs and outputs are
++defined with the \f(CW%file\fR and \f(CW%expect\fR* sections.
++.IP "%require [\-q]" 8
++.IX Item "%require [-q]"
++A shell script (in sh syntax) defining prerequisites that must be satisfied
++before the test can run. Every command in the script must succeed, with
++exit status 0, for the test to run. \f(CW%require\fR's output is not checked,
++however. The \f(CW\*(C`\-q\*(C'\fR flag tells testie not to print an error message if a
++requirement fails.
++.IP "%desc" 8
++.IX Item "%desc"
++A short description of the test. In \-\-superverbose mode, its contents are
++printed before the test results.
++.IP "%info" 8
++.IX Item "%info"
++This section is ignored. It is intended for information about the test.
++.IP "%cut" 8
++.IX Item "%cut"
++This section is ignored. It is intended to comment out obsolete parts of
++the test.
++.IP "%file [\-d] [+LENGTH] \s-1FILENAME\s0..." 8
++.IX Item "%file [-d] [+LENGTH] FILENAME..."
++Create an input file for the script. \s-1FILENAME\s0 can be 'stdin', which sets
++the script's standard input. If \s-1LENGTH\s0 is provided, the file data consists
++of the \s-1LENGTH\s0 bytes following this line. Otherwise, it consists of the data
++up to the next section. The \f(CW\*(C`\-d\*(C'\fR flag tells testie to delete the
++first character of each line in the section; this makes it possible to
++include files that have lines that start with %. \s-1FILENAME\s0 cannot contain
++slashes.
++.IP "%expectv [\-a] [\-d] [+LENGTH] \s-1FILENAME\s0..." 8
++.IX Item "%expectv [-a] [-d] [+LENGTH] FILENAME..."
++An expected output file for the script. \s-1FILENAME\s0 can be 'stdout', for
++standard output. If \s-1LENGTH\s0 is provided, the file data consists of the
++\&\s-1LENGTH\s0 bytes following this line; otherwise, it consists of the data up to
++the next section.
++.Sp
++Testie will run the script, then compare the script's output file with the
++provided data. They must match exactly or the test fails.
++.Sp
++The \f(CW\*(C`\-a\*(C'\fR flag marks this expected output as an alternate. Testie will
++compare the script's output file with each provided alternate; the test
++succeeds if any of the alternates match. The \f(CW\*(C`\-d\*(C'\fR flag behaves as in
++\&\f(CW%file\fR.
++.IP "%expect [\-a] [\-d] [\-i] [+LENGTH] \s-1FILENAME\s0..." 8
++.IX Item "%expect [-a] [-d] [-i] [+LENGTH] FILENAME..."
++An expected output file for the script. Arguments are as for \f(CW%expectv\fR.
++.Sp
++Testie will run the script, then compare the file generated by script
++with the provided data. The files are compared line\-by\-line. Testie
++ignores trailing whitespace on each line and in the files at large. It also
++ignores lines in the script output that match \f(CW%ignore\fR patterns (see below).
++Blank lines in the \f(CW%expect\fR data match one or more blank lines in the
++output. \f(CW%expect\fR lines can contain Perl regular expressions, enclosed by two
++sets of braces; so the \f(CW%expect\fR line
++.Sp
++.Vb 1
++\& foo{{(bar)?}}
++.Ve
++.Sp
++matches either 'foo' or 'foobar'. The \f(CW\*(C`\-i\*(C'\fR flag makes any regular
++expressions case\-insensitive.
++.IP "%expectx [\-a] [\-d] [\-i] [+LENGTH] \s-1FILENAME\s0..." 8
++.IX Item "%expectx [-a] [-d] [-i] [+LENGTH] FILENAME..."
++%expectx is just like \f(CW%expect\fR, except that every line is treated as a
++regular expression (so there is no need for the \*(L"{{ }}\*(R" escapes).
++.IP "%stdin [+LENGTH]" 8
++.IX Item "%stdin [+LENGTH]"
++Same as '%file stdin [\s-1ARGS\s0]'.
++.IP "%stdout [\-a] [\-d] [\-i] [+LENGTH]" 8
++.IX Item "%stdout [-a] [-d] [-i] [+LENGTH]"
++Same as '%expect stdout'.
++.IP "%stderr [\-a] [\-d] [\-i] [+LENGTH]" 8
++.IX Item "%stderr [-a] [-d] [-i] [+LENGTH]"
++Same as '%expect stderr'.
++.IP "%ignorex [\-d] [\-i] [+LENGTH] [\s-1FILENAME\s0]" 8
++.IX Item "%ignorex [-d] [-i] [+LENGTH] [FILENAME]"
++Each line in the \f(CW%ignorex\fR section is a Perl regular expression. Lines in
++the supplied \s-1FILENAME\s0 that match any of those regular expressions will not
++be considered when comparing files with \f(CW%expect\fR[x] data. The regular
++expression must match the whole line. \s-1FILENAME\s0 may be 'all', in which case
++the regular expressions will apply to all \f(CW%expect\fR[x] files.
++.ie n .IP "%ignore, %ignorev" 8
++.el .IP "%ignore, \f(CW%ignorev\fR" 8
++.IX Item "%ignore, %ignorev"
++Like '%ignorex', but '%ignore' parses regular expressions only inside
++double braces (\*(L"{{ }}\*(R"), and '%ignorev' lines must match exactly.
++.IP "%eot" 8
++.IX Item "%eot"
++Marks the end of the current test. The rest of the file will be parsed for
++additional tests.
++.IP "%eof" 8
++.IX Item "%eof"
++The rest of the file is ignored.
++.SH "EXAMPLE"
++.IX Header "EXAMPLE"
++This simple testie script checks that 'grep \-c' works for a simple output
++file.
++.PP
++.Vb 7
++\& %script
++\& grep -c B.
++\& %stdin
++\& Bfoo
++\& B
++\& %stdout
++\& 1
++.Ve
++.SH "AUTHOR"
++.IX Header "AUTHOR"
++Eddie Kohler, <kohler@cs.ucla.edu>
+diff -Nurb click-1.6.0/inst/share/man/man5/click.5 click-1.6.0-27/inst/share/man/man5/click.5
+--- click-1.6.0/inst/share/man/man5/click.5 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man5/click.5 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,785 @@
++.\" -*- mode: nroff -*-
++.ds V 1.1
++.ds E " \-\-
++.if t .ds E \(em
++.de OP
++.BR "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
++..
++.de OA
++.IR "\fB\\$1\& \|\fI\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
++..
++.de QO
++.RB ` "\\$1" "'\\$2"
++..
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.TH CLICK 5 "16/Mar/2004" "Version \*V"
++.SH NAME
++click \- Click configuration language
++'
++.SH DESCRIPTION
++The Click language describes the configuration of a Click router. It has
++two main directives:
++.IR declarations
++declare new elements, and
++.IR connections
++connect those elements together. Click router configurations are like
++directed graphs of elements; in this interpretation, declarations specify
++the vertices of the graph and connections specify the edges. Other
++language statements define configuration parameters and create new element
++types.
++'
++.SS "Declarations"
++'
++A declaration looks like this:
++.Rs
++.IR "name" " :: " "class" ( "config" );
++.Re
++(The semicolon, like all semicolons in Click syntax, is optional.)
++This declares an element called
++.IR name
++that has element class
++.IR class
++and configuration arguments
++.IR config .
++If the configuration string is empty, the parentheses can be left off.
++Also, there can be two or more names in a comma-separated list, which has
++the same effect as multiple declarations.
++.Rs
++.IR "name" " :: " "class" ;
++.br
++.IR "name1" ", " "name2" ", ..., " "nameN" " ::"
++.IR "class" ( "config" );
++.Re
++'
++.SS "Connections"
++'
++A connection looks like this:
++.Rs
++.IR "name1" " [" "port1" "] -> [" "port2" "] " "name2" ;
++.Re
++where the two
++.IR name s
++are names of previously declared elements, and the two
++.IR port s
++are nonnegative integers. This says that
++.IR name1 "'s output port " port1
++should be connected to
++.IR name2 "'s input port " port2 .
++Two connections can be strung together into a single statement if the
++output element of one is the same as the input element of the other:
++.Rs
++.IR "n1" " [" "p1" "] -> [" "p2" "] " "x" ;
++.br
++.IR "x" " [" "p3" "] -> [" "p4" "] " "n2" ;
++.Re
++is the same as
++.Rs
++.IR "n1" " [" "p1" "] -> [" "p2" "] " "x"
++.RI "[" "p3" "] -> [" "p4" "] " "n2" ;
++.Re
++This can be extended to three or more connections. Furthermore, if an input
++or output port is 0, it can be omitted along with the brackets. These two
++lines are equivalent:
++.Rs
++.IR "n1" " [0] -> [0] " "n2" ;
++.br
++.IR "n1" " -> " "n2" ;
++.Re
++.PP
++You can also declare elements inside connections:
++.Rs
++.RI "... -> [" "p1" "] " "name" " ::"
++.IR "class" ( "config" ") [" "p2" "] -> ...;"
++.Re
++is equivalent to
++.Rs
++.IR "name" " :: " "class" ( "config" );
++.br
++.RI "... -> [" "p1" "] " "name" " [" "p2" "] -> ...;"
++.Re
++Every such declaration can declare at most one element.
++'
++.SS "Anonymous elements"
++You may declare an element without specifying its name, in which case the
++system will choose an element name for you. For example:
++.Rs
++.IR class "(" config ");"
++.Re
++is equivalent to
++.Rs
++.IR generatedname " :: " class ( config );
++.Re
++As usual, the parentheses can be left off if
++.I config
++is empty. You may also declare an anonymous element inside a connection:
++.Rs
++.RI "... -> [" p1 "] " class ( config )
++.RI "[" p2 "] -> ...;"
++.Re
++is equivalent to
++.Rs
++.IR generatedname " :: " class ( config );
++.br
++.RI "... -> [" p1 "] " generatedname " [" p2 "] -> ...;"
++.Re
++.PP
++The
++.I generatedname
++has the form
++.RI ` class "@" number ',
++where the
++.IR number
++is chosen to make the name unique. These numbers are predictable: when the
++system parses a Click file twice, that file's anonymous elements will get
++the same generated names each time. Nothing prevents a user from declaring
++an element named like an anonymous element. We suggest that users avoid the `@'
++character in their element names.
++.PP
++Not all elements can usefully be anonymous, since an anonymous element can
++be part of at most two connections (once as input, once as output).
++'
++.SH "CONFIGURATION STRINGS"
++'
++Click configuration strings are comma-separated lists of arguments, where
++each argument is a space-separated list of objects. This section describes
++some common object types. See the element documentation for argument types
++expected by a particular element.
++.PP
++Configuration strings may contain comments (`// ... EOL' and `/* ... */'),
++which are replaced with single space characters. Inside single- or
++double-quoted strings, commas, spaces, and comment-starting sequences lose
++their regular meaning and are treated as normal characters.
++.PP
++The most common object types are:
++.TP 3
++\(bu
++.B Strings.
++Any sequence of characters. Single- or double-quoted strings are allowed
++(and required, if the string contains a space or comma). Inside
++double-quoted strings, backslash substitutions are performed; see below.
++You can concatenate strings by juxtaposing them. For example, `a"b"c' is
++equivalent to `abc'.
++.TP
++\(bu
++.B Booleans.
++`0', `false', and `no' mean false; `1', `true', and `yes' mean true.
++.TP
++\(bu
++.B Integers
++preceded by an optional `+' or `\-' sign. Decimal, octal (first digit `0'),
++and hexadecimal (starting with `0x') are allowed.
++.TP
++\(bu
++.B Real numbers
++in decimal notation.
++.TP
++\(bu
++.B Times and delays
++in decimal real notation, followed by an optional unit: `s'/`sec', `ms',
++`us', `ns', `m'/`min', `h'/`hr'.
++.TP
++\(bu
++.B Bandwidths
++in decimal real notation, followed by an optional unit: `bps' or `Bps' for
++bits or bytes per second, with an optional SI prefix `k', `M', or `G'. The
++default unit is generally `Bps'.
++.TP
++\(bu
++.B IP addresses
++in the conventional `n.n.n.n' form (for example, `18.26.4.15').
++.TP
++\(bu
++.B IP network prefixes
++in the CIDR form `n.n.n.n/k' (for example, `18.26.4/24').
++.TP
++\(bu
++.B IPv6 addresses
++in any of the conventional forms (for example, `::',
++`1080::8:800:200C:417A', or `::18.26.4.15').
++.TP
++\(bu
++.B Ethernet addresses
++in the conventional `x:x:x:x:x:x' form (for example, `0:a0:c9:9c:fd:9c').
++.TP
++\(bu
++.B Element names.
++.PD
++.PP
++Some elements, like
++.IR Classifier ,
++take arguments that don't fit any of these types. See the element
++documentation for details.
++.PP
++If the last argument in a configuration string is empty (containing only
++whitespace and comments), then it is ignored. Thus, `Element(1, )',
++`Element(1, /* comment */)', and `Element(1)' behave exactly alike.
++.PP
++Configuration strings may also contain parameter references, such as
++`$interface'. The parameter values are substituted in. Parameters may be
++defined either by compound element arguments, by explicit `define'
++statements, or on the command line.
++'
++.SS "Backslash Substitutions"
++.PP
++The following backslash substitutions are performed inside double quotes.
++Additionally, as a special case, a bare data substitution sequence `\e<
++\&... >' acts as if it were enclosed in double quotes. (Inside single
++quotes, `\e< ... >' is not special.)
++.TP 4
++1.
++'
++C-like substitutions. Specifically, `\ea', `\eb', `\et', `\en', `\ev',
++`\ef', `\er', `\e\e', and `\e[1, 2, or 3 octal digits]' have their C
++meanings. `\ex[any number of hex digits]' is replaced with the byte
++defined by the last 2 hex digits.
++.TP 4
++2.
++Data substitutions. An escape sequence `\e< ... hex digits and spaces ...
++>' is replaced with the data represented by the hex digits. For example,
++the sequence `\e< 48 45 4c 4C 4f >' is replaced with `HELLO'.
++.TP
++3.
++Backlash-newline sequences (`\e[LF]', `\e[CR]', or `\e[CR][LF]') are removed.
++.TP
++4.
++Any other `\e[CHAR]' sequence is replaced with `[CHAR]'.
++'
++.SH "COMPOUND ELEMENTS"
++'
++A
++.I compound element
++is a scoped collection of elements that acts like a single element from
++outside. A compound element can be used anywhere an element class is
++expected (that is, in a declaration or connection). Syntactically, a
++compound element is a set of Click statements enclosed in braces `{ }'.
++Inside the braces, the special names `input' and `output' represent
++connections from or to the outside. Before a router is put on line,
++compound elements are systematically expanded until none remain; thus, they
++have no run-time overhead.
++.PP
++Here are some examples. This code, with a compound element,
++.Rs
++a -> { input -> X -> output } -> b;
++.Re
++expands to
++.Rs
++a -> X -> b;
++.Re
++Here is a more complicated example, with multiple ports:
++.Rs
++compound :: {
++.br
++\% input -> X -> output;
++.br
++\% input [1] -> Y -> [1] output;
++.br
++};
++.br
++a -> compound -> b;
++.br
++c -> [1] compound [1] -> d;
++.Re
++expands to
++.Rs
++a -> X -> b;
++.br
++c -> Y -> d;
++.Re
++.PP
++The `input' and `output' pseudoelements incur no run-time overhead. (In
++fact, they are connection tunnel endpoints; see below for more.)
++.PP
++The actual expansions will differ from these examples because the elements
++will have different names. A prefix is prepended to the components' names,
++providing locality relative to other names in the configuration. The new
++names have the form
++.RI ` "compoundname" / "componentname" ',
++where
++.I compoundname
++is the name of the compound element being expanded, and
++.I componentname
++is the name of the component element inside that compound. For example,
++.Rs
++compound :: { input -> x :: X -> output };
++.br
++a -> compound -> b;
++.Re
++is really expanded to
++.Rs
++a -> compound/x :: X -> b;
++.Re
++For this purpose, anonymous compound elements are given constructed names
++like
++.RI `@ number '.
++Nothing prevents a user from declaring an element named like a compound
++element component. We suggest that users generally avoid using the `/'
++character in their element names.
++.PP
++It is an error to use the `input' pseudoelement's input ports or the
++`output' pseudoelement's output ports. It is also an error to leave an
++intermediate port unused\*Efor example, to use `input [0]' and `input [2]'
++but not `input [1]'.
++'
++.SS "The `elementclass' statement"
++'
++The `elementclass' statement lets the user name a frequently-occurring
++compound element, and use the name as if it were a primitive element class.
++Syntactically, it looks like this:
++.Rs
++elementclass
++.I identifier
++.I compoundelement
++;
++.Re
++After this statement, every occurrence of the
++.I identifier
++will be replaced with the
++.IR compoundelement .
++For example, this code, with an `elementclass':
++.Rs
++elementclass MyQueue {
++.br
++\% input -> Queue -> Shaper(1000) -> output;
++.br
++}
++.br
++q :: MyQueue;
++.br
++a -> q -> b;
++.Re
++is equivalent to this code, without it:
++.Rs
++q :: { input -> Queue -> Shaper(1000) -> output };
++.br
++a -> q -> b;
++.Re
++which roughly expands to:
++.Rs
++a -> Queue -> Shaper(1000) -> b;
++.Re
++.PP
++The user can declare element classes that have the names of previously
++existing element classes:
++.Rs
++elementclass Queue {
++.br
++\% input -> Queue -> Shaper(1000) -> output;
++.br
++}
++.Re
++Element classes are nonrecursive and lexically scoped, so the `Queue'
++inside this definition refers to the original `Queue'. The scope of an
++element class definition extends from immediately after its closing right
++brace to the end of the enclosing scope.
++.PP
++A variant of the elementclass statement makes synonyms for preexisting
++element classes. For example, this statement
++.Rs
++elementclass MyQueue Queue;
++.Re
++makes MyQueue a synonym for Queue.
++'
++.SS "Configuration parameters"
++'
++Compound elements may take configuration parameters, which are expanded
++into the configuration strings of its components. The parameters are named
++at the beginning of the compound element. Each parameter looks like a Perl
++variable\*Ea dollar sign followed by one or more letters, numbers, and
++underscores. For example, this compound element
++.Rs
++{ $a, $b | ... }
++.Re
++takes two configuration parameters, named `$a' and `$b'. Keyword arguments
++are also supported. For example, this compound element
++.Rs
++{ COUNT $count | ... }
++.Re
++takes a COUNT keyword parameter. Mismatched configuration parameters cause
++errors; for example:
++.Rs
++\%{ $a, $b | ... } (1) // Error: too few arguments
++.br
++\%{ $a, $b | ... } (1, 2, 3) // Error: too many arguments
++.br
++\%{ COUNT $count | ... } (1) // Error: missing 'COUNT' parameter
++.Re
++The special keyword `__REST__' matches any additional arguments supplied to
++the compound element. For example:
++.Rs
++\%{ $a, COUNT $count, __REST__ $rest | ... }
++.br
++\% (1, 2, COUNT 3, FOO 4)
++.Re
++This compound element will be expanded with `$a' set to `1', `$count' set
++to `3', and `$rest' set to `2, FOO 4'.
++.PP
++In a compound element definition, all positional parameters must precede
++any keyword parameters, and `__REST__', if present, must appear last of
++all.
++.PP
++As the compound is expanded, its components' configuration strings are
++searched for references to the parameters. Any such references are replaced
++with the supplied arguments. For example, this code:
++.Rs
++\&... -> { $a | input ->
++.br
++\% A(1, $a, 3) -> output } (100) -> ...
++.Re
++expands to this:
++.Rs
++\&... -> A(1, 100, 3) -> ...
++.Re
++You can avoid substitution by putting the dollar sign inside single quotes.
++.PP
++Use braces, like `${a}', to avoid including following letters in a variable
++name. Click also supports the shell-like `${VAR-DEFAULT}' syntax, which
++substitutes the value of `$VAR', or `DEFAULT' if that variable was not set.
++See also PARAMETER DEFINITIONS, below.
++'
++.SS "Overloading"
++'
++A single compound element may contain multiple overloaded definitions
++separated from one another by two vertical bars "\f(CW||\fR". Different
++definitions may have different numbers of input ports, different numbers of
++output ports, or different sets of configuration arguments. For example,
++this extended MyQueue compound element takes an optional capacity argument,
++just like Queue itself:
++.Rs
++elementclass MyQueue {
++.br
++\% input -> Queue -> Shaper(1000) -> output;
++.br
++\%||
++.br
++\% $cap | input -> Queue($cap)
++.br
++\% -> Shaper(1000) -> output;
++.br
++}
++.Re
++For each use of an overloaded compound element, Click will choose the first
++definition that matches the provided number of input ports, number of
++output ports, and configuration arguments. It is an error if no definition
++matches these properties exactly.
++.PP
++It is also possible to extend an existing element class with new overloaded
++definitions with "\f(CW...\fR". For example, this definition introduces a
++two-argument version of Queue:
++.Rs
++elementclass Queue {
++.br
++\% $cap, $rate | input -> Queue($cap)
++.br
++\% -> Shaper($rate) -> output;
++.br
++\%|| ...
++.br
++}
++.Re
++(The ellipsis in this example must be typed verbatim.) The overloadings
++visible at a given declaration are those that lexically precede that
++declaration. For example, the following example is an error since the
++two-argument version of Test is not visible at the declaration where it is
++required:
++.Rs
++elementclass Test { $a | /* nothing */ }
++.br
++test :: Test(1, 2);
++.br
++elementclass Test { $a, $b | /* nothing */ || ... }
++.Re
++'
++.SH "CONNECTION TUNNELS"
++'
++A
++.I connection tunnel
++is a pair of element names that acts as a tunnel for connections.
++Consider a tunnel
++.RI ` p1 " -> " p2 '.
++Then connections to
++.I p1
++pass through the tunnel and are transformed, at compile time, into
++connections from
++.IR p2 .
++For example, this code, with a tunnel,
++.Rs
++connectiontunnel p1 -> p2;
++.br
++a -> p1; p2 -> b;
++.Re
++is transformed into this code, without it:
++.Rs
++a -> b;
++.Re
++The connections to p1's
++.IR i th
++input port have been expanded into connections from p2's
++.IR i th
++output port. Thus, a is connected to b in the result because a was
++connected to p1's input port 0, and p2's output port 0 was connected to b.
++Here is a slightly more complicated example involving several connections
++and different port numbers:
++.Rs
++connectiontunnel p1 -> p2;
++.br
++a -> p1; b -> p1; p2 -> c;
++.br
++a [1] -> [1] p1; p2 [1] -> Discard;
++.Re
++is transformed into
++.Rs
++a -> c; b -> c;
++.br
++a [1] -> Discard;
++.Re
++And one final example:
++.Rs
++connectiontunnel p1 -> p2;
++.br
++a -> p1; p2 -> b; p2 -> c;
++.Re
++becomes
++.Rs
++a -> b; a -> c;
++.Re
++.PP
++Connection tunnels can be connected to each other. The system will
++recursively expand the tunnels until none of them remain. (Circular
++connections are silently ignored.) For example:
++.Rs
++connectiontunnel p1 -> p2, q1 -> q2;
++.br
++a -> p1; p2 -> q1; q2 -> b;
++.Re
++becomes
++.Rs
++a -> b;
++.Re
++.PP
++An identifier that has been used for a connection tunnel cannot be used for
++an element, and vice versa. However, an identifier can be used for two
++tunnels, once as the input end and once as the output end. For example:
++.Rs
++connectiontunnel p -> p/input, p/output -> p;
++.br
++a -> p; // using `p' as input
++.br
++p/input -> Counter -> p/output;
++.br
++p -> b; // using `p' as output
++.Re
++becomes
++.Rs
++a -> Counter -> b;
++.Re
++Compound elements use this mechanism.
++'
++.SH "REQUIREMENTS"
++'
++A configuration can say that it depends on optional packages by using the
++`require' statement. Its argument is a comma-separated list of package
++names:
++.Rs
++require(fastclassifier, specialcode);
++.Re
++Installation programs can use the package names to find and upload any
++necessary package code. Furthermore, the required package names are checked
++against a list of currently active packages when a configuration is
++installed. If any required packages are unavailable, an error is reported.
++'
++.SH "PARAMETER DEFINITIONS"
++'
++Parameters are defined using the `define' statement. Its argument is a
++comma-separated list of pairs, each pair consisting of a configuration
++variable and a value:
++.Rs
++define($DEVNAME eth0, $COUNT 1);
++.Re
++This sets the `$DEVNAME' parameter to `eth0' and the `$COUNT' parameter to
++`1'. Definitions are lexically scoped, so definitions inside a compound
++element are not visible outside it. However, all definitions in a given
++scope take place simultaneously, regardless of their ordering. The
++following two configurations have the same effect:
++.Rs
++1) define($a 2); Message($a)
++.br
++2) Message($a); define($a 2)
++.Re
++It is an error to define a parameter more than once in any single
++scope. Click programs such as
++.M click 1
++and
++.M click-install 1
++allow parameters to specified on the command line; these override any
++global parameters with the same names.
++'
++.SH "LEXICAL ISSUES"
++'
++Click identifiers are nonempty sequences of letters, numbers, underscores
++`_', at-signs `@', and slashes `/' that do not begin or end with a slash.
++The system uses `@' and `/' for special purposes: `@' in constructed names
++for anonymous elements and prefixes, and `/' in names for components of
++compound elements. Users are discouraged from using these characters in
++their own identifiers. Identifiers are case-sensitive. No component of an
++identifier may consist solely of numbers; for example, `1/x' is an illegal
++identifier.
++.PP
++The keywords `connectiontunnel', `elementclass', `require', and `define'
++may not be used as identifiers. The normal identifiers `input' and `output'
++have special meaning inside compound element definitions.
++.PP
++The following characters and multi-character sequences are single Click
++tokens:
++.RS
++->\~\~::\~\~;\~\~,\~\~(\~\~)\~\~[\~\~]\~\~{\~\~}\~\~|\~\~||\~\~...
++.RE
++.PP
++Whitespace (using the C definition) and comments separate Click tokens.
++Click uses C++-style comments: from `//' to the end of the line, or from
++`/*' to the next `*/'. Either form of comment terminates an identifier, so
++this Click fragment
++.RS
++an/identifier/with/slashes//too/many
++.RE
++has an identifier `an/identifier/with/slashes' and a comment
++`//too/many'. No identifier contains two consecutive slashes.
++.PP
++Parameters, which are used in compound elements, look like Perl variables. A
++parameter consists of a dollar sign `$' followed by one or more letters,
++numbers, and underscores.
++.PP
++A configuration string starts immediately following a left parenthesis `(',
++and continues up to the next unbalanced right parenthesis `)'. However,
++parentheses inside single or double quotes or comments do not affect
++balancing. Here are several examples; in each case, the configuration
++string consists of the text between the `#' marks (including the `#' marks
++themselves).
++.Rs
++C1(#simple string#)
++.br
++C2(#string with (balanced parens)#)
++.br
++C3(#string with ")quoted" paren#)
++.br
++C4(#// end-of-line comment)
++.br
++\% still going!#)
++.br
++C5(#/* slash-star comment) */ and backslash \e#)
++.Re
++.PP
++A Click program may contain C preprocessor-style line directives. These
++lines start with `#' and have the form `# \fIlinenumber\fP
++"\fIfilename\fP"' or `#line \fIlinenumber\fP "\fIfilename\fP"'; they change
++the filenames and line numbers used for error messages. The filename
++portion is optional. Line directives are not recognized inside
++configuration strings.
++'
++.SH "ARCHIVES"
++Many Click programs also accept
++.M ar 1
++archives as configurations. The archive must contain a member called
++`config', which is treated as a Click-language configuration. The archive
++may also contain package code required by the configuration. The
++.M click-install 1
++and
++.M click 1
++programs will decompose the archive and install any package code before
++installing the configuration itself. The
++.M click.o 8
++kernel module will not accept archives; use
++.M click-install 1 .
++'
++.SH "BNF GRAMMAR"
++'
++.IR stmts " ::= " stmts " " stmt " | " empty
++.br
++.IR stmt " ::= " declaration " | " connection
++.br
++.RI " | " tunnelstmt " | " elementclassstmt " | " requirestmt
++.br
++.RI " | " definestmt " | "";"""
++.br
++.IR declaration " ::= " element-names " ""::"" "
++.IR class " " opt-config
++.br
++.IR element-names " ::= " element-name
++.br
++.RI " | " element-names " "","" " element-name
++.br
++.IR element-name " ::= identifier
++.\" | ""^"" identifier
++.br
++.IR class " ::= identifier | ""{"" " compounds " ""}"""
++.br
++.RI " | ""{"" " compounds " ""||"" ""..."" ""}"""
++.br
++.IR compounds " ::= " compound " | " compounds " ""||"" " compound
++.br
++.IR compound " ::= " stmts " | " opt-formals " ""|"" " stmts
++.br
++.IR opt-formals " ::= " formals " | " empty
++.br
++.IR formals " ::= " formal " | " formals " "","" " formal
++.br
++.IR formal " ::= parameter | identifier parameter"
++.br
++.IR connection " ::= " element " " opt-port " ""->"" " opt-port " " conntail
++.br
++.IR conntail " ::= " element " | " connection
++.br
++.IR element " ::= " element-name
++.br
++.RI " | " element-name " ""::"" " class " " opt-config
++.br
++.RI " | " class " " opt-config
++.br
++.IR opt-config " ::= ""("" configstring "")"" | " empty
++.br
++.IR opt-port " ::= ""["" portnumber ""]"" | " empty
++.br
++.IR tunnelstmt " ::= ""connectiontunnel"" identifier ""->"" identifier"
++.br
++.IR elementclassstmt " ::= ""elementclass"" identifier " class
++.br
++.IR requirestmt " ::= ""require"" ""("" configstring "")"""
++.br
++.IR definestmt " ::= ""define"" ""("" configstring "")"""
++.br
++.IR empty " ::= "
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click-install 1 ,
++.M click.o 8
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man7/elementdoc.7 click-1.6.0-27/inst/share/man/man7/elementdoc.7
+--- click-1.6.0/inst/share/man/man7/elementdoc.7 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man7/elementdoc.7 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,526 @@
++.\" -*- mode: nroff -*-
++.ds V 1.1
++.ds D 29/Apr/2000
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.de K
++.BR "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
++..
++.de RK
++.RB "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
++..
++.TH ELEMENTDOC 7 "\*D" "Version \*V"
++.SH NAME
++elementdoc \- how to write Click element documentation
++'
++.SH DESCRIPTION
++Documentation for a Click element is automatically generated from formatted
++comments in its header files. This manual page describes how to write one
++of these formatted comments.
++.PP
++Click element documentation syntax is based on Perl-style PODs; see
++.M perlpod 1
++for more information. However, not all POD constructs are usable in element
++documentation at the moment; and Click element documentation is
++line-oriented, not paragraph-oriented.
++'
++.SH "COMMAND QUICK REFERENCE"
++These are the sectioning commands and the sections they correspond to,
++listed in the conventional order.
++.RS 5
++.PP
++.PD 0
++.IP "\f(CW=c\fR" 15
++SYNOPSIS
++.IP "\f(CW=s\fR \fIcategory\fR" 15
++NAME (one-line summary)
++.IP "\f(CW=io\fR" 15
++INPUTS AND OUTPUTS
++.IP "\f(CW=processing\fR" 15
++PROCESSING TYPE
++.IP "\f(CW=d\fR" 15
++DESCRIPTION
++.IP "\f(CW=n\fR" 15
++NOTES
++.IP "\f(CW=e\fR" 15
++EXAMPLES
++.IP "\f(CW=h\fR \fIname\fR \fItype\fR" 15
++ELEMENT HANDLERS
++.IP "\f(CW=a\fR" 15
++SEE ALSO
++.IP "\f(CW=head1\fR \fItext\fR" 15
++other heading
++.PD
++.RE
++.PP
++These are the other commands used in element documentation.
++.RS 5
++.PP
++.PD 0
++.IP "\f(CW=head2\fR \fItext\fR" 15
++subheading
++.IP "\f(CW=over\fR \fIamount\fR" 15
++begin item list
++.IP "\f(CW=item\fR \fItext\fR" 15
++add item
++.IP "\f(CW=back\fR" 15
++end item list
++.IP "\f(CW=for\fR \fIformat\fR" 15
++selective formatting
++.IP "\f(CW=begin\fR \fIformat\fR" 15
++selective formatting
++.IP "\f(CW=end\fR \fIformat\fR" 15
++selective formatting
++.IP "\f(CW=deprecated\fR \fInew-element\fR" 15
++element is deprecated
++.PD
++.RE
++.PP
++These are the formatting commands, used inside ordinary text.
++.RS 5
++.PP
++.PD 0
++.IP "\f(CWB<\fItext\fR\f(CW>\fR" 15
++boldface
++.IP "\f(CWI<\fItext\fR\f(CW>\fR" 15
++italics
++.IP "\f(CWU<\fItext\fR\f(CW>\fR" 15
++underlined (if possible)
++.IP "\f(CWP<\fItext\fR\f(CW>\fR" 15
++plain text (i.e., no automatic links)
++.IP "\f(CWC<\fItext\fR\f(CW>\fR" 15
++code (fixed-width)
++.IP "\f(CWF<\fItext\fR\f(CW>\fR" 15
++filename (italics)
++.IP "\f(CWL<\fItext\fR|\fIlink\fR\f(CW>\fR" 15
++hyperlink
++.IP "\f(CWN<>\fR" 15
++line break
++.IP "\f(CWE<\fIname\fR\f(CW>\fR" 15
++entity
++.IP "\f(CWV<\fItext\fR\f(CW>\fR" 15
++hide text
++.PD
++.RE
++.PP
++And these are the category keywords, used in the summary section to
++categorize elements.
++.RS 5
++.PP
++.PD 0
++.IP "\f(CWbasicsources\fR" 22
++Basic Sources and Sinks
++.IP "\f(CWclassification\fR" 22
++Basic Classification and Selection
++.IP "\f(CWbasictransfer\fR" 22
++Basic Packet Transfer
++.IP "\f(CWcounters\fR" 22
++Counters
++.IP "\f(CWtimestamps\fR" 22
++Timestamps
++.IP "\f(CWbasicmod\fR" 22
++Basic Packet Modification
++.IP "\f(CWstorage\fR" 22
++Packet Storage
++.IP "\f(CWaqm\fR" 22
++Active Queue Management
++.IP "\f(CWscheduling\fR" 22
++Packet Scheduling
++.IP "\f(CWshaping\fR" 22
++Traffic Shaping
++.IP "\f(CWinformation\fR" 22
++Information Elements
++.IP "\f(CWnetdevices\fR" 22
++Network Devices
++.IP "\f(CWcomm\fR" 22
++Host and Socket Communication
++.IP "\f(CWethernet\fR" 22
++Ethernet
++.IP "\f(CWarp\fR" 22
++ARP
++.IP "\f(CWip\fR" 22
++IPv4
++.IP "\f(CWiproute\fR" 22
++IPv4 Routing
++.IP "\f(CWicmp\fR" 22
++ICMP
++.IP "\f(CWnat\fR" 22
++Network Address Translation
++.IP "\f(CWtcp\fR" 22
++TCP
++.IP "\f(CWudp\fR" 22
++UDP
++.IP "\f(CWapp\fR" 22
++Applications
++.IP "\f(CWtraces\fR" 22
++Trace Manipulation
++.IP "\f(CWipmeasure\fR" 22
++TCP/IP Measurement
++.IP "\f(CWaggregates\fR" 22
++Aggregates
++.IP "\f(CWip6\fR" 22
++IPv6
++.IP "\f(CWipsec\fR" 22
++IPsec
++.IP "\f(CWcrc\fR" 22
++CRCs
++.IP "\f(CWpaint\fR" 22
++Paint Annotations
++.IP "\f(CWannotations\fR" 22
++Annotations
++.IP "\f(CWdebugging\fR" 22
++Debugging
++.IP "\f(CWcontrol\fR" 22
++Control
++.IP "\f(CWsmpclick\fR" 22
++Multithreaded Click
++.IP "\f(CWtest\fR" 22
++Regression Tests
++.PD
++.RE
++'
++.SH "COMMENT SYNTAX"
++Each piece of documentation is stored in a single block comment
++`\f(CW/*...*/\fR'. Two kinds of block comment are recognized:
++.PP
++.nf
++ /*
++ =c
++ ElementName(...)
++ ... and so on ...
++ */
++
++ /*
++ * =c
++ * ElementName(...)
++ * ... and so on ...
++ */
++.fi
++.PP
++In the first form, commands and normal text MUST begin in the first column
++of each line. In the second form, commands and normal text MUST begin in
++the fourth column of each line, immediately following the initial star and
++spaces `\f(CW\ *\ \fR'. Indented lines are treated as verbatim text, as in
++POD.
++'
++.SH "COMMANDS"
++Commands are lines that begin with `\f(CW=\fR' and a lower-case letter.
++There are two kinds of commands, those that start new sections and those
++that occur within sections. There is also a set of formatting
++commands\*Efor turning text bold, for example\*Ethat occurs inside normal
++text; they are described in the next section.
++'
++.SS "Section Commands"
++.IP "\f(CW=s\fR [\fIcategory\fR]" 5
++Begin the summary section. This should contain a very short,
++one-line summary of the element's function. For example, for a
++.M Queue n
++element:
++.nf
++ =s storage
++ stores packets in a FIFO queue
++.fi
++The summary text should generally be a verb phrase.
++.RS 5
++.PP
++The optional \fIcategory\fR specifies one or more element categories into
++which this element fits, separated by commas. Specifying meaningful
++categories helps a lot; documentation tools use categories to divide
++elements into manageable groups. Use existing categories, defined by the
++list of category keywords above in the Command Quick Reference, or create
++your own.
++.RE
++.TP 5
++\f(CW=c\fR
++Begin the synopsis section. This section is mandatory.
++.RS 5
++.PP
++The \f(CW=c\fR section gives the element's name and any of its
++configuration arguments. For example:
++.nf
++ =c
++ IPEncap(PROTOCOL, SADDR, DADDR)
++.fi
++.PP
++Configuration arguments should be specified as all-upper-case words. The
++description section will use those upper-case words to talk about the
++arguments. Use brackets to show that an argument is optional:
++.nf
++ =c
++ UDPIPEncap(SADDR, SPORT, DADDR, DPORT [, CHECKSUM?])
++.fi
++.PP
++Do not use anything more complicated than brackets. If an element has
++complex syntax, either use upper-case words and talk about the syntax more
++in the description section, or give multiple lines:
++.nf
++ =c
++ ControlSocket(tcp, PORTNUMBER [, READONLY?])
++ ControlSocket(unix, PORTNUMBER [, READONLY?])
++.fi
++(`tcp' and `unix' are lowercase because they should be typed verbatim.)
++.RE
++'
++.TP 5
++\f(CW=io\fR
++Begin the inputs and outputs section. This section mentions how many inputs
++and outputs the element has. It is usually quite short; for example:
++.nf
++ =io
++ None
++.fi
++This section is optional, and most elements don't bother to have one; they
++mention inputs and outputs in the description section.
++'
++.TP 5
++\f(CW=processing\fR
++Begin the processing type section. This section mentions the processing
++types of the element's input and output ports. It is usually quite short; for
++example:
++.nf
++ =processing
++ Push inputs, pull outputs
++.fi
++This section is optional. Documentation processing tools will generate a
++\f(CW=processing\fR section from the element's \fBprocessing\fP() method,
++if possible.
++'
++.TP 5
++\f(CW=d\fR
++Begin the description section.
++This section tells how the element should be used. It is usually the
++longest section. When mentioning configuration arguments, use the
++upper-case words given in the \f(CW=c\fR section.
++'
++.TP 5
++\f(CW=n\fR
++Begin the notes section.
++'
++.TP 5
++\f(CW=e\fR
++Begin the examples section.
++'
++.TP 5
++\f(CW=h\fR \fIhandlername\fP \fItype\fP
++Begin a handler description. Use this section to describe any special
++handlers that the element installs. \fIHandlername\fP should be the name of
++the handler, and \fItype\fP its type (either `\f(CWread-only\fR',
++`\f(CWwrite-only\fR', or `\f(CWread/write\fR'). The following text should
++describe that handler. For example:
++.nf
++ =h capacity read/write
++ Returns or sets the queue's capacity.
++.fi
++'
++.TP 5
++\f(CW=a\fR [\fItext\fP]
++Begin the "see also" section. Use this section to mention other relevant
++elements and programs, when appropriate. The more references, the better.
++For example:
++.nf
++ =a RED, FrontDropQueue
++.fi
++The optional \fItext\fP is just part of the body of the section.
++.RS 5
++.PP
++The references in this section should be either manual page references,
++like `\f(CWtcpdump(1)\fR', or text references, like `RFC 959: File Transfer
++Protocol'. However, the first paragraph in the section is special; there,
++you can just give element names without `\f(CW(n)\fP' suffixes.
++.PP
++If one of these references occurs in some other section, it will be
++formatted like a link. For example, in
++.nf
++ =d
++ This element is like Queue.
++ =a Queue
++.fi
++the mention of `\f(CWQueue\fR' in the description section will be formatted
++like a link.
++.RE
++'
++.TP 5
++\f(CW=head1\fR \fIsectionname\fR
++Begin a section other than those listed. \fISectionname\fR is the name of
++the section.
++'
++.SS "Other Commands"
++.TP 5
++\f(CW=head2\fR \fItext\fR
++Produce a subheading with \fItext\fR as the text.
++.TP 5
++\f(CW=over\fR \fIamount\fR
++Begin a list of items that is indented by
++\fIamount\fR characters. (Some translators may ignore \fIamount\fR.)
++.TP 5
++\f(CW=item\fR \fItext\fR
++Add an item to the latest list opened by \f(CW=over\fR. It is illegal to
++use \f(CW=item\fR outside of any \f(CW=over\fR list. The text of the item
++is \fItext\fR. If you are creating a bulleted list, use `\f(CW*\fR' as the
++text; if you are creating a numbered list, use `\f(CW1.\fR', `\f(CW2.\fR',
++and so forth.
++.TP 5
++\f(CW=back\fR
++Close the latest list opened by \f(CW=over\fR.
++.TP 5
++\f(CW=for\fR \fIformat\fR
++'
++Output the next paragraph only when generating documentation in
++\fIformat\fR. Valid \fIformat\fRs include `html', `man', and `roff'. The
++paragraph ends at the next command or blank line, and it consists of text
++in the given format, not element documentation. For example, this code
++includes a picture in HTML mode:
++.nf
++ =for html
++ <p>Here is a pretty picture:
++ <img src="pretty.gif"></p>
++
++ Back to B<normal text> here.
++.fi
++.TP 5
++\f(CW=begin\fR \fIformat\fR ... \f(CW=end\fR \fIformat\fR
++'
++This is like \f(CW=for\fR, but can encompass multiple paragraphs. It
++outputs text in between the \f(CW=begin\fR command and the \f(CW=end\fR
++command only when generating documentation in \fIformat\fR.
++.TP 5
++\f(CW=deprecated\fR \fInew-element\fR
++This command notes that the element has been deprecated in favor of
++\fInew-element\fR. It does not result in any output.
++'
++.SH TEXT
++Each line that doesn't begin with `\f(CW=\fR' and a lower-case letter is
++treated as text. (Unless it starts with a space or tab; see verbatim text,
++below.) This text is formatted nicely, and perhaps even justified. You can
++use several formatting commands inside normal text; they consist of an
++uppercase letter, followed by `\f(CW<\fR', some text, and `\f(CW>\fR'. The
++commands are:
++.TP 10
++\f(CWB<\fItext\fR\f(CW>\fR
++Print \fItext\fR in \fBboldface\fR.
++.TP 10
++\f(CWI<\fItext\fR\f(CW>\fR
++Print \fItext\fR in \fIitalic\fR.
++.TP 10
++\f(CWR<\fItext\fR\f(CW>\fR
++Print \fItext\fR in \fRroman\fR. Useful inside \f(CWB<...>\fR and so forth,
++or to prevent words from being highlighted.
++.TP 10
++\f(CWC<\fItext\fR\f(CW>\fR
++Print \fItext\fR like source code, in a constant-width font.
++.TP 10
++\f(CWF<\fItext\fR\f(CW>\fR
++Print \fItext\fR like a filename. By default, filenames appear in italics.
++.TP 10
++\f(CWL<\fItext\fR|\fIlink\fR\f(CW>\fR
++Print \fItext\fR as a hyperlink with destination \fIlink\fR. This usually
++just comes out as \fItext\fR.
++.TP 10
++\f(CWN<>\fR
++Put a line break here.
++.TP 10
++\f(CWE<\fIname\fR\f(CW>\fR
++'
++Print the HTML-style entity named \fIname\fR. There are six entities:
++\f(CWE<lt>\fR is `<', \f(CWE<gt>\fR is `>', \f(CWE<amp>\fR is `&',
++\f(CWE<solid>\fR is `/', \f(CWE<verbar>\fR is `|', \f(CWE<star>\fR is `*',
++and \f(CWE<eq>\fR is `='. This is useful for typing one of these characters
++in a context that would seem like a command or formatting command.
++.TP 10
++\f(CWV<\fItext\fR\f(CW>\fR
++Do not print \fItext\fR.
++'
++.SH VERBATIM TEXT
++Lines that start with a space or tab character are printed out
++verbatim\*Ethat is, without any changes, and with the line breaks and
++indentation you specified. You can't use formatting commands
++in verbatim text. Verbatim text is useful for showing example code; for
++example:
++.PP
++.nf
++ This code
++ q :: Queue;
++ ... -> RED(5, 50, 0.02) -> q -> ...
++ adds RED dropping to q.
++.fi
++'
++.SH EXAMPLES
++.nf
++/* =c
++ * Align(MODULUS, OFFSET)
++ * =s modification
++ * aligns packet data
++ * =d
++ * Aligns packet data. Each input packet is aligned so that
++ * its first byte is OFFSET bytes off from a MODULUS-byte
++ * boundary. This may involve a packet copy.
++ *
++ * MODULUS I<must> be 2, 4, or 8.
++ * =n
++ * The click-align(1) tool will insert this element
++ * automatically wherever it is required.
++ * =e
++ * ... -> Align(4, 0) -> ...
++ * =a AlignmentInfo, click-align(1) */
++.fi
++.PP
++.nf
++/* =c
++ * Counter([TYPE])
++ * =s measurement
++ * measures packet count and rate
++ * =d
++ * Passes packets unchanged from its input to its output,
++ * maintaining statistics information about packet count and
++ * rate if TYPE is "packets", or byte count and byte rate if
++ * TYPE is "bytes". The default TYPE is "packets".
++ * =h count read-only
++ * Returns the number of packets/bytes that have passed through.
++ * =h rate read-only
++ * Returns the recent arrival rate (measured by exponential
++ * weighted moving average) in packets/bytes per second.
++ * =h reset write-only
++ * Resets the count and rate to zero.
++ */
++.fi
++'
++.SH "SEE ALSO"
++.M perlpod 1 ,
++.M click 1 ,
++.M click 5
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++Robert Morris, rtm@lcs.mit.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/man8/click.o.8 click-1.6.0-27/inst/share/man/man8/click.o.8
+--- click-1.6.0/inst/share/man/man8/click.o.8 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/man8/click.o.8 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,345 @@
++.\" -*- mode: nroff -*-
++.ds V 1.5
++.ds D 15/Dec/2006
++.ds E " \-\-
++.if t .ds E \(em
++.de Sp
++.if n .sp
++.if t .sp 0.4
++..
++.de Es
++.Sp
++.RS 5
++.nf
++..
++.de Ee
++.fi
++.RE
++.PP
++..
++.de Rs
++.RS
++.Sp
++..
++.de Re
++.Sp
++.RE
++..
++.de M
++.BR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RB "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH CLICK.O 8 "\*D" "Version \*V"
++.SH NAME
++click.o \- Click kernel module driver for Linux
++'
++.SH DESCRIPTION
++'
++The Click modular router can be compiled as a Linux kernel module, called
++.BR click.o .
++It can steal packets from network devices before Linux gets a chance to
++handle them, send packets directly to devices, and send packets to Linux
++for normal processing.
++.PP
++The right way to load the Click kernel module is with
++.M click-install 1 ". "
++This installs the module if necessary, mounts the Click file system onto
++the /click directory, and installs a configuration, including any required
++packages. The right way to unload the Click kernel module is with
++.M click-uninstall 1 ". "
++For example:
++.sp
++.nf
++ # click-install config.click
++ # click-uninstall
++.fi
++'
++.SH "HANDLERS"
++The module's API is a filesystem similar to the
++.M proc 5
++filesystem. Click creates a number of files under /click (or wherever you
++have mounted the filesystem), some read-only and some read/write (writable
++by the superuser). You control the module by writing to these files, which
++are called
++.IR handlers .
++.PP
++.B click-install
++installs a router configuration by writing it to /click/config or
++/click/hotconfig. The configuration can use most of Click's element classes
++(see
++.M elements n ).
++Several element classes control how the module receives and transmits
++packets:
++.M FromDevice n
++and
++.M PollDevice n
++steal packets from devices before Linux processes them,
++.M ToDevice n
++sends packets directly to devices, and
++.M ToHost n
++sends packets to Linux for normal processing. Removing the module or
++installing a null configuration will restore your machine's default
++networking behavior.
++.PP
++The handlers under /click include:
++.TP 5
++.B /click/config
++Read/write. Contains a Click-language description (see
++.M click 5 )
++of the most recent router configuration, not including any run-time
++reconfiguration.
++.B click-install
++writes a Click-language router description to this file to
++install a new router configuration.
++'
++.TP
++.B /click/hotconfig
++Write-only.
++.B 'click-install -h'
++writes a Click-language router description to this file to
++hot-swap install a new router configuration. The new router is installed
++only if it initializes correctly; otherwise, error messages will be
++reported to /click/errors, but the old router will keep working
++without interruption. If the new router initializes successfully, state
++from the old router, such as any packets stored in
++.M Queue n
++elements, will be moved into the new router before it is installed. This
++happens on a per-element basis, and it only works if the new element and
++the old element have the same name. In contrast,
++/click/config always throws away the old router.
++'
++.TP
++.B /click/errors
++Read-only. Errors reported by the Click router since the last
++reconfiguration (that is, the last write to /click/config or
++/click/hotconfig). Errors are also printed to the system log. Only the most
++recent 2-4KB of error messages are saved in this file.
++'
++.TP
++.B /click/messages
++Read-only. All messages printed by the Click router since the last
++reconfiguration (that is, the last write to /click/config or
++/click/hotconfig). This includes messages generated by Print, among
++others. Messages are also printed to the system log. Only the most recent
++2-4KB of messages are saved in this file.
++'
++.TP
++.B /click/classes
++Read-only. The primitive element classes supported by the router, listed
++one per line.
++'
++.TP
++.B /click/list
++Read-only. The names of the elements in the current router configuration,
++listed one per line. The first line is an integer: the number of elements.
++'
++.TP
++.B /click/flatconfig
++Read-only. A Click-language description of the current router
++configuration, including the effects of any run-time reconfiguration. All
++element declarations come first, then all connections. Compound elements
++are expanded into their primitive components.
++'
++.TP
++.B /click/packages
++Read-only. The packages that are currently linked to the Click module,
++listed one per line.
++'
++.TP
++.B /click/requirements
++Read-only. The packages required by the current configuration, listed one
++per line.
++'
++.TP
++.B /click/cycles, /click/meminfo
++Read-only. Cycle count and memory usage statistics.
++'
++.TP
++.B /click/threads
++Read-only. The PIDs of any currently running Click kernel threads, listed
++one per line.
++'
++.TP
++.B /click/priority
++Read/write. The CPU priority for Click kernel threads. Lower values have
++higher priority.
++'
++.TP
++.B /click/version
++Read-only. The kernel module's version number.
++'
++.PP
++When compiled with --enable-adaptive, Click provides three additional
++handlers:
++'
++.TP
++.B /click/min_cpu_share
++Read/write. The minimum fraction of CPU time Click will use, even if it has
++no work to do. Expressed as a real number between 0.001 and 0.999. Default
++is 0.005. Raising this number will help Click in polling mode respond more
++quickly to network events.
++'
++.TP
++.B /click/max_cpu_share
++Read/write. The maximum fraction of CPU time Click will use, no matter how
++much work it has to do. Expressed as a real number between 0.001 and 0.999.
++Default is 0.8. Lowering this number will help user-level programs make
++progress, even under high network load.
++'
++.TP
++.B /click/cpu_share
++Read-only. The fraction of CPU time Click is currently using, expressed as
++a real number between 0 and 1.
++'
++.PP
++When compiled with --enable-kassert, Click provides one additional
++handler:
++'
++.TP
++.B /click/assert_stop
++Read/write. A Boolean value. If true, then Click will attempt to stop the
++running router, if any, if an assertion fails. Default is false.
++'
++.SS "Element directories"
++'
++Every element in the current router configuration has a directory under
++/click. You can access the directory by number or element name. The
++.IR i th
++element in /click/list has directory
++.RI `/click/ i ',
++and if the element is named
++.IR n ,
++that directory can be accessed as
++.RI `/click/ n '.
++This works even if the name contains slashes
++.RB ( click.o
++creates directories for each name component). However, if an element name
++conflicts with a handler name, the handler is preferred. Thus, if you call
++an element "config", you will be able to access that element's handlers
++only via its number directory.
++.PP
++Handlers in these element directories include:
++'
++.TP 5
++.BI /click/xxx/class
++Read-only. The element's class.
++.TP
++.BI /click/xxx/name
++Read-only. The element's name.
++.TP
++.BI /click/xxx/config
++Read/write if the element supports run-time reconfiguration; otherwise
++read-only. The element's current configuration. Writing to this file (if it
++is writable) causes the element to reconfigure itself on the fly. If the
++reconfiguration fails, the element's old configuration is used instead.
++.TP
++.BI /click/xxx/ports
++Read-only. Describes the element's input and output ports: how many there
++are, their processing type, and (for pull inputs and push outputs) what
++they are connected to.
++.TP
++.BI /click/xxx/handlers
++Read-only. Lists the element's handlers, one per line. Each line has the
++handler name and, after a tab, a permissions word. The permissions word is
++currently "r" (read-only), "w" (write-only), or "rw" (read/write).
++'
++.PP
++Elements that have associated tasks often provide these two additional
++handlers:
++'
++.TP 5
++.BI /click/xxx/scheduled
++Read-only. A Boolean value: "true" if the element is currently on the task
++list, "false" if it is not.
++.TP
++.BI /click/xxx/tickets
++Read/write. Returns or sets the element's tickets, an integer that
++influences task scheduling priority. The more tickets a task has, the more
++often it will be scheduled relative to other tasks.
++'
++.PP
++Particular elements may add additional handlers to their directories. For
++example, RED elements (see
++.M RED n )
++add read/write
++.BR min_thresh ", " max_thresh ", and " max_p
++files representing RED parameters, and Counter elements (see
++.M Counter n )
++provide read-only
++.BR count " and " rate
++files to report packet counts and the recent rate.
++.PP
++The subdirectories and generic files are always created, but
++element-specific files are created only if the router configuration was
++initialized successfully.
++'
++.SH "MANUAL LOADING"
++You almost certainly should load Click using
++.M click-install 1 ". "
++Nevertheless, the manual loading steps are as follows.
++.TP 3
++1.
++Load the
++.B proclikefs
++module with
++.M insmod 8 :
++"/sbin/insmod proclikefs.ko". This module takes charge of the Click
++filesystem, allowing you to safely unload the Click module even if
++user-level programs have Click control files open.
++.TP
++2.
++Load the
++.B click
++module with
++.BR insmod :
++"/sbin/insmod click.ko".
++.TP
++3.
++Mount the Click filesystem on a directory using
++.M mount 8 ". "
++The usual choice is /click: "mount -t click none /click". The Click kernel
++module installs a symbolic link from /proc/click to /click.
++.TP
++4.
++Install a configuration by writing it to /click/config:
++"cat CONFIGFILE > /click/config", for example.
++.LP
++To uninstall Click without
++.M click-uninstall 1 ,
++kill the current router by installing an empty configuration ("echo >
++/click/config"), unload any element packages, and finally
++.M rmmod 8
++the "click" module.
++'
++.SH "BUGS"
++If you get an unaligned access error, try running your configuration
++through
++.M click-align 1
++before installing it.
++'
++.SH "SEE ALSO"
++.M click 1 ,
++.M click-align 1 ,
++.M click-install 1 ,
++.M click-uninstall 1 ,
++.M insmod 1 ,
++.M rmmod 1 ,
++.M click 5 ,
++.M elements n ,
++.M FromDevice n ,
++.M PollDevice n ,
++.M ToDevice n ,
++.M FromHost n ,
++.M ToHost n ,
++.M Queue n
++'
++.SH AUTHOR
++.na
++Eddie Kohler, kohler@cs.ucla.edu
++.br
++Robert Morris, rtm@lcs.mit.edu
++.br
++http://www.pdos.lcs.mit.edu/click/
++'
+diff -Nurb click-1.6.0/inst/share/man/mann/ARPFaker.n click-1.6.0-27/inst/share/man/mann/ARPFaker.n
+--- click-1.6.0/inst/share/man/mann/ARPFaker.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ARPFaker.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,50 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/arpfaker.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ARPFAKER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ARPFaker \- Click element;
++periodically generates an ARP reply
++.SH "SYNOPSIS"
++\fBARPFaker\fR(DSTIP, DSTETH, SRCIP, SRCETH)
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Every 10 seconds,
++sends an ARP "reply" packet to DSTIP/DSTETH claiming that SRCIP has ethernet
++address SRCETH. Generates the ethernet header as well as the
++ARP header.
++.PP
++
++.SH "EXAMPLES"
++Sends ARP packets to 18.26.4.1 (with ether addr 0:e0:2b:b:1a:0)
++claiming that 18.26.4.99's ethernet address is 00:a0:c9:9c:fd:9c.
++.PP
++.nf
++\& ARPFaker(18.26.4.1, 0:e0:2b:b:1a:0, 18.26.4.99, 00:a0:c9:9c:fd:9c)
++\& -> ToDevice(eth0);
++.fi
++.PP
++
++
++
++.SH "NOTES"
++You probably want to use
++.M ARPResponder "n"
++rather than \fBARPFaker\fR.
++.PP
++
++.SH "SEE ALSO"
++.M ARPQuerier n ,
++.M ARPResponder "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ARPPrint.n click-1.6.0-27/inst/share/man/mann/ARPPrint.n
+--- click-1.6.0/inst/share/man/mann/ARPPrint.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ARPPrint.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,45 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/arpprint.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ARPPRINT" n "11/Feb/2009" "Click"
++.SH "NAME"
++ARPPrint \- Click element;
++pretty-prints ARP packets a la tcpdump
++.SH "SYNOPSIS"
++\fBARPPrint\fR([TAG, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Expects ARP packets as input.
++.PP
++Prints out ARP packets in a human-readable tcpdump-like format, preceded by
++the TAG text.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "TIMESTAMP" 2
++Boolean. Determines whether to print each packet's timestamp in seconds since
++1970. Default is true.
++.IP "" 2
++.IP "OUTFILE" 2
++String. Only available at user level. Print information to the file specified
++by OUTFILE instead of standard error.
++.IP "" 2
++.PP
++
++.SH "SEE ALSO"
++.M Print n ,
++.M CheckARPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ARPQuerier.n click-1.6.0-27/inst/share/man/mann/ARPQuerier.n
+--- click-1.6.0/inst/share/man/mann/ARPQuerier.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ARPQuerier.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,119 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/arpquerier.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ARPQUERIER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ARPQuerier \- Click element;
++encapsulates IP packets in Ethernet headers found via ARP
++.SH "SYNOPSIS"
++\fBARPQuerier\fR(IP, ETH, \fIkeywords\fR)
++.br
++\fBARPQuerier\fR(NAME, \fIkeywords\fR)
++
++\fBPorts\fR: 2 inputs, 1-2 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Handles most of the ARP protocol. Argument IP should be
++this host's IP address, and ETH should be this host's
++Ethernet address. (In
++the one-argument form, NAME should be shorthand for
++both an IP and an Ethernet address; see
++.M AddressInfo n .)
++.PP
++Packets arriving on input 0 should be IP packets, and must have their
++destination address annotations set.
++If an Ethernet address is already known
++for the destination, the IP packet is wrapped in an Ethernet
++header and sent to output 0. Otherwise the IP packet is saved and
++an ARP query is sent instead. If an ARP response arrives
++on input 1 for an IP address that we need, the mapping is
++recorded and any saved IP packets are sent.
++.PP
++The ARP reply packets on input 1 should include the Ethernet header.
++.PP
++\fBARPQuerier\fR may have one or two outputs. If it has two, then ARP queries
++are sent to the second output.
++.PP
++\fBARPQuerier\fR will not send queries for packets addressed to 0.0.0.0,
++255.255.255.255, or, if specified, any BROADCAST address. Packets addressed
++to 0.0.0.0 are dropped; packets for broadcast addresses are forwarded with
++destination Ethernet address FF:FF:FF:FF:FF:FF.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "CAPACITY" 8
++Unsigned integer. The maximum number of saved IP packets the element will
++hold at a time. Default is 2048. Note that, unlike the number of packets,
++the total number of ARP entries the element will hold is currently unlimited.
++.IP "" 8
++.IP "BROADCAST" 8
++IP address. Local broadcast IP address. Packets sent to this address will be
++forwarded to Ethernet address FF:FF:FF:FF:FF:FF. Defaults to the local
++broadcast address that can be extracted from the IP address's corresponding
++prefix, if any.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& c :: Classifier(12/0806 20/0002, 12/0800, ...);
++\& a :: ARPQuerier(18.26.4.24, 00:00:C0:AE:67:EF);
++\& c[0] -> a[1];
++\& c[1] -> ... -> a[0];
++\& a[0] -> ... -> ToDevice(eth0);
++.fi
++.PP
++
++
++
++.SH "NOTES"
++If a host has multiple interfaces, it will need multiple
++instances of \fBARPQuerier\fR.
++.PP
++\fBARPQuerier\fR uses packets' destination IP address annotations, and can destroy
++their next packet annotations.
++.PP
++\fBARPQuerier\fR will send at most 10 queries a second for any IP address.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBipaddr\fR (read/write)" 5
++Returns or sets the \fBARPQuerier\fR's source IP address.
++.IP "" 5
++.IP "\fBtable\fR (read-only)" 5
++Returns a textual representation of the ARP table.
++.IP "" 5
++.IP "\fBstats\fR (read-only)" 5
++Returns textual statistics (queries and drops).
++.IP "" 5
++.IP "\fBqueries\fR (read-only)" 5
++Returns the number of queries sent.
++.IP "" 5
++.IP "\fBresponses\fR (read-only)" 5
++Returns the number of responses received.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ARPResponder n ,
++.M ARPFaker n ,
++.M AddressInfo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ARPResponder.n click-1.6.0-27/inst/share/man/mann/ARPResponder.n
+--- click-1.6.0/inst/share/man/mann/ARPResponder.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ARPResponder.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,66 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/arpresponder.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ARPRESPONDER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ARPResponder \- Click element;
++generates responses to ARP queries
++.SH "SYNOPSIS"
++\fBARPResponder\fR(IP/MASK1 [IP/MASK...] ETH1, IP/MASK2 ETH2, ...)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Input should be ARP request packets, including the Ethernet header.
++Forwards an ARP reply if we know the answer -- that is, if one of the
++IPPREFIX arguments matches the requested IP address, then it outputs an ARP
++reply giving the corresponding ETH address. Could be used for proxy ARP as
++well as producing replies for a host's own address.
++.PP
++The IP/MASK arguments are IP network addresses (IP address/netmask pairs).
++The netmask can be specified in CIDR form (`\f(CW18.26.7.0/24\fR') or dotted
++decimal form (`\f(CW18.26.7.0/255.255.255.0\fR').
++.PP
++\fBARPResponder\fR sets the device annotations on generated ARP responses to the
++device annotations from the corresponding queries.
++.PP
++
++.SH "NOTES"
++.M AddressInfo "n"
++elements can simplify the arguments to \fBARPResponder\fR. In
++particular, if \f(CWNAME\fR is shorthand for both an IP network address (or IP
++address) \f(CWIP\fR and an Ethernet address \f(CWETH\fR, then \f(CWARPResponder(NAME)\fR is
++equivalent to \f(CWARPResponder(IP ETH)\fR. If \f(CWNAME\fR is short for both an IP
++address and an IP network address, then \fBARPResponder\fR will prefer the IP
++address. (You can say \f(CWNAME:ipnet\fR to use the IP network address.)
++.PP
++
++.SH "EXAMPLES"
++Produce ARP replies for the local machine (18.26.4.24)
++as well as proxy ARP for all machines on net 18.26.7
++directing their packets to the local machine:
++.PP
++.nf
++\& c :: Classifier(12/0806 20/0001, ...);
++\& ar :: ARPResponder(18.26.4.24 18.26.7.0/24 00:00:C0:AE:67:EF);
++\& c[0] -> ar;
++\& ar -> ToDevice(eth0);
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ARPQuerier n ,
++.M ARPFaker n ,
++.M AddressInfo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/AdaptiveRED.n click-1.6.0-27/inst/share/man/mann/AdaptiveRED.n
+--- click-1.6.0/inst/share/man/mann/AdaptiveRED.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/AdaptiveRED.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/aqm/adaptivered.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ADAPTIVERED" n "11/Feb/2009" "Click"
++.SH "NAME"
++AdaptiveRED \- Click element;
++drops packets according to Adaptive RED
++.SH "SYNOPSIS"
++\fBAdaptiveRED\fR(TARGET, MAX_P [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: aqm (core)
++.br
++.SH "DESCRIPTION"
++Implements the Adaptive Random Early Detection packet dropping algorithm. This
++algorithm implements Random Early Detection, as by the
++.M RED "n"
++element, plus
++automatic parameter setting.
++.PP
++The TARGET argument is the target queue length.
++.M RED "n" 's
++MIN_THRESH parameter
++is set to TARGET/2, and MAX_THRESH to 3*TARGET/2. The MAX_P parameter, and
++QUEUES and STABILITY keywords, are as in the
++.M RED "n"
++element.
++.PP
++
++.SH "SEE ALSO"
++.M RED "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/AddressInfo.n click-1.6.0-27/inst/share/man/mann/AddressInfo.n
+--- click-1.6.0/inst/share/man/mann/AddressInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/AddressInfo.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,85 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../include/click/standard/addressinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ADDRESSINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++AddressInfo \- Click element;
++specifies address information
++.SH "SYNOPSIS"
++\fBAddressInfo\fR(NAME ADDRESS [ADDRESS...], ...)
++
++\fBPorts\fR: None
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Lets you use mnemonic names for IPv4 and IPv6 addresses, IPv4 and IPv6
++address prefixes, and Ethernet addresses. Each argument has the form `NAME
++ADDRESS [ADDRESS...]', which associates the given ADDRESSes with NAME. For
++example, if a configuration contains this \fBAddressInfo\fR element,
++.PP
++.nf
++\& AddressInfo(mauer 10.0.0.1, mazu 10.0.0.10);
++.fi
++.PP
++then other configuration strings can use \f(CWmauer\fR and \f(CWmazu\fR as mnemonics
++for the IP addresses 10.0.0.1 and 10.0.0.10, respectively.
++.PP
++The mnemonic names introduced by \fBAddressInfo\fR elements are local with
++respect to compound elements. That is, names created inside a compound
++element apply only within that compound element and its subelements. For
++example:
++.PP
++.nf
++\& AddressInfo(mauer 10.0.0.1);
++\& compound :: {
++\& AddressInfo(mazu 10.0.0.10);
++\& ... -> IPEncap(6, mauer, mazu) -> ... // OK
++\& };
++\& ... -> IPEncap(6, mauer, mazu) -> ... // error: `mazu' undefined
++.fi
++.PP
++Any name can be simultaneously associated with an IP address, an IP network
++address, and an Ethernet address. The kind of address that is returned is
++generally determined from context. For example:
++.PP
++.nf
++\& AddressInfo(mauer 10.0.0.1/8 00:50:BA:85:84:A9);
++\& ... -> IPEncap(6, mauer, ...) // as IP address
++\& -> EtherEncap(0x0800, mauer, ...) -> ... // as Ethernet address
++\& ... -> ARPResponder(mauer) -> ... // as IP prefix AND Ethernet address!
++.fi
++.PP
++An optional suffix makes the context unambiguous. \f(CWNAME\fR is an ambiguous
++reference to some address, but \f(CWNAME:ip\fR is always an IPv4 address,
++\f(CWNAME:ipnet\fR is always an IPv4 network address (IPv4 address prefix),
++\f(CWNAME:ip6\fR is always an IPv6 address, \f(CWNAME:ip6net\fR is always an IPv6
++network address, and \f(CWNAME:eth\fR is always an Ethernet address.
++.PP
++
++
++.SH "DEFAULT ADDRESSES"
++If you do not define an address for a given name, \fBAddressInfo\fR will use the
++default, if any. Defaults are as follows:
++.PP
++
++
++.IP "*" 2
++If DEVNAME is the name of an Ethernet device, then \f(CWDEVNAME:eth\fR defaults to
++DEVNAME's Ethernet address. (At userlevel, this works only on BSD and Linux.)
++.IP "" 2
++.IP "*" 2
++\f(CWDEVNAME:ip\fR defaults to the first primary IPv4 address associated with the
++device DEVNAME.
++.IP "" 2
++.PP
++These defaults are not available on all platforms.
++.PP
++.SH "SEE ALSO"
++.M PortInfo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Align.n click-1.6.0-27/inst/share/man/mann/Align.n
+--- click-1.6.0/inst/share/man/mann/Align.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Align.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,48 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/align.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ALIGN" n "11/Feb/2009" "Click"
++.SH "NAME"
++Align \- Click element;
++aligns packet data
++.SH "SYNOPSIS"
++\fBAlign\fR(MODULUS, OFFSET)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Aligns packet data. Each input packet is aligned so that its first byte is
++OFFSET bytes off from a MODULUS-byte boundary. This may involve a packet
++copy.
++.PP
++MODULUS must be 2, 4, or 8.
++
++.SH "NOTES"
++The
++.M click-align 1
++tool will insert this element automatically wherever it
++is required.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ... -> Align(4, 0) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M AlignmentInfo n ,
++click-align(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/AlignmentInfo.n click-1.6.0-27/inst/share/man/mann/AlignmentInfo.n
+--- click-1.6.0/inst/share/man/mann/AlignmentInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/AlignmentInfo.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,36 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../include/click/standard/alignmentinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ALIGNMENTINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++AlignmentInfo \- Click element;
++specifies alignment information
++.SH "SYNOPSIS"
++\fBAlignmentInfo\fR(ELEMENT [MODULUS OFFSET ...], ...)
++
++\fBPorts\fR: None
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Provides information about the packet alignment specified elements can
++expect. Each configuration argument has the form
++`ELEMENT [MODULUS0 OFFSET0 MODULUS1 OFFSET1 ...]',
++where there are zero or more MODULUS-OFFSET pairs.
++All packets arriving at ELEMENT's
++\fIn\fRth input will start `OFFSET\fIn\fR' bytes
++off from a `MODULUS\fIn\fR'-byte boundary.
++
++.SH "NOTES"
++This element is inserted automatically by
++.M click-align 1 .
++
++.SH "SEE ALSO"
++.M Align n ,
++click-align(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/AverageCounter.n click-1.6.0-27/inst/share/man/mann/AverageCounter.n
+--- click-1.6.0/inst/share/man/mann/AverageCounter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/AverageCounter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,54 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/averagecounter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "AVERAGECOUNTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++AverageCounter \- Click element;
++measures historical packet count and rate
++.SH "SYNOPSIS"
++\fBAverageCounter\fR([IGNORE])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Passes packets unchanged from its input to its
++output, maintaining statistics information about
++packet count and packet rate using a strict average.
++.PP
++The rate covers only the time between the first and
++most recent packets.
++.PP
++IGNORE, by default, is 0. If it is greater than 0,
++the first IGNORE number of seconds are ignored in
++the count.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets that have passed through since the last reset.
++.IP "" 5
++.IP "\fBbyte_count\fR (read-only)" 5
++Returns the number of packets that have passed through since the last reset.
++.IP "" 5
++.IP "\fBrate\fR (read-only)" 5
++Returns packet arrival rate.
++.IP "" 5
++.IP "\fBbyte_rate\fR (read-only)" 5
++Returns packet arrival rate in bytes per second. (Beware overflow!)
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++Resets the count and rate to zero.
++.PP
++
+diff -Nurb click-1.6.0/inst/share/man/mann/BandwidthMeter.n click-1.6.0-27/inst/share/man/mann/BandwidthMeter.n
+--- click-1.6.0/inst/share/man/mann/BandwidthMeter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/BandwidthMeter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,59 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/bandwidthmeter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "BANDWIDTHMETER" n "11/Feb/2009" "Click"
++.SH "NAME"
++BandwidthMeter \- Click element;
++classifies packet stream by arrival rate
++.SH "SYNOPSIS"
++\fBBandwidthMeter\fR(RATE1, RATE2, ..., RATE\fIn\fR)
++
++\fBPorts\fR: 1 input, 2 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Classifies packet stream based on the rate of packet arrival. The rate
++is measured in bytes per second using an exponential weighted moving
++average. (The related
++.M Meter "n"
++element measures rates in packets per
++second.)
++.PP
++The configuration string consists of one or more RATE arguments. Each
++RATE is a bandwidth, such as "384 kbps". Earlier
++rates in the list must be less than later rates. A
++.M Meter "n"
++with \fIn\fR rate
++arguments will have \fIn\fR+1 outputs. It sends packets out the output
++corresponding to the current rate. If the rate is less than RATE1
++packets are sent to output 0; if it is >= RATE1 but < RATE2, packets are
++sent to output 1; and so on. If it is >= RATE\fIn\fR, packets are sent to
++output \fIn\fR.
++.PP
++
++.SH "EXAMPLES"
++This configuration fragment drops the input stream when it is generating
++more than 20,000 bytes per second.
++.PP
++.nf
++\& ... -> m :: BandwidthMeter(20kBps) -> ...;
++\& m[1] -> Discard;
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Meter n ,
++.M BandwidthShaper n ,
++.M Shaper n ,
++.M RatedSplitter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/BandwidthRatedSplitter.n click-1.6.0-27/inst/share/man/mann/BandwidthRatedSplitter.n
+--- click-1.6.0/inst/share/man/mann/BandwidthRatedSplitter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/BandwidthRatedSplitter.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,46 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/bwratedsplitter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "BANDWIDTHRATEDSPLITTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++BandwidthRatedSplitter \- Click element;
++splits flow of packets at specified bandwidth rate
++.SH "SYNOPSIS"
++\fBBandwidthRatedSplitter\fR(RATE)
++
++\fBPorts\fR: 1 input, 2 outputs
++.br
++\fBProcessing\fR: Push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBBandwidthRatedSplitter\fR has two output ports. All incoming packets up to a
++maximum of RATE are emitted on output port 0. Any remaining packets are
++emitted on output port 1. RATE is a bandwidth, such as "384 kbps".
++Unlike
++.M BandwidthMeter "n" ,
++the base RATE is emitted on output port
++0 even when the input rate is greater than RATE.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBrate\fR (read/write)" 5
++rate of splitting
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RatedSplitter n ,
++.M BandwidthMeter n ,
++.M BandwidthShaper n ,
++.M BandwidthRatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/BandwidthRatedUnqueue.n click-1.6.0-27/inst/share/man/mann/BandwidthRatedUnqueue.n
+--- click-1.6.0/inst/share/man/mann/BandwidthRatedUnqueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/BandwidthRatedUnqueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,32 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/bwratedunqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "BANDWIDTHRATEDUNQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++BandwidthRatedUnqueue \- Click element;
++pull-to-push converter
++.SH "SYNOPSIS"
++\fBBandwidthRatedUnqueue\fR(RATE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: Pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets at the given bandwidth RATE, and pushes them out its single
++output. RATE is a bandwidth, such as "384 kbps".
++.PP
++
++.SH "SEE ALSO"
++.M RatedUnqueue n ,
++.M Unqueue n ,
++.M BandwidthShaper n ,
++.M BandwidthRatedSplitter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/BandwidthShaper.n click-1.6.0-27/inst/share/man/mann/BandwidthShaper.n
+--- click-1.6.0/inst/share/man/mann/BandwidthShaper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/BandwidthShaper.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,43 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/bandwidthshaper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "BANDWIDTHSHAPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++BandwidthShaper \- Click element;
++shapes traffic to maximum rate (bytes/s)
++.SH "SYNOPSIS"
++\fBBandwidthShaper\fR(RATE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: Pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBBandwidthShaper\fR is a pull element that allows a maximum bandwidth of
++RATE to pass through. That is, output traffic is shaped to RATE.
++If a \fBBandwidthShaper\fR receives a large number of
++evenly-spaced pull requests, then it will emit packets at the specified
++RATE with low burstiness.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Shaper n ,
++.M BandwidthRatedSplitter n ,
++.M BandwidthRatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Burster.n click-1.6.0-27/inst/share/man/mann/Burster.n
+--- click-1.6.0/inst/share/man/mann/Burster.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Burster.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,35 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/burster.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "BURSTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++Burster \- Click element;
++pull-to-push converter
++.SH "SYNOPSIS"
++\fBBurster\fR(INTERVAL, BURST)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls BURST packets each INTERVAL (seconds) from its input.
++Pushes them out its single output. The interval can be
++a floating point number. Default BURST is 8.
++.PP
++There are usually Queues both upstream and downstream
++of \fBBurster\fR elements.
++.PP
++
++.SH "NOTES"
++The UNIX and Linux timers have granularity of about 10
++milliseconds, so this \fBBurster\fR can only produce high packet
++rates by being bursty.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CPUQueue.n click-1.6.0-27/inst/share/man/mann/CPUQueue.n
+--- click-1.6.0/inst/share/man/mann/CPUQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CPUQueue.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,35 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/cpuqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CPUQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++CPUQueue \- Click element;
++stores packets in FIFO queues.
++.SH "SYNOPSIS"
++CPUQueue
++.br
++\fBCPUQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a first-in-first-out queue. Each CPU has its own
++queue. The incoming packet is always enqueued onto the queue of the CPU
++calling the push method. Drops incoming packets if the queue already holds
++CAPACITY packets. The default for CAPACITY is 128.
++.PP
++
++.SH "SEE ALSO"
++.M Queue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CPUSwitch.n click-1.6.0-27/inst/share/man/mann/CPUSwitch.n
+--- click-1.6.0/inst/share/man/mann/CPUSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CPUSwitch.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,32 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/cpuswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CPUSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++CPUSwitch \- Click element;
++classifies packets by cpu
++.SH "SYNOPSIS"
++\fBCPUSwitch\fR()
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Can have any number of outputs.
++Chooses the output on which to emit each packet based on the thread's cpu.
++
++.SH "SEE ALSO"
++.M RoundRobinSwitch n ,
++.M StrideSwitch n ,
++.M HashSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ChangeUID.n click-1.6.0-27/inst/share/man/mann/ChangeUID.n
+--- click-1.6.0/inst/share/man/mann/ChangeUID.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ChangeUID.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/changeuid.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHANGEUID" n "11/Feb/2009" "Click"
++.SH "NAME"
++ChangeUID \- Click element;
++relinquish root privilege
++.SH "SYNOPSIS"
++\fBChangeUID\fR()
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Sets the current process's effective user and group IDs to its real user and
++group IDs, respectively. This relinquishes any set-uid-root privilege.
++.PP
++
++.SH "NOTES"
++\fBChangeUID\fR's configure phase is set so that it runs immediately after the
++"privileged" elements FromDevice.u and ToDevice.u, but before most other
++elements. Thus, this configuration:
++.PP
++.nf
++\& f1 :: FromDevice(eth0) -> ...
++\& f2 :: FromDump(/tmp/x) -> ...
++\& ChangeUID()
++.fi
++.PP
++should fail to initialize if the user cannot read file \fI/tmp/x\fR. However,
++your mileage may vary. Set-uid-root programs are a bad idea, and Click is no
++exception.
++
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ChatterSocket.n click-1.6.0-27/inst/share/man/mann/ChatterSocket.n
+--- click-1.6.0/inst/share/man/mann/ChatterSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ChatterSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,101 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/chattersocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHATTERSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++ChatterSocket \- Click element;
++reports chatter messages to connected sockets
++.SH "SYNOPSIS"
++\fBChatterSocket\fR("TCP", PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBChatterSocket\fR("UNIX", FILENAME [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Opens a chatter socket that allows other user-level programs to receive copies
++of router chatter traffic. Depending on its configuration string,
++\fBChatterSocket\fR will listen on TCP port PORTNUMBER, or on a UNIX-domain socket
++named FILENAME.
++.PP
++The "server" (that is, the \fBChatterSocket\fR element) simply echoes any messages
++generated by the router configuration to any existing "clients". The server
++does not read any data from its clients.
++.PP
++When a connection is opened, \fBChatterSocket\fR responds by stating its protocol
++version number with a line like "Click::ChatterSocket/1.0\\r\\n". The current
++version number is 1.0.
++.PP
++\fBChatterSocket\fR broadcasts copies of messages generated by the default
++ErrorHandler or the \f(CWclick_chatter\fR function. Most elements report messages
++or run-time errors using one of these mechanisms.
++.PP
++If a client falls more than 500,000 bytes behind, \fBChatterSocket\fR automatically
++closes its connection.
++.PP
++\fBChatterSocket\fR supports hot-swapping, meaning you can change configurations
++without interrupting existing clients. The hot-swap will succeed only if the
++old \fBChatterSocket\fR and the new \fBChatterSocket\fR have the same element name, and
++the same socket type, port/filename, and chatter channel parameters.
++Additionally, the new \fBChatterSocket\fR must have RETRIES set to 1 or more, since
++the old \fBChatterSocket\fR has already bound the relevant socket.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "CHANNEL" 8
++Text word. The socket outputs messages sent to this chatter channel. Default
++is the default channel, which corresponds to \f(CWclick_chatter()\fR.
++.IP "" 8
++Channels help you organize extensive debugging output. For example, you could
++send extremely verbose messages to a `\f(CWverbose\fR' channel, then only connect
++to that channel when you want verbosity.
++.IP "" 8
++To send messages to a particular channel, you should fetch the ErrorHandler
++object corresponding to that channel, using the Router member function
++\f(CWRouter::chatter_channel(const String &channel_name)\fR.
++.IP "" 8
++.IP "QUIET_CHANNEL" 8
++Boolean. Messages sent to a non-default channel are not normally printed on
++standard error. If QUIET_CHANNEL is false, however, the channel's messages do
++go to standard error, along with chatter messages. Default is true.
++.IP "" 8
++.IP "GREETING" 8
++Boolean. Determines whether the \f(CWClick::ChatterSocket/1.0\fR greeting is sent.
++Default is true.
++.IP "" 8
++.IP "RETRIES" 8
++Integer. If greater than 0, \fBChatterSocket\fR won't immediately fail when it can't
++open its socket. Instead, it will attempt to open the socket once a second
++until it succeeds, or until RETRIES unsuccessful attempts (after which it will
++stop the router). Default is 0.
++.IP "" 8
++.IP "RETRY_WARNINGS" 8
++Boolean. If true, \fBChatterSocket\fR will print warning messages every time it
++fails to open a socket. If false, it will print messages only on the final
++failure. Default is true.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ChatterSocket(unix, /tmp/clicksocket);
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ControlSocket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckARPHeader.n click-1.6.0-27/inst/share/man/mann/CheckARPHeader.n
+--- click-1.6.0/inst/share/man/mann/CheckARPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckARPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,71 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/checkarpheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKARPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckARPHeader \- Click element;
++checks ARP header
++.SH "SYNOPSIS"
++\fBCheckARPHeader\fR([OFFSET, \fIkeywords\fR OFFSET, VERBOSE, DETAILS])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Input packets should have ARP headers starting OFFSET bytes in. Default OFFSET
++is zero. Checks that the packet's length is reasonable.
++.PP
++\fBCheckARPHeader\fR emits valid packets on output 0. Invalid packets are pushed out
++on output 1, unless output 1 was unused; if so, drops invalid packets.
++.PP
++\fBCheckARPHeader\fR prints a message to the console the first time it encounters an
++incorrect ARP packet (but see VERBOSE below).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "OFFSET" 5
++Unsigned integer. Byte position at which the ARP header begins. Default is 0.
++.IP "" 5
++.IP "VERBOSE" 5
++Boolean. If it is true, then a message will be printed for every erroneous
++packet, rather than just the first. False by default.
++.IP "" 5
++.IP "DETAILS" 5
++Boolean. If it is true, then \fBCheckARPHeader\fR will maintain detailed counts of
++how many packets were dropped for each possible reason, accessible through the
++\f(CWdrop_details\fR handler. False by default.
++.IP "" 5
++.PP
++
++.SH "NOTES"
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of incorrect packets \fBCheckARPHeader\fR has seen.
++.IP "" 5
++.IP "\fBdrop_details\fR (read-only)" 5
++Returns a text file showing how many erroneous packets \fBCheckARPHeader\fR has seen,
++subdivided by error. Only available if the DETAILS keyword argument was true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ARPPrint n ,
++.M ARPQuerier n ,
++.M ARPResponder n ,
++.M ARPFaker "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckCRC32.n click-1.6.0-27/inst/share/man/mann/CheckCRC32.n
+--- click-1.6.0/inst/share/man/mann/CheckCRC32.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckCRC32.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,31 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/checkcrc32.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKCRC32" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckCRC32 \- Click element;
++checks packet CRC32s
++.SH "SYNOPSIS"
++\fBCheckCRC32\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Check that the CRC32 appended by
++.M SetCRC32 "n"
++is OK.
++If so, delete the CRC from the packet.
++Otherwise, drop the packet.
++
++.SH "SEE ALSO"
++.M SetCRC32 "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckICMPHeader.n click-1.6.0-27/inst/share/man/mann/CheckICMPHeader.n
+--- click-1.6.0/inst/share/man/mann/CheckICMPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckICMPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,63 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/checkicmpheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKICMPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckICMPHeader \- Click element;
++checks ICMP header on ICMP packets
++.SH "SYNOPSIS"
++\fBCheckICMPHeader\fR([\fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Expects ICMP packets as input. Checks that the packet's length is sensible
++and that its checksum field is valid. Pushes invalid packets out on output
++1, unless output 1 was unused; if so, drops invalid packets.
++.PP
++Prints a message to the console the first time it encounters an incorrect IP
++packet (but see VERBOSE below).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "VERBOSE" 5
++Boolean. If it is true, then a message will be printed for every erroneous
++packet, rather than just the first. False by default.
++.IP "" 5
++.IP "DETAILS" 5
++Boolean. If it is true, then \fBCheckICMPHeader\fR will maintain detailed counts of
++how many packets were dropped for each possible reason, accessible through the
++\f(CWdrop_details\fR handler. False by default.
++.IP "" 5
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of incorrect packets \fBCheckICMPHeader\fR has seen.
++.IP "" 5
++.IP "\fBdrop_details\fR (read-only)" 5
++Returns a text file showing how many erroneous packets \fBCheckICMPHeader\fR has seen,
++subdivided by error. Only available if the DETAILS keyword argument was true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M CheckTCPHeader n ,
++.M CheckUDPHeader n ,
++.M MarkIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckIPHeader.n click-1.6.0-27/inst/share/man/mann/CheckIPHeader.n
+--- click-1.6.0/inst/share/man/mann/CheckIPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckIPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,119 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/checkipheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKIPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckIPHeader \- Click element;
++checks IP header
++.SH "SYNOPSIS"
++\fBCheckIPHeader\fR([OFFSET, \fIkeywords\fR OFFSET, INTERFACES, BADSRC,
++.br
++.nf
++\& GOODDST, CHECKSUM, VERBOSE, DETAILS])
++.fi
++.PP
++
++
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Input packets should have IP headers starting OFFSET bytes in. Default OFFSET
++is zero. Checks that the packet's length is reasonable, and that the IP
++version, header length, length, and checksum fields are valid. Checks that the
++IP source address is a legal unicast address, or that the packet is destined
++for one of this machine's addresses (see below). Shortens packets to the IP
++length, if the IP length is shorter than the nominal packet length (due to
++Ethernet padding, for example). Also sets the destination IP address
++annotation to the actual destination IP address.
++.PP
++\fBCheckIPHeader\fR emits valid packets on output 0. Invalid packets are pushed out
++on output 1, unless output 1 was unused; if so, drops invalid packets.
++.PP
++\fBCheckIPHeader\fR checks packets' source addresses for validity if one or more of
++the INTERFACES, BADSRC, and GOODDST keyword arguments are supplied (RFC1812
++5.3.7).
++.PP
++\fBCheckIPHeader\fR prints a message to the console the first time it encounters an
++incorrect IP packet (but see VERBOSE below).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "CHECKSUM" 5
++Boolean. If true, then check each packet's checksum for validity; if false, do
++not check the checksum. Default is true.
++.IP "" 5
++.IP "OFFSET" 5
++Unsigned integer. Byte position at which the IP header begins. Default is 0.
++.IP "" 5
++.IP "BADSRC" 5
++Space-separated list of IP addresses. \fBCheckIPHeader\fR will drop packets whose
++source address is on this list (but see GOODDST below). Default is empty.
++.IP "" 5
++.IP "GOODDST" 5
++Space-separated list of IP addresses. \fBCheckIPHeader\fR exempts packets whose
++destination address is on this list from BADSRC processing. Default is empty.
++.IP "" 5
++.IP "INTERFACES" 5
++Space-separated list of IP addresses with network prefixes, meant to represent
++this router's interface addresses. This argument specifies both BADSRC and
++GOODDST. Specifically, the argument "INTERFACES 18.26.4.9/24 18.32.9.44/28"
++acts like a BADSRC of "18.26.4.255 18.32.9.47 0.0.0.0 255.255.255.255" -- the
++set of broadcast addresses for this router -- and a GOODDST of "18.26.4.9
++18.32.9.44". Default is not given.
++.IP "" 5
++.IP "VERBOSE" 5
++Boolean. If it is true, then a message will be printed for every erroneous
++packet, rather than just the first. False by default.
++.IP "" 5
++.IP "DETAILS" 5
++Boolean. If it is true, then \fBCheckIPHeader\fR will maintain detailed counts of
++how many packets were dropped for each possible reason, accessible through the
++\f(CWdrop_details\fR handler. False by default.
++.IP "" 5
++.PP
++
++.SH "NOTES"
++\fBCheckIPHeader\fR supports an old configuration syntax:
++.PP
++\fBCheckIPHeader\fR([BADSRC2, OFFSET, \fIkeywords\fR])
++.PP
++The BADSRC2 argument behaves like the BADSRC keyword, except that if you use
++this syntax, 0.0.0.0 and 255.255.255.255 considered bad addresses in addition
++to those explicitly in the list. This syntax is deprecated and should not be
++used in new configurations.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of incorrect packets \fBCheckIPHeader\fR has seen.
++.IP "" 5
++.IP "\fBdrop_details\fR (read-only)" 5
++Returns a text file showing how many erroneous packets \fBCheckIPHeader\fR has seen,
++subdivided by error. Only available if the DETAILS keyword argument was true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader2 n ,
++.M MarkIPHeader n ,
++.M SetIPChecksum n ,
++.M StripIPHeader n ,
++.M CheckTCPHeader n ,
++.M CheckUDPHeader n ,
++.M CheckICMPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckIPHeader2.n click-1.6.0-27/inst/share/man/mann/CheckIPHeader2.n
+--- click-1.6.0/inst/share/man/mann/CheckIPHeader2.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckIPHeader2.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,33 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/checkipheader2.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKIPHEADER2" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckIPHeader2 \- Click element;
++checks IP header, no checksum
++.SH "SYNOPSIS"
++\fBCheckIPHeader2\fR([OFFSET, \fIkeywords\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++This element behaves exactly like
++.M CheckIPHeader "n" ,
++except that it does not by
++default check packets' IP checksums.
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M StripIPHeader n ,
++.M MarkIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckLength.n click-1.6.0-27/inst/share/man/mann/CheckLength.n
+--- click-1.6.0/inst/share/man/mann/CheckLength.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckLength.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,26 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/checklength.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKLENGTH" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckLength \- Click element;
++drops large packets
++.SH "SYNOPSIS"
++\fBCheckLength\fR(LENGTH)
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBCheckLength\fR checks every packet's length against LENGTH. If the packet is
++no larger than LENGTH, it is sent to output 0; otherwise, it is sent to
++output 1 (or dropped if there is no output 1).
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckPaint.n click-1.6.0-27/inst/share/man/mann/CheckPaint.n
+--- click-1.6.0/inst/share/man/mann/CheckPaint.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckPaint.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,31 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/checkpaint.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKPAINT" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckPaint \- Click element;
++checks packets' paint annotation
++.SH "SYNOPSIS"
++\fBCheckPaint\fR(COLOR)
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Checks that incoming packets have paint annotation equal to COLOR. If their
++paints are not equal to COLOR, then they are dropped or emitted on output 1,
++depending on how many outputs were used.
++.PP
++
++.SH "SEE ALSO"
++.M Paint n ,
++.M PaintTee "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckTCPHeader.n click-1.6.0-27/inst/share/man/mann/CheckTCPHeader.n
+--- click-1.6.0/inst/share/man/mann/CheckTCPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckTCPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,64 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/checktcpheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKTCPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckTCPHeader \- Click element;
++checks TCP header on TCP/IP packets
++.SH "SYNOPSIS"
++\fBCheckTCPHeader\fR([\fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Expects TCP/IP packets as input. Checks that the TCP header length and
++checksum fields are valid. Pushes invalid packets out on output 1, unless
++output 1 was unused; if so, drops invalid packets.
++.PP
++Prints a message to the console the first time it encounters an incorrect
++packet (but see VERBOSE below).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "VERBOSE" 5
++Boolean. If it is true, then a message will be printed for every erroneous
++packet, rather than just the first. False by default.
++.IP "" 5
++.IP "DETAILS" 5
++Boolean. If it is true, then \fBCheckTCPHeader\fR will maintain detailed counts of
++how many packets were dropped for each possible reason, accessible through the
++\f(CWdrop_details\fR handler. False by default.
++.IP "" 5
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of incorrect packets \fBCheckTCPHeader\fR has seen.
++.IP "" 5
++.IP "\fBdrop_details\fR (read-only)" 5
++Returns a text file showing how many erroneous packets \fBCheckTCPHeader\fR has
++seen, subdivided by error. Only available if the DETAILS keyword argument was
++true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M CheckUDPHeader n ,
++.M CheckICMPHeader n ,
++.M MarkIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CheckUDPHeader.n click-1.6.0-27/inst/share/man/mann/CheckUDPHeader.n
+--- click-1.6.0/inst/share/man/mann/CheckUDPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CheckUDPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,64 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/checkudpheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CHECKUDPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++CheckUDPHeader \- Click element;
++checks UDP header on UDP/IP packets
++.SH "SYNOPSIS"
++\fBCheckUDPHeader\fR([\fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Expects UDP/IP packets as input. Checks that the UDP header length and
++checksum fields are valid. Pushes invalid packets out on output 1, unless
++output 1 was unused; if so, drops invalid packets.
++.PP
++Prints a message to the console the first time it encounters an incorrect
++packet (but see VERBOSE below).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "VERBOSE" 5
++Boolean. If it is true, then a message will be printed for every erroneous
++packet, rather than just the first. False by default.
++.IP "" 5
++.IP "DETAILS" 5
++Boolean. If it is true, then \fBCheckUDPHeader\fR will maintain detailed counts of
++how many packets were dropped for each possible reason, accessible through the
++\f(CWdrop_details\fR handler. False by default.
++.IP "" 5
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of incorrect packets \fBCheckUDPHeader\fR has seen.
++.IP "" 5
++.IP "\fBdrop_details\fR (read-only)" 5
++Returns a text file showing how many erroneous packets \fBCheckUDPHeader\fR has
++seen, subdivided by error. Only available if the DETAILS keyword argument was
++true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M CheckTCPHeader n ,
++.M CheckICMPHeader n ,
++.M MarkIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Classifier.n click-1.6.0-27/inst/share/man/mann/Classifier.n
+--- click-1.6.0/inst/share/man/mann/Classifier.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Classifier.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,105 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/classifier.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CLASSIFIER" n "11/Feb/2009" "Click"
++.SH "NAME"
++Classifier \- Click element;
++classifies packets by contents
++.SH "SYNOPSIS"
++\fBClassifier\fR(pattern1, ..., patternN)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Classifies packets. The \fBClassifier\fR has N outputs, each associated with the
++corresponding pattern from the configuration string.
++A pattern is a set of clauses, where each clause is either "offset/value"
++or "offset/value%mask". A pattern matches if the packet has the indicated
++value at each offset.
++.PP
++The clauses in each pattern are separated
++by spaces. A clause consists of the offset, "/", the value, and (optionally)
++"%" and a mask. The offset is in decimal. The value and mask are in hex.
++The length of the value is implied by the number of hex digits, which must
++be even. "?" is also allowed as a "hex digit"; it means "don't care about
++the value of this nibble".
++.PP
++If present, the mask must have the same number of hex digits as the value.
++The matcher will only check bits that are 1 in the mask.
++.PP
++A clause may be preceded by "!", in which case the clause must NOT match
++the packet.
++.PP
++As a special case, a pattern consisting of "-" matches every packet.
++.PP
++The patterns are scanned in order, and the packet is sent to the output
++corresponding to the first matching pattern. Thus more specific patterns
++should come before less specific ones. You will get a warning if no packet
++could ever match a pattern. Usually, this is because an earlier pattern is
++more general, or because your pattern is contradictory (`12/0806 12/0800').
++.PP
++
++.SH "NOTES"
++The
++.M IPClassifier "n"
++and
++.M IPFilter "n"
++elements have a friendlier syntax if you are
++classifying IP packets.
++.PP
++
++.SH "EXAMPLES"
++For example,
++.PP
++.nf
++\& Classifier(12/0806 20/0001,
++\& 12/0806 20/0002,
++\& 12/0800,
++\& -);
++.fi
++.PP
++creates an element with four outputs intended to process
++Ethernet packets.
++ARP requests are sent to output 0, ARP replies are sent to
++output 1, IP packets to output 2, and all others to output 3.
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBprogram\fR (read-only)" 5
++Returns a human-readable definition of the program the \fBClassifier\fR element
++is using to classify packets. At each step in the program, four bytes
++of packet data are ANDed with a mask and compared against four bytes of
++classifier pattern.
++.IP "" 5
++The \fBClassifier\fR patterns above compile into the following program:
++.IP "" 5
++.nf
++\& 0 12/08060000%ffff0000 yes->step 1 no->step 3
++\& 1 20/00010000%ffff0000 yes->[0] no->step 2
++\& 2 20/00020000%ffff0000 yes->[1] no->[3]
++\& 3 12/08000000%ffff0000 yes->[2] no->[3]
++\& safe length 22
++\& alignment offset 0
++.fi
++.IP "" 5
++
++
++.PP
++
++.SH "SEE ALSO"
++.M IPClassifier n ,
++.M IPFilter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CompareBlock.n click-1.6.0-27/inst/share/man/mann/CompareBlock.n
+--- click-1.6.0/inst/share/man/mann/CompareBlock.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CompareBlock.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,62 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/compblock.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "COMPAREBLOCK" n "11/Feb/2009" "Click"
++.SH "NAME"
++CompareBlock \- Click element;
++drops packets out of rate range
++.SH "SYNOPSIS"
++\fBCompareBlock\fR(FWD_WEIGHT, REV_WEIGHT, THRESH)
++
++\fBPorts\fR: 1 input, 2 outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++FWD_WEIGHT, REV_WEIGHT, and THRESH are integers
++.PP
++Splits packets based on the fwd_rate_anno and rev_rate_anno rate annotations
++set by
++.M IPRateMonitor "n" .
++If either annotation is greater than THRESH,
++and FWD_WEIGHT*fwd_rate_anno > REV_WEIGHT*rev_rate_anno,
++the packet is pushed on output 1, otherwise on output 0.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& b :: CompareBlock(5, 2, 100);
++.fi
++.PP
++if (5*fwd_rate > 2*rev_rate) AND (fwd_rate > 100 or rev_rate > 100), send
++packet out on output 1, otherwise on output 0.
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBfwd_weight\fR (read/write)" 5
++value of FWD_WEIGHT
++.IP "" 5
++.IP "\fBrev_weight\fR (read/write)" 5
++value of REV_WEIGHT
++.IP "" 5
++.IP "\fBthresh\fR (read/write)" 5
++value of THRESH
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Block n ,
++.M IPRateMonitor "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ControlSocket.n click-1.6.0-27/inst/share/man/mann/ControlSocket.n
+--- click-1.6.0/inst/share/man/mann/ControlSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ControlSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,181 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/controlsocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CONTROLSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++ControlSocket \- Click element;
++opens control sockets for other programs
++.SH "SYNOPSIS"
++\fBControlSocket\fR("TCP", PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBControlSocket\fR("UNIX", FILENAME [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Opens a control socket that allows other user-level programs to call read or
++write handlers on the router. Depending on its configuration string,
++\fBControlSocket\fR will listen on TCP port PORTNUMBER, or on a UNIX-domain socket
++named FILENAME. With the PROXY keyword argument, you can make \fBControlSocket\fR speak to
++a kernel driver; see below.
++.PP
++The "server" (that is, the \fBControlSocket\fR element) speaks a relatively
++simple line-based protocol. Commands sent to the server are single lines of
++text; they consist of words separated by spaces. The server responds to
++every command with at least one message line followed optionally by some
++data. Message lines start with a three-digit response code, as in FTP. When
++multiple message lines are sent in response to a single command, all but
++the last begin with the response code and a hyphen (as in "200-Hello!");
++the last line begins with the response code and a space (as in "200
++Hello!").
++.PP
++The server will accept lines terminated by CR, LF, or CRLF. Its response
++lines are always terminated by CRLF.
++.PP
++When a connection is opened, the server responds by stating its protocol
++version number with a line like "Click::ControlSocket/1.1". The current
++version number is 1.1. Changes in minor version number will only add commands
++and functionality to this specification, not change existing functionality.
++.PP
++\fBControlSocket\fR supports hot-swapping, meaning you can change configurations
++without interrupting existing clients. The hot-swap will succeed only if the
++old \fBControlSocket\fR and the new \fBControlSocket\fR have the same element name, and
++the same socket type and port/filename parameters. Additionally, the new
++\fBControlSocket\fR must have RETRIES set to 1 or more, since the old \fBControlSocket\fR
++has already bound the relevant socket.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "READONLY" 8
++Boolean. Disallows write handlers if true (it is false by
++default).
++.IP "" 8
++.IP "PROXY" 8
++String. Specifies an element proxy. When a user requests the value of handler
++E.H, \fBControlSocket\fR will actually return the value of `PROXY.E.H'. This is
++useful with elements like
++.M KernelHandlerProxy "n" .
++Default is empty (no proxy).
++.IP "" 8
++.IP "VERBOSE" 8
++Boolean. When true, \fBControlSocket\fR will print messages whenever it accepts a
++new connection or drops an old one. Default is false.
++.IP "" 8
++.IP "RETRIES" 8
++Integer. If greater than 0, \fBControlSocket\fR won't immediately fail when it can't
++open its socket. Instead, it will attempt to open the socket once a second
++until it succeeds, or until RETRIES unsuccessful attempts (after which it will
++stop the router). Default is 0.
++.IP "" 8
++.IP "RETRY_WARNINGS" 8
++Boolean. If true, \fBControlSocket\fR will print warning messages every time it
++fails to open a socket. If false, it will print messages only on the final
++failure. Default is true.
++.IP "" 8
++.PP
++
++.SH "SERVER COMMANDS"
++The server currently supports the following six commands. Many of the commands
++take a \fIhandler\fR argument. These arguments name handlers, and take one of
++three forms: \f(CW\fIelementname\fR.\fIhandlername\fR\fR names a particular element's
++handler; \f(CW\fIelementnumber\fR.\fIhandlername\fR\fR also names an element handler, but
++the element is identified by index, starting from 1; and \f(CW\fIhandlername\fR\fR
++names a global handler. (There are seven global read handlers, named
++\f(CWversion\fR, \f(CWlist\fR, \f(CWclasses\fR, \f(CWconfig\fR, \f(CWflatconfig\fR, \f(CWpackages\fR, and
++\f(CWrequirements\fR. See click.o(8) for more information.)
++.PP
++
++
++.IP "READ \fIhandler\fR [\fIparams...\fR]" 5
++Call a read \fIhandler\fR, passing the \fIparams\fR, if any,
++as arguments, and return the results.
++On success, responds with a "success" message (response
++code 2xy) followed by a line like "DATA \fIn\fR". Here, \fIn\fR is a
++decimal integer indicating the length of the read handler data. The \fIn\fR
++bytes immediately following (the CRLF that terminates) the DATA line are
++the handler's results.
++.IP "" 5
++.IP "WRITE \fIhandler\fR \fIparams...\fR" 5
++Call a write \fIhandler\fR, passing the \fIparams\fR, if any, as arguments.
++.IP "" 5
++.IP "WRITEDATA \fIhandler\fR \fIn\fR" 5
++Call a write \fIhandler\fR. The arguments to pass are the \fIn\fR bytes immediately
++following (the CRLF that terminates) the WRITEDATA line.
++.IP "" 5
++.IP "CHECKREAD \fIhandler\fR" 5
++Checks whether a \fIhandler\fR exists and is readable. The return status is 200
++for readable handlers, and an appropriate error status for non-readable
++handlers or nonexistent handlers.
++.IP "" 5
++.IP "CHECKWRITE \fIhandler\fR" 5
++Checks whether a \fIhandler\fR exists and is writable.
++.IP "" 5
++.IP "LLRPC \fIllrpc\fR [\fIn\fR]" 5
++Call an LLRPC \fIllrpc\fR and return the results. \fILlrpc\fR should have the form
++\f(CW\fIelement\fR#\fIhexnumber\fR\fR. The \f(CW\fIhexnumber\fR\fR is the LLRPC number, from
++\f(CW<click/llrpc.h>\fR, in hexadecimal network format. Translate \f(CWCLICK_LLRPC\fR
++constants to network format by calling
++\f(CWCLICK_LLRPC_HTON(CLICK_LLRPC_...)\fR. If \fIn\fR is given, then the \fIn\fR bytes
++immediately following (the CRLF that terminates) the LLRPC line are passed in
++as an argument. The results are returned after a "DATA \fInn\fR" line, as in
++READ.
++.IP "" 5
++\fBControlSocket\fR will not call an LLRPC unless it can determine (from the command
++number) how much data the LLRPC expects and returns. (Only "flat" LLRPCs may
++be called; they are declared using the _CLICK_IOC_[RWS]F macros.)
++.IP "" 5
++.IP "QUIT" 5
++Close the connection.
++.IP "" 5
++.PP
++The server's response codes follow this pattern.
++.PP
++
++.IP "2xy" 5
++The command succeeded.
++.IP "" 5
++.IP "5xy" 5
++The command failed.
++.IP "" 5
++.PP
++Here are some of the particular error messages:
++.PP
++.nf
++\& 200 OK.
++\& 220 OK, but the handler reported some warnings.
++\& 500 Syntax error.
++\& 501 Unimplemented command.
++\& 510 No such element.
++\& 511 No such handler.
++\& 520 Handler error.
++\& 530 Permission denied.
++\& 540 No router installed.
++.fi
++.PP
++\fBControlSocket\fR is only available in user-level processes.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ControlSocket(unix, /tmp/clicksocket);
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ChatterSocket n ,
++.M KernelHandlerProxy "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Counter.n click-1.6.0-27/inst/share/man/mann/Counter.n
+--- click-1.6.0/inst/share/man/mann/Counter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Counter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,81 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/counter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "COUNTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++Counter \- Click element;
++measures packet count and rate
++.SH "SYNOPSIS"
++\fBCounter\fR([\fIkeywords COUNT_CALL, BYTE_COUNT_CALL\fR])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Passes packets unchanged from its input to its output, maintaining statistics
++information about packet count and packet rate.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "COUNT_CALL" 8
++Argument is `\fIN\fR \fIHANDLER\fR [\fIVALUE\fR]'. When the packet count reaches \fIN\fR,
++call the write handler \fIHANDLER\fR with value \fIVALUE\fR.
++.IP "" 8
++.IP "BYTE_COUNT_CALL" 8
++Argument is `\fIN\fR \fIHANDLER\fR [\fIVALUE\fR]'. When the byte count reaches or
++exceeds \fIN\fR, call the write handler \fIHANDLER\fR with value \fIVALUE\fR.
++.IP "" 8
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets that have passed through since the last reset.
++.IP "" 5
++.IP "\fBbyte_count\fR (read-only)" 5
++Returns the number of bytes that have passed through since the last reset.
++.IP "" 5
++.IP "\fBrate\fR (read-only)" 5
++Returns the recent arrival rate, measured by exponential
++weighted moving average, in packets per second.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets the counts and rates to zero.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++Same as 'reset_counts'.
++.IP "" 5
++.IP "\fBcount_call\fR (write-only)" 5
++Writes a new COUNT_CALL argument. The handler can be omitted.
++.IP "" 5
++.IP "\fBbyte_count_call\fR (write-only)" 5
++Writes a new BYTE_COUNT_CALL argument. The handler can be omitted.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_GET_RATE\fR (llrpc)" 5
++Argument is a pointer to an integer that must be 0. Returns the recent
++arrival rate (measured by exponential weighted moving average) in
++packets per second.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_GET_COUNT\fR (llrpc)" 5
++Argument is a pointer to an integer that must be 0 (packet count) or 1 (byte
++count). Returns the current packet or byte count.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_GET_COUNTS\fR (llrpc)" 5
++Argument is a pointer to a click_llrpc_counts_st structure (see
++<click/llrpc.h>). The \f(CWkeys\fR components must be 0 (packet count) or 1 (byte
++count). Stores the corresponding counts in the corresponding \f(CWvalues\fR
++components.
++.PP
++
+diff -Nurb click-1.6.0/inst/share/man/mann/CycleCountAccum.n click-1.6.0-27/inst/share/man/mann/CycleCountAccum.n
+--- click-1.6.0/inst/share/man/mann/CycleCountAccum.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/CycleCountAccum.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,60 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/cyclecountaccum.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "CYCLECOUNTACCUM" n "11/Feb/2009" "Click"
++.SH "NAME"
++CycleCountAccum \- Click element;
++collects differences in cycle counters
++.SH "SYNOPSIS"
++\fBCycleCountAccum\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Incoming packets should have their cycle counter annotation set. Measures the
++current value of the cycle counter, and keeps track of the total accumulated
++difference. Packets whose cycle counter annotations are zero are not added to
++the count or difference.
++.PP
++
++.SH "NOTES"
++A packet has room for either exactly one cycle count or exactly one
++performance metric.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets that have passed.
++.IP "" 5
++.IP "\fBcycles\fR (read-only)" 5
++Returns the accumulated cycles for all passing packets.
++.IP "" 5
++.IP "\fBzero_count\fR (read-only)" 5
++Returns the number of packets with zero-valued cycle counter annotations that
++have passed. These aren't included in the \f(CWcount\fR.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets \f(CWcount\fR, \f(CWcycles\fR, and \f(CWzero_count\fR counters to zero when written.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M SetCycleCount n ,
++.M RoundTripCycleCount n ,
++.M SetPerfCount n ,
++.M PerfCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DRRSched.n click-1.6.0-27/inst/share/man/mann/DRRSched.n
+--- click-1.6.0/inst/share/man/mann/DRRSched.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DRRSched.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/drr.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DRRSCHED" n "11/Feb/2009" "Click"
++.SH "NAME"
++DRRSched \- Click element;
++pulls from inputs with deficit round robin scheduling
++.SH "SYNOPSIS"
++DRRSched
++
++\fBPorts\fR: one output, zero or more inputs
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Schedules packets with deficit round robin scheduling, from
++Shreedhar and Varghese's SIGCOMM 1995 paper "Efficient Fair
++Queuing using Deficit Round Robin."
++.PP
++The inputs usually come from Queues or other pull schedulers.
++\fBDRRSched\fR uses notification to avoid pulling from empty inputs.
++.PP
++
++.SH "NOTES"
++\fBDRRSched\fR is a notifier signal, active iff any of the upstream notifiers
++are active.
++.PP
++
++.SH "SEE ALSO"
++.M PrioSched n ,
++.M StrideSched n ,
++.M RoundRobinSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DecIPTTL.n click-1.6.0-27/inst/share/man/mann/DecIPTTL.n
+--- click-1.6.0/inst/share/man/mann/DecIPTTL.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DecIPTTL.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,47 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/decipttl.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DECIPTTL" n "11/Feb/2009" "Click"
++.SH "NAME"
++DecIPTTL \- Click element;
++decrements IP time-to-live, drops dead packets
++.SH "SYNOPSIS"
++DecIPTTL
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packet as input.
++If the ttl is <= 1 (i.e. has expired),
++\fBDecIPTTL\fR sends the packet to output 1 (or discards it if there is no
++output 1).
++Otherwise it decrements the ttl, re-calculates the checksum,
++and sends the packet to output 0.
++.PP
++Ordinarily output 1 is connected to an ICMP error packet generator.
++.PP
++
++.SH "EXAMPLES"
++This is a typical IP input processing sequence:
++.PP
++.nf
++\& ... -> CheckIPHeader -> dt::DecIPTTL -> ...
++\& dt[1] -> ICMPError(18.26.4.24, 11, 0) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ICMPError n ,
++.M CheckIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DelayShaper.n click-1.6.0-27/inst/share/man/mann/DelayShaper.n
+--- click-1.6.0/inst/share/man/mann/DelayShaper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DelayShaper.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,54 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/delayshaper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DELAYSHAPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++DelayShaper \- Click element;
++shapes traffic to meet delay requirements
++.SH "SYNOPSIS"
++\fBDelayShaper\fR(DELAY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets from the single input port. Delays them for at least DELAY
++seconds, with microsecond precision. A packet with timestamp T will be emitted
++no earlier than time (T + DELAY). On output, the packet's timestamp is set to
++the current time.
++.PP
++Differs from
++.M DelayUnqueue "n"
++in that both its input and output are pull. Packets
++being delayed are enqueued until the necessary time has passed. At most one
++packet is enqueued at a time.
++.M DelayUnqueue "n"
++returns null for every pull request
++until the enqueued packet is ready.
++.PP
++.M SetTimestamp "n"
++element can be used to stamp the packet.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdelay\fR (read/write)" 5
++Returns or sets the DELAY parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M BandwidthShaper n ,
++.M DelayUnqueue n ,
++.M SetTimestamp "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DelayUnqueue.n click-1.6.0-27/inst/share/man/mann/DelayUnqueue.n
+--- click-1.6.0/inst/share/man/mann/DelayUnqueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DelayUnqueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/delayunqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DELAYUNQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++DelayUnqueue \- Click element;
++delay inducing pull-to-push converter
++.SH "SYNOPSIS"
++\fBDelayUnqueue\fR(DELAY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets from the single input port. Delays them for at least DELAY
++seconds, with microsecond precision. A packet with timestamp T will be emitted
++no earlier than time (T + DELAY). On output, the packet's timestamp is set to
++the current time.
++.PP
++\fBDelayUnqueue\fR listens for upstream notification, such as that available from
++.M Queue "n" .
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M Unqueue n ,
++.M RatedUnqueue n ,
++.M BandwidthRatedUnqueue n ,
++.M LinkUnqueue n ,
++.M DelayShaper n ,
++.M SetTimestamp "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DirectIPLookup.n click-1.6.0-27/inst/share/man/mann/DirectIPLookup.n
+--- click-1.6.0/inst/share/man/mann/DirectIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DirectIPLookup.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,98 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/directiplookup.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DIRECTIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++DirectIPLookup \- Click element;
++IP routing lookup using direct-indexed tables
++.SH "SYNOPSIS"
++\fBDirectIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel, bsdmodule
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects a destination IP address annotation with each packet. Looks up that
++address in its routing table, using longest-prefix-match, sets the destination
++annotation to the corresponding GW (if specified), and emits the packet on the
++indicated OUTput port.
++.PP
++Each argument is a route, specifying a destination and mask, an optional
++gateway IP address, and an output port. No destination-mask pair should occur
++more than once.
++.PP
++\fBDirectIPLookup\fR is optimized for lookup speed at the expense of extensive RAM
++usage. Each longest-prefix lookup is accomplished in one to maximum two DRAM
++accesses, regardless on the number of routing table entries. Individual
++entries can be dynamically added to or removed from the routing table with
++relatively low CPU overhead, allowing for high update rates.
++.PP
++\fBDirectIPLookup\fR implements the \fIDIR-24-8-BASIC\fR lookup scheme described by
++Gupta, Lin, and McKeown in the paper cited below.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtable\fR (read-only)" 5
++Outputs a human-readable version of the current routing table.
++.IP "" 5
++.IP "\fBlookup\fR (read-only)" 5
++Reports the OUTput port and GW corresponding to an address.
++.IP "" 5
++.IP "\fBadd\fR (write-only)" 5
++Adds a route to the table. Format should be `\f(CWADDR/MASK [GW] OUT\fR'.
++Fails if a route for \f(CWADDR/MASK\fR already exists.
++.IP "" 5
++.IP "\fBset\fR (write-only)" 5
++Sets a route, whether or not a route for the same prefix already exists.
++.IP "" 5
++.IP "\fBremove\fR (write-only)" 5
++Removes a route from the table. Format should be `\f(CWADDR/MASK\fR'.
++.IP "" 5
++.IP "\fBctrl\fR (write-only)" 5
++Adds or removes a group of routes. Write `\f(CWadd\fR/\f(CWset ADDR/MASK [GW] OUT\fR' to
++add a route, and `\f(CWremove ADDR/MASK\fR' to remove a route. You can supply
++multiple commands, one per line; all commands are executed as one atomic
++operation.
++.IP "" 5
++.IP "\fBflush\fR (write-only)" 5
++Clears the entire routing table in a single atomic operation.
++.IP "" 5
++.PP
++
++.SH "NOTES"
++See
++.M IPRouteTable "n"
++for a performance comparison of the various IP routing
++elements.
++.PP
++\fBDirectIPLookup\fR's memory allocation does not work in the Linux kernel, because
++Linux uses a special function vmalloc() to allocate huge objects. A useful
++project would be to make \fBDirectIPLookup\fR suitable for the Linux kernel module,
++by changing its memory allocation to use vmalloc().
++.PP
++
++.SH "SEE ALSO"
++.M IPRouteTable n ,
++.M RangeIPLookup n ,
++.M RadixIPLookup n ,
++.M StaticIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup n ,
++.M LinuxIPLookup n
++.PP
++Pankaj Gupta, Steven Lin, and Nick McKeown. "Routing Lookups in Hardware at
++Memory Access Speeds". In Proc. IEEE Infocom 1998, Vol. 3, pp. 1240-1247.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Discard.n click-1.6.0-27/inst/share/man/mann/Discard.n
+--- click-1.6.0/inst/share/man/mann/Discard.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Discard.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,43 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/discard.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DISCARD" n "11/Feb/2009" "Click"
++.SH "NAME"
++Discard \- Click element;
++drops all packets
++.SH "SYNOPSIS"
++\fBDiscard\fR
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Discards all packets received on its single input. If used in a pull context,
++it initiates pulls whenever packets are available, and listens for activity
++notification, such as that available from
++.M Queue "n" .
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets discarded.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets "count" to 0.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DiscardNoFree.n click-1.6.0-27/inst/share/man/mann/DiscardNoFree.n
+--- click-1.6.0/inst/share/man/mann/DiscardNoFree.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DiscardNoFree.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,25 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/discardnofree.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DISCARDNOFREE" n "11/Feb/2009" "Click"
++.SH "NAME"
++DiscardNoFree \- Click element;
++drops all packets, but does not free any of them.
++.SH "SYNOPSIS"
++DiscardNoFree
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Discards all packets received on its single input, but does not free any of
++them. Only useful for benchmarking.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DriverManager.n click-1.6.0-27/inst/share/man/mann/DriverManager.n
+--- click-1.6.0/inst/share/man/mann/DriverManager.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DriverManager.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,55 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/drivermanager.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DRIVERMANAGER" n "11/Feb/2009" "Click"
++.SH "NAME"
++DriverManager \- Click element;
++a
++.M Script "n"
++that manages driver stop events
++.SH "SYNOPSIS"
++\fBDriverManager\fR(INSTRUCTIONS...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBDriverManager\fR is simply a
++.M Script "n"
++element whose default TYPE is "\f(CWDRIVER\fR".
++.PP
++Click \fIdriver stop events\fR suggest that the driver should stop processing.
++Any element can register a driver stop event; for instance, trace processing
++elements can stop the driver when they finish a trace file. You generally
++request this functionality by supplying a 'STOP true' keyword argument.
++.PP
++Driver stop events normally stop the driver: the user-level driver calls
++\f(CWexit(0)\fR, or the kernel driver kills the relevant kernel threads. The
++\fBDriverManager\fR element changes this behavior. When a driver stop event occurs,
++the router steps through the \fBDriverManager\fR's script by calling its \f(CWstep\fR
++handler. The driver exits only when the script ends or a \f(CWstop\fR instruction
++is executed.
++.PP
++For example, the following \fBDriverManager\fR element ensures that an element,
++\f(CWk\fR, has time to clean itself up before the driver is stopped. It waits for
++the first driver stop event, then calls \f(CWk\fR's \f(CWcleanup\fR handler, waits for a
++tenth of a second, and stops the driver.
++.PP
++.nf
++\& DriverManager(pause, write k.cleanup, wait 0.1s, stop);
++.fi
++.PP
++Use this idiom when one of your elements must emit a last packet or two before
++the router configuration is destroyed.
++.PP
++
++
++.SH "SEE ALSO"
++.M Script "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DropBroadcasts.n click-1.6.0-27/inst/share/man/mann/DropBroadcasts.n
+--- click-1.6.0/inst/share/man/mann/DropBroadcasts.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DropBroadcasts.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,32 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/dropbroadcasts.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DROPBROADCASTS" n "11/Feb/2009" "Click"
++.SH "NAME"
++DropBroadcasts \- Click element;
++drops link-level broadcast and multicast packets
++.SH "SYNOPSIS"
++DropBroadcasts
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Drop packets that arrived as link-level broadcast or multicast.
++Used to implement the requirement that IP routers not forward
++link-level broadcasts.
++Looks at the packet_type_anno annotation, which
++.M FromDevice "n"
++sets.
++
++.SH "SEE ALSO"
++.M FromDevice "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/DynamicUDPIPEncap.n click-1.6.0-27/inst/share/man/mann/DynamicUDPIPEncap.n
+--- click-1.6.0/inst/share/man/mann/DynamicUDPIPEncap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/DynamicUDPIPEncap.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,56 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/dynudpipencap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "DYNAMICUDPIPENCAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++DynamicUDPIPEncap \- Click element;
++encapsulates packets in dynamic UDP/IP headers
++.SH "SYNOPSIS"
++\fBDynamicUDPIPEncap\fR(SRC, SPORT, DST, DPORT [, CHECKSUM, INTERVAL])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Encapsulates each incoming packet in a UDP/IP packet
++with source address SRC, source port SPORT,
++destination address DADDR, and destination port
++DPORT. The UDP checksum is calculated if CHECKSUM? is
++true; it is true by default. SPORT and DPORT are
++incremented by 1 every INTERVAL number of packets. By
++default, INTERVAL is 0, which means do not increment.
++This is the same element as
++.M UDPIPEncap "n" ,
++except for
++the INTERVAL functionality.
++.PP
++The \fBDynamicUDPIPEncap\fR element adds both a UDP header
++and an IP header.
++.PP
++The
++.M Strip "n"
++element can be used by the receiver to get
++rid of the encapsulation header.
++
++.SH "EXAMPLES"
++
++.nf
++\& DynamicUDPIPEncap(1.0.0.1, 1234, 2.0.0.2, 1234, 1, 10)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Strip n ,
++.M IPEncap n ,
++.M UDPIPEncap "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/EnsureEther.n click-1.6.0-27/inst/share/man/mann/EnsureEther.n
+--- click-1.6.0/inst/share/man/mann/EnsureEther.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/EnsureEther.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,49 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/ensureether.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ENSUREETHER" n "11/Feb/2009" "Click"
++.SH "NAME"
++EnsureEther \- Click element;
++ensures that IP packets are Ethernet encapsulated
++.SH "SYNOPSIS"
++\fBEnsureEther\fR([ETHERTYPE, SRC, DST])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Ensures that IP packets are encapsulated in an Ethernet header. Non-IP
++packets, and IP packets that look Ethernet-encapsulated, are emitted on the
++first output unchanged. Other IP packets are encapsulated in an Ethernet
++header before being emitted. If the IP packet looks like it had an Ethernet
++header that was stripped off, then that header is used. Otherwise, the header
++specified by the arguments is prepended to the packet.
++.PP
++
++.SH "EXAMPLES"
++Encapsulate packets in an Ethernet header with type
++ETHERTYPE_IP (0x0800), source address 1:1:1:1:1:1, and
++destination address 2:2:2:2:2:2:
++.PP
++.nf
++\& EtherEncap(0x0800, 1:1:1:1:1:1, 2:2:2:2:2:2)
++.fi
++.PP
++
++
++
++.SH "NOTES"
++For IP packets you probably want to use ARPQuerier instead.
++.PP
++
++.SH "SEE ALSO"
++.M EtherEncap "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Error.n click-1.6.0-27/inst/share/man/mann/Error.n
+--- click-1.6.0/inst/share/man/mann/Error.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Error.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,30 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../include/click/standard/errorelement.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ERROR" n "11/Feb/2009" "Click"
++.SH "NAME"
++Error \- Click element;
++always fails
++.SH "SYNOPSIS"
++\fBError\fR(...)
++
++\fBPorts\fR: any number of inputs, any number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++The \fBError\fR element always fails to initialize. It has any number of inputs
++and outputs, and accepts any configuration string without complaint. It is
++useful to prevent a router from initializing while avoiding
++spurious error messages about bad configuration strings or connections.
++
++.SH "SEE ALSO"
++.M Message "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/EtherEncap.n click-1.6.0-27/inst/share/man/mann/EtherEncap.n
+--- click-1.6.0/inst/share/man/mann/EtherEncap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/EtherEncap.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,60 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/etherencap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ETHERENCAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++EtherEncap \- Click element;
++encapsulates packets in Ethernet header
++.SH "SYNOPSIS"
++\fBEtherEncap\fR(ETHERTYPE, SRC, DST)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Encapsulates each packet in the Ethernet header specified by its arguments.
++ETHERTYPE should be in host order.
++.PP
++
++.SH "EXAMPLES"
++Encapsulate packets in an Ethernet header with type
++ETHERTYPE_IP (0x0800), source address 1:1:1:1:1:1, and
++destination address 2:2:2:2:2:2:
++.PP
++.nf
++\& EtherEncap(0x0800, 1:1:1:1:1:1, 2:2:2:2:2:2)
++.fi
++.PP
++
++
++
++.SH "NOTES"
++For IP packets you probably want to use
++.M ARPQuerier "n"
++instead.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBsrc\fR (read/write)" 5
++Returns or sets the SRC parameter.
++.IP "" 5
++.IP "\fBdst\fR (read/write)" 5
++Returns or sets the DST parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ARPQuerier n ,
++.M EnsureEther "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/EtherMirror.n click-1.6.0-27/inst/share/man/mann/EtherMirror.n
+--- click-1.6.0/inst/share/man/mann/EtherMirror.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/EtherMirror.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,25 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/ethermirror.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ETHERMIRROR" n "11/Feb/2009" "Click"
++.SH "NAME"
++EtherMirror \- Click element;
++swaps Ethernet source and destination
++.SH "SYNOPSIS"
++\fBEtherMirror\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Incoming packets are Ethernet. Their source and destination Ethernet
++addresses are swapped before they are output.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FTPPortMapper.n click-1.6.0-27/inst/share/man/mann/FTPPortMapper.n
+--- click-1.6.0/inst/share/man/mann/FTPPortMapper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FTPPortMapper.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,111 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/app/ftpportmapper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FTPPORTMAPPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++FTPPortMapper \- Click element;
++manipulates
++.M IPRewriter "n"
++for FTP
++.SH "SYNOPSIS"
++\fBFTPPortMapper\fR(CONTROL_REWRITER, DATA_REWRITER, PATTERN FOUTPUT ROUTPUT)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: app (core)
++.br
++.SH "DESCRIPTION"
++Expects FTP control packets. Watches packets for PORT commands and installs
++corresponding mappings into the specified
++.M IPRewriter "n" .
++This makes FTP
++possible through a NAT-like
++.M IPRewriter "n"
++setup.
++.PP
++CONTROL_REWRITER and DATA_REWRITER are the names of
++.M IPRewriter "n" -like
++elements. CONTROL_REWRITER must be a
++.M TCPRewriter "n"
++element, through which the
++FTP control packets are passed. Packets from \fBFTPPortMapper\fR must pass
++downstream through CONTROL_REWRITER. DATA_REWRITER can be any
++.M IPRewriter "n" -like
++element; packets from the FTP data port must pass through
++DATA_REWRITER. CONTROL_REWRITER and DATA_REWRITER might be the same
++element.
++.PP
++PATTERN is a pattern specification -- either a pattern name (see
++.M IPRewriterPatterns "n" )
++or a `SADDR SPORT DADDR DPORT' quadruple. See
++.M IPRewriter "n"
++for more information. The address and port specified in the
++PORT command correspond to `SADDR' and `SPORT' in the pattern. If a new
++SADDR and SPORT are chosen, then the PORT command is rewritten to reflect
++the new SADDR and SPORT.
++.PP
++In summary: Assume that an FTP packet with source address and port
++1.0.0.2:6587 and destination address and port 2.0.0.2:21 contains a command
++`PORT 1,0,0,2,3,9' (that is, 1.0.0.2:777). Furthermore assume that the
++PATTERN is `1.0.0.1 9000-14000 - -'. Then \fBFTPPortMapper\fR performs the
++following actions:
++.PP
++
++
++.IP "*" 3
++Creates a new mapping using the PATTERN. Say it returns 9000 as the new
++source port.
++.IP "" 3
++.IP "*" 3
++Installs the following mappings into the rewriter:
++.IP "" 3
++.RS 3
++
++.IP "1." 3
++(1.0.0.2, 777, 2.0.0.2, 20) => (1.0.0.1, 9000, 2.0.0.2, 20) with output
++port FOUTPUT.
++.IP "" 3
++.IP "2." 3
++(2.0.0.2, 20, 1.0.0.1, 9000) => (2.0.0.2, 20, 1.0.0.2, 777) with output
++port ROUTPUT.
++.IP "" 3
++.RE
++.IP "" 3
++
++.IP "*" 3
++Rewrites the PORT command to `PORT 1,0,0,1,35,40' (that is,
++1.0.0.1:9000).
++.IP "" 3
++.IP "*" 3
++Updates the packet's IP and TCP checksums.
++.IP "" 3
++.IP "*" 3
++Updates the downstream CONTROL_REWRITER to reflect the change in
++sequence numbers introduced by the new PORT command. (The modified packet
++containing the new PORT command will likely have a different length than
++the original packet, so some sequence number patching is required.)
++.IP "" 3
++.IP "*" 3
++Does \fInot\fR change the control packet header's addresses or port numbers.
++.IP "" 3
++.PP
++For a PORT command to be recognized, it must be completely contained within
++one packet, and it must be the first command in the packet. This is usually
++the case. Also, the destination FTP data port is always assumed to be one
++less than the destination FTP control port, which is read as the packet's
++destination port number. This is also usually the case.
++.PP
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M TCPRewriter n ,
++.M IPRewriterPatterns n
++.PP
++RFC 959, File Transfer Protocol (FTP)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FastTCPFlows.n click-1.6.0-27/inst/share/man/mann/FastTCPFlows.n
+--- click-1.6.0/inst/share/man/mann/FastTCPFlows.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FastTCPFlows.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,86 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/fasttcpflows.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FASTTCPFLOWS" n "11/Feb/2009" "Click"
++.SH "NAME"
++FastTCPFlows \- Click element;
++creates packets flows with static TCP/IP/Ethernet headers
++.SH "SYNOPSIS"
++\fBFastTCPFlows\fR(RATE, LIMIT, LEN,
++.br
++.nf
++\& SETHADDR, SIPADDR,N<>
++\& DETHADDR, DIPADDR,N<>
++\& FLOWS, FLOWSIZE [, ACTIVE])
++.fi
++.PP
++
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++\fBFastTCPFlows\fR is a benchmark tool. At initialization time, \fBFastTCPFlows\fR
++creates FLOWS number of fake TCP/IP packets of length LEN (min 60), with
++source ethernet address SETHADDR, source IP address SIPADDR, destination
++ethernet address DETHADDR, and destination IP address DIPADDR. Source and
++destination ports are randomly generated. The TCP checksum is calculated.
++Each time the \fBFastTCPFlows\fR element is called, it selects a flow, increments
++the reference count on the skbuff created and returns the skbuff object w/o
++copying or cloning. Therefore, the packet returned by \fBFastTCPFlows\fR should
++not be modified.
++.PP
++\fBFastTCPFlows\fR sents packets at RATE packets per second. It will send LIMIT
++number of packets in total. Each flow is limited to FLOWSIZE number of
++packets. After FLOWSIZE number of packets are sent, the sort and dst port
++will be modified. FLOWSIZE must be greater than or equal to 3. For each
++flow, a SYN packet, a DATA packet, and a FIN packet are sent. These packets
++have the invalid sequence numbers, in order to avoid recomputing checksum.
++.PP
++After \fBFastTCPFlows\fR has sent LIMIT packets, it will calculate the average
++send rate (packets per second) between the first and last packets sent and
++make that available in the rate handler.
++.PP
++By default \fBFastTCPFlows\fR is ACTIVE.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the total number of packets that have been generated.
++.IP "" 5
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.IP "\fBreset\fR (write)" 5
++Reset and restart.
++.IP "" 5
++.IP "\fBactive\fR (write)" 5
++Change ACTIVE
++.IP "" 5
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FastTCPFlows(100000, 500000, 60,
++\& 0:0:0:0:0:0, 1.0.0.1, 1234,
++\& 1:1:1:1:1:1, 2.0.0.2, 1234,
++\& 100, 10)
++\& -> ToDevice;
++.fi
++.PP
++
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FastUDPFlows.n click-1.6.0-27/inst/share/man/mann/FastUDPFlows.n
+--- click-1.6.0/inst/share/man/mann/FastUDPFlows.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FastUDPFlows.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,84 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/fastudpflows.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FASTUDPFLOWS" n "11/Feb/2009" "Click"
++.SH "NAME"
++FastUDPFlows \- Click element;
++creates packets flows with static UDP/IP/Ethernet headers
++.SH "SYNOPSIS"
++\fBFastUDPFlows\fR(RATE, LIMIT, LEN,
++.br
++.nf
++\& SETHADDR, SIPADDR,N<>
++\& DETHADDR, DIPADDR,N<>
++\& FLOWS, FLOWSIZE [, CHECKSUM?, ACTIVE])
++.fi
++.PP
++
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++\fBFastUDPFlows\fR is a benchmark tool. At initialization time, \fBFastUDPFlows\fR
++creates FLOWS number of UDP/IP packets of length LEN (min 60), with source
++ethernet address SETHADDR, source IP address SIPADDR, destination ethernet
++address DETHADDR, and destination IP address DIPADDR. Source and
++destination ports are randomly generated. The UDP checksum is calculated if
++CHECKSUM? is true; it is true by default. Each time the \fBFastUDPFlows\fR
++element is called, it selects a flow, increments the reference count on the
++skbuff created and returns the skbuff object w/o copying or cloning.
++Therefore, the packet returned by \fBFastUDPFlows\fR should not be modified.
++.PP
++\fBFastUDPFlows\fR sents packets at RATE packets per second. It will send LIMIT
++number of packets in total. Each flow is limited to FLOWSIZE number of
++packets. After FLOWSIZE number of packets are sent, the sort and dst port
++will be modified.
++.PP
++After \fBFastUDPFlows\fR has sent LIMIT packets, it will calculate the average
++send rate (packets per second) between the first and last packets sent and
++make that available in the rate handler.
++.PP
++By default \fBFastUDPFlows\fR is ACTIVE.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the total number of packets that have been generated.
++.IP "" 5
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.IP "\fBreset\fR (write)" 5
++Reset and restart.
++.IP "" 5
++.IP "\fBactive\fR (write)" 5
++Change ACTIVE
++.IP "" 5
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FastUDPFlows(100000, 500000, 60,
++\& 0:0:0:0:0:0, 1.0.0.1, 1234,
++\& 1:1:1:1:1:1, 2.0.0.2, 1234,
++\& 100, 10)
++\& -> ToDevice;
++.fi
++.PP
++
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FastUDPSource.n click-1.6.0-27/inst/share/man/mann/FastUDPSource.n
+--- click-1.6.0/inst/share/man/mann/FastUDPSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FastUDPSource.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,81 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/fastudpsrc.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FASTUDPSOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++FastUDPSource \- Click element;
++creates packets with static UDP/IP/Ethernet headers
++.SH "SYNOPSIS"
++\fBFastUDPSource\fR(RATE, LIMIT, LEN, SETHADDR, SIPADDR, SPORT, DETHADDR, DIPADDR, DPORT [, CHECKSUM?, INTERVAL, ACTIVE])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++\fBFastUDPSource\fR is a benchmark tool. At initialization
++time, \fBFastUDPSource\fR creates a UDP/IP packet of length
++LEN (min 60), with source ethernet address SETHADDR,
++source IP address SIPADDR, source port SPORT,
++destination ethernet address DETHADDR, destination IP
++address DIPADDR, and destination port DPORT. The UDP
++checksum is calculated if CHECKSUM? is true; it is
++true by default. Each time the \fBFastUDPSource\fR element
++is called, it increments the reference count on the
++skbuff created and returns the skbuff object w/o
++copying or cloning. Therefore, the packet returned by
++\fBFastUDPSource\fR should not be modified.
++.PP
++\fBFastUDPSource\fR sents packets at RATE packets per
++second. It will send LIMIT number of packets in
++total.
++.PP
++After \fBFastUDPSource\fR has sent LIMIT packets, it will
++calculate the average send rate (packets per second)
++between the first and last packets sent and make that
++available in the rate handler.
++.PP
++By default \fBFastUDPSource\fR is ACTIVE.
++.PP
++PACKET is zero by default. If it is not 0, after
++PACKET number of packets, both sport and dport will
++be incremented by 1. Checksum will be recomputed.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the total number of packets that have been generated.
++.IP "" 5
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.IP "\fBreset\fR (write)" 5
++Reset and restart.
++.IP "" 5
++.IP "\fBactive\fR (write)" 5
++Change ACTIVE
++.IP "" 5
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FastUDPSource(100000, 500000, 60, 0:0:0:0:0:0, 1.0.0.1, 1234,
++\& 1:1:1:1:1:1, 2.0.0.2, 1234)
++\& -> ToDevice;
++.fi
++.PP
++
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FixIPSrc.n click-1.6.0-27/inst/share/man/mann/FixIPSrc.n
+--- click-1.6.0/inst/share/man/mann/FixIPSrc.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FixIPSrc.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/fixipsrc.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FIXIPSRC" n "11/Feb/2009" "Click"
++.SH "NAME"
++FixIPSrc \- Click element;
++sets IP source field if requested by annotation
++.SH "SYNOPSIS"
++\fBFixIPSrc\fR(IPADDR)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects an IP packet as input. If its Fix IP Source annotation is set, then
++changes its IP source address field to IPADDR and recomputes the checksum.
++Used by elements such as
++.M ICMPError "n"
++that are required by standards to use
++the IP address on the outgoing interface as the source. Such elements must
++set ip_src to something reasonable in case the outgoing interface has no IP
++address.
++.PP
++Also clears the Fix IP Source annotation.
++.PP
++
++.SH "NOTES"
++The Fix IP Source annotation is stored as user annotation 3.
++.PP
++
++.SH "SEE ALSO"
++.M ICMPError "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromDevice.n click-1.6.0-27/inst/share/man/mann/FromDevice.n
+--- click-1.6.0/inst/share/man/mann/FromDevice.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromDevice.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,89 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/fromdevice.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMDEVICE" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromDevice \- Click element;
++reads packets from network device (Linux kernel)
++.SH "SYNOPSIS"
++\fBFromDevice\fR(DEVNAME [, \fIkeywords\fR PROMISC, BURST, TIMESTAMP...])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++This manual page describes the Linux kernel module version of the \fBFromDevice\fR
++element. For the user-level element, read the
++.M FromDevice.u "n"
++manual page.
++.PP
++Intercepts all packets received by the Linux network interface named DEVNAME
++and pushes them out output 0. The packets include the link-level header.
++DEVNAME may also be an Ethernet address, in which case \fBFromDevice\fR searches for
++a device with that address.
++.PP
++\fBFromDevice\fR receives packets at interrupt time. As this happens, \fBFromDevice\fR
++simply stores the packets in an internal queue. Later, in the Click kernel
++thread -- that is, not at interrupt time -- \fBFromDevice\fR emits packets from that
++queue as it is scheduled by the driver. It emits at most BURST packets per
++scheduling; BURST is 8 by default.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "PROMISC" 8
++Boolean. If true, the device is put into promiscuous mode while \fBFromDevice\fR is
++active. Default is false.
++.IP "" 8
++.IP "BURST" 8
++Unsigned integer. Sets the BURST parameter.
++.IP "" 8
++.IP "TIMESTAMP" 8
++Boolean. If true, then ensure that received packets have correctly-set
++timestamp annotations. Default is true.
++.IP "" 8
++.IP "QUIET" 8
++Boolean. If true, then suppress device up/down messages. Default is false.
++.IP "" 8
++.IP "ALLOW_NONEXISTENT" 8
++Allow nonexistent devices. If true, and no device named DEVNAME exists when
++the router is initialized, then \fBFromDevice\fR will report a warning (rather than
++an error). Later, while the router is running, if a device named DEVNAME
++appears, \fBFromDevice\fR will seamlessly begin outputing its packets. Default is
++false.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Linux won't see any packets from the device. If you want Linux to process
++packets, you should hand them to
++.M ToHost "n" .
++.PP
++\fBFromDevice\fR accesses packets the same way Linux does: through interrupts.
++This is bad for performance. If you care about performance and have a
++polling-capable device, use
++.M PollDevice "n"
++instead.
++.PP
++Linux device drivers, and thus \fBFromDevice\fR, should set packets' timestamp,
++packet-type, and device annotations.
++.PP
++
++.SH "SEE ALSO"
++.M PollDevice n ,
++.M ToDevice n ,
++.M FromHost n ,
++.M ToHost n ,
++.M FromDevice.u "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromDevice.u.n click-1.6.0-27/inst/share/man/mann/FromDevice.u.n
+--- click-1.6.0/inst/share/man/mann/FromDevice.u.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromDevice.u.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,133 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/fromdevice.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMDEVICE.U" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromDevice.u \- Click element;
++reads packets from network device (user-level)
++.SH "SYNOPSIS"
++\fBFromDevice\fR(DEVNAME [, \fIkeywords\fR SNIFFER, PROMISC, SNAPLEN, FORCE_IP, CAPTURE, BPF_FILTER, OUTBOUND])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++This manual page describes the user-level version of the \fBFromDevice\fR
++element. For the Linux kernel module element, read the
++.M FromDevice n
++manual
++page.
++.PP
++Reads packets from the kernel that were received on the network controller
++named DEVNAME.
++.PP
++User-level \fBFromDevice\fR behaves like a packet sniffer by default. Packets
++emitted by \fBFromDevice\fR are also received and processed by the kernel. Thus, it
++doesn't usually make sense to run a router with user-level Click, since each
++packet will get processed twice (once by Click, once by the kernel). Install
++firewalling rules in your kernel if you want to prevent this, for instance
++using the
++.M KernelFilter "n"
++element or \fBFromDevice\fR's SNIFFER false argument.
++.PP
++Under Linux, a \fBFromDevice\fR element will not receive packets sent by a
++ToDevice element for the same device. Under other operating systems, your
++mileage may vary.
++.PP
++Sets the packet type annotation appropriately. Also sets the timestamp
++annotation to the time the kernel reports that the packet was received.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SNIFFER" 8
++Boolean. Specifies whether \fBFromDevice\fR should run in sniffer mode. In
++non-sniffer mode, \fBFromDevice\fR installs
++.M KernelFilter "n"
++filtering rules to block
++the kernel from handling any packets arriving on device DEVNAME. Default is
++true (sniffer mode).
++.IP "" 8
++.IP "PROMISC" 8
++Boolean. \fBFromDevice\fR puts the device in promiscuous mode if PROMISC is true.
++The default is false.
++.IP "" 8
++.IP "SNAPLEN" 8
++Unsigned. On some systems, packets larger than SNAPLEN will be truncated.
++Defaults to 2046.
++.IP "" 8
++.IP "FORCE_IP" 8
++Boolean. If true, then output only IP packets. (Any link-level header remains,
++but the IP header annotation has been set appropriately.) Default is false.
++.IP "" 8
++.IP "CAPTURE" 8
++Word. Defines the capture method \fBFromDevice\fR will use to read packets from the
++kernel. Linux targets generally support PCAP and LINUX; other targets support
++only PCAP. Defaults to LINUX on Linux targets (unless you give a BPF_FILTER),
++and PCAP elsewhere.
++.IP "" 8
++.IP "BPF_FILTER" 8
++String. A BPF filter expression used to select the interesting packets.
++Default is the empty string, which means all packets. If CAPTURE is not PCAP,
++then any filter expression is ignored with a warning.
++.IP "" 8
++.IP "OUTBOUND" 8
++Boolean. If true, then emit packets that the kernel sends to the given
++interface, as well as packets that the kernel receives from it. Default is
++false.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FromDevice(eth0) -> ...
++.fi
++.PP
++
++
++
++.SH "NOTES"
++\fBFromDevice\fR sets packets' extra length annotations as appropriate.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets read by the device.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets "count" to zero.
++.IP "" 5
++.IP "\fBkernel_drops\fR (read-only)" 5
++Returns the number of packets dropped by the kernel, probably due to memory
++constraints, before \fBFromDevice\fR could get them. This may be an integer; the
++notation \f(CW"<\fId\fR"\fR, meaning at most \f(CW\fId\fR\fR drops; or \f(CW"??"\fR, meaning the
++number of drops is not known.
++.IP "" 5
++.IP "\fBencap\fR (read-only)" 5
++Returns a string indicating the encapsulation type on this link. Can be
++`\f(CWIP\fR', `\f(CWETHER\fR', or `\f(CWFDDI\fR', for example.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ToDevice.u n ,
++.M FromDump n ,
++.M ToDump n ,
++.M KernelFilter n ,
++\fBFromDevice\fR(n)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromDump.n click-1.6.0-27/inst/share/man/mann/FromDump.n
+--- click-1.6.0/inst/share/man/mann/FromDump.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromDump.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,176 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/fromdump.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMDUMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromDump \- Click element;
++reads packets from a tcpdump file
++.SH "SYNOPSIS"
++\fBFromDump\fR(FILENAME [, \fIkeywords\fR TIMING, STOP, SAMPLE, FORCE_IP, START, START_AFTER, END, END_AFTER, INTERVAL, END_CALL, FILEPOS])
++
++\fBPorts\fR: no inputs, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBDrivers\fR: userlevel, ns
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads packets from a file produced by `tcpdump -w FILENAME' or
++.M ToDump "n" .
++Pushes
++them out the output, and optionally stops the driver when there are no more
++packets. If TIMING is true, then \fBFromDump\fR tries to maintain the timing of the
++original packet stream. TIMING is false by default.
++.PP
++\fBFromDump\fR also transparently reads gzip- and bzip2-compressed tcpdump files, if
++you have zcat(1) and bzcat(1) installed.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SAMPLE" 8
++Unsigned real number between 0 and 1. \fBFromDump\fR will output each packet with
++probability SAMPLE. Default is 1. \fBFromDump\fR uses fixed-point arithmetic, so the
++actual sampling probability may differ substantially from the requested
++sampling probability. Use the \f(CWsampling_prob\fR handler to find out the actual
++probability.
++.IP "" 8
++.IP "FORCE_IP" 8
++Boolean. If true, then \fBFromDump\fR will emit only IP packets with their IP header
++annotations correctly set. (If \fBFromDump\fR has two outputs, non-IP packets are
++pushed out on output 1; otherwise, they are dropped.) Default is false.
++.IP "" 8
++.IP "STOP" 8
++Boolean. If true, then \fBFromDump\fR will ask the router to stop when it is done
++reading its tcpdump file (or the END time is reached). Default is false.
++.IP "" 8
++.IP "START" 8
++Absolute time in seconds since the epoch. \fBFromDump\fR will output packets with
++timestamps after that time.
++.IP "" 8
++.IP "START_AFTER" 8
++Argument is relative time in seconds (or supply a suffix like `min', `h').
++\fBFromDump\fR will skip the first \fIT\fR seconds in the log.
++.IP "" 8
++.IP "END" 8
++Absolute time in seconds since the epoch. \fBFromDump\fR will stop when encountering
++a packet with timestamp at or after that time.
++.IP "" 8
++.IP "END_AFTER" 8
++Argument is relative time in seconds (or supply a suffix like `min', `h').
++\fBFromDump\fR will stop at the first packet whose timestamp is at least \fIT\fR
++seconds after the first timestamp in the log.
++.IP "" 8
++.IP "INTERVAL" 8
++Argument is relative time in seconds (or supply a suffix like `min', `h').
++\fBFromDump\fR will stop at the first packet whose timestamp is at least \fIT\fR
++seconds after the first packet output.
++.IP "" 8
++.IP "END_CALL" 8
++Specify a handler to call once the end time is reached, or the dump runs out
++of packets. This defaults to '\fIFromDump\fR.active false'. END_CALL and STOP
++are mutually exclusive.
++.IP "" 8
++.IP "TIMING" 8
++Boolean. Same as the TIMING argument.
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. If false, then \fBFromDump\fR will not emit packets (until the `\f(CWactive\fR'
++handler is written). Default is true.
++.IP "" 8
++.IP "MMAP" 8
++Boolean. If true, then \fBFromDump\fR will use
++.M mmap 2
++to access the tcpdump file.
++This can result in slightly better performance on some machines. \fBFromDump\fR's
++regular file discipline is pretty optimized, so the difference is often small
++in practice. Default is true on most operating systems, but false on Linux.
++.IP "" 8
++.IP "FILEPOS" 8
++File offset. If supplied, then \fBFromDump\fR will start emitting packets from
++this (uncompressed) file position. This is dangerous; there's no cheap way
++to check whether you got the offset wrong, and if you did get it wrong,
++\fBFromDump\fR will emit garbage.
++.IP "" 8
++.PP
++You can supply at most one of START and START_AFTER, and at most one of END,
++END_AFTER, and INTERVAL.
++.PP
++Only available in user-level processes.
++.PP
++.SH "NOTES"
++By default, `tcpdump -w FILENAME' dumps only the first 68 bytes of
++each packet. You probably want to run `tcpdump -w FILENAME -s 2000' or some
++such.
++.PP
++\fBFromDump\fR sets packets' extra length annotations to any additional length
++recorded in the dump.
++.PP
++\fBFromDump\fR is a notifier signal, active when the element is active and the dump
++contains more packets.
++.PP
++If \fBFromDump\fR uses mmap, then a corrupt file might cause Click to crash with a
++segmentation violation.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets output so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets "count" to 0.
++.IP "" 5
++.IP "\fBsampling_prob\fR (read-only)" 5
++Returns the sampling probability (see the SAMPLE keyword argument).
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Value is a Boolean.
++.IP "" 5
++.IP "\fBencap\fR (read-only)" 5
++Returns the file's encapsulation type.
++.IP "" 5
++.IP "\fBfilename\fR (read-only)" 5
++Returns the filename supplied to \fBFromDump\fR.
++.IP "" 5
++.IP "\fBfilesize\fR (read-only)" 5
++Returns the length of the \fBFromDump\fR file, in bytes, or "-" if that length
++cannot be determined (because the file was compressed, for example).
++.IP "" 5
++.IP "\fBfilepos\fR (read/write)" 5
++Returns or sets \fBFromDump\fR's position in the (uncompressed) file, in bytes.
++.IP "" 5
++.IP "\fBpacket_filepos\fR (read-only)" 5
++Returns the (uncompressed) file position of the last packet emitted, in bytes.
++This handler is useful for elements like
++.M AggregateIPFlows "n"
++that can record
++statistics about portions of a trace; with packet_filepos, they can note
++exactly where the relevant portion begins.
++.IP "" 5
++.IP "\fBextend_interval\fR (write-only)" 5
++Text is a time interval. If END_TIME or one of its cousins was specified, then
++writing to this handler extends END_TIME by that many seconds. Also, ACTIVE is
++set to true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ToDump n ,
++.M FromDevice.u n ,
++.M ToDevice.u n ,
++.M tcpdump 1 ,
++.M mmap 2 ,
++.M AggregateIPFlows n ,
++.M FromTcpdump "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromHost.n click-1.6.0-27/inst/share/man/mann/FromHost.n
+--- click-1.6.0/inst/share/man/mann/FromHost.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromHost.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,83 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/fromhost.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMHOST" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromHost \- Click element;
++reads packets from Linux
++.SH "SYNOPSIS"
++\fBFromHost\fR(DEVNAME, ADDR/MASK [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Captures packets orginating from the Linux kernel and pushes them on output
++0. Output packets have Ethernet headers; only the protocol field is
++interesting.
++.PP
++Installs a fake interface called DEVNAME, and changes the routing table so
++that every packet destined for ADDR/MASK is sent through that interface.
++The packet then leaves on output 0. The device's native address is ADDR.
++.PP
++After the fake device is created, the effect of bringing up the interface
++and changing the routing table is analogous to:
++.PP
++.nf
++\& % /sbin/ifconfig DEVNAME up
++\& % /sbin/route add -net ADDR netmask MASK DEVNAME
++.fi
++.PP
++This element is only available in the Linux kernel module.
++.PP
++Keyword arguments are:
++.PP
++
++
++
++.IP "ETHER" 8
++Ethernet address. Specifies the fake device's Ethernet address. Default is
++00:01:02:03:04:05.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Linux will send ARP queries to the fake device. You must respond to these
++queries in order to receive any IP packets, but you can obviously respond
++with any Ethernet address you'd like. Here is one common idiom:
++.PP
++.nf
++\& FromHost(fake0, 192.0.0.1/8)
++\& -> fromhost_cl :: Classifier(12/0806, 12/0800);
++\& fromhost_cl[0] -> ARPResponder(0.0.0.0/0 1:1:1:1:1:1) -> ToHost;
++\& fromhost_cl[1] -> ... // IP packets
++.fi
++.PP
++
++
++
++.SH "EXAMPLES"
++
++.nf
++\& FromHost(fake0, 192.0.0.1/8) -> ...;
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ToHost n ,
++.M FromDevice n ,
++.M PollDevice n ,
++.M ToDevice "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromHost.u.n click-1.6.0-27/inst/share/man/mann/FromHost.u.n
+--- click-1.6.0/inst/share/man/mann/FromHost.u.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromHost.u.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,95 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/fromhost.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMHOST.U" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromHost.u \- Click element;
++interface to /dev/net/tun or ethertap (user-level)
++.SH "SYNOPSIS"
++\fBFromHost\fR(DEVNAME [, DST, GATEWAY, HEADROOM] [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads packets from and writes packets through the universal TUN/TAP
++module in Linux (the /dev/net/tun device). This allows a
++user-level Click to hand packets to the virtual ethernet
++device. \fBFromHost\fR will also transfer packets from the virtual
++ethernet device.
++.PP
++To use this element your kernel config must support CONFIG_TUN and
++CONFIG_ETHERTAP. Either modules (tun.o) or compiled in should work.
++.PP
++\fBFromHost\fR allocates a /dev/net/tun device (this might fail) and runs
++.M ifconfig 8
++to set the interface's local (i.e., kernel) address and netmask
++to DST, which must be an IP prefix such as 18.26.4.9/24. If DST is not
++specified, then \fBFromHost\fR
++assumes the tunnel has already been configured to the correct address. If
++a nonzero GATEWAY IP address (which must be on the same network as the tun)
++is specified, then \fBFromHost\fR tries to set up a default route through that
++host. HEADROOM is the number of bytes left empty before the packet data
++(to leave room for additional encapsulation headers). Default HEADROOM is
++0.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "ETHER" 8
++Ethernet address. Specifies the fake device's Ethernet address. Default is
++not specified, in which case the fake device's address is whatever the
++kernel chooses.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Linux will send ARP queries to the fake device. You must respond to these
++queries in order to receive any IP packets, but you can obviously respond
++with any Ethernet address you'd like. Here is one common idiom:
++.PP
++.nf
++\& tap0 :: FromHost(fake, 192.0.0.1/8)
++\& -> fromhost_cl :: Classifier(12/0806, 12/0800);
++\& fromhost_cl[0] -> ARPResponder(0.0.0.0/0 1:1:1:1:1:1) -> tap0;
++\& fromhost_cl[1] -> ... // IP packets
++.fi
++.PP
++
++
++
++.SH "EXAMPLES"
++
++.nf
++\& FromHost(fake, 192.0.0.1/8) -> ...;
++.fi
++.PP
++An error like "open /dev/net/tun: No such file or directory" usually means
++that you have not enabled tunnel support in your kernel.
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdev_name\fR (read-only)" 5
++Returns the name of the device that this element is using.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ToHost.u n ,
++.M ifconfig 8
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromRawSocket.n click-1.6.0-27/inst/share/man/mann/FromRawSocket.n
+--- click-1.6.0/inst/share/man/mann/FromRawSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromRawSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,60 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/fromrawsocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMRAWSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromRawSocket \- Click element;
++reads raw IP packets from safe raw socket (user-level)
++.SH "SYNOPSIS"
++\fBFromRawSocket\fR("TCP", <TCP source port number> [, \fIKEYWORDS\fR])
++.br
++\fBFromRawSocket\fR("UDP", <UDP source port number> [, \fIKEYWORDS\fR])
++.br
++\fBFromRawSocket\fR("GRE", <GRE key or PPTP call ID> [, \fIKEYWORDS\fR])
++.br
++\fBFromRawSocket\fR("ICMP", <ICMP identifier> [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads data from a raw IPv4 socket. The raw IPv4 socket may optionally
++be bound to a source port number in the case of TCP/UDP, a GRE key or
++PPTP call ID in the case of GRE, or an identifier in the case of
++ICMP. Binding a port to a raw IPv4 socket to reserve it and suppress
++TCP RST and ICMP Unreachable errors, is specific to PlanetLab Linux.
++.PP
++This element exists only for backward compatibility. See the more
++general
++.M RawSocket "n"
++implementation for details, and for supported
++keyword arguments. A \fBFromRawSocket\fR is equivalent to a
++.M RawSocket "n"
++with
++no inputs.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FromRawSocket(UDP, 53) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ToRawSocket n ,
++.M RawSocket n ,
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FromSocket.n click-1.6.0-27/inst/share/man/mann/FromSocket.n
+--- click-1.6.0/inst/share/man/mann/FromSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FromSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,58 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/fromsocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FROMSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++FromSocket \- Click element;
++reads data from socket (user-level)
++.SH "SYNOPSIS"
++\fBFromSocket\fR("TCP", IP, PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBFromSocket\fR("UDP", IP, PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBFromSocket\fR("UNIX", FILENAME [, \fIKEYWORDS\fR])
++.br
++\fBFromSocket\fR("UNIX_DGRAM", FILENAME [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads data from the specified socket. Packets received from the remote
++host or process are emitted on the output.
++.PP
++This element exists only for backward compatibility. See the more
++general
++.M Socket "n"
++implementation for details, and for supported keyword
++arguments. A \fBFromSocket\fR is equivalent to a
++.M Socket "n"
++with the CLIENT
++keyword set to FALSE or a
++.M Socket "n"
++with no inputs.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& FromSocket(TCP, 0.0.0.0, 80) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ToSocket n ,
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/FrontDropQueue.n click-1.6.0-27/inst/share/man/mann/FrontDropQueue.n
+--- click-1.6.0/inst/share/man/mann/FrontDropQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/FrontDropQueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,62 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/frontdropqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "FRONTDROPQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++FrontDropQueue \- Click element;
++stores packets in drop-from-front FIFO queue
++.SH "SYNOPSIS"
++FrontDropQueue
++.br
++\fBFrontDropQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a first-in-first-out queue. Drops the head packet
++before inserting the incoming packet if the queue already holds CAPACITY
++packets. The default for CAPACITY is 1000.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBhighwater_length\fR (read-only)" 5
++Returns the maximum number of packets that have ever been in the queue at once.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped by the
++.M Queue "n"
++so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++When written, resets the \f(CWdrops\fR and \f(CWhighwater_length\fR counters.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in the
++.M Queue "n" .
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M SimpleQueue n ,
++.M MixedQueue n ,
++.M RED "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/GetIPAddress.n click-1.6.0-27/inst/share/man/mann/GetIPAddress.n
+--- click-1.6.0/inst/share/man/mann/GetIPAddress.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/GetIPAddress.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/getipaddress.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "GETIPADDRESS" n "11/Feb/2009" "Click"
++.SH "NAME"
++GetIPAddress \- Click element;
++sets destination IP address annotation from packet data
++.SH "SYNOPSIS"
++\fBGetIPAddress\fR(OFFSET)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Copies 4 bytes from the packet, starting at OFFSET, to the destination IP
++address annotation. OFFSET is usually 16, to fetch the destination address
++from an IP packet.
++.PP
++
++.SH "NOTES"
++The destination address annotation is used by elements
++that need to know where the packet is going.
++Such elements include
++.M ARPQuerier "n"
++and LookupIPRoute.
++.PP
++
++.SH "SEE ALSO"
++.M ARPQuerier n ,
++.M StaticIPLookup n ,
++.M SetIPAddress n ,
++.M StoreIPAddress "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/HashSwitch.n click-1.6.0-27/inst/share/man/mann/HashSwitch.n
+--- click-1.6.0/inst/share/man/mann/HashSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/HashSwitch.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,44 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/hashswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "HASHSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++HashSwitch \- Click element;
++classifies packets by hash of contents
++.SH "SYNOPSIS"
++\fBHashSwitch\fR(OFFSET, LENGTH)
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Can have any number of outputs.
++Chooses the output on which to emit each packet based on
++a hash of the LENGTH bytes starting at OFFSET.
++Could be used for stochastic fair queuing.
++
++.SH "EXAMPLES"
++This element expects IP packets and chooses the output
++based on a hash of the IP destination address:
++.PP
++.nf
++\& HashSwitch(16, 4)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Switch n ,
++.M RoundRobinSwitch n ,
++.M StrideSwitch n ,
++.M RandomSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/HostEtherFilter.n click-1.6.0-27/inst/share/man/mann/HostEtherFilter.n
+--- click-1.6.0/inst/share/man/mann/HostEtherFilter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/HostEtherFilter.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,49 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ethernet/hostetherfilter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "HOSTETHERFILTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++HostEtherFilter \- Click element;
++drops Ethernet packets sent to other machines
++.SH "SYNOPSIS"
++\fBHostEtherFilter\fR(ETHER [, DROP_OWN, DROP_OTHER, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ethernet (core)
++.br
++.SH "DESCRIPTION"
++Expects Ethernet packets as input. Acts basically like Ethernet input hardware
++for a device with address ETHER.
++.PP
++In particular, \fBHostEtherFilter\fR sets each packet's packet type annotation to
++HOST, BROADCAST, MULTICAST, or OTHERHOST based on its Ethernet destination
++address. Emits most packets on the first output. If DROP_OWN is true, drops
++packets whose source address is ETHER; defaults to false. If DROP_OTHER is
++true, drops packets sent to hosts other than ETHER (that is, packets with
++unicast destination addresses not equal to ETHER); defaults to true. If the
++element has two outputs, filtered packets are emitted on the second output
++rather than dropped.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DROP_OWN" 8
++Same as the DROP_OWN parameter.
++.IP "" 8
++.IP "DROP_OTHER" 8
++Same as the DROP_OTHER parameter.
++.IP "" 8
++.IP "OFFSET" 8
++The ethernet header starts OFFSET bytes into the packet. Default OFFSET is 0.
++.IP "" 8
++.PP
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPError.n click-1.6.0-27/inst/share/man/mann/ICMPError.n
+--- click-1.6.0/inst/share/man/mann/ICMPError.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPError.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,102 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmperror.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPERROR" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPError \- Click element;
++generates ICMP error packets
++.SH "SYNOPSIS"
++\fBICMPError\fR(SRC, TYPE [, CODE, \fIkeywords\fR BADADDRS, MTU])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Generate an ICMP error packet, with specified TYPE and CODE,
++in response to an incoming IP packet. The output is an IP/ICMP packet.
++The ICMP packet's IP source address is set to SRC.
++The error packet will include (as payload)
++the original packet's IP header and an initial segment of its
++IP payload. \fBICMPError\fR sets the packet destination IP and
++fix_ip_src annotations.
++.PP
++TYPE and CODE may be integers between 0 and 255 or mnemonic names; CODE
++defaults to 0. Valid named TYPEs are `unreachable' [3], `sourcequench' [4],
++`redirect' [5], `timeexceeded' [11], and `parameterproblem' [12]. Valid
++named CODEs are `net' [0], `host' [1], `protocol' [2], `port' [3], and
++`needfrag' [4] for `unreachable'; `net' [0] and `host' [1] for `redirect';
++`transit' [0] and `reassembly' [1] for `timeexceeded'; and `erroratptr'
++[0], `missingopt' [1], and `length' [2] for `parameterproblem'.
++.PP
++The intent is that elements that give rise to errors, like
++.M DecIPTTL "n" ,
++should have two outputs, one of which is connected to an \fBICMPError\fR.
++Perhaps the \fBICMPError\fR should be followed by a rate limiting
++element.
++.PP
++\fBICMPError\fR never generates a packet in response to an ICMP error packet, a
++fragment, or a link broadcast. The BADADDRS keyword argument supplies an
++optional list of bad IP addresses; if it is present, then \fBICMPError\fR doesn't
++generate packets in response to packets with one of those addresses as
++either source or destination.
++.PP
++The output of \fBICMPError\fR should be connected to the routing lookup
++machinery, much as if the ICMP errors came from a hardware interface.
++.PP
++If TYPE is 12 (`parameterproblem') and CODE is 0 (`erroratptr'), \fBICMPError\fR
++takes the error pointer from the packet's ICMP parameter problem
++annotation. The
++.M IPGWOptions "n"
++element sets the annotation.
++.PP
++If TYPE is 5 (`redirect'), produces an ICMP redirect message. The gateway
++address is taken from the destination annotation. Usually a Paint-PaintTee
++element pair hands the packet to a redirect \fBICMPError\fR. RFC1812 says only
++code 1 (`host') should be used.
++.PP
++If TYPE is 3 ('unreachable') and CODE is 4 ('needfrag'), produces
++an ICMP unreachable message containing the MTU of the next-hop
++interface, specified by the PMTU keyword. This error should be
++returned to the sender of an IP packet with the DF bit set, that is
++longer than the next-hop MTU, to support Path MTU Discovery.
++.PP
++If the input packet has a source route option, the output packet will also
++have a source route option, containing the routers from the input source
++route, reversed.
++.PP
++Will not generate a packet larger than MTU, which defaults to 576.
++.PP
++
++.SH "EXAMPLES"
++This configuration fragment produces ICMP Time Exceeded error
++messages in response to TTL expirations, but limits the
++rate at which such messages can be sent to 10 per second:
++.PP
++.nf
++\& dt : DecIPTTL;
++\& dt[1] -> ICMPError(18.26.4.24, timeexceeded) -> m :: RatedSplitter(10) -> ...
++\& m[1] -> Discard;
++.fi
++.PP
++
++
++
++.SH "NOTES"
++\fBICMPError\fR can't decide if the packet's source or destination address is an
++IP directed broadcast address; it is supposed to ignore packets with such
++addresses.
++.PP
++
++.SH "SEE ALSO"
++.M DecIPTTL n ,
++.M FixIPSrc n ,
++.M IPGWOptions "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPPingEncap.n click-1.6.0-27/inst/share/man/mann/ICMPPingEncap.n
+--- click-1.6.0/inst/share/man/mann/ICMPPingEncap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPPingEncap.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,54 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmppingencap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPPINGENCAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPPingEncap \- Click element;
++encapsulates packets in ICMP ping headers
++.SH "SYNOPSIS"
++\fBICMPPingEncap\fR(SRC, DST [, \fIkeyword\fR IDENTIFIER])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Encapsulates input packets in an ICMP ping header with source IP address SRC
++and destination IP address DST. Advances the "sequence" field by one for
++each packet. (The sequence field is stored in network byte order in the
++packet.)
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "IDENTIFIER" 8
++Integer. Determines the ICMP identifier field in emitted pings. Default is
++0.
++.IP "" 8
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBsrc\fR (read/write)" 5
++Returns or sets the SRC argument.
++.IP "" 5
++.IP "\fBdst\fR (read/write)" 5
++Returns or sets the DST argument.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ICMPPingSource n ,
++.M ICMPPingResponder n ,
++.M ICMPPingRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPPingResponder.n click-1.6.0-27/inst/share/man/mann/ICMPPingResponder.n
+--- click-1.6.0/inst/share/man/mann/ICMPPingResponder.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPPingResponder.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,39 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmppingresponder.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPPINGRESPONDER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPPingResponder \- Click element;
++responds to ICMP echo requests
++.SH "SYNOPSIS"
++\fBICMPPingResponder\fR()
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Respond to ICMP echo requests. Incoming packets must have their IP header
++annotations set. The corresponding reply is generated for any ICMP echo
++request and emitted on output 0. The reply's destination IP address annotation
++is set appropriately, its paint annotation is cleared, and its timestamp is
++set to the current time. Other annotations are copied from the input packet.
++IP packets other than ICMP echo requests are emitted on the second output, if
++there are two outputs; otherwise, they are dropped.
++.PP
++
++.SH "BUGS"
++\fBICMPPingResponder\fR does not pay attention to source route options; it should.
++.PP
++
++.SH "SEE ALSO"
++.M ICMPSendPings n ,
++.M ICMPError "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPPingRewriter.n click-1.6.0-27/inst/share/man/mann/ICMPPingRewriter.n
+--- click-1.6.0/inst/share/man/mann/ICMPPingRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPPingRewriter.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,66 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmppingrewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPPINGREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPPingRewriter \- Click element;
++rewrites ICMP echo requests and replies
++.SH "SYNOPSIS"
++\fBICMPPingRewriter\fR(SRC, DST, \fIkeywords\fR DST_ANNO)
++
++\fBPorts\fR: 1-2 inputs, 1-2 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Rewrites ICMP echo requests and replies by changing their source and/or
++destination addresses. This lets pings pass through a NAT gateway.
++.PP
++Expects ICMP echo requests and echo replies. Each ICMP echo request is
++rewritten to have source IP address SRC and destination IP address DST.
++However, if either address is a single dash `\f(CW-\fR', the corresponding field in
++the IP header won't be changed. The ICMP `identifier' field is also rewritten
++to a unique number. Replies to the rewritten request are themselves rewritten;
++the rewritten replies look like they were responding to the original request.
++\fBICMPPingRewriter\fR optionally changes destination IP address annotations; see
++the DST_ANNO keyword argument below.
++.PP
++\fBICMPPingRewriter\fR actually keeps a table of mappings. Each mapping changes
++a given (source address, destination address, identifier) triple into another
++triple. Say that \fBICMPPingRewriter\fR receives a request packet with triple
++(\fIsrc\fR, \fIdst\fR, \fIident\fR), and chooses for it a new triple, (\fIsrc2\fR,
++\fIdst2\fR, \fIident2\fR). The rewriter will then store two mappings in the table.
++The first mapping changes requests (\fIsrc\fR, \fIdst\fR, \fIident\fR) into requests
++(\fIsrc2\fR, \fIdst2\fR, \fIident2\fR). The second mapping changes \fIreplies\fR (\fIdst2\fR, \fIsrc2\fR, \fIident2\fR) into replies (\fIdst\fR, \fIsrc\fR, \fIident\fR). Mappings are removed if they go unused for 5 minutes.
++.PP
++\fBICMPPingRewriter\fR may have one or two outputs. If it has two outputs,
++then requests are emitted on output 0, replies on output 1. Otherwise,
++all packets are emitted on output 0.
++.PP
++It may also have one or two inputs. They differ in how unexpected packets
++are handled. On the first input, echo requests with no corresponding
++mapping cause new mappings to be created, while echo replies with no
++corresponding mapping are passed along unchanged. On the second input,
++echo requests or replies with no corresponding mapping are simply dropped.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DST_ANNO" 8
++Boolean. If true, then set the destination IP address annotation on passing
++packets to the rewritten destination address. Default is true.
++.IP "" 8
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M ICMPPingResponder "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPPingSource.n click-1.6.0-27/inst/share/man/mann/ICMPPingSource.n
+--- click-1.6.0/inst/share/man/mann/ICMPPingSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPPingSource.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,106 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmpsendpings.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPPINGSOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPPingSource \- Click element;
++periodically sends ICMP echo requests
++.SH "SYNOPSIS"
++\fBICMPPingSource\fR(SADDR, DADDR [, \fIkeywords\fR INTERVAL, IDENTIFIER, LIMIT, DATA, ACTIVE])
++
++\fBPorts\fR: at most 1 input, 1 output
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Periodically emits ping packets with source IP address SRC and destination
++address DST. Advances the "sequence" field by one each time. (The sequence
++field is stored in network byte order in the packet.) When its output is
++pull, generates a ping packet on every pull.
++.PP
++\fBICMPPingSource\fR's optional input accepts replies to the pings it sends. If you
++send replies to this input, \fBICMPPingSource\fR will print reply reports and keep
++loss and RTT statistics like the ping(1) program. You can access those
++stistics with the "\f(CWsummary\fR" handler.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "INTERVAL" 8
++Amount of time between pings, in seconds. Default is 1.
++.IP "" 8
++.IP "IDENTIFIER" 8
++Integer. Determines the ICMP identifier field in emitted pings. Default is
++0.
++.IP "" 8
++.IP "LIMIT" 8
++Integer. The number of pings to send; but if LIMIT is negative, sends pings
++forever. Default is -1.
++.IP "" 8
++.IP "DATA" 8
++String. Extra data in emitted pings. Default is the empty string (nothing).
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. Whether \fBICMPPingSource\fR is active. Default is true.
++.IP "" 8
++.IP "VERBOSE" 8
++Boolean. Whether \fBICMPPingSource\fR should print reports when echo replies
++arrive. Default is true.
++.IP "" 8
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBactive\fR (read/write)" 5
++Returns or sets the ACTIVE argument.
++.IP "" 5
++.IP "\fBcount\fR (read-only)" 5
++Reports the number of packets sent so far.
++.IP "" 5
++.IP "\fBlimit\fR (write-only)" 5
++Sets the LIMIT argument.
++.IP "" 5
++.IP "\fBinterval\fR (write-only)" 5
++Sets the INTERVAL argument.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets all counters to zero.
++.IP "" 5
++.IP "\fBsrc\fR (read/write)" 5
++Returns or sets the SRC argument.
++.IP "" 5
++.IP "\fBdst\fR (read/write)" 5
++Returns or sets the DST argument.
++.IP "" 5
++.IP "\fBsummary\fR (read-only)" 5
++Returns ping(1)-style summary information: number of packets sent and
++received, loss rate, and RTT statistics. Only available if \fBICMPPingSource\fR had
++an input.
++.IP "" 5
++.IP "\fBrtt_min\fR (read-only)" 5
++Returns the minimum RTT observed, or 0 if no RTTs have been observed. Only
++available if \fBICMPPingSource\fR had an input.
++.IP "" 5
++.IP "\fBrtt_max\fR (read-only)" 5
++Returns the maximum RTT observed, or 0 if no RTTs have been observed. Only
++available if \fBICMPPingSource\fR had an input.
++.IP "" 5
++.IP "\fBrtt_avg\fR (read-only)" 5
++Returns the average RTT observed, or 0 if no RTTs have been observed. Only
++available if \fBICMPPingSource\fR had an input.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ICMPPingEncap n ,
++.M ICMPPingResponder n ,
++.M ICMPPingRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ICMPRewriter.n click-1.6.0-27/inst/share/man/mann/ICMPRewriter.n
+--- click-1.6.0/inst/share/man/mann/ICMPRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ICMPRewriter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,73 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/icmp/icmprewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ICMPREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++ICMPRewriter \- Click element;
++rewrites ICMP packets based on IP rewriter mappings
++.SH "SYNOPSIS"
++\fBICMPRewriter\fR(MAPS, \fIkeywords\fR DST_ANNO)
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: icmp (core)
++.br
++.SH "DESCRIPTION"
++Rewrites ICMP error packets by changing their source and/or destination
++addresses and some of their payloads. It checks MAPS, a space-separated list
++of
++.M IPRewriter "n" -like
++elements, to see how to rewrite. This lets source quenches,
++redirects, TTL-expired messages, and so forth pass through a NAT gateway.
++.PP
++ICMP error packets are sent in response to normal IP packets, and include a
++small portion of the relevant IP packet data. If the IP packet had been sent
++through
++.M IPRewriter "n" ,
++.M ICMPPingRewriter "n" ,
++or a similar element, then the ICMP
++packet will be in response to the rewritten address. \fBICMPRewriter\fR takes such
++ICMP error packets and checks a list of IPRewriters for a relevant mapping. If
++a mapping is found, \fBICMPRewriter\fR will rewrite the ICMP packet so it appears
++like a response to the original packet and emit the result on output 0.
++.PP
++\fBICMPRewriter\fR may have one or two outputs. If it has one, then any
++non-rewritten ICMP error packets, and any ICMP packets that are not errors,
++are dropped. If it has two, then these kinds of packets are emitted on output
++1.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DST_ANNO" 8
++Boolean. If true, then set the destination IP address annotation on passing
++packets to the rewritten destination address. Default is true.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++\fBICMPRewriter\fR supports the following ICMP types: destination unreachable, time
++exceeded, parameter problem, source quench, and redirect.
++.PP
++MAPS elements may have element class
++.M IPAddrRewriter "n" ,
++.M IPRewriter "n" ,
++.M TCPRewriter "n" ,
++.M ICMPPingRewriter "n" ,
++or other related classes.
++.PP
++
++.SH "SEE ALSO"
++.M IPAddrRewriter n ,
++.M IPRewriter n ,
++.M ICMPPingRewriter n ,
++.M TCPRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPAddrPairRewriter.n click-1.6.0-27/inst/share/man/mann/IPAddrPairRewriter.n
+--- click-1.6.0/inst/share/man/mann/IPAddrPairRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPAddrPairRewriter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,121 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipaddrpairrewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPADDRPAIRREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPAddrPairRewriter \- Click element;
++rewrites IP packets' addresses by address pair
++.SH "SYNOPSIS"
++\fBIPAddrPairRewriter\fR(INPUTSPEC1, ..., INPUTSPECn)
++
++\fBPorts\fR: 1 or more inputs, 1-256 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Rewrites the source and/or destination addresses on IP packets, along with
++their checksums. \fBIPAddrPairRewriter\fR implements per-address-pair network
++address translation, a midpoint between Basic NAT (see
++.M IPAddrRewriter "n" )
++and
++NAPT (see
++.M IPRewriter "n"
++and
++.M TCPRewriter "n" ).
++.PP
++\fBIPAddrPairRewriter\fR maintains a \fImapping table\fR that records how addresses are
++rewritten. On receiving a packet, \fBIPAddrPairRewriter\fR first looks up that
++packet in the mapping table by source/destination address pair. If the table
++contains a mapping, then the packet is rewritten according to the mapping and
++emitted on the specified output port. If there was no mapping, the packet is
++handled by the INPUTSPEC corresponding to the input port on which the packet
++arrived. (There are as many input ports as INPUTSPECs.) Most INPUTSPECs
++install new mappings, so that future packets from the same address are handled
++by the mapping table rather than some INPUTSPEC. The six forms of INPUTSPEC
++handle input packets as follows:
++.PP
++
++
++.IP "\&'drop', 'pass OUTPUT', 'keep FOUTPUT ROUTPUT', 'ELEMENTNAME'" 5
++These INPUTSPECs behave like those in
++.M IPRewriter "n" .
++.IP "" 5
++.IP "\&'pattern SADDR[-SADDR2] DADDR FOUTPUT ROUTPUT'" 5
++Creates a mapping according to the given pattern, 'SADDR DADDR'. Either
++pattern field may be a dash '-', in which case the corresponding field is left
++unchanged. For instance, the pattern '1.0.0.1 -' will rewrite input packets'
++source address, but leave its destination address unchanged. SADDR may be a
++range 'L-H' or prefix 'ADDR/PFX';
++.M IPRewriter "n"
++will choose an unallocated
++address in that range, or drop the packet if no address is available.
++Normally addresses are chosen randomly within the range. To allocate
++addresses sequentially (which can make testing easier), append a pound sign to
++the range, as in '1.0.0.1-1.255.255.254#'.
++.IP "" 5
++Say a packet with address pair (SA, DA) is received, and the corresponding new
++addresses are (SA', DA'). Then two mappings are installed:
++.IP "" 5
++.nf
++\& (SA, DA) => (SA', DA') [FOUTPUT]
++\& (DA', SA') => (DA, SA) [ROUTPUT]
++.fi
++.IP "" 5
++Thus, the input packet is rewritten and sent to FOUTPUT, and packets from the
++reply flow are rewritten to look like part of the original flow and sent to
++ROUTPUT.
++.IP "" 5
++
++.IP "\&'pattern PATNAME FOUTPUT ROUTPUT'" 5
++Behaves like the version in
++.M IPRewriter "n" ,
++except that PATNAME must name an
++.M IPAddrRewriter "n" -like
++pattern.
++.IP "" 5
++.PP
++Input packets must have their IP header annotations set.
++.M IPAddrRewriter "n"
++changes IP packet data and destination IP address annotations.
++.PP
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBmappings\fR (read-only)" 5
++Returns a human-readable description of the
++.M IPAddrRewriter "n" 's
++current set of
++mappings.
++.IP "" 5
++.IP "\fBnmappings\fR (read-only)" 5
++Returns the number of currently installed mappings.
++.IP "" 5
++.IP "\fBpatterns\fR (read-only)" 5
++Returns a human-readable description of the patterns associated with this
++.M IPAddrRewriter "n" .
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M IPAddrRewriter n ,
++.M TCPRewriter n ,
++.M IPRewriterPatterns n ,
++.M RoundRobinIPMapper n ,
++.M FTPPortMapper n ,
++.M ICMPRewriter n ,
++.M ICMPPingRewriter n ,
++.M StoreIPAddress n
++(
++.M for n
++.M simple n
++uses)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPAddrRewriter.n click-1.6.0-27/inst/share/man/mann/IPAddrRewriter.n
+--- click-1.6.0/inst/share/man/mann/IPAddrRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPAddrRewriter.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,113 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipaddrrewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPADDRREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPAddrRewriter \- Click element;
++rewrites IP packets' addresses
++.SH "SYNOPSIS"
++\fBIPAddrRewriter\fR(INPUTSPEC1, ..., INPUTSPECn)
++
++\fBPorts\fR: 1 or more inputs, 1-256 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Rewrites the source and/or destination addresses on IP packets, along with
++their checksums. \fBIPAddrRewriter\fR implements the functionality of a network
++address translator (Basic NAT), where internal hosts are assigned
++temporary IP addresses as they access the Internet. Basic NAT works for any
++IP protocol, but the number of internal hosts that can access the Internet
++simultaneously is limited by the number of external IP addresses available.
++See also
++.M IPRewriter "n"
++and
++.M TCPRewriter "n" ,
++which implement network address/port
++translation (NAPT).
++.PP
++\fBIPAddrRewriter\fR maintains a \fImapping table\fR that records how addresses are
++rewritten. On receiving a packet, \fBIPAddrRewriter\fR first looks up that packet
++in the mapping table by source or destination address. If the table contains
++a mapping for either address, then the packet is rewritten according to the
++mapping and emitted on the specified output port. If there was no mapping,
++the packet is handled by the INPUTSPEC corresponding to the input port on
++which the packet arrived. (There are as many input ports as INPUTSPECs.)
++Most INPUTSPECs install new mappings, so that future packets from the same
++address are handled by the mapping table rather than some INPUTSPEC. The six
++forms of INPUTSPEC handle input packets as follows:
++.PP
++
++
++.IP "\&'drop', 'pass OUTPUT', 'keep FOUTPUT ROUTPUT', 'ELEMENTNAME'" 5
++These INPUTSPECs behave like those in
++.M IPRewriter "n" .
++.IP "" 5
++.IP "\&'pattern SADDR[-SADDR2] - FOUTPUT ROUTPUT'" 5
++Creates a mapping according to the given pattern. The destination
++address must be a dash '-', since \fBIPAddrRewriter\fR only changes outgoing
++packets' source addresses. (If you want to rewrite destination addresses,
++use
++.M IPAddrPairRewriter "n"
++instead.)
++SADDR may be a range 'L-H' or prefix 'ADDR/PFX';
++.M IPRewriter "n"
++will choose an unallocated address in that range, or drop the
++packet if no address is available. Normally addresses are chosen randomly
++within the range. To allocate addresses sequentially (which can make testing
++easier), append a pound sign to the range, as in '1.0.0.1-1.255.255.254#'.
++SADDR may also be a dash, in which case the source address is left unchanged.
++.IP "" 5
++Packets sent from the old source address are rewritten and sent to FOUTPUT,
++and packets sent to the new source address are rewritten back and sent to
++ROUTPUT.
++.IP "" 5
++.IP "\&'pattern PATNAME FOUTPUT ROUTPUT'" 5
++Behaves like the version in
++.M IPRewriter "n" ,
++except that PATNAME must name an
++\fBIPAddrRewriter\fR-like pattern.
++.IP "" 5
++.PP
++Input packets must have their IP header annotations set. \fBIPAddrRewriter\fR
++changes IP packet data and destination IP address annotations.
++.PP
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBmappings\fR (read-only)" 5
++Returns a human-readable description of the \fBIPAddrRewriter\fR's current set of
++mappings.
++.IP "" 5
++.IP "\fBnmappings\fR (read-only)" 5
++Returns the number of currently installed mappings.
++.IP "" 5
++.IP "\fBpatterns\fR (read-only)" 5
++Returns a human-readable description of the patterns associated with this
++\fBIPAddrRewriter\fR.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M IPAddrPairRewriter n ,
++.M TCPRewriter n ,
++.M IPRewriterPatterns n ,
++.M RoundRobinIPMapper n ,
++.M FTPPortMapper n ,
++.M ICMPRewriter n ,
++.M ICMPPingRewriter n ,
++.M StoreIPAddress n
++(
++.M for n
++.M simple n
++uses)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPClassifier.n click-1.6.0-27/inst/share/man/mann/IPClassifier.n
+--- click-1.6.0/inst/share/man/mann/IPClassifier.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPClassifier.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,239 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipclassifier.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPCLASSIFIER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPClassifier \- Click element;
++classifies IP packets by contents
++.SH "SYNOPSIS"
++\fBIPClassifier\fR(PATTERN_1, ..., PATTERN_N)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Classifies IP packets according to
++.M tcpdump 1 -like
++patterns. The
++\fBIPClassifier\fR has N outputs, each associated with the corresponding pattern
++from the configuration string. The input packets must have their IP header
++annotation set;
++.M CheckIPHeader "n"
++and
++.M MarkIPHeader "n"
++do this.
++.PP
++Patterns are built from \fIpattern primitives\fR. The primitives
++\fBIPClassifier\fR understands are:
++.PP
++
++
++.IP "\fBip proto PROTO\fR" 8
++PROTO is an IP protocol name (see below) or a valid IP protocol number.
++Matches packets of the given protocol.
++.IP "" 8
++.IP "\fB[SRCORDST] host IPADDR\fR" 8
++IPADDR is an IP address and SRCORDST is 'src', 'dst', 'src or dst', or 'src
++and dst'. (If SRCORDST is missing, 'src or dst' is assumed.) Matches
++packets sent to and/or from the given address.
++.IP "" 8
++.IP "\fB[SRCORDST] net NETADDR\fR" 8
++NETADDR is an IP network address (either CIDR-style 'IPADDR/BITS' or
++\&'IPADDR mask MASK') and SRCORDST is as above. Matches packets sent to
++and/or from the given network.
++.IP "" 8
++.IP "\fB[SRCORDST] [tcp | udp] port PORT\fR" 8
++PORT is a TCP or UDP port name (see below) or number and SRCORDST is as
++above. Matches packets sent to and/or from the given TCP or UDP port. If
++you leave out 'tcp' or 'udp', then either TCP or UDP is accepted.
++.IP "" 8
++.IP "\fBip vers VERSION\fR" 8
++VERSION is a value between 0 and 15. Matches IP packets with the given
++version.
++.IP "" 8
++.IP "\fBip hl HL\fR" 8
++HL is a value between 0 and 15. Matches IP packets with the given header
++length.
++.IP "" 8
++.IP "\fBip id ID\fR" 8
++ID is a value between 0 and 65535. Matches IP packets with the given IP ID.
++.IP "" 8
++.IP "\fBip tos TOS\fR" 8
++TOS is a value between 0 and 255. Matches IP packets with the given TOS
++value.
++.IP "" 8
++.IP "\fBip dscp DSCP\fR" 8
++DSCP is a value between 0 and 63. Matches IP packets with the given DSCP
++value (the upper 6 bits of TOS).
++.IP "" 8
++.IP "\fBip ect\fR" 8
++Matches IP packets with ECN Capable Transport turned on.
++.IP "" 8
++.IP "\fBip ce\fR" 8
++Matches IP packets with ECN Congestion Experienced set.
++.IP "" 8
++.IP "\fBip ttl TTL\fR" 8
++TTL is a value between 0 and 255. Matches IP packets with the given TTL value.
++.IP "" 8
++.IP "\fBip frag\fR" 8
++Matches fragmented IP packets (that is, packets with the more-fragments bit
++set and/or a nonzero fragment offset).
++.IP "" 8
++.IP "\fBip unfrag\fR" 8
++Equivalent to 'not ip frag'.
++.IP "" 8
++.IP "\fBtcp opt TCPOPT\fR" 8
++TCPOPT is a TCP option name (see below). Matches TCP packets with the given
++option.
++.IP "" 8
++.IP "\fBtcp win TCPWIN\fR" 8
++TCPWIN is a TCP receive window length. Matches TCP packets with the given
++window length. Note that window scaling is not applied.
++.IP "" 8
++.IP "\fBicmp type TYPE\fR" 8
++TYPE is a value between 0 and 255 or an ICMP type name (see below). Matches
++ICMP packets with the given ICMP type.
++.IP "" 8
++.IP "\fBip[POS:LEN] VALUE\fR" 8
++Matches packets whose IP header field starting at byte position POS, and going
++on for LEN bytes, equals VALUE. You can say \fBip[POS]\fR instead of
++\fBip[POS:1]\fR.
++.IP "" 8
++.IP "\fBtransp[POS:LEN] VALUE\fR" 8
++Like \fBip[POS:LEN]\fR, but for transport header fields. You can also give
++particular transport protocols, such as \fBtcp[POS:LEN]\fR.
++.IP "" 8
++.IP "\fBtrue\fR" 8
++Matches every packet.
++.IP "" 8
++.IP "\fBfalse\fR" 8
++Matches no packets.
++.IP "" 8
++.PP
++These primitives can be combined with the connectives 'and', 'or', and 'not'
++(synonyms '&&', '||', and '!'), with the ternary operator '?:' (the colon
++must be surrounded by spaces!), and with parentheses. For example, '(dst port
++www or dst port ssh) and tcp opt syn'.
++.PP
++All primitives except \fBtcp opt\fR accept an optional OPERATION, '==' or '!=',
++which can occur before the actual option. If no OPERATION is specified, '=='
++is assumed. 'src host == 10.0.0.10' matches packets whose source host is
++10.0.0.10; 'src host != 10.0.0.10' matches packets whose source host \fIis not\fR
++10.0.0.10. Directives with integer values also support the '<', '>', '<=',
++and '>=' operations.
++.PP
++For \fBport\fR and \fBicmp type\fR directives, 'DIRECTIVE != VALUE' is not the
++same as 'not (DIRECTIVE == VALUE)'. For example, 'src tcp port != 5'
++matches TCP packets whose source port is not 5, while '!(src tcp port ==
++5)' matches non-TCP packets as well. (The 'src tcp port != 5' option is
++effectively equivalent to 'tcp and not src tcp port 5'.) Similarly, 'icmp
++type != 4' will not match non-ICMP packets. The same goes for the '<', '>',
++\&'<=', and '>=' relations.
++.PP
++Most primitives also accept bitmasks: 'DIRECTIVE & MASK [[OP] VALUE]'. For
++instance, 'src tcp port & 10 == 8'.
++.PP
++The \fBport\fR, \fBicmp type\fR, and \fBtcp opt\fR directives will only match first
++fragments.
++.PP
++You can omit a lot of this syntax. For example, instead of 'ip proto tcp',
++you can just say 'tcp'; and similarly for 'port www' (just say 'www'), 'tcp
++opt syn' (just say 'syn'), 'net 10.0.0.0/24' (just say '10.0.0.0/24'), and
++\&'ip unfrag' (just say 'unfrag'). You can often eliminate repetitive
++qualifiers, too: 'src port 80 or 81' is the same as 'src port 80 or src
++port 81'.
++.PP
++A pattern consisting entirely of "-", "any", or "all" matches every packet.
++.PP
++The patterns are scanned in order, and the packet is sent to the output
++corresponding to the first matching pattern. Thus more specific patterns
++should come before less specific ones. You will get a warning if no packet
++will ever match a pattern. Usually, this is because an earlier pattern is
++more general, or because your pattern is contradictory ('src port www and
++src port ftp').
++.PP
++.SH "NOTES"
++Valid IP port names: 'echo', 'discard', 'daytime', 'chargen', 'ftp-data',
++\&'ftp', 'ssh', 'telnet', 'smtp', 'domain', 'dns', 'bootps', 'bootpc',
++\&'tftp', 'finger', 'www', 'pop3', 'sunrpc', 'auth', 'nntp', 'ntp',
++\&'netbios-ns', 'netbios-dgm', 'netbios-ssn', 'snmp', 'snmp-trap', 'irc',
++\&'imap3', 'https', 'rip', 'route', 'imaps', 'pop3s'
++.PP
++Valid IP protocol names: 'icmp', 'igmp', 'ipip', 'tcp', 'udp'
++.PP
++Valid TCP options: 'syn', 'fin', 'ack', 'rst', 'psh', 'urg'
++.PP
++Valid ICMP type names: 'echo-reply', 'unreachable', 'sourcequench',
++\&'redirect', 'echo', 'routeradvert', 'routersolicit', 'timeexceeded',
++\&'parameterproblem', 'timestamp', 'timestamp-reply', 'inforeq',
++\&'inforeq-reply', 'maskreq', 'maskreq-reply'
++.PP
++This element correctly handles IP packets with options.
++.PP
++\fB[tcp | udp] port\fR, \fBicmp type\fR, \fBtcp opt\fR, and \fBtcp win\fR directives can
++only be true on the first fragment of a fragmented packet.
++.PP
++Every \fBIPClassifier\fR element has an equivalent corresponding
++.M IPFilter "n"
++element
++and vice versa. Use the element whose syntax is more convenient for your
++needs.
++.PP
++
++.SH "EXAMPLES"
++For example,
++.PP
++.nf
++\& IPClassifier(10.0.0.0/24 and syn,
++\& 10.0.0.0/24 and fin ack,
++\& 10.0.0.0/24 and tcp,
++\& -);
++.fi
++.PP
++creates an element with four outputs. The first three outputs are for TCP
++packets from net 10.0.0.x. SYN packets are sent to output 0, FIN packets
++with the ACK bit set to output 1, and all other TCP packets to output 2.
++The last output is for all other IP packets, and non-TCP packets from net
++10.0.0.x.
++.PP
++.nf
++\& IPClassifier(dst tcp port 8000 or 8080,
++\& dst tcp port > 1023,
++\& tcp);
++.fi
++.PP
++creates an element with three outputs. The first output is for TCP packets
++destined for port 8000 or 8080; the second output is for TCP packets
++destined for any other user port (that is, port > 1023); and the third
++output is for all other TCP packets. Non-TCP packets are dropped.
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBprogram\fR (read-only)" 5
++Returns a human-readable definition of the program the \fBIPClassifier\fR element
++is using to classify packets. At each step in the program, four bytes
++of packet data are ANDed with a mask and compared against four bytes of
++classifier pattern.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Classifier n ,
++.M IPFilter n ,
++.M CheckIPHeader n ,
++.M MarkIPHeader n ,
++.M CheckIPHeader2 n ,
++tcpdump(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPEncap.n click-1.6.0-27/inst/share/man/mann/IPEncap.n
+--- click-1.6.0/inst/share/man/mann/IPEncap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPEncap.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,91 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipencap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPENCAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPEncap \- Click element;
++encapsulates packets in static IP header
++.SH "SYNOPSIS"
++\fBIPEncap\fR(PROTO, SRC, DST, \fIKEYWORDS\fR)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Encapsulates each incoming packet in an IP packet with protocol
++PROTO, source address SRC, and destination address DST.
++This is most useful for IP-in-IP encapsulation.
++Its destination address annotation is also set to DST.
++.PP
++As a special case, if DST is "DST_ANNO", then the destination address
++is set to the incoming packet's destination address annotation.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "TTL" 8
++Byte. The IP header's time-to-live field. Default is 250.
++.IP "" 8
++.IP "DSCP" 8
++Number between 0 and 63. The IP header's DSCP value. Default is 0.
++.IP "" 8
++.IP "ECT" 8
++Boolean or "2". If true, sets the IP header's ECN bits to ECN Capable
++Transport. If "true", "1" or "yes", sets the ECN bits to 1; but if "2", sets
++them to 2. Default is false.
++.IP "" 8
++.IP "CE" 8
++Boolean. If true, sets the IP header's ECN bits to 3 (Congestion Experienced).
++Default is false.
++.IP "" 8
++.IP "TOS" 8
++Byte. The IP header's TOS value. Default is 0. If you specify TOS, you may not
++specify DSCP, ECT, or CE.
++.IP "" 8
++.IP "DF" 8
++Boolean. If true, sets the IP header's Don't Fragment bit to 1. Default is
++false.
++.IP "" 8
++.PP
++The
++.M StripIPHeader "n"
++element can be used by the receiver to get rid
++of the encapsulation header.
++.PP
++.SH "EXAMPLES"
++Wraps packets in an IP header specifying IP protocol 4
++(IP-in-IP), with source 18.26.4.24 and destination 140.247.60.147:
++.PP
++.nf
++\& IPEncap(4, 18.26.4.24, 140.247.60.147)
++.fi
++.PP
++You could also say "\f(CWIPEncap(ipip, ...)\fR".
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBsrc\fR (read/write)" 5
++Returns or sets the SRC parameter.
++.IP "" 5
++.IP "\fBdst\fR (read/write)" 5
++Returns or sets the DST parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M UDPIPEncap n ,
++.M StripIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPFilter.n click-1.6.0-27/inst/share/man/mann/IPFilter.n
+--- click-1.6.0/inst/share/man/mann/IPFilter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPFilter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,145 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipfilter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPFILTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPFilter \- Click element;
++filters IP packets by contents
++.SH "SYNOPSIS"
++\fBIPFilter\fR(ACTION_1 PATTERN_1, ..., ACTION_N PATTERN_N)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Filters IP packets. \fBIPFilter\fR can have an arbitrary number of filters, which
++are ACTION-PATTERN pairs. The ACTIONs describe what to do with packets,
++while the PATTERNs are
++.M tcpdump 1 -like
++patterns; see
++.M IPClassifier n
++for a
++description of their syntax. Packets are tested against the filters in
++order, and are processed according to the ACTION in the first filter that
++matched.
++.PP
++Each ACTION is either a port number, which specifies that the packet should be
++sent out on that port; '\f(CWallow\fR', which is equivalent to '\f(CW0\fR'; or '\f(CWdrop\fR'
++, which means drop the packet. You can also say '\f(CWdeny\fR' instead of
++\&'\f(CWdrop\fR', but see the compatibility note below.
++.PP
++The \fBIPFilter\fR element has an arbitrary number of outputs. Input packets must
++have their IP header annotation set;
++.M CheckIPHeader "n"
++and
++.M MarkIPHeader "n"
++do
++this.
++.PP
++
++.SH "NOTES"
++Every \fBIPFilter\fR element has an equivalent corresponding
++.M IPClassifier "n"
++element
++and vice versa. Use the element whose syntax is more convenient for your
++needs.
++.PP
++\fBCompatibility note\fR: '\f(CWdeny\fR' formerly meant '\f(CW1\fR' if the element had at
++least two outputs and '\f(CWdrop\fR' if it did not. We decided this was
++error-prone; now it just means '\f(CWdrop\fR'. For now, however, '\f(CWdeny\fR' will
++print a warning if used on an element with more than one output.
++.PP
++
++.SH "EXAMPLES"
++This large \fBIPFilter\fR implements the incoming packet filtering rules for the
++"Interior router" described on pp691-692 of \fIBuilding Internet Firewalls,
++Second Edition\fR (Elizabeth D. Zwicky, Simon Cooper, and D. Brent Chapman,
++O'Reilly and Associates, 2000). The captialized words (\f(CWINTERNALNET\fR,
++\f(CWBASTION\fR, etc.) are addresses that have been registered with
++.M AddressInfo n .
++The rule FTP-7 has a port range that cannot be implemented
++with \fBIPFilter\fR.
++.PP
++.nf
++\& IPFilter(// Spoof-1:
++\& deny src INTERNALNET,
++\& // HTTP-2:
++\& allow src BASTION && dst INTERNALNET
++\& && tcp && src port www && dst port > 1023 && ack,
++\& // Telnet-2:
++\& allow dst INTERNALNET
++\& && tcp && src port 23 && dst port > 1023 && ack,
++\& // SSH-2:
++\& allow dst INTERNALNET && tcp && src port 22 && ack,
++\& // SSH-3:
++\& allow dst INTERNALNET && tcp && dst port 22,
++\& // FTP-2:
++\& allow dst INTERNALNET
++\& && tcp && src port 21 && dst port > 1023 && ack,
++\& // FTP-4:
++\& allow dst INTERNALNET
++\& && tcp && src port > 1023 && dst port > 1023 && ack,
++\& // FTP-6:
++\& allow src BASTION && dst INTERNALNET
++\& && tcp && src port 21 && dst port > 1023 && ack,
++\& // FTP-7 omitted
++\& // FTP-8:
++\& allow src BASTION && dst INTERNALNET
++\& && tcp && src port > 1023 && dst port > 1023,
++\& // SMTP-2:
++\& allow src BASTION && dst INTERNAL_SMTP
++\& && tcp && src port 25 && dst port > 1023 && ack,
++\& // SMTP-3:
++\& allow src BASTION && dst INTERNAL_SMTP
++\& && tcp && src port > 1023 && dst port 25,
++\& // NNTP-2:
++\& allow src NNTP_FEED && dst INTERNAL_NNTP
++\& && tcp && src port 119 && dst port > 1023 && ack,
++\& // NNTP-3:
++\& allow src NNTP_FEED && dst INTERNAL_NNTP
++\& && tcp && src port > 1023 && dst port 119,
++\& // DNS-2:
++\& allow src BASTION && dst INTERNAL_DNS
++\& && udp && src port 53 && dst port 53,
++\& // DNS-4:
++\& allow src BASTION && dst INTERNAL_DNS
++\& && tcp && src port 53 && dst port > 1023 && ack,
++\& // DNS-5:
++\& allow src BASTION && dst INTERNAL_DNS
++\& && tcp && src port > 1023 && dst port 53,
++\& // Default-2:
++\& deny all);
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBprogram\fR (read-only)" 5
++Returns a human-readable definition of the program the \fBIPFilter\fR element
++is using to classify packets. At each step in the program, four bytes
++of packet data are ANDed with a mask and compared against four bytes of
++classifier pattern.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M IPClassifier n ,
++.M Classifier n ,
++.M CheckIPHeader n ,
++.M MarkIPHeader n ,
++.M CheckIPHeader2 n ,
++.M AddressInfo n ,
++tcpdump(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPFragmenter.n click-1.6.0-27/inst/share/man/mann/IPFragmenter.n
+--- click-1.6.0/inst/share/man/mann/IPFragmenter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPFragmenter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,69 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipfragmenter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPFRAGMENTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPFragmenter \- Click element;
++fragments large IP packets
++.SH "SYNOPSIS"
++\fBIPFragmenter\fR(MTU, [\fIkeywords\fR HONOR_DF, VERBOSE])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packets as input. If the IP packet size is <= MTU, just emits
++the packet on output 0. If the size is greater than MTU and the
++don't-fragment bit (DF) isn't set, \fBIPFragmenter\fR splits the packet into
++fragments emitted on output 0. If DF is set and the packet size is greater
++than MTU, sends the packet to output 1 (but see HONOR_DF below). Ordinarily
++output 1 is connected to an
++.M ICMPError "n"
++element with type 3 (UNREACH) and
++code 4 (NEEDFRAG).
++.PP
++Only the mac_broadcast annotation is copied into the fragments.
++.PP
++Sends the fragments in order, starting with the first.
++.PP
++It is best to Strip() the MAC header from a packet before sending it to
++\fBIPFragmenter\fR, since any MAC header is not copied to second and subsequent
++fragments.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "HONOR_DF" 8
++Boolean. If HONOR_DF is false, \fBIPFragmenter\fR will ignore the don't-fragment
++(DF) bit and fragment every packet larger than MTU. Default is true.
++.IP "" 8
++.IP "VERBOSE" 8
++Boolean. If true, \fBIPFragmenter\fR will print a message every time it sees a
++packet with DF; otherwise, it will print a message only the first 5 times.
++Default is false.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ... -> fr::IPFragmenter(1024) -> Queue(20) -> ...
++\& fr[1] -> ICMPError(18.26.4.24, 3, 4) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M ICMPError n ,
++.M CheckLength "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPGWOptions.n click-1.6.0-27/inst/share/man/mann/IPGWOptions.n
+--- click-1.6.0/inst/share/man/mann/IPGWOptions.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPGWOptions.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,50 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipgwoptions.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPGWOPTIONS" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPGWOptions \- Click element;
++processes router IP options
++.SH "SYNOPSIS"
++\fBIPGWOptions\fR(MYADDR [, OTHERADDRS])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Process the IP options that should be processed by every router,
++not just when ip_dst refers to the current router. At the moment
++that amounts to Record Route and Timestamp (in particular,
++not the source route options). MYADDR is the router's
++IP address on the interface downstream from the element.
++.PP
++Probably needs to be placed on the output path, since MYADDR
++must be the outgoing interface's IP address (rfc1812 4.2.2.2).
++.PP
++Recomputes the IP header checksum if it modifies the packet.
++.PP
++The optional OTHERADDRS argument should be a space-separated list of IP
++addresses containing the router's other interface addresses. It is used to
++implement the Timestamp option.
++.PP
++The second output may be connected to an
++.M ICMPError "n"
++to produce
++a parameter problem (type=12,code=0) message. \fBIPGWOptions\fR sets
++the param_off packet annotation so that
++.M ICMPError "n"
++can set
++the Parameter Problem pointer to point to the erroneous byte.
++.PP
++
++.SH "SEE ALSO"
++.M ICMPError "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPInputCombo.n click-1.6.0-27/inst/share/man/mann/IPInputCombo.n
+--- click-1.6.0/inst/share/man/mann/IPInputCombo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPInputCombo.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,48 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipinputcombo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPINPUTCOMBO" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPInputCombo \- Click element;
++input combo for IP routing
++.SH "SYNOPSIS"
++\fBIPInputCombo\fR(COLOR [, BADSRC, \fIkeywords\fR INTERFACES, BADSRC, GOODDST])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++A single element encapsulating common tasks on an IP router's input path.
++Effectively equivalent to
++.PP
++.nf
++\& elementclass IPInputCombo { $COLOR, $BADADDRS |
++\& input[0] -> Paint($COLOR)
++\& -> Strip(14)
++\& -> CheckIPHeader($BADADDRS)
++\& -> GetIPAddress(16)
++\& -> [0]output;
++\& }
++.fi
++.PP
++The INTERFACES, BADSRC, and GOODDST keyword arguments correspond to
++.M CheckIPHeader "n" 's
++versions.
++.PP
++
++
++.SH "SEE ALSO"
++.M Paint n ,
++.M CheckIPHeader n ,
++.M Strip n ,
++.M GetIPAddress n ,
++.M IPOutputCombo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPMirror.n click-1.6.0-27/inst/share/man/mann/IPMirror.n
+--- click-1.6.0/inst/share/man/mann/IPMirror.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPMirror.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,31 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipmirror.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPMIRROR" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPMirror \- Click element;
++swaps IP source and destination
++.SH "SYNOPSIS"
++\fBIPMirror\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Incoming packets must have their IP header annotations set. Swaps packets'
++source and destination IP addresses. Packets containing TCP or UDP
++headers---that is, first fragments of packets with protocol 6 or 17---also
++have their source and destination ports swapped. TCP packets also have their
++seq and ack numbers swapped.
++.PP
++The IP and TCP or UDP checksums are not changed. They don't need to be; these
++swap operations do not affect checksums.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPNameInfo.n click-1.6.0-27/inst/share/man/mann/IPNameInfo.n
+--- click-1.6.0/inst/share/man/mann/IPNameInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPNameInfo.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,23 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipnameinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPNAMEINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPNameInfo \- Click element;
++stores name information about IP packets
++.SH "SYNOPSIS"
++\fBIPNameInfo\fR()
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Contains IP-related name mappings, such as the names for common IP protocols.
++This element should not be used in configurations.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPOutputCombo.n click-1.6.0-27/inst/share/man/mann/IPOutputCombo.n
+--- click-1.6.0/inst/share/man/mann/IPOutputCombo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPOutputCombo.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,69 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipoutputcombo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPOUTPUTCOMBO" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPOutputCombo \- Click element;
++output combo for IP routing
++.SH "SYNOPSIS"
++\fBIPOutputCombo\fR(COLOR, IPADDR, MTU)
++
++\fBPorts\fR: 1 input, 5 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++A single element encapsulating common tasks on an IP router's output path.
++Effectively equivalent to
++.PP
++.nf
++\& elementclass IPOutputCombo { $COLOR, $IPADDR, $MTU |
++\& input[0] -> DropBroadcasts
++\& -> p::PaintTee($COLOR)
++\& -> g::IPGWOptions($IPADDR)
++\& -> FixIPSrc($IPADDR)
++\& -> d::DecIPTTL
++\& -> l::CheckLength($MTU)
++\& -> [0]output;
++\& p[1] -> [1]output;
++\& g[1] -> [2]output;
++\& d[1] -> [3]output;
++\& l[1] -> [4]output;
++\& }
++.fi
++.PP
++Output 0 is the path for normal packets; outputs 1 through 3 are error
++outputs for
++.M PaintTee "n" ,
++.M IPGWOptions "n" ,
++and
++.M DecIPTTL "n" ,
++respectively; and
++output 4 is for packets longer than MTU.
++.PP
++
++
++.SH "NOTES"
++\fBIPOutputCombo\fR does no fragmentation. You'll still need an
++.M IPFragmenter "n"
++for
++that.
++.PP
++
++.SH "SEE ALSO"
++.M DropBroadcasts n ,
++.M PaintTee n ,
++.M CheckLength n ,
++.M IPGWOptions n ,
++.M FixIPSrc n ,
++.M DecIPTTL n ,
++.M IPFragmenter n ,
++.M IPInputCombo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPPrint.n click-1.6.0-27/inst/share/man/mann/IPPrint.n
+--- click-1.6.0/inst/share/man/mann/IPPrint.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPPrint.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,91 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipprint.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPPRINT" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPPrint \- Click element;
++pretty-prints IP packets
++.SH "SYNOPSIS"
++\fBIPPrint\fR([LABEL, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packets as input. Should be placed downstream of a
++.M CheckIPHeader "n"
++or equivalent element.
++.PP
++Prints out IP packets in a human-readable tcpdump-like format, preceded by
++the LABEL text.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "CONTENTS" 8
++Determines whether the packet data is printed. It may be `NONE' (do not print
++packet data), `HEX' (print packet data in hexadecimal), or `ASCII' (print
++packet data in plaintext). Default is `NONE'.
++.IP "" 8
++.IP "PAYLOAD" 8
++Like CONTENTS, but prints only the packet payload, rather than the entire
++packet. Specify at most one of CONTENTS and PAYLOAD.
++.IP "" 8
++.IP "NBYTES" 8
++If CONTENTS is `hex' or `ascii', then NBYTES determines the number of bytes to
++dump. Default is 1500.
++.IP "" 8
++.IP "ID" 8
++Boolean. Determines whether to print each packet's IP ID field. Default is
++false.
++.IP "" 8
++.IP "TTL" 8
++Boolean. Determines whether to print each packet's IP TOS field. Default is
++false.
++.IP "" 8
++.IP "TOS" 8
++Boolean. Determines whether to print each packet's IP TOS field. Default is
++false.
++.IP "" 8
++.IP "LENGTH" 8
++Boolean. Determines whether to print each packet's IP length field. Default is
++false.
++.IP "" 8
++.IP "TIMESTAMP" 8
++Boolean. Determines whether to print each packet's timestamp in seconds since
++1970. Default is true.
++.IP "" 8
++.IP "AGGREGATE" 8
++Boolean. Determines whether to print each packet's aggregate annotation.
++Default is false.
++.IP "" 8
++.IP "PAINT" 8
++Boolean. Determines whether to print each packet's paint annotation. Default is false.
++.IP "" 8
++.IP "SWAP" 8
++Boolean. Determines whether to swap bytes before printing the values
++of ICMP sequence and ID numbers. Default is false. The RFC does not
++require these two-byte values to be sent in any particular byte order.
++For example, OpenBSD/i386 writes ping (ICMP echo) sequence numbers in
++network byte order, while Linux/i386 writes them in host byte order
++(often little-endian).
++.IP "" 8
++.IP "OUTFILE" 8
++String. Only available at user level. Print information to the file specified
++by OUTFILE instead of standard error.
++.IP "" 8
++.PP
++
++.SH "SEE ALSO"
++.M Print n ,
++.M CheckIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPRateMonitor.n click-1.6.0-27/inst/share/man/mann/IPRateMonitor.n
+--- click-1.6.0/inst/share/man/mann/IPRateMonitor.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPRateMonitor.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,88 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipratemon.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPRATEMONITOR" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPRateMonitor \- Click element;
++measures coming and going IP traffic rates
++.SH "SYNOPSIS"
++\fBIPRateMonitor\fR(TYPE, RATIO, THRESH [, MEMORY, ANNO])
++
++\fBPorts\fR: 1-2 inputs, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Monitors network traffic rates. Can monitor either packet or byte rate (per
++second) to and from an address. When forward or reverse rate for a
++particular address exceeds THRESH, rates will then be kept for host or
++subnet addresses within that address. May update each packet's
++dst_rate_anno and src_rate_anno with the rates for dst or src IP address.
++.PP
++Packets coming in one input 0 are inspected on src address. Packets coming
++in on input 1 are insepected on dst address. This enables \fBIPRateMonitor\fR to
++annotate packets with both the forward rate and reverse rate.
++.PP
++TYPE: PACKETS or BYTES. Count number of packets or bytes.
++.PP
++RATIO: chance that EWMA gets updated before packet is annotated with EWMA
++value.
++.PP
++THRESH: \fBIPRateMonitor\fR further splits a subnet if rate is over THRESH number
++packets or bytes per second. Always specify value as if RATIO were 1.
++.PP
++MEMORY: How much memory can \fBIPRateMonitor\fR use in kilobytes? Minimum of 100
++is enforced. 0 is unlimited memory.
++.PP
++ANNO: if on (by default, it is), annotate packets with rates.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlook\fR ((read))" 5
++Returns the rate of counted to and from a cluster of IP addresses. The first
++printed line is the number of 'jiffies' that have past since the last reset.
++There are 100 jiffies in one second.
++.IP "" 5
++.IP "\fBthresh\fR ((read))" 5
++Returns THRESH.
++.IP "" 5
++.IP "\fBreset\fR ((write))" 5
++When written, resets all rates.
++.IP "" 5
++.IP "\fBanno_level\fR ((write))" 5
++Expects "IPAddress level when". When written, makes \fBIPRateMonitor\fR stop
++expanding at "level" (0-3) for the IPAddress, until "when" (seconds). For
++example, if "18.26.4.0 2 100" is specified, \fBIPRateMonitor\fR will stop
++expanding when 18.26.4 is reached for the next 100 seconds. After 100
++seconds, any level below 18.26.4 may be reached again.
++.IP "" 5
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& IPRateMonitor(PACKETS, 0.5, 256, 600);
++.fi
++.PP
++Monitors packet rates. The memory usage is limited to 600K. When rate for a
++network address (e.g. 18.26.*.*) exceeds 256 packets per second, start
++monitor subnet or host addresses (e.g. 18.26.4.*).
++.PP
++
++
++.SH "SEE ALSO"
++.M IPFlexMonitor n ,
++.M CompareBlock "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPReassembler.n click-1.6.0-27/inst/share/man/mann/IPReassembler.n
+--- click-1.6.0/inst/share/man/mann/IPReassembler.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPReassembler.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,55 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ipreassembler.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPREASSEMBLER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPReassembler \- Click element;
++Reassembles fragmented IP packets
++.SH "SYNOPSIS"
++\fBIPReassembler\fR([\fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packets as input to port 0. If input packets are fragments,
++\fBIPReassembler\fR holds them until it has enough fragments to recreate a complete
++packet. When a complete packet is constructed, it is emitted onto output 0. If
++a set of fragments making a single packet is incomplete and dormant for 30
++seconds, the fragments are generally dropped. If \fBIPReassembler\fR has two
++outputs, however, a single packet containing all the received fragments at
++their proper offsets is pushed onto output 1.
++.PP
++\fBIPReassembler\fR's memory usage is bounded. When memory consumption rises above
++HIMEM bytes, \fBIPReassembler\fR throws away old fragments until memory consumption
++drops below 3/4*HIMEM bytes. Default HIMEM is 256K.
++.PP
++Output packets have no MAC headers, and input MAC headers are ignored.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "HIMEM" 8
++The upper bound for memory consumption, in bytes. Default is 256K.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++You may want to attach an \f(CWICMPError(ADDR, timeexceeded, reassembly)\fR to the
++second output.
++.PP
++\fBIPReassembler\fR destroys its input packets' "next packet" annotations.
++.PP
++
++.SH "SEE ALSO"
++.M IPFragmenter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPRewriter.n click-1.6.0-27/inst/share/man/mann/IPRewriter.n
+--- click-1.6.0/inst/share/man/mann/IPRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPRewriter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,183 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/iprewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPRewriter \- Click element;
++rewrites TCP/UDP packets' addresses and ports
++.SH "SYNOPSIS"
++\fBIPRewriter\fR(INPUTSPEC1, ..., INPUTSPECn [, \fIkeywords\fR])
++
++\fBPorts\fR: 1 or more inputs, 1-256 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Rewrites the source address, source port, destination address, and/or
++destination port on TCP and UDP packets, along with their checksums.
++\fBIPRewriter\fR implements the functionality of a network address/port translator
++(NAPT). See also
++.M IPAddrRewriter "n"
++and
++.M IPAddrPairRewriter "n" ,
++which
++implement Basic NAT, and
++.M TCPRewriter "n" ,
++which implements NAPT plus sequence
++number changes for TCP packets.
++.PP
++\fBIPRewriter\fR maintains a \fImapping table\fR that records how packets are
++rewritten. The mapping table is indexed by \fIflow identifier\fR, the quintuple
++of source address, source port, destination address, destination port, and IP
++protocol (TCP or UDP). Each mapping contains a new flow identifier and an
++output port. Input packets with the indexed flow identifier are rewritten to
++use the new flow identifier, then emitted on the output port. A mapping is
++written as follows:
++.PP
++.nf
++\& (SA, SP, DA, DP, PROTO) => (SA', SP', DA', DP') [OUTPUT]
++.fi
++.PP
++When \fBIPRewriter\fR receives a packet, it first looks up that packet in the
++mapping table by flow identifier. If the table contains a mapping for the
++input packet, then the packet is rewritten according to the mapping and
++emitted on the specified output port. If there was no mapping, the packet is
++handled by the INPUTSPEC corresponding to the input port on which the packet
++arrived. (There are as many input ports as INPUTSPECs.) Most INPUTSPECs
++install new mappings, so that future packets from the same TCP or UDP flow are
++handled by the mapping table rather than some INPUTSPEC. The six forms of
++INPUTSPEC handle input packets as follows:
++.PP
++
++
++
++.IP "\&'drop' or 'discard'" 5
++Discards input packets.
++.IP "" 5
++.IP "\&'pass OUTPUT'" 5
++Sends input packets to output port OUTPUT. No mappings are installed.
++.IP "" 5
++.IP "\&'keep FOUTPUT ROUTPUT'" 5
++Installs mappings that preserve the input packet's flow ID. Specifically,
++given an input packet with flow ID (SA, SP, DA, DP, PROTO), two mappings are
++installed:
++.IP "" 5
++.nf
++\& (SA, SP, DA, DP, PROTO) => (SA, SP, DA, DP) [FOUTPUT]
++\& (DA, DP, SA, SP, PROTO) => (DA, DP, SA, SP) [ROUTPUT]
++.fi
++.IP "" 5
++Thus, the input packet is emitted on output port FOUTPUT unchanged, and
++packets from the reply flow are emitted on output port ROUTPUT unchanged.
++.IP "" 5
++
++.IP "\&'pattern SADDR SPORT DADDR DPORT FOUTPUT ROUTPUT'" 5
++Creates a mapping according to the given pattern, 'SADDR SPORT DADDR DPORT'.
++Any pattern field may be a dash '-', in which case the packet's corresponding
++field is left unchanged. For instance, the pattern '1.0.0.1 20 - -' will
++rewrite input packets' source address and port, but leave its destination
++address and port unchanged. SPORT may be a port range 'L-H'; \fBIPRewriter\fR will
++choose a source port in that range so that the resulting mappings don't
++conflict with any existing mappings. If no source port is available, the
++packet is dropped. Normally source ports are chosen randomly within the
++range. To allocate source ports sequentially (which can make testing easier),
++append a pound sign to the range, as in '1024-65535#'.
++.IP "" 5
++Say a packet with flow ID (SA, SP, DA, DP, PROTO) is received, and the
++corresponding new flow ID is (SA', SP', DA', DP'). Then two mappings are
++installed:
++.IP "" 5
++.nf
++\& (SA, SP, DA, DP, PROTO) => (SA', SP', DA', DP') [FOUTPUT]
++\& (DA', DP', SA', SP', PROTO) => (DA, DP, SA, SP) [ROUTPUT]
++.fi
++.IP "" 5
++Thus, the input packet is rewritten and sent to FOUTPUT, and packets from the
++reply flow are rewritten to look like part of the original flow and sent to
++ROUTPUT.
++.IP "" 5
++
++.IP "\&'pattern PATNAME FOUTPUT ROUTPUT'" 5
++Like 'pattern' above, but refers to named patterns defined by an
++.M IPRewriterPatterns "n"
++element.
++.IP "" 5
++.IP "\&'ELEMENTNAME'" 5
++Creates mappings according to instructions from the element ELEMENTNAME. This
++element must implement the IPMapper interface. One example mapper is
++.M RoundRobinIPMapper "n" .
++.IP "" 5
++.PP
++\fBIPRewriter\fR has no mappings when first initialized.
++.PP
++Input packets must have their IP header annotations set. Non-TCP and UDP
++packets, and second and subsequent fragments, are dropped unless they arrive
++on a 'pass' input port. \fBIPRewriter\fR changes IP packet data and, optionally,
++destination IP address annotations; see the DST_ANNO keyword argument below.
++.PP
++Keyword arguments determine how often stale mappings should be removed.
++.PP
++
++.IP "TCP_TIMEOUT \fItime\fR" 5
++Time out TCP connections every \fItime\fR seconds. Default is 24 hours.
++.IP "" 5
++.IP "TCP_DONE_TIMEOUT \fItime\fR" 5
++Time out completed TCP connections every \fItime\fR seconds. Default is 30
++seconds. FIN and RST flags mark TCP connections as complete.
++.IP "" 5
++.IP "UDP_TIMEOUT \fItime\fR" 5
++Time out UDP connections every \fItime\fR seconds. Default is 1 minute.
++.IP "" 5
++.IP "REAP_TCP \fItime\fR" 5
++Reap timed-out TCP connections every \fItime\fR seconds. If no packets
++corresponding to a given mapping have been seen for TCP_TIMEOUT, remove the
++mapping as stale. Default is 1 hour.
++.IP "" 5
++.IP "REAP_TCP_DONE \fItime\fR" 5
++Reap timed-out completed TCP connections every \fItime\fR seconds. Default is 10
++seconds.
++.IP "" 5
++.IP "REAP_UDP \fItime\fR" 5
++Reap timed-out UDP connections every \fItime\fR seconds. Default is 10 seconds.
++.IP "" 5
++.IP "DST_ANNO" 5
++Boolean. If true, then set the destination IP address annotation on passing
++packets to the rewritten destination address. Default is true.
++.IP "" 5
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtcp_mappings\fR (read-only)" 5
++Returns a human-readable description of the \fBIPRewriter\fR's current set of
++TCP mappings.
++.IP "" 5
++.IP "\fBudp_mappings\fR (read-only)" 5
++Returns a human-readable description of the \fBIPRewriter\fR's current set of
++UDP mappings.
++.IP "" 5
++.IP "\fBtcp_done_mappings\fR (read-only)" 5
++Returns a human-readable description of the \fBIPRewriter\fR's current set of
++mappings for completed TCP sessions.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M TCPRewriter n ,
++.M IPAddrRewriter n ,
++.M IPAddrPairRewriter n ,
++.M IPRewriterPatterns n ,
++.M RoundRobinIPMapper n ,
++.M FTPPortMapper n ,
++.M ICMPRewriter n ,
++.M ICMPPingRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPRewriterPatterns.n click-1.6.0-27/inst/share/man/mann/IPRewriterPatterns.n
+--- click-1.6.0/inst/share/man/mann/IPRewriterPatterns.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPRewriterPatterns.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,33 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/iprwpatterns.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPREWRITERPATTERNS" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPRewriterPatterns \- Click element;
++specifies shared
++.M IPRewriter n
++patterns
++.SH "SYNOPSIS"
++\fBIPRewriterPatterns\fR(NAME PATTERN, ...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++This element stores information about shared patterns that
++.M IPRewriter "n"
++and
++related elements can use. Each configuration argument is a name and a
++pattern, 'NAME SADDR SPORT DADDR DPORT'. The NAMEs for every argument in
++every \fBIPRewriterPatterns\fR element in the configuration must be distinct.
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/IPRouteTable.n click-1.6.0-27/inst/share/man/mann/IPRouteTable.n
+--- click-1.6.0/inst/share/man/mann/IPRouteTable.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/IPRouteTable.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,177 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/iproutetable.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IPROUTETABLE" n "11/Feb/2009" "Click"
++.SH "NAME"
++IPRouteTable \- Click element;
++IP routing table superclass
++.SH "SYNOPSIS"
++\fBIPRouteTable\fR
++
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++\fBIPRouteTable\fR defines an interface useful for implementing IPv4 route lookup
++elements. It parses configuration strings -- see
++.M LinearIPLookup "n"
++for an example
++-- and calls virtual functions to add the resulting routes. A default \f(CWpush\fR
++function uses those virtual functions to look up routes and output packets
++accordingly. There are also some functions useful for implementing handlers.
++.PP
++
++.SH "PERFORMANCE"
++Click provides several elements that implement all or part of the \fBIPRouteTable\fR
++interface. Marko Zec has compared their performance, in terms of lookup speed
++and memory size, for full BGP feeds; here are the results.
++.PP
++Methodology: 2.8GHz Pentium P4 CPU, 521K L2 cache, FreeBSD 4.10, userspace
++Click.
++.M RangeIPLookup "n"
++has two lookup tables, the larger of which is used only
++at update time. The "warm cache" numbers perform the same lookup several
++times in a loop to populate the cache; only the last lookup's performance is
++reported.
++.PP
++.nf
++\& ICSI BGP dump, 150700 routes, 2 next-hops
++\&
++\& Element | cycles | lookups | setup | lookup
++\& | /lookup | /sec | time | tbl. size
++\& -----------------+---------+---------+-------+----------------
++\& RadixIPLookup | 1025 | 2.73M | 0.59s | 5.8 MB
++\& DirectIPLookup | 432 | 6.48M | 0.74s | 33 MB
++\& RangeIPLookup | 279 | 10.0 M | 0.83s | 0.21MB (+33MB)
++\& " (warm cache) | 44 | 63.6 M | " | " "
++\&
++\& routeviews.org dump, 167000 routes, 52 nexthops
++\&
++\& Element | cycles | lookups | setup | lookup
++\& | /lookup | /sec | time | tbl. size
++\& -----------------+---------+---------+-------+----------------
++\& RadixIPLookup | 1095 | 2.55M | 0.67s | 6.6 MB
++\& DirectIPLookup | 434 | 6.45M | 0.77s | 33 MB
++\& RangeIPLookup | 508 | 5.51M | 0.88s | 0.51MB (+33MB)
++\& " (warm cache) | 61 | 45.9 M | " | " "
++.fi
++.PP
++The
++.M RadixIPLookup "n" ,
++.M DirectIPLookup "n" ,
++and
++.M RangeIPLookup "n"
++elements are well suited
++for implementing large tables. We also provide the
++.M LinearIPLookup "n" ,
++.M StaticIPLookup "n" ,
++and
++.M SortedIPLookup "n"
++elements; they are simple, but their O(N)
++lookup speed is orders of magnitude slower.
++.M RadixIPLookup "n"
++or
++.M DirectIPLookup "n"
++should be preferred for almost all purposes.
++.nf
++\&
++\& 1500-entry fraction of the ICSI BGP dump
++\&
++\& Method | cycles | lookups | setup | lookup
++\& | /lookup | /sec | time | tbl. size
++\& ---------------+---------+---------+-------+----------
++\& LinearIPLookup | 12000 | 233K | 10s | 29 KB
++\& StaticIPLookup | 12000 | 233K | 10s | 29 KB
++\& SortedIPLookup | 12500 | 224K | 38s | 29 KB
++.fi
++.PP
++A Click script containing the 167000-route dump is available at
++http://www.read.cs.ucla.edu/click/routetabletest-167k.click.gz
++.PP
++
++
++.SH "INTERFACE"
++These four \fBIPRouteTable\fR virtual functions should generally be overridden by
++particular routing table elements.
++.PP
++
++
++.IP "\f(CWint \fBadd_route\fR(const IPRoute& r, bool set, IPRoute* old_route, ErrorHandler *errh)\fR" 4
++Add a route sending packets with destination addresses matching
++\f(CWr.addr/r.mask\fR to gateway \f(CWr.gw\fR, via output port \f(CWr.port\fR. If a route
++for this exact prefix already exists, then the behavior depends on \f(CWset\fR. If
++\f(CWset\fR is true, then any existing route is silently overwritten (after
++possibly being stored in \f(CW*old_route\fR); if \f(CWset\fR is false, the function
++should return \f(CW-EEXIST\fR. Report errors to \f(CWerrh\fR. Should return 0 on
++success and negative on failure. The default implementation reports an error
++"cannot add routes to this routing table".
++.IP "" 4
++.IP "\f(CWint \fBremove_route\fR(const IPRoute& r, IPRoute* old_route, ErrorHandler *errh)\fR" 4
++Removes the route sending packets with destination addresses matching
++\f(CWr.addr/r.mask\fR to gateway \f(CWr.gw\fR, via the element's output port \f(CWr.port\fR.
++All four fields must match, unless \f(CWr.port\fR is less than 0, in which case
++only \f(CWr.addr/r.mask\fR must match. If no route for that prefix exists, the
++function should return \f(CW-ENOENT\fR; otherwise, the old route should be stored
++in \f(CW*old_route\fR (assuming it's not null). Any errors are reported to
++\f(CWerrh\fR. Should return 0 on success and negative on failure. The default
++implementation reports an error "cannot delete routes from this routing
++table".
++.IP "" 4
++.IP "\f(CWint \fBlookup_route\fR(IPAddress dst, IPAddress &gw_return) const\fR" 4
++Looks up the route associated with address \f(CWdst\fR. Should set \f(CWgw_return\fR to
++the resulting gateway and return the relevant output port (or negative if
++there is no route). The default implementation returns -1.
++.IP "" 4
++.IP "\f(CWString \fBdump_routes\fR()\fR" 4
++Returns a textual description of the current routing table. The default
++implementation returns an empty string.
++.IP "" 4
++.PP
++The following functions, overridden by \fBIPRouteTable\fR, are available for use by
++subclasses.
++.PP
++
++.IP "\f(CWint \fBconfigure\fR(Vector<String> &conf, ErrorHandler *)\fR" 4
++The default implementation of \fBconfigure\fR parses \f(CWconf\fR as a list of routes,
++where each route is the space-separated list `\f(CWaddress/mask [gateway]
++output\fR'. The routes are successively added to the element with \fBadd_route\fR.
++.IP "" 4
++.IP "\f(CWvoid \fBpush\fR(int port, Packet *p)\fR" 4
++The default implementation of \fBpush\fR uses \fBlookup_route\fR to perform IP
++routing lookup. Normally, subclasses implement their own \fBpush\fR methods,
++avoiding virtual function call overhead.
++.IP "" 4
++.IP "\f(CWstatic int \fBadd_route_handler\fR(const String &, Element *, void *, ErrorHandler *)\fR" 4
++This write handler callback parses its input as an add-route request
++and calls \fBadd_route\fR with the results. Normally hooked up to the `\f(CWadd\fR'
++handler.
++.IP "" 4
++.IP "\f(CWstatic int \fBremove_route_handler\fR(const String &, Element *, void *, ErrorHandler *)\fR" 4
++This write handler callback parses its input as a remove-route request and
++calls \fBremove_route\fR with the results. Normally hooked up to the `\f(CWremove\fR'
++handler.
++.IP "" 4
++.IP "\f(CWstatic int \fBctrl_handler\fR(const String &, Element *, void *, ErrorHandler *)\fR" 4
++This write handler callback function parses its input as a route control
++request and calls \fBadd_route\fR or \fBremove_route\fR as directed. Normally hooked
++up to the `\f(CWctrl\fR' handler.
++.IP "" 4
++.IP "\f(CWstatic String \fBtable_handler\fR(Element *, void *)\fR" 4
++This read handler callback function returns the element's routing table via
++the \fBdump_routes\fR function. Normally hooked up to the `\f(CWtable\fR' handler.
++.IP "" 4
++.PP
++
++.SH "SEE ALSO"
++.M RadixIPLookup n ,
++.M DirectIPLookup n ,
++.M RangeIPLookup n ,
++.M StaticIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup n ,
++.M LinuxIPLookup "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Idle.n click-1.6.0-27/inst/share/man/mann/Idle.n
+--- click-1.6.0/inst/share/man/mann/Idle.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Idle.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,27 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/idle.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "IDLE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Idle \- Click element;
++discards packets
++.SH "SYNOPSIS"
++Idle
++
++\fBPorts\fR: any number of inputs, any number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Has zero or more agnostic outputs and zero or more agnostic inputs. It
++never pushes a packet to any output or pulls a packet from any input. Any
++packet it does receive is discarded. Used to avoid "input not connected"
++error messages.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/InfiniteSource.n click-1.6.0-27/inst/share/man/mann/InfiniteSource.n
+--- click-1.6.0/inst/share/man/mann/InfiniteSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/InfiniteSource.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,106 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/infinitesource.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "INFINITESOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++InfiniteSource \- Click element;
++generates packets whenever scheduled
++.SH "SYNOPSIS"
++\fBInfiniteSource\fR([DATA, LIMIT, BURST, ACTIVE, \fIKEYWORDS\fR])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Creates packets consisting of DATA. Pushes BURST such packets out its single
++output every time it is scheduled (which will be often). Stops sending after
++LIMIT packets are generated; but if LIMIT is negative, sends packets forever.
++Will send packets only if ACTIVE is true. (ACTIVE is true by default.) Default
++DATA is at least 64 bytes long. Default LIMIT is -1 (send packets forever).
++Default BURST is 1.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DATA" 8
++String. Same as the DATA argument.
++.IP "" 8
++.IP "DATASIZE" 8
++Integer. If set, ensures the outgoing packet contains at least this many bytes.
++.IP "" 8
++.IP "LIMIT" 8
++Integer. Same as the LIMIT argument.
++.IP "" 8
++.IP "BURST" 8
++Integer. Same as the BURST argument.
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. Same as the ACTIVE argument.
++.IP "" 8
++.IP "STOP" 8
++Boolean. If true, then stop the driver once LIMIT packets are sent. Default is
++false.
++.IP "" 8
++.PP
++To generate a particular traffic pattern, use this element and
++.M RatedSource "n"
++in conjunction with
++.M PokeHandlers "n" .
++.PP
++.SH "EXAMPLES"
++
++.nf
++\& InfiniteSource(\e<0800>) -> Queue -> ...
++.fi
++.PP
++
++
++
++.SH "NOTES"
++Useful for profiling and experiments. Packets' timestamp annotations are set
++to the current time.
++.PP
++\fBInfiniteSource\fR listens for downstream full notification.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the total number of packets that have been generated.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++Resets the number of generated packets to 0. The \fBInfiniteSource\fR will then
++generate another LIMIT packets (if it is active).
++.IP "" 5
++.IP "\fBdata\fR (read/write)" 5
++Returns or sets the DATA parameter.
++.IP "" 5
++.IP "\fBdatasize\fR (read/write)" 5
++Returns or sets the DATASIZE parameter.
++.IP "" 5
++.IP "\fBlimit\fR (read/write)" 5
++Returns or sets the LIMIT parameter.
++.IP "" 5
++.IP "\fBburstsize\fR (read/write)" 5
++Returns or sets the BURSTSIZE parameter.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Makes the element active or inactive.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RatedSource n ,
++.M PokeHandlers "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/KernelFilter.n click-1.6.0-27/inst/share/man/mann/KernelFilter.n
+--- click-1.6.0/inst/share/man/mann/KernelFilter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/KernelFilter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,53 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/kernelfilter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "KERNELFILTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++KernelFilter \- Click element;
++block kernel from handling packets
++.SH "SYNOPSIS"
++\fBKernelFilter\fR(FILTERSPEC, ...)
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++The \fBKernelFilter\fR element installs filter rules in the kernel to stop the
++kernel from handling certain types of packets. Use this in combination with
++.M FromDevice.u "n"
++to handle packets in user-level Click configurations.
++.PP
++\fBKernelFilter\fR uses iptables(1) to install filters; if your system does not
++support iptables(1), \fBKernelFilter\fR will fail.
++.PP
++\fBKernelFilter\fR uninstalls its firewall rules when Click shuts down. If Click
++shuts down uncleanly, for instance because of a segmentation fault or 'kill
++-9', then the rules will remain in place, and you'll have to remove them
++yourself.
++.PP
++Currently only one form of FILTERSPEC is understood.
++.PP
++
++
++.IP "\&'\f(CWdrop dev DEVNAME\fR'" 8
++The kernel is blocked from handling any packets arriving on device DEVNAME.
++However, these packets will still be visible to tcpdump(1), and to Click
++elements like
++.M FromDevice.u "n" .
++.IP "" 8
++.PP
++
++.SH "SEE ALSO"
++.M FromDevice.u n ,
++.M ToDevice.u n ,
++.M KernelTap n ,
++ifconfig(8)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/KernelHandlerProxy.n click-1.6.0-27/inst/share/man/mann/KernelHandlerProxy.n
+--- click-1.6.0/inst/share/man/mann/KernelHandlerProxy.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/KernelHandlerProxy.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,48 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/khandlerproxy.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "KERNELHANDLERPROXY" n "11/Feb/2009" "Click"
++.SH "NAME"
++KernelHandlerProxy \- Click element;
++proxies kernel module handlers at user level
++.SH "SYNOPSIS"
++\fBKernelHandlerProxy\fR([\fIKEYWORDS\fR])
++
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Provides one proxy handler for each handler in a Linux kernel module Click
++configuration. The proxy handler for an element \f(CWe\fR's handler \f(CWh\fR is named
++`\f(CWe.h\fR'. Reading \fBKernelHandlerProxy\fR's \f(CWe.h\fR handler will return the result
++of reading kernel element \f(CWe\fR's \f(CWh\fR handler. Similarly, writing a string to
++\fBKernelHandlerProxy\fR's \f(CWe.h\fR handler will cause the proxy to write that string
++to kernel element \f(CWe\fR's \f(CWh\fR handler.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "VERBOSE" 8
++Boolean. If true, print chatter messages when read handlers fail. (Errors with
++write handlers are reported to the supplied ErrorHandler, but read handlers
++don't take an ErrorHandler argument.) Default is false.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++\fBKernelHandlerProxy\fR does not decide ahead of time whether a given handler is
++active. Thus, for example, \fBKernelHandlerProxy\fR can report that a handler exists
++even when no corresponding element exists in the kernel configuration. Any
++error will be reported when the handler is actually called.
++.PP
++
++.SH "SEE ALSO"
++.M SocketHandlerProxy "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/KernelTap.n click-1.6.0-27/inst/share/man/mann/KernelTap.n
+--- click-1.6.0/inst/share/man/mann/KernelTap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/KernelTap.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,88 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/kerneltap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "KERNELTAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++KernelTap \- Click element;
++interface to /dev/tap or ethertap (user-level)
++.SH "SYNOPSIS"
++\fBKernelTap\fR(ADDR/MASK [, GATEWAY, \fIkeywords\fR ETHER, MTU, HEADROOM, IGNORE_QUEUE_OVERFLOWS])
++
++\fBPorts\fR: at most 1 input, 1-2 outputs
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads Ethernet packets from and writes Ethernet packets to a /dev/tun* or
++/dev/tap* device. This allows a user-level Click to hand packets to the
++virtual Ethernet device. \fBKernelTap\fR will also transfer packets from the
++virtual Ethernet device.
++.PP
++\fBKernelTap\fR allocates a /dev/tun* or tap* device (this might fail) and runs
++.M ifconfig 8
++to set the interface's local (i.e., kernel) address to ADDR and
++the netmask to MASK. If a nonzero GATEWAY IP address (which must be on the
++same network as the tun) is specified, then \fBKernelTap\fR tries to set up a
++default route through that host.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "ETHER" 8
++Ethernet address. Specifies the fake device's Ethernet address. Default is
++00:01:02:03:04:05. On Linux, you must supply an ETHER argument, and use that
++address as the destination Ethernet address for all packets sent to the tap
++element; otherwise, Linux will ignore your packets. On FreeBSD, there is no
++way to set the Ethernet address, and any ETHER argument is silently ignored,
++but it is safe to use any destination Ethernet address for packets sent to the
++tap.
++.IP "" 8
++.IP "MTU" 8
++Integer. The interface's maximum transmission unit. Default is 1500; some
++operating systems do not alllow it to be set.
++.IP "" 8
++.IP "HEADROOM" 8
++Integer. The number of bytes left empty before the packet data (to leave room
++for additional encapsulation headers). Default is 0.
++.IP "" 8
++.IP "IGNORE_QUEUE_OVERFLOWS" 8
++Boolean. If true, don't print more than one error message when there are
++queue overflow errors (ENOBUFS) when sending or receiving packets via the tun
++device. Default is false.
++.IP "" 8
++.PP
++\fBKernelTap\fR accepts the same arguments as
++.M KernelTun "n" .
++.PP
++.SH "NOTES"
++Linux will send ARP queries to the fake device. You must respond to these
++queries in order to receive any IP packets, but you can obviously respond
++with any Ethernet address you'd like. Here is one common idiom:
++.nf
++\&
++\& tap0 :: KernelTap(192.0.0.1/8)
++\& -> fromhost_cl :: Classifier(12/0806, 12/0800);
++\& fromhost_cl[0] -> ARPResponder(0.0.0.0/0 1:1:1:1:1:1) -> tap0;
++\& fromhost_cl[1] -> ... // IP packets
++\&
++.fi
++.PP
++An error like "could not allocate a /dev/tap* device : No such file or
++directory" usually means that you have not enabled /dev/tap* in your
++kernel.
++.PP
++
++
++.SH "SEE ALSO"
++.M ToHost n ,
++.M KernelTun n ,
++ifconfig(8)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/KernelTun.n click-1.6.0-27/inst/share/man/mann/KernelTun.n
+--- click-1.6.0/inst/share/man/mann/KernelTun.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/KernelTun.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,106 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/kerneltun.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "KERNELTUN" n "11/Feb/2009" "Click"
++.SH "NAME"
++KernelTun \- Click element;
++interface to /dev/tun or ethertap (user-level)
++.SH "SYNOPSIS"
++\fBKernelTun\fR(ADDR/MASK [, GATEWAY, \fIkeywords\fR HEADROOM, ETHER, MTU, IGNORE_QUEUE_OVERFLOWS])
++
++\fBPorts\fR: at most 1 input, 1-2 outputs
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads IP packets from and writes IP packets to a /dev/net/tun, /dev/tun*,
++or /dev/tap* device. This allows a user-level Click to hand packets to the
++ordinary kernel IP processing code. \fBKernelTun\fR will also install a routing
++table entry so that the kernel can pass packets to the \fBKernelTun\fR device.
++.PP
++\fBKernelTun\fR produces and expects IP packets. If, for some reason, the kernel
++passes up a non-IP packet (or an invalid IP packet), \fBKernelTun\fR will emit
++that packet on its second output, or drop it if there is no second output.
++.PP
++\fBKernelTun\fR allocates a /dev/net/tun, /dev/tun*, or /dev/tap* device (this
++might fail) and runs
++.M ifconfig 8
++to set the interface's local (i.e.,
++kernel) address to ADDR and the netmask to MASK. If a nonzero GATEWAY IP
++address (which must be on the same network as the tun) is specified, then
++\fBKernelTun\fR tries to set up a default route through that host.
++.PP
++When cleaning up, \fBKernelTun\fR attempts to bring down the device via
++.M ifconfig 8 .
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "HEADROOM" 8
++Integer. The number of bytes left empty before the packet data to leave
++room for additional encapsulation headers. Default is 28.
++.IP "" 8
++.IP "MTU" 8
++Integer. The interface's MTU. \fBKernelTun\fR will refuse to send packets larger
++than the MTU. Default is 1500; not all operating systems allow MTU to be set.
++.IP "" 8
++.IP "ETHER" 8
++Ethernet address. Specifies the tunnel device's Ethernet address. Default is
++00:01:02:03:04:05. On FreeBSD, any ETHER argument is silently ignored.
++.IP "" 8
++.IP "IGNORE_QUEUE_OVERFLOWS" 8
++Boolean. If true, don't print more than one error message when
++there are queue overflows error when sending/receiving packets
++to/from the tun device (e.g. there was an ENOBUFS error). Default
++is false.
++.IP "" 8
++.IP "DEVNAME" 8
++String. If specified, try to alloc a tun device with name DEVNAME.
++Otherwise, we'll just take the first virtual device we find. This option
++only works with the Linux Universal TUN/TAP driver.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Make sure that your kernel has tun support enabled before running
++\fBKernelTun\fR. Initialization errors like "no such device" or "no such file or
++directory" may indicate that your kernel isn't set up, or that some
++required kernel module hasn't been loaded (on Linux, the relevant module is
++"tun").
++.PP
++Packets sent to ADDR will be processed by the host kernel stack; packets sent
++to any other address in ADDR/MASK will be sent to \fBKernelTun\fR. Say you run this
++configuration:
++.PP
++.nf
++\& tun :: KernelTun(1.0.0.1/8);
++\& tun -> IPClassifier(icmp type echo) -> ICMPPingResponder
++\& -> IPPrint -> tun;
++.fi
++.PP
++If you then "\f(CWping 1.0.0.1\fR", \fIyour own kernel\fR will respond. Click will
++never see the packets, so it won't print anything. But if you "\f(CWping
++1.0.0.2\fR", the pings are sent to Click. You should see printouts from Click,
++and \f(CWping\fR should print Click's responses.
++.PP
++This element differs from
++.M KernelTap "n"
++in that it produces and expects IP
++packets, not IP-in-Ethernet packets.
++.PP
++
++
++.SH "SEE ALSO"
++.M FromDevice.u n ,
++.M ToDevice.u n ,
++.M KernelTap n ,
++ifconfig(8)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/LinearIPLookup.n click-1.6.0-27/inst/share/man/mann/LinearIPLookup.n
+--- click-1.6.0/inst/share/man/mann/LinearIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/LinearIPLookup.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,100 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/lineariplookup.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "LINEARIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++LinearIPLookup \- Click element;
++simple IP routing table
++.SH "SYNOPSIS"
++\fBLinearIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++\fBNote:\fR Lookups and table updates with \fBLinearIPLookup\fR are extremely slow; the
++.M RadixIPLookup "n"
++and
++.M DirectIPLookup "n"
++elements should be preferred in almost all
++cases. See
++.M IPRouteTable "n"
++for a performance comparison. We provide
++\fBLinearIPLookup\fR nevertheless for its simplicity.
++.PP
++Expects a destination IP address annotation with each packet. Looks up that
++address in its routing table, using longest-prefix-match, sets the destination
++annotation to the corresponding GW (if specified), and emits the packet on the
++indicated OUTput port.
++.PP
++Each argument is a route, specifying a destination and mask, an optional
++gateway IP address, and an output port.
++.PP
++\fBLinearIPLookup\fR uses a linear search algorithm that may look at every route on
++each packet. It is therefore most suitable for small routing tables.
++.PP
++
++.SH "EXAMPLES"
++This example delivers broadcasts and packets addressed to the local
++host (18.26.4.24) to itself, packets to net 18.26.4 to the
++local interface, and all others via gateway 18.26.4.1:
++.PP
++.nf
++\& ... -> GetIPAddress(16) -> rt;
++\& rt :: LinearIPLookup(18.26.4.24/32 0,
++\& 18.26.4.255/32 0,
++\& 18.26.4.0/32 0,
++\& 18.26.4/24 1,
++\& 0/0 18.26.4.1 1);
++\& rt[0] -> ToHost;
++\& rt[1] -> ... -> ToDevice(eth0);
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtable\fR (read-only)" 5
++Outputs a human-readable version of the current routing table.
++.IP "" 5
++.IP "\fBlookup\fR (read-only)" 5
++Reports the OUTput port and GW corresponding to an address.
++.IP "" 5
++.IP "\fBadd\fR (write-only)" 5
++Adds a route to the table. Format should be `\f(CWADDR/MASK [GW] OUT\fR'.
++Fails if a route for \f(CWADDR/MASK\fR already exists.
++.IP "" 5
++.IP "\fBset\fR (write-only)" 5
++Sets a route, whether or not a route for the same prefix already exists.
++.IP "" 5
++.IP "\fBremove\fR (write-only)" 5
++Removes a route from the table. Format should be `\f(CWADDR/MASK\fR'.
++.IP "" 5
++.IP "\fBctrl\fR (write-only)" 5
++Adds or removes a group of routes. Write `\f(CWadd\fR/\f(CWset ADDR/MASK [GW] OUT\fR' to
++add a route, and `\f(CWremove ADDR/MASK\fR' to remove a route. You can supply
++multiple commands, one per line; all commands are executed as one atomic
++operation.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RadixIPLookup n ,
++.M DirectIPLookup n ,
++.M RangeIPLookup n ,
++.M StaticIPLookup n ,
++.M SortedIPLookup n ,
++.M LinuxIPLookup n ,
++.M IPRouteTable "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/LinkUnqueue.n click-1.6.0-27/inst/share/man/mann/LinkUnqueue.n
+--- click-1.6.0/inst/share/man/mann/LinkUnqueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/LinkUnqueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,70 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/linkunqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "LINKUNQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++LinkUnqueue \- Click element;
++link emulator
++.SH "SYNOPSIS"
++\fBLinkUnqueue\fR(LATENCY, BANDWIDTH)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++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.
++.PP
++\fBLinkUnqueue\fR listens for upstream notification, such as that available from
++.M Queue "n" .
++.PP
++\fBLinkUnqueue\fR 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 "
++.M Queue "n"
++-> \fBLinkUnqueue\fR" combination.
++.PP
++\fBLinkUnqueue\fR uses its input packets' "extra length" annotations, destroys their
++"next packet" annotations, and updates their timestamp annotations.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlatency\fR (read-only)" 5
++The LATENCY argument.
++.IP "" 5
++.IP "\fBbandwidth\fR (read-only)" 5
++The BANDWIDTH argument.
++.IP "" 5
++.IP "\fBsize\fR (read-only)" 5
++The number of packets currently in, or partially in, the emulated link.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in, or partially in, the emulated link.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M DelayUnqueue n ,
++.M Queue n ,
++.M Unqueue n ,
++.M RatedUnqueue n ,
++.M BandwidthRatedUnqueue n ,
++.M DelayShaper n ,
++.M SetTimestamp "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/LinuxIPLookup.n click-1.6.0-27/inst/share/man/mann/LinuxIPLookup.n
+--- click-1.6.0/inst/share/man/mann/LinuxIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/LinuxIPLookup.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,62 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/lookupiproutelinux.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "LINUXIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++LinuxIPLookup \- Click element;
++interface to Linux's routing table
++.SH "SYNOPSIS"
++\fBLinuxIPLookup\fR(if0, if1, ..., ifN)
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Looks up each packet's destination annotation address in the
++Linux routing table. Replaces the annotation with the
++routing table entry's gateway field (if non-zero).
++Emits the packet on an output that depends on the Linux
++interface device mentioned in the routing table entry:
++if the device name is the Ith configuration argument,
++the element sends the packet on output I (zero origin).
++.PP
++If the packet can't be routed, the element emits it on
++the output with number equal to the number of configuration arguments.
++A packet can't be routed if there is no matching routing
++table entry, or if the device mentioned in the Linux
++routing table isn't mentioned in the configuration.
++.PP
++If run outside the kernel, the element reads the routing table
++just once (at startup) from /proc/net/route.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& r : LinuxIPLookup(eth0, eth1)
++\& r[0] -> ... -> ToDevice(eth0)
++\& r[1] -> ... -> ToDevice(eth1)
++\& r[2] -> ICMPError(18.26.4.24, 3, 0) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M RadixIPLookup n ,
++.M DirectIPLookup n ,
++.M RangeIPLookup n ,
++.M StaticIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/LookupIPRouteMP.n click-1.6.0-27/inst/share/man/mann/LookupIPRouteMP.n
+--- click-1.6.0/inst/share/man/mann/LookupIPRouteMP.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/LookupIPRouteMP.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/lookupiproutemp.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "LOOKUPIPROUTEMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++LookupIPRouteMP \- Click element;
++simple static IP routing table
++.SH "SYNOPSIS"
++\fBLookupIPRouteMP\fR(DST1/MASK1 [GW1] OUT1, DST2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Interfaces are exactly the same as
++.M LookupIPRoute "n" .
++The only difference is
++when operating in SMP mode, each processor has a processor local cache,
++hence the element is MT SAFE.
++.PP
++
++.SH "SEE ALSO"
++.M LookupIPRoute "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/MSQueue.n click-1.6.0-27/inst/share/man/mann/MSQueue.n
+--- click-1.6.0/inst/share/man/mann/MSQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/MSQueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,48 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/msqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "MSQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++MSQueue \- Click element;
++stores packets in a FIFO queue
++.SH "SYNOPSIS"
++MSQueue
++.br
++\fBMSQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a multiple producer single consumer
++first-in-first-out queue. Enqueue operations are synchronized, dequeue
++operations are not. Drops incoming packets if the queue already holds
++CAPACITY packets. The default for CAPACITY is 1000.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBdropd\fR (read-only)" 5
++Returns the number of packets dropped by the queue so far.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/MarkIPCE.n click-1.6.0-27/inst/share/man/mann/MarkIPCE.n
+--- click-1.6.0/inst/share/man/mann/MarkIPCE.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/MarkIPCE.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,27 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/markipce.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "MARKIPCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++MarkIPCE \- Click element;
++sets IP packets' ECN field to Congestion Experienced
++.SH "SYNOPSIS"
++\fBMarkIPCE\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packets as input. Sets each incoming packet's ECN field to
++Congestion Experienced (value 3), incrementally recalculates the IP checksum,
++and passes the packet to output 0. Non-IP packets, and IP packets whose ECN
++field is zero (not ECN-capable), are dropped.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/MarkIPHeader.n click-1.6.0-27/inst/share/man/mann/MarkIPHeader.n
+--- click-1.6.0/inst/share/man/mann/MarkIPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/MarkIPHeader.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,38 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/markipheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "MARKIPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++MarkIPHeader \- Click element;
++sets IP header annotation
++.SH "SYNOPSIS"
++\fBMarkIPHeader\fR([OFFSET])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Marks packets as IP packets by setting the IP Header annotation. The IP
++header starts OFFSET bytes into the packet. Default OFFSET is 0.
++.PP
++Does not check length fields for sanity, shorten packets to the IP length,
++or set the destination IP address annotation. Use
++.M CheckIPHeader "n"
++or
++.M CheckIPHeader2 "n"
++for that.
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M CheckIPHeader2 n ,
++.M StripIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Message.n click-1.6.0-27/inst/share/man/mann/Message.n
+--- click-1.6.0/inst/share/man/mann/Message.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Message.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/messageelement.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "MESSAGE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Message \- Click element;
++prints a message on configuration
++.SH "SYNOPSIS"
++\fBMessage\fR(MESSAGE [, TYPE])
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++The \fBMessage\fR element prints a message, warning, or error when configured. It
++can be used to provide configuration-level documentation. The MESSAGE
++argument is the message (a string); TYPE should be MESSAGE, WARNING, or
++ERROR. The default is MESSAGE.
++.PP
++If TYPE is ERROR the router will fail to initialize.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& Message("This configuration is deprecated; use test-tun.click instead.", WARNING)
++\& tun :: KernelTap(1.0.0.1/8);
++\& ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Error "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Meter.n click-1.6.0-27/inst/share/man/mann/Meter.n
+--- click-1.6.0/inst/share/man/mann/Meter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Meter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,65 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/meter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "METER" n "11/Feb/2009" "Click"
++.SH "NAME"
++Meter \- Click element;
++classifies packet stream by rate (pkt/s)
++.SH "SYNOPSIS"
++\fBMeter\fR(RATE1, RATE2, ..., RATE\fIn\fR)
++
++\fBPorts\fR: 1 input, 2 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Classifies packets based on the rate of packet arrival. The rate is
++measured in packets per second using an exponential weighted moving
++average. (The related
++.M BandwidthMeter "n"
++element measures rates in bytes per
++second.)
++.PP
++The configuration string consists of one or more rate arguments. Earlier
++rates in the list must be less than later rates. A \fBMeter\fR with \fIn\fR rate
++arguments will have \fIn\fR+1 outputs. It sends packets out the output
++corresponding to the current rate. If the rate is less than RATE1 packets
++are sent to output 0; if it is >= RATE1 but < RATE2, packets are sent to
++output 1; and so on. If it is >= RATE\fIn\fR, packets are sent to output \fIn\fR.
++.PP
++
++.SH "NOTES"
++The entire packet stream is sent to the output corresponding to the current
++rate. If you would like the packet stream to be split, with at most RATE1
++packets per second being sent out the first output and the remainder being
++sent to the second output, check out
++.M RatedSplitter "n" .
++.PP
++
++.SH "EXAMPLES"
++This configuration fragment drops the input stream when it is generating
++more than 10,000 packets per second.
++.PP
++.nf
++\& ... -> m :: Meter(10000) -> ...;
++\& m[1] -> Discard;
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M BandwidthMeter n ,
++.M RatedSplitter n ,
++.M Shaper n ,
++.M BandwidthShaper n ,
++.M RatedUnqueue n ,
++.M BandwidthRatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/MixedQueue.n click-1.6.0-27/inst/share/man/mann/MixedQueue.n
+--- click-1.6.0/inst/share/man/mann/MixedQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/MixedQueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,90 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/mixedqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "MIXEDQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++MixedQueue \- Click element;
++stores packets in a FIFO/LIFO queue
++.SH "SYNOPSIS"
++MixedQueue
++.br
++\fBMixedQueue\fR(CAPACITY)
++
++\fBPorts\fR: 2 inputs, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a mixed first-in-first-out/last-in-first-out queue.
++In particular, \fBMixedQueue\fR's first input is FIFO, but its second input is LIFO.
++The queue is full when it holds CAPACITY packets. When full, \fBMixedQueue\fR drops
++incoming FIFO packets, but drops the oldest packet to make room for incoming
++LIFO packets. The default for CAPACITY is 1000.
++.PP
++\fBMixedQueue\fR notifies interested parties when it becomes empty and when a
++formerly-empty queue receives a packet. The empty notification takes place
++some time after the queue goes empty, to prevent thrashing for queues that
++hover around 1 or 2 packets long.
++.PP
++
++.SH "EXAMPLES"
++This diagram shows the state of a \fBMixedQueue\fR after 5 pushes, of packets A
++through E. The queue's head is on the left.
++.PP
++.nf
++\& initial state empty
++\& push(0, A) [A]
++\& push(0, B) [A B]
++\& push(1, C) [C A B]
++\& push(0, D) [C A B D]
++\& push(1, E) [E C A B D]
++.fi
++.PP
++
++
++
++.SH "SYNCHRONIZATION"
++Note for multithreaded Click: Unlike
++.M Queue "n" ,
++whose input and output ports need
++not be synchronized, \fBMixedQueue\fR requires synchronization between its LIFO
++input and its output. You will need to prevent a thread from pushing to the
++LIFO input at the same time that a different thread pulls from the output.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBhighwater_length\fR (read-only)" 5
++Returns the maximum number of packets that have ever been in the queue at once.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped by the queue so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++When written, resets the \f(CWdrops\fR and \f(CWhighwater_length\fR counters.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in the queue.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M SimpleQueue n ,
++.M FrontDropQueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/NotifierQueue.n click-1.6.0-27/inst/share/man/mann/NotifierQueue.n
+--- click-1.6.0/inst/share/man/mann/NotifierQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/NotifierQueue.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,83 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/notifierqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "NOTIFIERQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++NotifierQueue \- Click element;
++stores packets in a FIFO queue
++.SH "SYNOPSIS"
++NotifierQueue
++.br
++\fBNotifierQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a first-in-first-out queue.
++Drops incoming packets if the queue already holds CAPACITY packets.
++The default for CAPACITY is 1000.
++.PP
++\fBNotifierQueue\fR notifies interested parties when it becomes empty and when a
++formerly-empty queue receives a packet. The empty notification takes place
++some time after the queue goes empty, to prevent thrashing for queues that
++hover around 1 or 2 packets long. In all other respects, \fBNotifierQueue\fR behaves
++like
++.M SimpleQueue "n" .
++.PP
++\fBMultithreaded Click note:\fR \fBNotifierQueue\fR is designed to be used in an
++environment with at most one concurrent pusher and at most one concurrent
++puller. Thus, at most one thread pushes to the \fBNotifierQueue\fR at a time and at
++most one thread pulls from the \fBNotifierQueue\fR at a time. Different threads can
++push to and pull from the \fBNotifierQueue\fR concurrently, however. See
++.M MSQueue "n"
++for
++a queue that can support multiple concurrent pushers.
++.PP
++
++.SH "NOTES"
++The
++.M Queue "n"
++element acts like \fBNotifierQueue\fR, but additionally notifies
++interested parties when it changes state from nonfull to full or vice versa.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBhighwater_length\fR (read-only)" 5
++Returns the maximum number of packets that have ever been in the queue at once.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped by the queue so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++When written, resets the \f(CWdrops\fR and \f(CWhighwater_length\fR counters.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in the queue.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M SimpleQueue n ,
++.M MixedQueue n ,
++.M FrontDropQueue n ,
++.M MSQueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Null.n click-1.6.0-27/inst/share/man/mann/Null.n
+--- click-1.6.0/inst/share/man/mann/Null.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Null.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,29 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/nullelement.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "NULL" n "11/Feb/2009" "Click"
++.SH "NAME"
++Null \- Click element;
++passes packets unchanged
++.SH "SYNOPSIS"
++\fBNull\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Just passes packets along without doing anything else.
++.PP
++
++.SH "SEE ALSO"
++.M PushNull n ,
++.M PullNull "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Null1.n click-1.6.0-27/inst/share/man/mann/Null1.n
+--- click-1.6.0/inst/share/man/mann/Null1.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Null1.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,35 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/nulls.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "NULL1" n "11/Feb/2009" "Click"
++.SH "NAME"
++Null1 \- Click element;
++copy of
++.M Null "n"
++.SH "SYNOPSIS"
++\fBNull1\fR() ... Null8()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++The elements \fBNull1\fR through Null8 are reimplementations of
++.M Null "n" .
++However, each
++has independent code, so the i-cache cost of using all eight elements (\fBNull1\fR
++through Null8) is eight times the cost of eight
++.M Null "n"
++elements.
++.PP
++
++.SH "SEE ALSO"
++.M Null "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Paint.n click-1.6.0-27/inst/share/man/mann/Paint.n
+--- click-1.6.0/inst/share/man/mann/Paint.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Paint.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/paint.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PAINT" n "11/Feb/2009" "Click"
++.SH "NAME"
++Paint \- Click element;
++sets packet paint annotations
++.SH "SYNOPSIS"
++\fBPaint\fR(COLOR)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Sets each packet's paint annotation to COLOR, an integer 0..255. Note that a
++packet may only be painted with one color.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcolor\fR (read/write)" 5
++get/set the color to paint
++.IP "" 5
++.PP
++
++.SH "NOTES"
++The paint annotation is stored in user annotation 0.
++.PP
++
++.SH "SEE ALSO"
++.M PaintTee "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PaintSwitch.n click-1.6.0-27/inst/share/man/mann/PaintSwitch.n
+--- click-1.6.0/inst/share/man/mann/PaintSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PaintSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,43 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/paintswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PAINTSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++PaintSwitch \- Click element;
++sends packet stream to output chosen per-packet
++.SH "SYNOPSIS"
++\fBPaintSwitch\fR
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBPaintSwitch\fR sends every incoming packet to one of its output ports --
++specifically, output port number K, where K is the value of the
++incoming packet's
++.M Paint "n"
++annotation. If the paint annotation is set to
++255, the packet is duplicated and sent to all outputs. Since there
++are only 256 different paint annotations, including the special value
++of 255, \fBPaintSwitch\fR can have up to 255 outputs. If there is no output
++port K, the packet is dropped.
++.PP
++
++.SH "SEE ALSO"
++.M StaticSwitch n ,
++.M PullSwitch n ,
++.M RoundRobinSwitch n ,
++.M StrideSwitch n ,
++.M HashSwitch n ,
++.M RandomSwitch n ,
++.M Paint n ,
++.M PaintTee "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PaintTee.n click-1.6.0-27/inst/share/man/mann/PaintTee.n
+--- click-1.6.0/inst/share/man/mann/PaintTee.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PaintTee.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,47 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/painttee.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PAINTTEE" n "11/Feb/2009" "Click"
++.SH "NAME"
++PaintTee \- Click element;
++duplicates packets with given paint annotation
++.SH "SYNOPSIS"
++\fBPaintTee\fR(COLOR)
++
++\fBPorts\fR: 1 input, 2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBPaintTee\fR sends every packet through output 0. If the packet's
++color annotation is equal to COLOR (an integer), it also
++sends a copy through output 1.
++.PP
++
++.SH "EXAMPLES"
++Intended to produce redirects in conjunction with
++.M Paint "n"
++and
++.M ICMPError "n"
++as follows:
++.PP
++.nf
++\& FromDevice(eth7) -> Paint(7) -> ...
++\& routingtable[7] -> pt :: PaintTee(7) -> ... -> ToDevice(eth7)
++\& pt[1] -> ICMPError(18.26.4.24, 5, 1) -> [0]routingtable;
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Paint n ,
++.M ICMPError "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PerfCountAccum.n click-1.6.0-27/inst/share/man/mann/PerfCountAccum.n
+--- click-1.6.0/inst/share/man/mann/PerfCountAccum.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PerfCountAccum.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,59 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/perfcountaccum.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PERFCOUNTACCUM" n "11/Feb/2009" "Click"
++.SH "NAME"
++PerfCountAccum \- Click element;
++collects differences in Pentium Pro performance metrics
++.SH "SYNOPSIS"
++\fBPerfCountAccum\fR(TYPE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Expects incoming packets to have their performance metric annotation set
++according to the Pentium Pro performance metric TYPE. Calculates the
++current value of the performance metric TYPE, and keeps track of the total
++accumulated difference.
++.PP
++
++.SH "NOTES"
++A packet has room for either exactly one cycle count or exactly one
++performance metric.
++.PP
++See
++.M SetPerfCount "n"
++for valid performance metric names.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets that have passed.
++.IP "" 5
++.IP "\fBaccum\fR (read-only)" 5
++Returns the accumulated changes in the metric TYPE for all passing packets.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets \f(CWcount\fR and \f(CWaccum\fR counters to zero when written.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M SetPerfCount n ,
++.M SetCycleCount n ,
++.M CycleCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PerfCountInfo.n click-1.6.0-27/inst/share/man/mann/PerfCountInfo.n
+--- click-1.6.0/inst/share/man/mann/PerfCountInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PerfCountInfo.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,47 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/perfcountinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PERFCOUNTINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++PerfCountInfo \- Click element;
++turn on Pentium Pro performance metrics
++.SH "SYNOPSIS"
++\fBPerfCountInfo\fR([TYPE0, TYPE1])
++
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++The Pentium Pro CPU can maintain up to two performance counters.
++\fBPerfCountInfo\fR turns on those counters. TYPE0 is the type of performance
++counter 0, TYPE1 is the type of performance counter 1. Either type may be
++empty, in which case that counter will not be used.
++.PP
++The
++.M SetPerfCount "n"
++and
++.M PerfCountAccum "n"
++elements automatically turn on the
++relevant counters, so \fBPerfCountInfo\fR is not normally needed. It is useful if
++you are instrumenting individual elements.
++.PP
++
++.SH "NOTES"
++Valid performance metric names are \f(CWBUS_TRAN_INVAL\fR, \f(CWBUS_TRAN_MEM\fR,
++\f(CWDCU_MISS_OUTSTANDING\fR, \f(CWIFU_FETCH\fR, \f(CWIFU_FETCH_MISS\fR, \f(CWIFU_MEM_STALL\fR,
++\f(CWINST_RETIRED\fR, \f(CWL2_IFETCH\fR, \f(CWL2_LD\fR, \f(CWL2_LINES_IN\fR, \f(CWL2_LINES_OUT\fR,
++\f(CWL2_LINES_OUTM\fR, and \f(CWL2_RQSTS\fR.
++.PP
++
++.SH "SEE ALSO"
++.M SetPerfCount n ,
++.M PerfCountAccum n ,
++.M SetCycleCount n ,
++.M CycleCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PokeHandlers.n click-1.6.0-27/inst/share/man/mann/PokeHandlers.n
+--- click-1.6.0/inst/share/man/mann/PokeHandlers.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PokeHandlers.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,82 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/pokehandlers.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "POKEHANDLERS" n "11/Feb/2009" "Click"
++.SH "NAME"
++PokeHandlers \- Click element;
++calls write handlers at specified times
++.SH "SYNOPSIS"
++\fBPokeHandlers\fR(DIRECTIVE, ...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBThis element is deprecated. Use the Script element instead.\fR
++.PP
++Runs read and write handlers at specified times. Each configuration argument
++is a directive, taken from this list:
++.PP
++
++
++.IP "`read HANDLER'" 8
++Call a read handler and report its result. At user level, the result is
++printed on standard error; in a Linux kernel, it is printed to
++/var/log/messages. HANDLER should be either a global read handler name, or
++`ELEMENT.HNAME', where ELEMENT is an element name and HNAME the name of one of
++its read handlers.
++.IP "" 8
++.IP "`write HANDLER [VALUE]'" 8
++Call a write handler with a given value. At user level, errors reported by
++write handlers are printed to standard error. In the Linux kernel module, they
++are printed to /var/log/messages (accessible through
++.M dmesg 1 )
++and to
++/proc/click/errors.
++.IP "" 8
++.IP "`stop'" 8
++Stop the driver.
++.IP "" 8
++.IP "`wait DELAY'" 8
++Wait for DELAY seconds before continuing to the next directive.
++.IP "" 8
++.IP "`pause'" 8
++Wait until the `unpause' write handler is called, then continue to the next directive.
++.IP "" 8
++.IP "`loop'" 8
++Start over from the first directive.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& PokeHandlers(write red.max_p 0.8,
++\& wait 1.5, // delay for 1.5 seconds
++\& write red.max_p 0.5);
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBunpause\fR (write-only)" 5
++If paused, continue to next directive. Otherwise, there is no effect.
++.IP "" 5
++.IP "\fBpaused\fR (read-only)" 5
++Returns `true' if paused, else `false'.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++dmesg(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PollDevice.n click-1.6.0-27/inst/share/man/mann/PollDevice.n
+--- click-1.6.0/inst/share/man/mann/PollDevice.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PollDevice.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,103 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/polldevice.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "POLLDEVICE" n "11/Feb/2009" "Click"
++.SH "NAME"
++PollDevice \- Click element;
++polls packets from network device (kernel)
++.SH "SYNOPSIS"
++\fBPollDevice\fR(DEVNAME [, \fIkeywords\fR PROMISC, BURST, TIMESTAMP...])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Poll packets received by the Linux network interface named DEVNAME. Packets
++will be pushed to output 0. The packets include the link-level header. DEVNAME
++may also be an Ethernet address, in which case \fBPollDevice\fR searches for a
++device with that address.
++.PP
++Each time \fBPollDevice\fR is scheduled, it emits at most BURST packets. By default,
++BURST is 8.
++.PP
++This element is only available in the Linux kernel module.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "PROMISC" 8
++Boolean. If true, the device is put into promiscuous mode while
++.M FromDevice "n"
++is
++active. Default is false.
++.IP "" 8
++.IP "BURST" 8
++Unsigned integer. Sets the BURST parameter.
++.IP "" 8
++.IP "TIMESTAMP" 8
++Boolean. If true, then ensure that received packets have correctly-set
++timestamp annotations. Default is true.
++.IP "" 8
++.IP "QUIET" 8
++Boolean. If true, then suppress device up/down messages. Default is false.
++.IP "" 8
++.IP "HEADROOM" 8
++Unsigned. Amount of extra headroom to request on each packet. Default is 64.
++.IP "" 8
++.IP "ALLOW_NONEXISTENT" 8
++Allow nonexistent devices. If true, and no device named DEVNAME exists when
++the router is initialized, then \fBPollDevice\fR will report a warning (rather than
++an error). Later, while the router is running, if a device named DEVNAME
++appears, \fBPollDevice\fR will seamlessly begin emitting its packets. Default is
++false.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Linux won't see any packets from the device. If you want Linux to process
++packets, you should hand them to
++.M ToHost "n" .
++Also, if you would like to send
++packets while using \fBPollDevice\fR, you should also define a
++.M ToDevice "n"
++on the same
++device.
++.PP
++This element can only be used with devices that support the Click polling
++extension. We have written polling patches for the Tulip Ethernet driver.
++.PP
++Linux device drivers, and thus
++.M FromDevice "n" ,
++should set packets' timestamp,
++packet-type, and device annotations.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets \fBPollDevice\fR has received from the input card.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets \f(CWcount\fR counter to zero when written.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M FromDevice n ,
++.M ToDevice n ,
++.M FromHost n ,
++.M ToHost "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PortInfo.n click-1.6.0-27/inst/share/man/mann/PortInfo.n
+--- click-1.6.0/inst/share/man/mann/PortInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PortInfo.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,65 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../include/click/standard/portinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PORTINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++PortInfo \- Click element;
++stores named TCP/UDP port information
++.SH "SYNOPSIS"
++\fBPortInfo\fR(NAME PORT[/PROTOCOL], ...)
++
++\fBPorts\fR: None
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Lets you use mnemonic names for TCP and UDP ports. Each argument has the form
++`NAME PORT[/PROTOCOL]', which associates the given PORT/PROTOCOL pair with the
++NAME. If PROTOCOL is left off, the NAME applies to both TCP and UDP. For
++example, in a configuration containing
++.PP
++.nf
++\& PortInfo(ssh 22, http 80),
++.fi
++.PP
++configuration strings can use \f(CWssh\fR and \f(CWhttp\fR as mnemonics for the port
++numbers 22 and 80, respectively.
++.PP
++\fBPortInfo\fR names are local with respect to compound elements. That is, names
++created inside a compound element apply only within that compound element and
++its subelements. For example:
++.PP
++.nf
++\& PortInfo(src 10);
++\& compound :: {
++\& PortInfo(dst 100);
++\& ... -> UDPIPEncap(1.0.0.1, src, 2.0.0.1, dst) -> ... // OK
++\& };
++\& ... -> UDPIPEncap(1.0.0.1, src, 2.0.0.1, dst) -> ...
++\& // error: `dst' undefined
++.fi
++.PP
++
++
++
++.SH "NOTES"
++If you do not define a port for a given name, \fBPortInfo\fR will use the default,
++if any. At user level, \fBPortInfo\fR uses the
++.M getservbyname 3
++function to look
++up ports by name. In the kernel, there are no default ports.
++.PP
++\fBPortInfo\fR will parse arguments containing more than one name, as `\f(CWNAME
++PORT/PROTOCOL NAME...\fR', and comments starting with `\f(CW#\fR' are ignored. Thus,
++lines from \fI/etc/services\fR can be used verbatim as \fBPortInfo\fR configuration
++arguments.
++.PP
++
++.SH "SEE ALSO"
++.M AddressInfo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Print.n click-1.6.0-27/inst/share/man/mann/Print.n
+--- click-1.6.0/inst/share/man/mann/Print.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Print.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,53 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/print.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PRINT" n "11/Feb/2009" "Click"
++.SH "NAME"
++Print \- Click element;
++prints packet contents
++.SH "SYNOPSIS"
++\fBPrint\fR([LABEL, LENGTH, \fIkeywords\fR])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Prints up to LENGTH bytes of data from each packet, in hex, preceded by the
++LABEL text. Default LENGTH is 24.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "LENGTH" 8
++Number of bytes to print. Default is 24.
++.IP "" 8
++.IP "CONTENTS" 8
++Determines whether the packet data is printed. It may be `NONE' (do not print
++packet data), `HEX' (print packet data in hexadecimal), or `ASCII' (print
++packet data in plaintext). Default is `HEX'.
++.IP "" 8
++.IP "TIMESTAMP" 8
++Boolean. Determines whether to print each packet's timestamp in seconds since
++1970. Default is false.
++.IP "" 8
++.IP "PRINTANNO" 8
++Boolean. Determines whether to print each packet's user annotation bytes. Default is false.
++.IP "" 8
++.IP "CPU" 8
++Boolean; available only in the Linux kernel module. Determines whether to
++print the current CPU ID for every packet. Default is false.
++.IP "" 8
++.PP
++
++.SH "SEE ALSO"
++.M IPPrint "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PrioSched.n click-1.6.0-27/inst/share/man/mann/PrioSched.n
+--- click-1.6.0/inst/share/man/mann/PrioSched.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PrioSched.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,38 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/priosched.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PRIOSCHED" n "11/Feb/2009" "Click"
++.SH "NAME"
++PrioSched \- Click element;
++pulls from priority-scheduled inputs
++.SH "SYNOPSIS"
++PrioSched
++
++\fBPorts\fR: any number of inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Each time a pull comes in the output, \fBPrioSched\fR pulls from
++each of the inputs starting from input 0.
++The packet from the first successful pull is returned.
++This amounts to a strict priority scheduler.
++.PP
++The inputs usually come from Queues or other pull schedulers.
++\fBPrioSched\fR uses notification to avoid pulling from empty inputs.
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M RoundRobinSched n ,
++.M StrideSched n ,
++.M DRRSched n ,
++.M SimplePrioSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ProgressBar.n click-1.6.0-27/inst/share/man/mann/ProgressBar.n
+--- click-1.6.0/inst/share/man/mann/ProgressBar.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ProgressBar.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,137 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/progressbar.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PROGRESSBAR" n "11/Feb/2009" "Click"
++.SH "NAME"
++ProgressBar \- Click element;
++prints a progress bar to standard error
++.SH "SYNOPSIS"
++\fBProgressBar\fR(POSHANDLER [, SIZEHANDLER, \fIKEYWORDS\fR])
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads progress information from handlers, and displays an ASCII-art progress
++bar on standard error, indicating how much progress has been made and how much
++remains to go.
++.PP
++POSHANDLER and SIZEHANDLER are read handlers. Each of them should return a
++nonnegative real number. POSHANDLER is checked each time the progress bar
++displays; SIZEHANDLER is checked just once, the first time the progress bar
++comes up. Intuitively, POSHANDLER represents the "position"; the process is
++complete when its value equals the "size" returned by SIZEHANDLER. You may
++give multiple position and/or size handlers, as a space-separated list; their
++values are added together.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "FIXED_SIZE" 8
++Nonnegative real number. Used as the size when SIZEHANDLER is not supplied.
++Default is no fixed size.
++.IP "" 8
++.IP "BANNER" 8
++String. Print this string before the progress bar. For example, this might be
++a section of some filename. Default is empty.
++.IP "" 8
++.IP "UPDATE" 8
++Time in seconds (millisecond precision). The progress bar updates itself with
++this frequency. Default is 1/4 second.
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. The progress bar will not initially display itself if this is false.
++Default is true.
++.IP "" 8
++.IP "DELAY" 8
++Time in seconds (millisecond precision). Don't print a progress bar until at
++least DELAY seconds have passed. Use this to avoid trivial progress bars (that
++is, progress bars that immediately go to 100%). Default is no delay.
++.IP "" 8
++.IP "CHECK_STDOUT" 8
++Boolean. If true, and the standard output is connected to a terminal, then do
++not print a progress bar. Default is false.
++.IP "" 8
++.PP
++Only available in user-level processes.
++.PP
++.SH "EXAMPLES"
++This \fBProgressBar\fR shows how far into the file
++.M FromDump "n"
++has gotten:
++.PP
++.nf
++\& fd :: FromDump(~/largedump.gz) -> ...
++\& ProgressBar(fd.filepos, fd.filesize);
++.fi
++.PP
++Here are some example progress bars. The first form occurs when the file size
++is known; the second, when it is not known.
++.PP
++.nf
++\& 74% |************** | 23315KB 00:01 ETA
++\&
++\& | *** | 5184KB --:-- ETA
++.fi
++.PP
++
++
++
++.SH "NOTES"
++Code based on the progress bar in the OpenSSH project's \fBscp\fR program, whose
++authors are listed as Timo Rinne, Tatu Ylonen, Theo de Raadt, and Aaron
++Campbell.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBmark_stopped\fR (write-only)" 5
++When written, the progress bar changes to indicate that the transfer has
++stopped, possibly prematurely.
++.IP "" 5
++.IP "\fBmark_done\fR (write-only)" 5
++When written, the progress bar changes to indicate that the transfer has
++successfully completed.
++.IP "" 5
++.IP "\fBpos\fR (read-only)" 5
++Returns the progress bar's current position.
++.IP "" 5
++.IP "\fBsize\fR (read/write)" 5
++Returns or sets the progress bar's size value, which is used to compute how
++close the process is to completion.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Returns or sets the ACTIVE setting, a Boolean value. An inactive progress bar
++will not redraw itself.
++.IP "" 5
++.IP "\fBbanner\fR (read/write)" 5
++Returns or sets the BANNER string.
++.IP "" 5
++.IP "\fBposhandler\fR (read/write)" 5
++Returns or sets the read handlers used to read the position, as a
++space-separated list.
++.IP "" 5
++.IP "\fBsizehandler\fR (read/write)" 5
++Returns or sets the read handlers used to read the size, as a space-separated
++list.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, resets the progress bar to its initial state: the size is read
++again, for example. Also sets ACTIVE to true.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M FromDump "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PullNull.n click-1.6.0-27/inst/share/man/mann/PullNull.n
+--- click-1.6.0/inst/share/man/mann/PullNull.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PullNull.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,30 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/nullelement.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PULLNULL" n "11/Feb/2009" "Click"
++.SH "NAME"
++PullNull \- Click element;
++passes packets unchanged
++.SH "SYNOPSIS"
++\fBPullNull\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Responds to each pull request by pulling a packet from its input and returning
++that packet unchanged.
++.PP
++
++.SH "SEE ALSO"
++.M Null n ,
++.M PushNull "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PullSwitch.n click-1.6.0-27/inst/share/man/mann/PullSwitch.n
+--- click-1.6.0/inst/share/man/mann/PullSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PullSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,53 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/pullswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PULLSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++PullSwitch \- Click element;
++forwards pull requests to settable input
++.SH "SYNOPSIS"
++\fBPullSwitch\fR([INPUT])
++
++\fBPorts\fR: any number of inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++On every pull, \fBPullSwitch\fR returns the packet pulled from one of its input
++ports -- specifically, INPUT. The default INPUT is zero; negative INPUTs
++mean always return a null packet. You can change INPUT with a write handler.
++\fBPullSwitch\fR has an unlimited number of inputs.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBswitch\fR (read/write)" 5
++Return or set the K parameter.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_GET_SWITCH\fR (llrpc)" 5
++Argument is a pointer to an integer, in which the
++.M Switch "n" 's
++K parameter is
++stored.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_SET_SWITCH\fR (llrpc)" 5
++Argument is a pointer to an integer. Sets the K parameter to that integer.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M StaticPullSwitch n ,
++.M PrioSched n ,
++.M RoundRobinSched n ,
++.M StrideSched n ,
++.M Switch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PullTee.n click-1.6.0-27/inst/share/man/mann/PullTee.n
+--- click-1.6.0/inst/share/man/mann/PullTee.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PullTee.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/tee.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TEE, PULLTEE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Tee, PullTee \- Click elements;
++duplicates packets
++.SH "SYNOPSIS"
++\fBTee\fR([N])
++.br
++\fBPullTee\fR([N])
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBTee\fR sends a copy of each incoming packet out each output.
++.PP
++\fBPullTee\fR's input and its first output are pull; its other outputs are push.
++Each time the pull output pulls a packet, it
++sends a copy out the push outputs.
++.PP
++\fBTee\fR and \fBPullTee\fR have however many outputs are used in the configuration,
++but you can say how many outputs you expect with the optional argument
++N.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/PushNull.n click-1.6.0-27/inst/share/man/mann/PushNull.n
+--- click-1.6.0/inst/share/man/mann/PushNull.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/PushNull.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,29 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/nullelement.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "PUSHNULL" n "11/Feb/2009" "Click"
++.SH "NAME"
++PushNull \- Click element;
++passes packets unchanged
++.SH "SYNOPSIS"
++\fBPushNull\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Responds to each pushed packet by pushing it unchanged out its first output.
++.PP
++
++.SH "SEE ALSO"
++.M Null n ,
++.M PullNull "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Queue.n click-1.6.0-27/inst/share/man/mann/Queue.n
+--- click-1.6.0/inst/share/man/mann/Queue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Queue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,81 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/fullnotequeue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "QUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Queue \- Click element;
++stores packets in a FIFO queue
++.SH "SYNOPSIS"
++Queue
++.br
++\fBQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a first-in-first-out queue.
++Drops incoming packets if the queue already holds CAPACITY packets.
++The default for CAPACITY is 1000.
++.PP
++\fBQueue\fR notifies interested parties when it becomes empty and when a
++formerly-empty queue receives a packet. The empty notification takes place
++some time after the queue goes empty, to prevent thrashing for queues that
++hover around 1 or 2 packets long. This behavior is the same as that of
++.M NotifierQueue "n" .
++\fBQueue\fR additionally notifies interested parties that it is
++non-full, and when a formerly-full queue gains some free space. In all
++respects but notification, \fBQueue\fR behaves exactly like
++.M SimpleQueue "n" .
++.PP
++You may also use the old element name "FullNoteQueue".
++.PP
++\fBMultithreaded Click note:\fR \fBQueue\fR is designed to be used in an
++environment with at most one concurrent pusher and at most one concurrent
++puller. Thus, at most one thread pushes to the \fBQueue\fR at a time and at
++most one thread pulls from the \fBQueue\fR at a time. Different threads can
++push to and pull from the \fBQueue\fR concurrently, however. See
++.M MSQueue "n"
++for
++a queue that can support multiple concurrent pushers.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBhighwater_length\fR (read-only)" 5
++Returns the maximum number of packets that have ever been in the queue at once.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped by the queue so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++When written, resets the \f(CWdrops\fR and \f(CWhighwater_length\fR counters.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in the queue.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M SimpleQueue n ,
++.M NotifierQueue n ,
++.M MixedQueue n ,
++.M FrontDropQueue n ,
++.M MSQueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/QuitWatcher.n click-1.6.0-27/inst/share/man/mann/QuitWatcher.n
+--- click-1.6.0/inst/share/man/mann/QuitWatcher.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/QuitWatcher.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,23 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/quitwatcher.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "QUITWATCHER" n "11/Feb/2009" "Click"
++.SH "NAME"
++QuitWatcher \- Click element;
++stops router processing
++.SH "SYNOPSIS"
++\fBQuitWatcher\fR(ELEMENT, ...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stops router processing when at least one of the ELEMENTs is no longer
++scheduled.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RED.n click-1.6.0-27/inst/share/man/mann/RED.n
+--- click-1.6.0/inst/share/man/mann/RED.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RED.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,113 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/aqm/red.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RED" n "11/Feb/2009" "Click"
++.SH "NAME"
++RED \- Click element;
++drops packets according to RED
++.SH "SYNOPSIS"
++\fBRED\fR(MIN_THRESH, MAX_THRESH, MAX_P [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: aqm (core)
++.br
++.SH "DESCRIPTION"
++Implements the Random Early Detection packet dropping
++algorithm.
++.PP
++A \fBRED\fR element is associated with one or more Storage elements (usually
++Queues). It maintains a running average of the sum of the queue lengths, and
++marks packets with a probability proportional to that sum. By default, the
++Queues are found with flow-based router context. If the \fBRED\fR is a push element,
++it uses the nearest downstream Queues; if it is a pull element, it uses the
++nearest upstream Queues.
++.PP
++Marked packets are dropped, or emitted on output 1 if \fBRED\fR has two output
++ports.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "QUEUES" 8
++This argument is a space-separated list of Storage element names. \fBRED\fR will use
++those elements' queue lengths, rather than any elements found via flow-based
++router context.
++.IP "" 8
++.IP "STABILITY" 8
++Unsigned. This number determines how stable the average queue size is -- that
++is, how quickly it changes due to fluctuations in the instantaneous queue
++size. Higher numbers mean more stability. The corresponding conventional \fBRED\fR
++parameter is w_q; STABILITY equals -log_2(w_q).
++.IP "" 8
++STABILITY should equal
++.IP "" 8
++.nf
++\& -log_2 (1 - e^(-1/K)),
++.fi
++.IP "" 8
++where K is the link bandwidth in packets per second. Default STABILITY is 4.
++This is very low (unstable) for most purposes; it corresponds to a link
++bandwidth of roughly 15 packets per second, or a w_q of 0.25. The NS default
++setting for w_q is 0.002, corresponding to a STABILITY of roughly 9.
++.IP "" 8
++
++.PP
++The \fBRED\fR element implements the Gentle RED variant first proposed by Sally
++Floyd in October 1997.
++.PP
++.SH "EXAMPLES"
++
++.nf
++\& ... -> RED(5, 50, 0.02) -> Queue(200) -> ...
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBmin_thresh\fR (read/write)" 5
++Returns or sets the MIN_THRESH configuration parameter.
++.IP "" 5
++.IP "\fBmax_thresh\fR (read/write)" 5
++Returns or sets the MAX_THRESH configuration parameter.
++.IP "" 5
++.IP "\fBmax_p\fR (read/write)" 5
++Returns or sets the MAX_P configuration parameter.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped so far.
++.IP "" 5
++.IP "\fBqueues\fR (read-only)" 5
++Returns the Queues associated with this \fBRED\fR element, listed one per line.
++.IP "" 5
++.IP "\fBavg_queue_size\fR (read-only)" 5
++Returns the current average queue size.
++.IP "" 5
++.IP "\fBstats\fR (read-only)" 5
++Returns some human-readable statistics.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M AdaptiveRED n ,
++.M Queue n
++.PP
++Sally Floyd and Van Jacobson. \fIRandom Early Detection Gateways for
++Congestion Avoidance\fR. ACM Transactions on Networking, \fB1\fR(4), August
++1993, pp 397-413.
++.PP
++Sally Floyd. "Optimum functions for computing the drop
++probability", October 1997. \fBhttp://www.icir.org/floyd/REDfunc.txt\fR.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RFC2507Comp.n click-1.6.0-27/inst/share/man/mann/RFC2507Comp.n
+--- click-1.6.0/inst/share/man/mann/RFC2507Comp.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RFC2507Comp.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/rfc2507c.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RFC2507COMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++RFC2507Comp \- Click element;
++RFC2507 IPv4/TCP header compressor.
++.SH "SYNOPSIS"
++\fBRFC2507Comp\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Input packets need to be IPv4 (no ether header &c).
++It's OK if they're not TCP.
++.PP
++How to specify various kinds of output? There is not really
++a useful general standard. Perhaps emit each different format
++of output on a different output() and let further modules
++sort it out. Then we wouldn't be AGNOSTIC...
++.PP
++
++.SH "SEE ALSO"
++.M RFC2507Decomp "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RFC2507Decomp.n click-1.6.0-27/inst/share/man/mann/RFC2507Decomp.n
+--- click-1.6.0/inst/share/man/mann/RFC2507Decomp.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RFC2507Decomp.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,29 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/rfc2507d.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RFC2507DECOMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++RFC2507Decomp \- Click element;
++RFC2507 IPv4/TCP header decompressor.
++.SH "SYNOPSIS"
++\fBRFC2507Decomp\fR
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Input packets should be as produced by RFC2507c.
++Spits out IP packets.
++.PP
++
++.SH "SEE ALSO"
++.M RFC2507Comp "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RIPSend.n click-1.6.0-27/inst/share/man/mann/RIPSend.n
+--- click-1.6.0/inst/share/man/mann/RIPSend.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RIPSend.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/ripsend.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RIPSEND" n "11/Feb/2009" "Click"
++.SH "NAME"
++RIPSend \- Click element;
++periodically generates specified RIP II packet
++.SH "SYNOPSIS"
++\fBRIPSend\fR(SRC, DST, PREFIX, METRIC)
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Sends periodic RIP II packets with specified contents,
++including UDP and IP headers.
++
++.SH "EXAMPLES"
++Send out advertisements to net 18.26.4, indicating that
++route 18.26.4.24 knows how to get to net 10 with hop
++count 10:
++.PP
++.nf
++\& RIPSend(18.26.4.24, 18.26.4.255, 10.0.0.0/8, 10) ->
++\& EtherEncap(0x0008, 00:00:c0:ae:67:ef, ff:ff:ff:ff:ff:ff) ->
++\& ToDevice(eth0);
++.fi
++.PP
++
++
++
++.SH "NOTES"
++Note that this is just a tiny piece of a full RIP implementation.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RadixIPLookup.n click-1.6.0-27/inst/share/man/mann/RadixIPLookup.n
+--- click-1.6.0/inst/share/man/mann/RadixIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RadixIPLookup.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,85 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/radixiplookup.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RADIXIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++RadixIPLookup \- Click element;
++IP lookup using a radix trie
++.SH "SYNOPSIS"
++\fBRadixIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Performs IP lookup using a radix trie. The first level of the trie has 256
++buckets; each succeeding level has 16. The maximum number of levels that will
++be traversed is thus 7.
++.PP
++Expects a destination IP address annotation with each packet. Looks up that
++address in its routing table, using longest-prefix-match, sets the destination
++annotation to the corresponding GW (if specified), and emits the packet on the
++indicated OUTput port.
++.PP
++Each argument is a route, specifying a destination and mask, an optional
++gateway IP address, and an output port.
++.PP
++Uses the
++.M IPRouteTable "n"
++interface; see
++.M IPRouteTable "n"
++for description.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtable\fR (read-only)" 5
++Outputs a human-readable version of the current routing table.
++.IP "" 5
++.IP "\fBlookup\fR (read-only)" 5
++Reports the OUTput port and GW corresponding to an address.
++.IP "" 5
++.IP "\fBadd\fR (write-only)" 5
++Adds a route to the table. Format should be `\f(CWADDR/MASK [GW] OUT\fR'. Should
++fail if a route for \f(CWADDR/MASK\fR already exists, but currently does not.
++.IP "" 5
++.IP "\fBset\fR (write-only)" 5
++Sets a route, whether or not a route for the same prefix already exists.
++.IP "" 5
++.IP "\fBremove\fR (write-only)" 5
++Removes a route from the table. Format should be `\f(CWADDR/MASK\fR'.
++.IP "" 5
++.IP "\fBctrl\fR (write-only)" 5
++Adds or removes a group of routes. Write `\f(CWadd\fR/\f(CWset ADDR/MASK [GW] OUT\fR' to
++add a route, and `\f(CWremove ADDR/MASK\fR' to remove a route. You can supply
++multiple commands, one per line; all commands are executed as one atomic
++operation.
++.IP "" 5
++.PP
++
++.SH "NOTES"
++See
++.M IPRouteTable "n"
++for a performance comparison of the various IP routing
++elements.
++.PP
++
++.SH "SEE ALSO"
++.M IPRouteTable n ,
++.M DirectIPLookup n ,
++.M RangeIPLookup n ,
++.M StaticIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup n ,
++.M LinuxIPLookup "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RandomBitErrors.n click-1.6.0-27/inst/share/man/mann/RandomBitErrors.n
+--- click-1.6.0/inst/share/man/mann/RandomBitErrors.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RandomBitErrors.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,49 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/randomerror.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RANDOMBITERRORS" n "11/Feb/2009" "Click"
++.SH "NAME"
++RandomBitErrors \- Click element;
++changes packet data with some probability
++.SH "SYNOPSIS"
++\fBRandomBitErrors\fR(P [, KIND, ACTIVE])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Change each bit in each packet with probability P. The KIND parameter
++determines the kind of change. `flip' (the default) flips bits, `set' sets
++bits to one, and `clear' sets bits to zero.
++.PP
++\fBRandomBitErrors\fR can be active or inactive. It only changes bits when
++active. It starts out active by default, but if you pass `false' for the
++ACTIVE parameter, it will start out inactive.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBp_bit_error\fR (read/write)" 5
++Returns or sets the P probability parameter.
++.IP "" 5
++.IP "\fBerror_kind\fR (read/write)" 5
++Returns or sets the KIND parameter.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Makes the element active or inactive.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RandomSample "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RandomSample.n click-1.6.0-27/inst/share/man/mann/RandomSample.n
+--- click-1.6.0/inst/share/man/mann/RandomSample.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RandomSample.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,68 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/randomsample.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RANDOMSAMPLE" n "11/Feb/2009" "Click"
++.SH "NAME"
++RandomSample \- Click element;
++samples packets with some probability
++.SH "SYNOPSIS"
++\fBRandomSample\fR([P, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Samples packets with probability P. One out of 1/P packets are sent to the
++first output. The remaining packets are dropped, unless the element has two
++outputs, in which case they are emitted on output 1.
++.PP
++If you don't specify P, you must supply one of the SAMPLE and DROP keyword
++arguments.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SAMPLE \fIP\fR" 8
++Sets the sampling probability to \fIP\fR.
++.IP "" 8
++.IP "DROP \fIQ\fR" 8
++The element will drop packets with probability \fIQ\fR. Same as suppling (1 -
++\fIQ\fR) as the sampling probability.
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. \fBRandomSample\fR is active or inactive; when inactive, it sends all
++packets to output 0. Default is true (active).
++.IP "" 8
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBsampling_prob\fR (read/write)" 5
++Returns or sets the sampling probability.
++.IP "" 5
++.IP "\fBdrop_prob\fR (read/write)" 5
++Returns or sets the drop probability, which is 1 minus the sampling
++probability.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Makes the element active or inactive.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RandomBitErrors "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RandomSource.n click-1.6.0-27/inst/share/man/mann/RandomSource.n
+--- click-1.6.0/inst/share/man/mann/RandomSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RandomSource.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,29 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/randomsource.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RANDOMSOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++RandomSource \- Click element;
++generates random packets whenever scheduled
++.SH "SYNOPSIS"
++\fBRandomSource\fR(LENGTH)
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Creates packets, of the indicated length, filled with random bytes.
++Packets' timestamp annotations are set to the current time.
++.PP
++
++.SH "SEE ALSO"
++.M InfiniteSource "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RandomSwitch.n click-1.6.0-27/inst/share/man/mann/RandomSwitch.n
+--- click-1.6.0/inst/share/man/mann/RandomSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RandomSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,31 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/randomswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RANDOMSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++RandomSwitch \- Click element;
++sends packets to random outputs
++.SH "SYNOPSIS"
++RandomSwitch
++
++\fBPorts\fR: one input, one or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pushes each arriving packet to one of the N outputs, choosing outputs randomly.
++.PP
++
++.SH "SEE ALSO"
++.M Switch n ,
++.M StrideSwitch n ,
++.M RoundRobinSwitch n ,
++.M HashSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RangeIPLookup.n click-1.6.0-27/inst/share/man/mann/RangeIPLookup.n
+--- click-1.6.0/inst/share/man/mann/RangeIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RangeIPLookup.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,96 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/rangeiplookup.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RANGEIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++RangeIPLookup \- Click element;
++IP routing lookup through binary search in a very compact table
++.SH "SYNOPSIS"
++\fBRangeIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel, bsdmodule
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects a destination IP address annotation with each packet. Looks up that
++address in its routing table, using longest-prefix-match, sets the destination
++annotation to the corresponding GW (if specified), and emits the packet on the
++indicated OUTput port.
++.PP
++Each argument is a route, specifying a destination and mask, an optional
++gateway IP address, and an output port. No destination-mask pair should occur
++more than once.
++.PP
++\fBRangeIPLookup\fR aims at achieving high lookup speeds through exploiting the CPU
++cache locality. The routing table is expanded into a very small lookup
++structure, typically occupying less then 4 bytes per IP prefix. As an example,
++a lookup structure corresponding to a routing table with 167000 entries (a
++realistic snapshot taken from a core Internet router) occupies only around
++512 KBytes of RAM. Depending on how sucessfully the CPU cache
++affinity can be maintained, worst-case lookup rates exceeding 20 million
++lookups per second can be achieved using modern commodity CPUs.
++.PP
++\fBRangeIPLookup\fR maintains a large
++.M DirectIPLookup "n"
++table as well as its own
++tables. Although this subsidiary table is only accessed during route updates,
++it significantly adds to \fBRangeIPLookup\fR's total memory footprint.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtable\fR (read-only)" 5
++Outputs a human-readable version of the current routing table.
++.IP "" 5
++.IP "\fBlookup\fR (read-only)" 5
++Reports the OUTput port and GW corresponding to an address.
++.IP "" 5
++.IP "\fBadd\fR (write-only)" 5
++Adds a route to the table. Format should be `\f(CWADDR/MASK [GW] OUT\fR'.
++Fails if a route for \f(CWADDR/MASK\fR already exists.
++.IP "" 5
++.IP "\fBset\fR (write-only)" 5
++Sets a route, whether or not a route for the same prefix already exists.
++.IP "" 5
++.IP "\fBremove\fR (write-only)" 5
++Removes a route from the table. Format should be `\f(CWADDR/MASK\fR'.
++.IP "" 5
++.IP "\fBctrl\fR (write-only)" 5
++Adds or removes a group of routes. Write `\f(CWadd\fR/\f(CWset ADDR/MASK [GW] OUT\fR' to
++add a route, and `\f(CWremove ADDR/MASK\fR' to remove a route. You can supply
++multiple commands, one per line; all commands are executed as one atomic
++operation.
++.IP "" 5
++.IP "\fBflush\fR (write-only)" 5
++Clears the entire routing table in a single atomic operation.
++.IP "" 5
++.PP
++
++.SH "NOTES"
++See
++.M IPRouteTable "n"
++for a performance comparison of the various IP routing
++elements.
++.PP
++
++.SH "SEE ALSO"
++.M IPRouteTable n ,
++.M RadixIPLookup n ,
++.M DirectIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup n ,
++.M StaticIPLookup n ,
++.M LinuxIPLookup "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RatedSource.n click-1.6.0-27/inst/share/man/mann/RatedSource.n
+--- click-1.6.0/inst/share/man/mann/RatedSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RatedSource.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,99 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/ratedsource.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RATEDSOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++RatedSource \- Click element;
++generates packets at specified rate
++.SH "SYNOPSIS"
++\fBRatedSource\fR([DATA, RATE, LIMIT, ACTIVE, \fIKEYWORDS\fR])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Creates packets consisting of DATA, emitting at most LIMIT such packets out
++its single output at a rate of RATE packets per second. When used as a push
++element, \fBRatedSource\fR will send a maximum of one packet per scheduling, so very
++high RATEs may not be achievable. If LIMIT is negative, sends packets forever.
++Will send packets only if ACTIVE is true. Default DATA is at least 64 bytes
++long. Default RATE is 10. Default LIMIT is -1 (send packets forever). Default
++ACTIVE is true.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DATA" 8
++String. Same as the DATA argument.
++.IP "" 8
++.IP "DATASIZE" 8
++Integer. If set, ensures the outgoing packet contains at least this many bytes.
++.IP "" 8
++.IP "RATE" 8
++Integer. Same as the RATE argument.
++.IP "" 8
++.IP "LIMIT" 8
++Integer. Same as the LIMIT argument.
++.IP "" 8
++.IP "ACTIVE" 8
++Boolean. Same as the ACTIVE? argument.
++.IP "" 8
++.IP "STOP" 8
++Boolean. If true, then stop the driver once LIMIT packets are sent. Default is
++false.
++.IP "" 8
++.PP
++To generate a particular repeatable traffic pattern, use this element's
++\fBrate\fR and \fBactive\fR handlers in conjunction with
++.M PokeHandlers "n" .
++.PP
++.SH "EXAMPLES"
++
++.nf
++\& RatedSource(\e<0800>, 10, 1000) -> Queue -> ...
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the total number of packets that have been generated.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++Resets the number of generated packets to 0. The \fBRatedSource\fR will then
++generate another LIMIT packets (if it is active).
++.IP "" 5
++.IP "\fBdata\fR (read/write)" 5
++Returns or sets the DATA parameter.
++.IP "" 5
++.IP "\fBdatasize\fR (read/write)" 5
++Returns or sets the DATASIZE parameter.
++.IP "" 5
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.IP "\fBlimit\fR (read/write)" 5
++Returns or sets the LIMIT parameter. Negative numbers mean no limit.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++Makes the element active or inactive.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M InfiniteSource n ,
++.M PokeHandlers "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RatedSplitter.n click-1.6.0-27/inst/share/man/mann/RatedSplitter.n
+--- click-1.6.0/inst/share/man/mann/RatedSplitter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RatedSplitter.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,71 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/ratedsplitter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RATEDSPLITTER" n "11/Feb/2009" "Click"
++.SH "NAME"
++RatedSplitter \- Click element;
++splits flow of packets at specified rate
++.SH "SYNOPSIS"
++\fBRatedSplitter\fR(RATE)
++
++\fBPorts\fR: 1 input, 2 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBRatedSplitter\fR has two output ports. All incoming packets up to a maximum of
++RATE packets per second are emitted on output port 0. Any remaining packets
++are emitted on output port 1. Unlike
++.M Meter "n" ,
++RATE packets per second are
++emitted on output port 0 even when the input rate is greater than RATE.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& rs :: RatedSplitter(2000);
++.fi
++.PP
++Split packets on port 0 at 2000 packets per second.
++.PP
++.nf
++\& elementclass RatedSampler {
++\& input -> rs :: RatedSplitter(2000);
++\& rs [0] -> t :: Tee;
++\& t [0] -> [0] output;
++\& t [1] -> [1] output;
++\& rs [1] -> [0] output;
++\& };
++.fi
++.PP
++In the above example, RatedSampler is a compound element that samples input
++packets at 2000 packets per second. All traffic is emitted on output 0; a
++maximum of 2000 packets per second are emitted on output 1 as well.
++.PP
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBrate\fR (read/write)" 5
++rate of splitting
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M BandwidthRatedSplitter n ,
++.M ProbSplitter n ,
++.M Meter n ,
++.M Shaper n ,
++.M RatedUnqueue n ,
++.M Tee "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RatedUnqueue.n click-1.6.0-27/inst/share/man/mann/RatedUnqueue.n
+--- click-1.6.0/inst/share/man/mann/RatedUnqueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RatedUnqueue.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/ratedunqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RATEDUNQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++RatedUnqueue \- Click element;
++pull-to-push converter
++.SH "SYNOPSIS"
++\fBRatedUnqueue\fR(RATE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets at the given RATE in packets per second, and pushes them out
++its single output.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBrate\fR (read/write)" 5
++
++.PP
++
++.SH "SEE ALSO"
++.M BandwidthRatedUnqueue n ,
++.M Unqueue n ,
++.M Shaper n ,
++.M RatedSplitter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RawSocket.n click-1.6.0-27/inst/share/man/mann/RawSocket.n
+--- click-1.6.0/inst/share/man/mann/RawSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RawSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,72 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/rawsocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "RAWSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++RawSocket \- Click element;
++transports raw IP packets via safe raw sockets (user-level)
++.SH "SYNOPSIS"
++\fBRawSocket\fR("TCP", <TCP source port number> [, \fIKEYWORDS\fR])
++.br
++\fBRawSocket\fR("UDP", <UDP source port number> [, \fIKEYWORDS\fR])
++.br
++\fBRawSocket\fR("GRE", <GRE key or PPTP call ID> [, \fIKEYWORDS\fR])
++.br
++\fBRawSocket\fR("ICMP", <ICMP identifier> [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Reads data from and writes data to a raw IPv4 socket. The raw IPv4
++socket may optionally be bound to a source port number in the case of
++TCP/UDP, a GRE key or PPTP call ID in the case of GRE, or an
++identifier in the case of ICMP. Binding a port to a raw IPv4 socket to
++reserve it and suppress TCP RST and ICMP Unreachable errors, is
++specific to PlanetLab Linux.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SNAPLEN" 8
++Unsigned integer. Maximum packet length. This value
++represents the MRU of the \fBRawSocket\fR if it is used as a
++packet source. If the MRU is violated by the peer, i.e. if a packet
++longer than SNAPLEN is sent, the connection may be terminated.
++.IP "" 8
++.IP "PROPER" 8
++Boolean. PlanetLab specific. If true and Click has been configured
++--with-proper, use Proper to bind a reserved port.
++.IP "" 8
++.IP "HEADROOM" 8
++Unsigned Integer. Amount of headroom to reserve in packets created
++by this element. This could be useful for encapsulation protocols
++which add headers to the packet, and can avoid expensive push
++operations later in the packet's life.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& RawSocket(UDP, 53) -> ...
++\&
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RoundRobinIPMapper.n click-1.6.0-27/inst/share/man/mann/RoundRobinIPMapper.n
+--- click-1.6.0/inst/share/man/mann/RoundRobinIPMapper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RoundRobinIPMapper.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,38 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/rripmapper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ROUNDROBINIPMAPPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++RoundRobinIPMapper \- Click element;
++round-robin mapper for
++.M IPRewriter n
++.SH "SYNOPSIS"
++\fBRoundRobinIPMapper\fR(PATTERN1, ..., PATTERNn)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Works in tandem with
++.M IPRewriter "n"
++to provide round-robin rewriting. This is
++useful, for example, in load-balancing applications. Implements the
++IPMapper interface.
++.PP
++Responds to mapping requests from an
++.M IPRewriter "n"
++by trying the PATTERNs in
++round-robin order and returning the first successfully created mapping.
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M TCPRewriter n ,
++.M IPRewriterPatterns "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RoundRobinSched.n click-1.6.0-27/inst/share/man/mann/RoundRobinSched.n
+--- click-1.6.0/inst/share/man/mann/RoundRobinSched.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RoundRobinSched.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,39 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/rrsched.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ROUNDROBINSCHED" n "11/Feb/2009" "Click"
++.SH "NAME"
++RoundRobinSched \- Click element;
++pulls from round-robin inputs
++.SH "SYNOPSIS"
++RoundRobinSched
++
++\fBPorts\fR: one output, zero or more inputs
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Each time a pull comes in the output, pulls from its inputs
++in turn until one produces a packet. When the next pull
++comes in, it starts from the input after the one that
++last produced a packet. This amounts to a round robin
++scheduler.
++.PP
++The inputs usually come from Queues or other pull schedulers.
++\fBRoundRobinSched\fR uses notification to avoid pulling from empty inputs.
++.PP
++
++.SH "SEE ALSO"
++.M PrioSched n ,
++.M StrideSched n ,
++.M DRRSched n ,
++.M RoundRobinSwitch n ,
++.M SimpleRoundRobinSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RoundRobinSwitch.n click-1.6.0-27/inst/share/man/mann/RoundRobinSwitch.n
+--- click-1.6.0/inst/share/man/mann/RoundRobinSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RoundRobinSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,33 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/rrswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ROUNDROBINSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++RoundRobinSwitch \- Click element;
++sends packets to round-robin outputs
++.SH "SYNOPSIS"
++RoundRobinSwitch
++
++\fBPorts\fR: one input, one or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pushes each arriving packet to one of the N outputs. The next packet
++will be pushed to the following output in round-robin order.
++.PP
++
++.SH "SEE ALSO"
++.M StrideSwitch n ,
++.M Switch n ,
++.M HashSwitch n ,
++.M RandomSwitch n ,
++.M RoundRobinSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/RoundTripCycleCount.n click-1.6.0-27/inst/share/man/mann/RoundTripCycleCount.n
+--- click-1.6.0/inst/share/man/mann/RoundTripCycleCount.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/RoundTripCycleCount.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,50 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/rtcycles.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ROUNDTRIPCYCLECOUNT" n "11/Feb/2009" "Click"
++.SH "NAME"
++RoundTripCycleCount \- Click element;
++measures round trip cycles on a push or pull path
++.SH "SYNOPSIS"
++\fBRoundTripCycleCount\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Measures the number of CPU cycles it takes for a push or pull to come back
++to the element. This is a good indication of how much CPU is spent on the
++Click path after or before this element.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBpackets\fR (read-only)" 5
++Returns the number of packets that have passed.
++.IP "" 5
++.IP "\fBcycles\fR (read-only)" 5
++Returns the accumulated round-trip cycles for all passing packets.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets \f(CWpackets\fR and \f(CWcycles\fR counters to zero when written.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M SetCycleCount n ,
++.M CycleCountAccum n ,
++.M SetPerfCount n ,
++.M PerfCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ScheduleInfo.n click-1.6.0-27/inst/share/man/mann/ScheduleInfo.n
+--- click-1.6.0/inst/share/man/mann/ScheduleInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ScheduleInfo.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,74 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../include/click/standard/scheduleinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SCHEDULEINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++ScheduleInfo \- Click element;
++specifies scheduling parameters
++.SH "SYNOPSIS"
++\fBScheduleInfo\fR(ELEMENT PARAM, ...)
++
++\fBPorts\fR: None
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Provides scheduling parameters for specified elements. Each configuration
++argument has the form `ELEMENT PARAM', meaning that the element
++named ELEMENT has scheduling parameter PARAM. Scheduling
++parameters are real numbers that set how often one element should be
++scheduled in relation to another. For example,
++if elements A and B have
++scheduling parameters 2 and 0.5, respectively, then A will be scheduled
++2/0.5 = 4 times as often as B. The default scheduling parameter is 1.
++.PP
++\fBScheduleInfo\fR elements inside a compound element can specify scheduling
++parameters for that compound's components.
++Outer \fBScheduleInfo\fR elements
++can specify a ``scheduling parameter'' for the compound
++element as a whole. This ``scheduling parameter'' is really a scaling
++factor affecting the compound's components. For example, consider this
++configuration,
++.PP
++.nf
++\& elementclass Compound {
++\& i :: InfiniteSource -> output;
++\& ScheduleInfo(i 0.5);
++\& }
++\& c :: Compound -> Discard;
++\& ScheduleInfo(c 4);
++.fi
++.PP
++which is the same as the following configuration, after compound elements
++are expanded.
++.PP
++.nf
++\& c/i :: InfiniteSource -> Discard@3 :: Discard;
++\& c/ScheduleInfo@2 :: ScheduleInfo(i 0.5);
++\& ScheduleInfo@4 :: ScheduleInfo(c 4);
++.fi
++.PP
++The name of the first \fBScheduleInfo\fR element starts with `c/', so it is
++used to look up scheduling parameters for elements named `c/\fIwhatever\fR'.
++(This includes all components of the compound element `c'.)
++The second \fBScheduleInfo\fR element, however, has no slash in its name,
++so it is used to look up all scheduling parameters,
++including scaling factors for compound elements.
++The InfiniteSource's final scaling parameter will be 2:
++the scaling factor 4 times the local scheduling parameter 0.5.
++.PP
++An outer \fBScheduleInfo\fR element can override local scheduling parameters.
++For example, if the second \fBScheduleInfo\fR element above was
++.PP
++.nf
++\& ScheduleInfo@4 :: ScheduleInfo(c 4, c/i 10.5)
++.fi
++.PP
++then the InfiniteSource's final scaling parameter would be 10.5.
++
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ScheduleLinux.n click-1.6.0-27/inst/share/man/mann/ScheduleLinux.n
+--- click-1.6.0/inst/share/man/mann/ScheduleLinux.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ScheduleLinux.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,30 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/schedulelinux.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SCHEDULELINUX" n "11/Feb/2009" "Click"
++.SH "NAME"
++ScheduleLinux \- Click element;
++returns to Linux scheduler
++.SH "SYNOPSIS"
++ScheduleLinux
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Returns to Linux's scheduler every time it is scheduled by Click. Use
++.M ScheduleInfo "n"
++to specify how often this should happen.
++.PP
++
++.SH "SEE ALSO"
++.M ScheduleInfo "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Script.n click-1.6.0-27/inst/share/man/mann/Script.n
+--- click-1.6.0/inst/share/man/mann/Script.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Script.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,267 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/script.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SCRIPT" n "11/Feb/2009" "Click"
++.SH "NAME"
++Script \- Click element;
++script a Click router configuration
++.SH "SYNOPSIS"
++\fBScript\fR(INSTRUCTIONS...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++The \fBScript\fR element implements a simple scripting language useful for
++controlling Click configurations. Scripts can set variables, call handlers,
++wait for prodding from other elements, and stop the router.
++.PP
++
++.SH "INSTRUCTIONS"
++Each configuration argument is an \fIinstruction\fR (except for optional
++keywords; see below). \fBScript\fR generally processes these instructions
++sequentially.
++.PP
++
++.SS "Handler Instructions"
++In all cases, text arguments are subject to substitutions; see below.
++.PP
++
++.IP "\&'\f(CWset\fR VAR TEXT'" 8
++Sets the script variable $VAR to TEXT.
++.IP "" 8
++.IP "\&'\f(CWinit\fR VAR TEXT'" 8
++Initializes the script variable $VAR to TEXT. This assignment happens exactly
++once, when the \fBScript\fR element is initialized; later the instruction has no
++effect.
++.IP "" 8
++.IP "\&'\f(CWprint\fR [>FILE | >>FILE] [TEXT | HANDLER]'" 8
++Prints text, or the result of calling a read handler, followed by a newline.
++At user level, the text is written to the standard output, except that if the
++argument begins with > or >>, then the text is written or appended to the
++specified FILE. In the kernel, the text is written to the system log.
++.IP "" 8
++If \f(CWprint\fR's argument starts with a letter, '@', or '_', then it is treated
++as a read handler. Otherwise, it is treated as quoted text; \fBScript\fR prints the
++unquoted version. For example, assuming the 'c.count' read handler
++returns "0":
++.IP "" 8
++.nf
++\& print c.count => 0
++\& print "c.count" => c.count
++\& print '"c.count"' => "c.count"
++\& set x c.count
++\& print $x => c.count
++\& print $($x) => 0
++.fi
++.IP "" 8
++
++
++.IP "\&'\f(CWread\fR HANDLER [ARG...]'" 8
++Call a read handler and print the handler name and result to standard error. (In the kernel, the result is printed to the system log.) For example, the
++configuration 'Idle -> c::Counter -> Idle; \fBScript\fR(read c.count)' would print
++print this to standard error:
++.IP "" 8
++.nf
++\& c.count:
++\& 0
++.fi
++.IP "" 8
++Contrast the '\f(CWprint\fR' instruction.
++.IP "" 8
++
++.IP "\&'\f(CWwrite\fR HANDLER [ARG...]'" 8
++Call a write handler. The handler's return status is available in following
++instructions as the '$?' variable.
++.IP "" 8
++.IP "\&'\f(CWreadq\fR HANDLER [ARG...]', '\f(CWwriteq\fR HANDLER [ARG...]'" 8
++Same as \f(CWread\fR and \f(CWwrite\fR, but removes one layer of quoting from the ARGs
++before calling the handler.
++.IP "" 8
++.PP
++
++.SS "Blocking Instructions"
++
++
++.IP "\&'\f(CWpause\fR [COUNT]'" 8
++Block until the \fBScript\fR element's 'step' handler is called COUNT times. COUNT
++defaults to 1.
++.IP "" 8
++.IP "\&'\f(CWwait\fR TIME'" 8
++Wait for TIME seconds, or until a step, whichever comes first; then go to the
++next instruction. TIME has microsecond precision.
++.IP "" 8
++.PP
++
++.SS "Control Instructions"
++
++
++.IP "\&'\f(CWlabel\fR LABEL'" 8
++Defines a label named LABEL.
++.IP "" 8
++.IP "\&'\f(CWgoto\fR LABEL [CONDITION]'" 8
++Transfers control to the named label. \fBScript\fR elements detect loops; if an
++element's script appears to be looping (it executes 1000 goto instructions
++without blocking), the script is disabled. If CONDITION is supplied, then the
++branch executes only when CONDITION is true.
++.IP "" 8
++As a special case, '\f(CWgoto exit [CONDITION]\fR' or '\f(CWgoto end [CONDITION]\fR'
++ends execution of the script, much like an '\f(CWexit\fR' or '\f(CWend\fR' instruction.
++.IP "" 8
++.IP "\&'\f(CWloop\fR'" 8
++Transfers control to the first instruction.
++.IP "" 8
++.IP "\&'\f(CWreturn\fR [VALUE]'" 8
++End execution of this script, returning VALUE. This instruction is most
++useful for passive scripts; VALUE will be returned as the value of the \f(CWrun\fR
++handler.
++.IP "" 8
++.IP "\&'\f(CWexit\fR', '\f(CWend\fR'" 8
++End execution of this script. For signal scripts, the '\f(CWexit\fR' instruction
++\fIdoes not\fR reinstall the script, whereas the '\f(CWend\fR' instruction does.
++.IP "" 8
++.PP
++
++.SH "SCRIPT TYPES"
++Scripts come in several types, including active scripts, which start running
++as soon as the configuration is loaded; passive scripts, which run only when
++prodded; signal scripts, which run in response to a signal; and driver
++scripts, which are active scripts that also control when the driver stops.
++The optional TYPE keyword argument is used to select a script type. The types
++are:
++.PP
++
++
++.IP "\f(CWACTIVE\fR" 8
++An active script starts running as soon as the router is initialized. This is
++the default.
++.IP "" 8
++.IP "\f(CWPASSIVE\fR" 8
++A passive script runs in response to a handler, namely the \f(CWrun\fR handler.
++Passive scripts can help build complex handlers from existing simple ones; for
++example, here's a passive script whose \f(CWs.run\fR read handler returns the sum
++of two Counter handlers.
++.IP "" 8
++.nf
++\& ... c1 :: Counter ... c2 :: Counter ...
++\& s :: Script(TYPE PASSIVE,
++\& return $(add $(c1.count) $(c2.count)))
++.fi
++.IP "" 8
++Within the script, the \f(CWrun\fR handler's arguments, if any, are available
++via the \f(CW$args\fR variable. The first, second, and so forth space-separated
++portions of \f(CW$args\fR are available via the \f(CW$1\fR, \f(CW$2\fR, ... variables.
++.nf
++\&
++.fi
++.IP "" 8
++
++
++.IP "\f(CWDRIVER\fR" 8
++A driver script manages the Click driver's stop events. See
++.M DriverManager "n"
++for
++more information.
++.IP "" 8
++.IP "\f(CWSIGNAL\fR SIGNO..." 8
++User-level only: A signal script runs in response to the signal(s) specified
++by the SIGNO argument(s). Each SIGNO can be an integer or a signal name, such
++as INT or HUP. Soon after the driver receives a named signal, this script
++will run. The signal handler is automatically blocked until the script runs.
++The signal script will be reinstalled atomically as long as the script
++completes without blocking. If it blocks, however, the signal script will not
++be installed from the blocking point until the script completes. If multiple
++\fBScript\fR elements select the same signal, all the scripts will run.
++.IP "" 8
++.PP
++
++.SH "SUBSTITUTIONS"
++Text in most \fBScript\fR instructions undergoes variable substitution. References
++to script variables, such as '\f(CW$x\fR', are replaced by the variable text.
++Additionally, the form '\f(CW$(HANDLER [ARG...])\fR' can be used to interpolate a
++read handler's value. Variable and handler references can be nested inside
++a '\f(CW$(...)\fR' block. For example, the following script will print 0, 1, 2, 3,
++and 4 on separate lines, then exit. Note the use of \fBScript\fR's arithmetic
++handlers.
++.PP
++.nf
++\& s :: Script(set x 0,
++\& label begin_loop,
++\& print $x,
++\& set x $(s.add $x 1),
++\& goto begin_loop $(s.lt $x 5),
++\& stop);
++.fi
++.PP
++This can be further shortened since local handler references do not require
++the element name. Thus, "$(s.add ...)" can be written "$(add ...)", as below.
++.PP
++.nf
++\& Script(set x 0,
++\& label begin_loop,
++\& print $x,
++\& set x $(add $x 1),
++\& goto begin_loop $(lt $x 5),
++\& stop);
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBstep\fR (write-only)" 5
++Advance the instruction pointer past the current blocking instruction (\f(CWpause\fR or \f(CWwait\fR). A numeric argument will step past that many blocking instructions.
++.IP "" 5
++.IP "\fBgoto\fR (write-only)" 5
++Move the instruction pointer to the specified label.
++.IP "" 5
++.IP "\fBrun\fR (read/write)" 5
++Run the script. If the script ends with a '\f(CWreturn\fR' instruction, then the
++handler returns with that value.
++.IP "" 5
++.IP "\fBadd\fR (read with parameters)" 5
++Useful for arithmetic. Adds a space-separated list of integers; for example,
++\&'\f(CWadd 10 5 2\fR' returns "\f(CW17\fR". (At user level, the arithmetic and
++comparison operators can parse floating-point numbers as well as integers.)
++.IP "" 5
++.IP "\fBsub\fR (read with parameters)" 5
++Subtracts a space-separated list of
++numbers; for example, '\f(CWsub 10 5 2\fR' returns
++"\f(CW3\fR".
++.IP "" 5
++.IP "\fBmul, div, idiv\fR (read with parameters)" 5
++Multiplies or divides a space-separated list of numbers and returns the
++result. At user level, the '\f(CWidiv\fR' handler truncates its result to an
++integer and returns that, whereas the '\f(CWdiv\fR' handler returns a
++floating-point number; in the kernel, '\f(CWidiv\fR' and '\f(CWdiv\fR' both perform
++integer division.
++.IP "" 5
++.IP "\fBeq, ne, lt, gt, le, ge\fR (read with parameters)" 5
++Compares two parameters and return the result. For example, '\f(CWeq 10
++0xA\fR' returns "\f(CWtrue\fR", but '\f(CWle 9 8\fR' returns "\f(CWfalse\fR". If either
++parameter cannot be interpreted as a number, performs a string comparison.
++For example, '\f(CWeq 10x 10x\fR' return "\f(CWtrue\fR".
++.IP "" 5
++.IP "\fBnot\fR (read with parameters)" 5
++Useful for true/false operations. Parses its parameter as a Boolean and
++returns its negation.
++.IP "" 5
++.IP "\fBsprintf\fR (read with parameters)" 5
++Parses its parameters as a space-separated list of arguments. The first
++argument is a format string; the remaining arguments are formatted
++accordingly. For example, '\f(CWsprintf "%05x" 127\fR' returns "\f(CW0007F\fR".
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M DriverManager "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetAnnoByte.n click-1.6.0-27/inst/share/man/mann/SetAnnoByte.n
+--- click-1.6.0/inst/share/man/mann/SetAnnoByte.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetAnnoByte.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/setannobyte.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETANNOBYTE" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetAnnoByte \- Click element;
++sets packet user annotations
++.SH "SYNOPSIS"
++\fBSetAnnoByte\fR(OFFSET, VALUE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Sets each packet's user annotation byte at OFFSET to VALUE, an integer
++0..255. Permissible values for OFFSET are 0 to n-1, inclusive, where
++n is typically 24.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBoffset\fR (read-only)" 5
++Returns OFFSET
++.IP "" 5
++.IP "\fBvalue\fR (read-only)" 5
++Returns VALUE
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Paint "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetCRC32.n click-1.6.0-27/inst/share/man/mann/SetCRC32.n
+--- click-1.6.0/inst/share/man/mann/SetCRC32.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetCRC32.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,28 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/setcrc32.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETCRC32" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetCRC32 \- Click element;
++calculates CRC32 and prepends to packet
++.SH "SYNOPSIS"
++\fBSetCRC32\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Computes a CRC32 over each packet and appends the 4 CRC
++bytes to the packet.
++
++.SH "SEE ALSO"
++.M CheckCRC32 "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetCycleCount.n click-1.6.0-27/inst/share/man/mann/SetCycleCount.n
+--- click-1.6.0/inst/share/man/mann/SetCycleCount.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetCycleCount.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/setcyclecount.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETCYCLECOUNT" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetCycleCount \- Click element;
++stores cycle count in annotation
++.SH "SYNOPSIS"
++\fBSetCycleCount\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Stores the current cycle count in an annotation in each packet. In
++combination with
++.M CycleCountAccum "n" ,
++this lets you measure how many cycles it
++takes a packet to pass from one point to another.
++.PP
++
++.SH "NOTES"
++A packet has room for either exactly one cycle count or exactly one
++performance metric.
++.PP
++
++.SH "SEE ALSO"
++.M CycleCountAccum n ,
++.M RoundTripCycleCount n ,
++.M SetPerfCount n ,
++.M PerfCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetIPAddress.n click-1.6.0-27/inst/share/man/mann/SetIPAddress.n
+--- click-1.6.0/inst/share/man/mann/SetIPAddress.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetIPAddress.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,30 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/setipaddress.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETIPADDRESS" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetIPAddress \- Click element;
++sets destination IP address annotations
++.SH "SYNOPSIS"
++\fBSetIPAddress\fR(IPADDR)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Set the destination IP address annotation of incoming packets to the
++static IP address IPADDR.
++.PP
++
++.SH "SEE ALSO"
++.M StoreIPAddress n ,
++.M GetIPAddress "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetIPChecksum.n click-1.6.0-27/inst/share/man/mann/SetIPChecksum.n
+--- click-1.6.0/inst/share/man/mann/SetIPChecksum.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetIPChecksum.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/setipchecksum.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETIPCHECKSUM" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetIPChecksum \- Click element;
++sets IP packets' checksums
++.SH "SYNOPSIS"
++\fBSetIPChecksum\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects an IP packet as input.
++Calculates the IP header's checksum and sets the checksum header field.
++.PP
++You will not normally need \fBSetIPChecksum\fR. Most elements that modify an IP
++header, like
++.M DecIPTTL "n" ,
++.M SetIPDSCP "n" ,
++and
++.M IPRewriter "n" ,
++already update the
++checksum incrementally.
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M DecIPTTL n ,
++.M SetIPDSCP n ,
++.M IPRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetIPDSCP.n click-1.6.0-27/inst/share/man/mann/SetIPDSCP.n
+--- click-1.6.0/inst/share/man/mann/SetIPDSCP.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetIPDSCP.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,28 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/setipdscp.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETIPDSCP" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetIPDSCP \- Click element;
++sets IP packets' DSCP fields
++.SH "SYNOPSIS"
++\fBSetIPDSCP\fR(DSCP)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Expects IP packets as input and
++sets their Differential Services Code Point to DSCP.
++Then it incrementally recalculates the IP checksum
++and passes the packet to output 0.
++The DSCP is the upper 6 bits of the IP TOS field.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetPacketType.n click-1.6.0-27/inst/share/man/mann/SetPacketType.n
+--- click-1.6.0/inst/share/man/mann/SetPacketType.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetPacketType.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,28 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/setpackettype.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETPACKETTYPE" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetPacketType \- Click element;
++sets packet type annotation
++.SH "SYNOPSIS"
++\fBSetPacketType\fR(TYPE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBSetPacketType\fR sets passing packets' packet type annotations to TYPE. The
++packet type annotation tells Linux about the packet's link-level
++characteristics. For example, was the packet sent directly to this host, or
++was it broadcast? TYPE should be one of `\f(CWHOST\fR', `\f(CWBROADCAST\fR',
++`\f(CWMULTICAST\fR', `\f(CWOTHERHOST\fR', `\f(CWOUTGOING\fR', or `\f(CWLOOPBACK\fR'.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetPerfCount.n click-1.6.0-27/inst/share/man/mann/SetPerfCount.n
+--- click-1.6.0/inst/share/man/mann/SetPerfCount.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetPerfCount.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,46 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/setperfcount.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETPERFCOUNT" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetPerfCount \- Click element;
++stores Pentium Pro performance metric in annotation
++.SH "SYNOPSIS"
++\fBSetPerfCount\fR(TYPE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Stores information about the Pentium Pro performance metric TYPE in each
++packet. In combination with
++.M PerfCountAccum "n" ,
++this lets you measure how the
++metric changes over the packet's lifetime.
++.PP
++
++.SH "NOTES"
++A packet has room for either exactly one cycle count or exactly one
++performance metric.
++.PP
++Valid performance metric names are \f(CWBUS_TRAN_INVAL\fR, \f(CWBUS_TRAN_MEM\fR,
++\f(CWDCU_MISS_OUTSTANDING\fR, \f(CWIFU_FETCH\fR, \f(CWIFU_FETCH_MISS\fR, \f(CWIFU_MEM_STALL\fR,
++\f(CWINST_RETIRED\fR, \f(CWL2_IFETCH\fR, \f(CWL2_LD\fR, \f(CWL2_LINES_IN\fR, \f(CWL2_LINES_OUT\fR,
++\f(CWL2_LINES_OUTM\fR, and \f(CWL2_RQSTS\fR.
++.PP
++
++.SH "SEE ALSO"
++.M PerfCountAccum n ,
++.M SetCycleCount n ,
++.M CycleCountAccum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetRandIPAddress.n click-1.6.0-27/inst/share/man/mann/SetRandIPAddress.n
+--- click-1.6.0/inst/share/man/mann/SetRandIPAddress.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetRandIPAddress.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,33 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/setrandipaddress.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETRANDIPADDRESS" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetRandIPAddress \- Click element;
++sets destination IP address annotations randomly
++.SH "SYNOPSIS"
++\fBSetRandIPAddress\fR(PREFIX, [LIMIT])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Set the destination IP address annotation to a random number within
++the specified PREFIX.
++.PP
++If LIMIT is given, at most LIMIT distinct addresses will be generated.
++.PP
++
++.SH "SEE ALSO"
++.M StoreIPAddress n ,
++.M GetIPAddress n ,
++.M SetIPAddress "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetTCPChecksum.n click-1.6.0-27/inst/share/man/mann/SetTCPChecksum.n
+--- click-1.6.0/inst/share/man/mann/SetTCPChecksum.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetTCPChecksum.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/settcpchecksum.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETTCPCHECKSUM" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetTCPChecksum \- Click element;
++sets TCP packets' checksums
++.SH "SYNOPSIS"
++\fBSetTCPChecksum\fR([FIXOFF])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Input packets should be TCP in IP.
++.PP
++Calculates the TCP header's checksum and sets the checksum header field.
++Uses the IP header fields to generate the pseudo-header.
++.PP
++
++.SH "SEE ALSO"
++.M CheckTCPHeader n ,
++.M SetIPChecksum n ,
++.M CheckIPHeader n ,
++.M SetUDPChecksum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetTimestamp.n click-1.6.0-27/inst/share/man/mann/SetTimestamp.n
+--- click-1.6.0/inst/share/man/mann/SetTimestamp.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetTimestamp.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,45 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/settimestamp.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETTIMESTAMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetTimestamp \- Click element;
++store the time in the packet's timestamp annotation
++.SH "SYNOPSIS"
++\fBSetTimestamp\fR([TIMESTAMP, \fIkeyword\fR FIRST, DELTA])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Store the specified TIMESTAMP in the packet's timestamp annotation. If
++TIMESTAMP is not specified, then sets the annotation to the system time when
++the packet arrived at the \fBSetTimestamp\fR element.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "FIRST" 8
++Boolean. If true, then set the packet's "first timestamp" annotation, not its
++timestamp annotation. Default is true.
++.IP "" 8
++.IP "DELTA" 8
++Boolean. If true, then set the packet's timestamp annotation to the
++difference between its current timestamp annotation and its "first timestamp"
++annotation. Default is false.
++.IP "" 8
++.PP
++
++.SH "SEE ALSO"
++.M StoreTimestamp n ,
++.M PrintOld "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SetUDPChecksum.n click-1.6.0-27/inst/share/man/mann/SetUDPChecksum.n
+--- click-1.6.0/inst/share/man/mann/SetUDPChecksum.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SetUDPChecksum.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,38 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/setudpchecksum.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SETUDPCHECKSUM" n "11/Feb/2009" "Click"
++.SH "NAME"
++SetUDPChecksum \- Click element;
++sets UDP packets' checksums
++.SH "SYNOPSIS"
++\fBSetUDPChecksum\fR()
++
++\fBPorts\fR: 1 input, 1-2 outputs
++.br
++\fBProcessing\fR: agnostic, but output 1 is push
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Input packets must be UDP in IP (the protocol field isn't checked).
++.PP
++Calculates the UDP checksum and sets the UDP header's checksum field. Uses
++IP header fields to generate the pseudo-header.
++.PP
++If input packets are IP fragments, or the UDP length is longer than the
++packet, then pushes the input packets to the 2nd output, or drops them if
++there is no 2nd output.
++.PP
++
++.SH "SEE ALSO"
++.M CheckUDPHeader n ,
++.M SetIPChecksum n ,
++.M CheckIPHeader n ,
++.M SetTCPChecksum "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Shaper.n click-1.6.0-27/inst/share/man/mann/Shaper.n
+--- click-1.6.0/inst/share/man/mann/Shaper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Shaper.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,54 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/shaper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SHAPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++Shaper \- Click element;
++shapes traffic to maximum rate (pkt/s)
++.SH "SYNOPSIS"
++\fBShaper\fR(RATE)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBShaper\fR is a pull element that allows a maximum of RATE packets per second
++to pass through. That is, traffic is shaped to RATE packets per
++second. \fBShaper\fR is dependent on the timing of its pull requests; if it
++receives only sporadic pull requests, then it will emit packets only
++sporadically. However, if it receives a large number of evenly-spaced pull
++requests, then it will emit packets at the specified RATE with low
++burstiness.
++.PP
++
++.SH "NOTES"
++\fBShaper\fR cannot implement every rate smoothly. For example, it can smoothly
++generate 1000000 packets per second and 1000244 packets per second, but not
++rates in between. (In-between rates will result in minor burstiness.) This
++granularity issue is negligible at low rates, and becomes serious at very
++high rates; for example, \fBShaper\fR cannot smoothly implement any rate between
++2.048e10 and 4.096e10 packets per second.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBrate\fR (read/write)" 5
++Returns or sets the RATE parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M BandwidthShaper n ,
++.M RatedSplitter n ,
++.M RatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SimpleQueue.n click-1.6.0-27/inst/share/man/mann/SimpleQueue.n
+--- click-1.6.0/inst/share/man/mann/SimpleQueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SimpleQueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,80 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/simplequeue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SIMPLEQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++SimpleQueue \- Click element;
++stores packets in a FIFO queue
++.SH "SYNOPSIS"
++SimpleQueue
++.br
++\fBSimpleQueue\fR(CAPACITY)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: push inputs, pull outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Stores incoming packets in a first-in-first-out queue.
++Drops incoming packets if the queue already holds CAPACITY packets.
++The default for CAPACITY is 1000.
++.PP
++\fBMultithreaded Click note:\fR \fBSimpleQueue\fR is designed to be used in an
++environment with at most one concurrent pusher and at most one concurrent
++puller. Thus, at most one thread pushes to the \fBSimpleQueue\fR at a time and at
++most one thread pulls from the \fBSimpleQueue\fR at a time. Different threads can
++push to and pull from the \fBSimpleQueue\fR concurrently, however. See
++.M MSQueue "n"
++for
++a queue that can support multiple concurrent pushers.
++.PP
++
++.SH "NOTES"
++The
++.M Queue "n"
++and
++.M NotifierQueue "n"
++elements act like \fBSimpleQueue\fR, but additionally
++notify interested parties when they change state (from nonempty to empty or
++vice versa, and/or from nonfull to full or vice versa).
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBlength\fR (read-only)" 5
++Returns the current number of packets in the queue.
++.IP "" 5
++.IP "\fBhighwater_length\fR (read-only)" 5
++Returns the maximum number of packets that have ever been in the queue at once.
++.IP "" 5
++.IP "\fBcapacity\fR (read/write)" 5
++Returns or sets the queue's capacity.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets dropped by the queue so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++When written, resets the \f(CWdrops\fR and \f(CWhighwater_length\fR counters.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++When written, drops all packets in the queue.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Queue n ,
++.M NotifierQueue n ,
++.M MixedQueue n ,
++.M RED n ,
++.M FrontDropQueue n ,
++.M MSQueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Socket.n click-1.6.0-27/inst/share/man/mann/Socket.n
+--- click-1.6.0/inst/share/man/mann/Socket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Socket.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,165 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/socket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++Socket \- Click element;
++a socket transport (user-level)
++.SH "SYNOPSIS"
++\fBSocket\fR("TCP", IP, PORTNUMBER [, LOCALIP] [, LOCALPORTNUMBER] [, \fIKEYWORDS\fR])
++.br
++\fBSocket\fR("UDP", IP, PORTNUMBER [, LOCALIP] [, LOCALPORTNUMBER] [, \fIKEYWORDS\fR])
++.br
++\fBSocket\fR("UNIX", FILENAME [, LOCALFILENAME] [, \fIKEYWORDS\fR])
++.br
++\fBSocket\fR("UNIX_DGRAM", FILENAME [, LOCALFILENAME] [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Transports packets over various types of sockets. Packets do not flow
++through \fBSocket\fR elements (i.e., \fBSocket\fR is an "x/y" element). Instead,
++input packets are sent to a remote host or process, and packets
++received from the remote host or process are emitted on the output.
++.PP
++A \fBSocket\fR element of type "TCP" or "UNIX" may be either a server (the
++default if CLIENT is not set) or a client (if CLIENT is set or if the
++element has no outputs). If a server, the specified address/port/file
++is bound and connections are accepted one at a time. If a client, a
++connection attempt is made to the specified address/port/file during
++element initialization.
++.PP
++A \fBSocket\fR element of type "UDP" or "UNIX_DGRAM" may also be either a
++server or client. However, because datagram sockets are not connection
++oriented, a datagram server may receive (and thus emit) packets from
++multiple remote hosts or processes. If a server, input packets are
++sent to the last remote host or process to send a packet to the
++server. If a client, input packets are sent to the specified
++address/port/file.
++.PP
++For convenience, if a client UDP \fBSocket\fR is configured with a zero IP
++address, the \fBSocket\fR will send input packets to the destination IP
++annotation of each packet.
++.PP
++If "LOCALIP"/"LOCALPORTNUMBER" or "LOCALFILENAME" is specified, CLIENT
++is assumed if not set and the specified local address/port/file will
++be bound before the connection attempt is made. If CLIENT is set to
++false, any "LOCALIP"/"LOCALPORTNUMBER" and "LOCALFILENAME" arguments
++are ignored.
++.PP
++\fBSocket\fR inputs are agnostic, i.e., they may be either "pull" or
++"push". If pushed, packets will block on the underlying socket;
++otherwise, the socket will pull packets as it can accept them. For
++best performance, place a Notifier element (such as NotifierQueue)
++upstream of a "pull" \fBSocket\fR.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SNAPLEN" 8
++Unsigned integer. Maximum length of packets that can be
++received. Default is 2048 bytes.
++.IP "" 8
++.IP "NODELAY" 8
++Boolean. Applies to TCP sockets only. If set, disable the Nagle
++algorithm. This means that segments are always sent as soon as
++possible, even if there is only a small amount of data. When not set,
++data is buffered until there is a sufficient amount to send out,
++thereby avoiding the frequent sending of small packets, which results
++in poor utilization of the network. Default is true.
++.IP "" 8
++.IP "CLIENT" 8
++Boolean. If set, forces the socket to connect() (if SOCK_STREAM) to
++the specified address/port (if AF_INET) or file handle (if AF_UNIX),
++instead of bind()-ing and listen()-ing to it.
++.IP "" 8
++Default is false. However, if a \fBSocket\fR element has no output and
++CLIENT is unspecified, it is assumed to be a client socket. If a
++\fBSocket\fR element has no input and CLIENT is unspecified, it is assumed
++to be a server socket.
++.IP "" 8
++.IP "SNDBUF" 8
++Unsigned integer. Sets the maximum size in bytes of the underlying
++socket send buffer. The default value is set by the wmem_default
++sysctl and the maximum allowed value is set by the wmem_max sysctl.
++.IP "" 8
++.IP "RCVBUF" 8
++Unsigned integer. Sets the maximum size in bytes of the underlying
++socket receive buffer. The default value is set by the rmem_default
++sysctl and the maximum allowed value is set by the rmem_max sysctl.
++.IP "" 8
++.IP "TIMESTAMP" 8
++Boolean. If set, sets the timestamp field on received packets to the
++current time. Default is true.
++.IP "" 8
++.IP "ALLOW" 8
++The name of an IPRouteTable element, like RadixIPLookup or
++DirectIPLookup. If set and the \fBSocket\fR element is a server, the \fBSocket\fR
++element will lookup source IP addresses of clients in the specified
++IPRouteTable before accepting a connection (if SOCK_STREAM) or
++datagram (if SOCK_DGRAM). If the address is found, the connection or
++datagram is accepted. If the address is not found, the DENY table will
++then be checked (see below).
++.IP "" 8
++.IP "DENY" 8
++The name of an IPRouteTable element, like RadixIPLookup or
++DirectIPLookup. If set and the \fBSocket\fR element is a server, the \fBSocket\fR
++element will lookup source IP addresses of clients in the specified
++IPRouteTable before accepting a connection (if SOCK_STREAM) or
++datagram (if SOCK_DGRAM). If the address is found, the connection or
++datagram is dropped, otherwise it is accepted. Note that the ALLOW
++table, if specified, is checked first. Wildcard matches may be
++specified with netmasks; for example, to deny all hosts, specify a
++route to "0.0.0.0/0" in the DENY table.
++.IP "" 8
++.IP "VERBOSE" 8
++Boolean. When true, \fBSocket\fR will print messages whenever it accepts a
++new connection or drops an old one. Default is false.
++.IP "" 8
++.IP "PROPER" 8
++Boolean. PlanetLab specific. If true and Click has been configured
++--with-proper, use Proper to bind a reserved port.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& // A server socket
++\& Socket(TCP, 0.0.0.0, 80) -> ...
++\&
++\& // A client socket
++\& ... -> Socket(TCP, 1.2.3.4, 80)
++\&
++\& // A bi-directional server socket (handles one client at a time)
++\& ... -> Socket(TCP, 0.0.0.0, 80) -> ...
++\&
++\& // A bi-directional client socket
++\& ... -> Socket(TCP, 1.2.3.4, 80, CLIENT true) -> ...
++\&
++\& // A bi-directional client socket bound to a particular local port
++\& ... -> Socket(TCP, 1.2.3.4, 80, 0.0.0.0, 54321) -> ...
++\&
++\& // A localhost server socket
++\& allow :: RadixIPLookup(127.0.0.1 0);
++\& deny :: RadixIPLookup(0.0.0.0/0 0);
++\& allow -> deny -> allow; // (makes the configuration valid)
++\& Socket(TCP, 0.0.0.0, 80, ALLOW allow, DENY deny) -> ...
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M RawSocket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SortedIPLookup.n click-1.6.0-27/inst/share/man/mann/SortedIPLookup.n
+--- click-1.6.0/inst/share/man/mann/SortedIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SortedIPLookup.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/sortediplookup.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SORTEDIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++SortedIPLookup \- Click element;
++simple IP routing table
++.SH "SYNOPSIS"
++\fBSortedIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++\fBSortedIPLookup\fR is a version of
++.M LinearIPLookup "n"
++that sorts the routing table.
++In practice, however, it performs worse than
++.M LinearIPLookup "n" ,
++which itself
++performs terribly, so it is deprecated.
++.PP
++
++.SH "SEE ALSO"
++.M LinearIPLookup "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SourceIPHashMapper.n click-1.6.0-27/inst/share/man/mann/SourceIPHashMapper.n
+--- click-1.6.0/inst/share/man/mann/SourceIPHashMapper.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SourceIPHashMapper.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/siphmapper.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SOURCEIPHASHMAPPER" n "11/Feb/2009" "Click"
++.SH "NAME"
++SourceIPHashMapper \- Click element;
++Source IP Hash mapper for
++.M IPRewriter n
++.SH "SYNOPSIS"
++\fBSourceIPHashMapper\fR(NNODES SEED, PATTERN1, ..., PATTERNn)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Works in tandem with
++.M IPRewriter "n"
++to provide source IP-based rewriting.
++This is useful, for example, in load-balancing applications. Implements the
++IPMapper interface.
++.PP
++Like
++.M RoundRobinIPMapper "n" ,
++but also uses consistent hashing to map
++map elements by source IP to the same node in the cluster, even
++if nodes are added or removed.
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M TCPRewriter n ,
++.M IPRewriterPatterns n ,
++.M RoundRobinIPMapper "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SpinlockAcquire.n click-1.6.0-27/inst/share/man/mann/SpinlockAcquire.n
+--- click-1.6.0/inst/share/man/mann/SpinlockAcquire.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SpinlockAcquire.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,24 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/spinlockacquire.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SPINLOCKACQUIRE" n "11/Feb/2009" "Click"
++.SH "NAME"
++SpinlockAcquire \- Click element;
++acquires spinlock
++.SH "SYNOPSIS"
++\fBSpinlockAcquire\fR(LOCK)
++
++\fBPorts\fR: any number of inputs, any number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Acquires the spinlock named LOCK. LOCK must be defined in a SpinlockInfo element.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SpinlockInfo.n click-1.6.0-27/inst/share/man/mann/SpinlockInfo.n
+--- click-1.6.0/inst/share/man/mann/SpinlockInfo.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SpinlockInfo.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,24 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/spinlockinfo.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SPINLOCKINFO" n "11/Feb/2009" "Click"
++.SH "NAME"
++SpinlockInfo \- Click element;
++specifies names of spinlocks
++.SH "SYNOPSIS"
++\fBSpinlockInfo\fR(NAME, ...)
++
++\fBPorts\fR: none
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Lets you use mnemonic names for spinlocks. Each name names a spinlock that
++the SpinlockAcquire and SpinlockRelease elements can use to reference a
++spinlock.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/SpinlockRelease.n click-1.6.0-27/inst/share/man/mann/SpinlockRelease.n
+--- click-1.6.0/inst/share/man/mann/SpinlockRelease.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/SpinlockRelease.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,24 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/spinlockrelease.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SPINLOCKRELEASE" n "11/Feb/2009" "Click"
++.SH "NAME"
++SpinlockRelease \- Click element;
++releases spinlock
++.SH "SYNOPSIS"
++\fBSpinlockRelease\fR(LOCK)
++
++\fBPorts\fR: any number of inputs, any number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Releases the spinlock named LOCK. LOCK must be defined in a SpinlockInfo element.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StaticIPLookup.n click-1.6.0-27/inst/share/man/mann/StaticIPLookup.n
+--- click-1.6.0/inst/share/man/mann/StaticIPLookup.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StaticIPLookup.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,60 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/lookupiproute.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STATICIPLOOKUP" n "11/Feb/2009" "Click"
++.SH "NAME"
++StaticIPLookup \- Click element;
++simple static IP routing table
++.SH "SYNOPSIS"
++\fBStaticIPLookup\fR(ADDR1/MASK1 [GW1] OUT1, ADDR2/MASK2 [GW2] OUT2, ...)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++\fBNote:\fR Lookups and table updates with \fBStaticIPLookup\fR are extremely slow; the
++.M RadixIPLookup "n" ,
++.M DirectIPLookup "n" ,
++and
++.M RangeIPLookup "n"
++elements should be preferred
++in almost all cases. See
++.M IPRouteTable "n"
++for a performance comparison. We
++provide \fBStaticIPLookup\fR nevertheless for its simplicity.
++.PP
++This element acts like
++.M LinearIPLookup "n" ,
++but does not allow dynamic adding and
++deleting of routes.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtable\fR (read-only)" 5
++Outputs a human-readable version of the current routing table.
++.IP "" 5
++.IP "\fBlookup\fR (read-only)" 5
++Reports the OUTput port and GW corresponding to an address.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RadixIPLookup n ,
++.M DirectIPLookup n ,
++.M RangeIPLookup n ,
++.M LinearIPLookup n ,
++.M SortedIPLookup n ,
++.M LinuxIPLookup n ,
++.M IPRouteTable "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StaticPullSwitch.n click-1.6.0-27/inst/share/man/mann/StaticPullSwitch.n
+--- click-1.6.0/inst/share/man/mann/StaticPullSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StaticPullSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/staticpullswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STATICPULLSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++StaticPullSwitch \- Click element;
++forwards pull requests to fixed input
++.SH "SYNOPSIS"
++\fBStaticPullSwitch\fR(INPUT)
++
++\fBPorts\fR: any number of inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++On every pull, \fBStaticPullSwitch\fR returns the packet pulled from one of its
++input ports -- specifically, INPUT. Negative INPUTs mean always return
++a null packet. \fBStaticPullSwitch\fR has an unlimited number of inputs.
++.PP
++
++.SH "NOTES"
++\fBStaticPullSwitch\fR differs from
++.M PullSwitch "n"
++in that it has no \f(CWswitch\fR write
++handler, and thus does not allow INPUT to be changed at run time.
++.PP
++
++.SH "SEE ALSO"
++.M PullSwitch n ,
++.M PrioSched n ,
++.M RoundRobinSched n ,
++.M StrideSched n ,
++.M Switch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StaticSwitch.n click-1.6.0-27/inst/share/man/mann/StaticSwitch.n
+--- click-1.6.0/inst/share/man/mann/StaticSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StaticSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,40 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/staticswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STATICSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++StaticSwitch \- Click element;
++sends packet stream to fixed output
++.SH "SYNOPSIS"
++\fBStaticSwitch\fR(OUTPUT)
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBStaticSwitch\fR sends every incoming packet to one of its output ports --
++specifically, OUTPUT. Negative OUTPUT means to destroy input packets
++instead of forwarding them. \fBStaticSwitch\fR has an unlimited number of
++outputs.
++.PP
++
++.SH "NOTES"
++\fBStaticSwitch\fR differs from
++.M Switch "n"
++in that it has no \f(CWswitch\fR write handler,
++and thus does not allow OUTPUT to be changed at run time.
++.PP
++
++.SH "SEE ALSO"
++.M Switch n ,
++.M StrideSwitch n ,
++.M PullSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StaticThreadSched.n click-1.6.0-27/inst/share/man/mann/StaticThreadSched.n
+--- click-1.6.0/inst/share/man/mann/StaticThreadSched.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StaticThreadSched.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,30 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/staticthreadsched.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STATICTHREADSCHED" n "11/Feb/2009" "Click"
++.SH "NAME"
++StaticThreadSched \- Click element;
++specifies element and thread scheduling parameters
++.SH "SYNOPSIS"
++\fBStaticThreadSched\fR(ELEMENT THREAD, ...)
++
++\fBPorts\fR: none
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Statically binds elements to threads. If more than one \fBStaticThreadSched\fR
++is specified, they will all run. The one that runs later may override an
++earlier run.
++
++.SH "SEE ALSO"
++.M ThreadMonitor n ,
++.M BalancedThreadSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StoreData.n click-1.6.0-27/inst/share/man/mann/StoreData.n
+--- click-1.6.0/inst/share/man/mann/StoreData.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StoreData.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,29 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/storedata.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STOREDATA" n "11/Feb/2009" "Click"
++.SH "NAME"
++StoreData \- Click element;
++changes packet data
++.SH "SYNOPSIS"
++\fBStoreData\fR(OFFSET, DATA)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Changes packet data starting at OFFSET to DATA.
++.PP
++
++.SH "SEE ALSO"
++.M AlignmentInfo n ,
++click-align(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StoreIPAddress.n click-1.6.0-27/inst/share/man/mann/StoreIPAddress.n
+--- click-1.6.0/inst/share/man/mann/StoreIPAddress.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StoreIPAddress.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,69 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/storeipaddress.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STOREIPADDRESS" n "11/Feb/2009" "Click"
++.SH "NAME"
++StoreIPAddress \- Click element;
++stores IP address in packet
++.SH "SYNOPSIS"
++\fBStoreIPAddress\fR(OFFSET)
++.br
++\fBStoreIPAddress\fR(ADDRESS, OFFSET)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++The one-argument form writes the destination IP address annotation into the
++packet at offset OFFSET, usually an integer. But if the annotation is zero, it
++doesn't change the packet.
++.PP
++The two-argument form writes ADDRESS into the packet at offset OFFSET. ADDRESS
++can be zero.
++.PP
++The OFFSET argument may be the special string 'src' or 'dst'. In this case,
++incoming packets must be IP packets. \fBStoreIPAddress\fR writes the address into
++either the source or destination field of the IP packet header, as specified,
++and incrementally updates the IP checksum (and, if appropriate, the TCP/UDP
++checksum) to account for the change.
++.PP
++
++.SH "NOTES"
++Unless you use a special OFFSET of 'src' or 'dst', this element doesn't
++recalculate any checksums. If you store the address into an existing IP
++packet, the packet's checksum will need to be set -- for example, with
++.M SetIPChecksum "n" .
++And don't forget that you might need to recalculate TCP and UDP
++checksums as well. Here's a useful compound element:
++.PP
++.nf
++\& elementclass FixIPChecksums {
++\& // fix the IP checksum, and any embedded checksums that
++\& // include data from the IP header (TCP and UDP in particular)
++\& input -> SetIPChecksum
++\& -> ipc :: IPClassifier(tcp, udp, -)
++\& -> SetTCPChecksum
++\& -> output;
++\& ipc[1] -> SetUDPChecksum -> output;
++\& ipc[2] -> output
++\& }
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M SetIPChecksum n ,
++.M SetTCPChecksum n ,
++.M SetUDPChecksum n ,
++.M IPAddrPairRewriter n ,
++.M IPAddrRewriter "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StrideSched.n click-1.6.0-27/inst/share/man/mann/StrideSched.n
+--- click-1.6.0/inst/share/man/mann/StrideSched.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StrideSched.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,52 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/stridesched.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STRIDESCHED" n "11/Feb/2009" "Click"
++.SH "NAME"
++StrideSched \- Click element;
++pulls from stride-scheduled inputs
++.SH "SYNOPSIS"
++\fBStrideSched\fR(TICKETS0, ..., TICKETS\fIN-1\fR)
++
++\fBPorts\fR: 1 or more inputs, 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Has one output and N inputs. Performs simple packet-based stride
++scheduling, assigning TICKETS\fIi\fR to input \fIi\fR for each input.
++.PP
++Each time a pull comes in on the output, it pulls on its inputs in the order
++specified by the stride scheduling queue, until all inputs have been tried
++or one produces a packet. If an input does not produce a packet, it is not
++tried again in the current round (for the current pull on the output) even
++if it has a very short stride. This minimizes overhead and ensures that
++an input that produces a packet, if any, is found as soon as possible,
++consistently with the stride scheduler ordering.
++.PP
++The inputs usually come from Queues or other pull schedulers.
++\fBStrideSched\fR uses notification to avoid pulling from empty inputs.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtickets0...tickets\fIN-1\fB\fR (read/write)" 5
++Returns or sets the number of tickets for each input port.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M PrioSched n ,
++.M RoundRobinSched n ,
++.M DRRSched n ,
++.M StrideSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StrideSwitch.n click-1.6.0-27/inst/share/man/mann/StrideSwitch.n
+--- click-1.6.0/inst/share/man/mann/StrideSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StrideSwitch.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,45 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/strideswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STRIDESWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++StrideSwitch \- Click element;
++sends packets to stride-scheduled outputs
++.SH "SYNOPSIS"
++\fBStrideSwitch\fR(TICKETS0, ..., TICKETS\fIN-1\fR)
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Has one input and N outputs. Performs simple packet-based stride
++switching, assigning TICKETS\fIi\fR to output \fIi\fR.
++.PP
++Each time a packet arrives on the input, \fBStrideSwitch\fR sends the packet to
++the next scheduled output according to the stride scheduling algorithm.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBtickets0...tickets\fIN-1\fB\fR (read/write)" 5
++Returns or sets the number of tickets for each output port.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RoundRobinSwitch n ,
++.M Switch n ,
++.M HashSwitch n ,
++.M RandomSwitch n ,
++.M StrideSched "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Strip.n click-1.6.0-27/inst/share/man/mann/Strip.n
+--- click-1.6.0/inst/share/man/mann/Strip.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Strip.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/strip.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STRIP" n "11/Feb/2009" "Click"
++.SH "NAME"
++Strip \- Click element;
++strips bytes from front of packets
++.SH "SYNOPSIS"
++\fBStrip\fR(LENGTH)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Deletes the first LENGTH bytes from each packet.
++
++.SH "EXAMPLES"
++Use this to get rid of the Ethernet header:
++.PP
++.nf
++\& Strip(14)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M StripToNetworkHeader n ,
++.M StripIPHeader n ,
++.M EtherEncap n ,
++.M IPEncap n ,
++.M Truncate "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StripIPHeader.n click-1.6.0-27/inst/share/man/mann/StripIPHeader.n
+--- click-1.6.0/inst/share/man/mann/StripIPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StripIPHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,42 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/stripipheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STRIPIPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++StripIPHeader \- Click element;
++strips outermost IP header
++.SH "SYNOPSIS"
++\fBStripIPHeader\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Strips the outermost IP header from IP packets, based on the IP Header
++annotation.
++.PP
++Note that the packet's annotations are not changed. Thus, the packet's IP
++header annotation continues to point at the IP header, even though the IP
++header's data is now out of range. To correctly handle an IP-in-IP packet,
++you will probably need to follow \fBStripIPHeader\fR with a
++.M CheckIPHeader "n"
++or
++.M MarkIPHeader "n"
++element, thus marking the packet's inner header.
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M CheckIPHeader2 n ,
++.M MarkIPHeader n ,
++.M UnstripIPHeader n ,
++.M Strip "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/StripToNetworkHeader.n click-1.6.0-27/inst/share/man/mann/StripToNetworkHeader.n
+--- click-1.6.0/inst/share/man/mann/StripToNetworkHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/StripToNetworkHeader.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,33 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/striptonet.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "STRIPTONETWORKHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++StripToNetworkHeader \- Click element;
++strips everything preceding network header
++.SH "SYNOPSIS"
++\fBStripToNetworkHeader\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Strips any data preceding the network header from every passing packet.
++Requires a network header annotation, such as an IP header annotation,
++on every packet.
++If the packet's network header annotation points before the start of the
++packet data, then \fBStripToNetworkHeader\fR will move the packet data pointer
++back, to point at the network header.
++.PP
++
++.SH "SEE ALSO"
++.M Strip "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Suppressor.n click-1.6.0-27/inst/share/man/mann/Suppressor.n
+--- click-1.6.0/inst/share/man/mann/Suppressor.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Suppressor.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,41 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/suppressor.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SUPPRESSOR" n "11/Feb/2009" "Click"
++.SH "NAME"
++Suppressor \- Click element;
++passes packets unchanged, optionally dropping some input ports
++.SH "SYNOPSIS"
++Suppressor
++
++\fBPorts\fR: any number of inputs, the same number of outputs
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBSuppressor\fR has \fIn\fR inputs and \fIn\fR outputs. It generally passes packets
++from input \fIi\fR to output \fIi\fR unchanged. However, any input port can be
++suppressed, through a handler or a method call by another element. Packets
++arriving on suppressed push input ports are dropped; pull requests arriving
++on suppressed pull output ports are ignored.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBactive0...active\fIN-1\fB\fR (read/write)" 5
++Returns or sets whether each port is active (that is, not suppressed).
++Every port starts out active.
++.IP "" 5
++.IP "\fBreset\fR (write-only)" 5
++Resets every port to active.
++.PP
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Switch.n click-1.6.0-27/inst/share/man/mann/Switch.n
+--- click-1.6.0/inst/share/man/mann/Switch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Switch.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,52 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/switch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "SWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++Switch \- Click element;
++sends packet stream to settable output
++.SH "SYNOPSIS"
++\fBSwitch\fR([OUTPUT])
++
++\fBPorts\fR: 1 input, any number of outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBSwitch\fR sends every incoming packet to one of its output ports --
++specifically, OUTPUT. The default OUTPUT is zero; negative OUTPUT means to
++destroy input packets instead of forwarding them. You can change OUTPUT with a
++write handler. \fBSwitch\fR has an unlimited number of outputs.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBswitch\fR (read/write)" 5
++Return or set the OUTPUT parameter.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_GET_SWITCH\fR (llrpc)" 5
++Argument is a pointer to an integer, in which the \fBSwitch\fR's K parameter is
++stored.
++.IP "" 5
++.IP "\fBCLICK_LLRPC_SET_SWITCH\fR (llrpc)" 5
++Argument is a pointer to an integer. Sets the K parameter to that integer.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M StaticSwitch n ,
++.M PullSwitch n ,
++.M RoundRobinSwitch n ,
++.M StrideSwitch n ,
++.M HashSwitch n ,
++.M RandomSwitch "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/TCPRewriter.n click-1.6.0-27/inst/share/man/mann/TCPRewriter.n
+--- click-1.6.0/inst/share/man/mann/TCPRewriter.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/TCPRewriter.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,87 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/tcprewriter.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TCPREWRITER" n "11/Feb/2009" "Click"
++.SH "NAME"
++TCPRewriter \- Click element;
++rewrites TCP packets' addresses, ports, and sequence numbers
++.SH "SYNOPSIS"
++\fBTCPRewriter\fR(INPUTSPEC1, ..., INPUTSPECn [, KEYWORDS])
++
++\fBPorts\fR: 1 or more inputs, 1-256 outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Rewrites TCP flows by changing their source address, source port, destination
++address, and/or destination port, and optionally, their sequence numbers and
++acknowledgement numbers. It also changes the destination IP address
++annotation; see the DST_ANNO keyword argument below.
++.PP
++This element is an
++.M IPRewriter "n" -like
++element. Please read the
++.M IPRewriter "n"
++documentation for more information and a detailed description of its
++INPUTSPEC arguments.
++.PP
++In addition to
++.M IPRewriter "n" 's
++functionality, the \fBTCPRewriter\fR element can add or
++subtract amounts from incoming packets' sequence and acknowledgement numbers,
++including any SACK acknowledgement numbers. Each newly created mapping starts
++with these deltas at zero; other elements can request changes to a given
++mapping. For example,
++.M FTPPortMapper "n"
++uses this facility.
++.PP
++Keyword arguments determine how often stale mappings should be removed.
++.PP
++
++
++.IP "TCP_TIMEOUT \fItime\fR" 5
++Time out TCP connections every \fItime\fR seconds. Default is 24 hours.
++.IP "" 5
++.IP "TCP_DONE_TIMEOUT \fItime\fR" 5
++Time out completed TCP connections every \fItime\fR seconds. Default is 30
++seconds. FIN and RST flags mark TCP connections as complete.
++.IP "" 5
++.IP "REAP_TCP \fItime\fR" 5
++Reap timed-out TCP connections every \fItime\fR seconds. If no packets
++corresponding to a given mapping have been seen for TCP_TIMEOUT, remove the
++mapping as stale. Default is 1 hour.
++.IP "" 5
++.IP "REAP_TCP_DONE \fItime\fR" 5
++Reap timed-out completed TCP connections every \fItime\fR seconds. Default is 10
++seconds.
++.IP "" 5
++.IP "DST_ANNO" 5
++Boolean. If true, then set the destination IP address annotation on passing
++packets to the rewritten destination address. Default is true.
++.IP "" 5
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBmappings\fR (read-only)" 5
++Returns a human-readable description of the \fBTCPRewriter\fR's current set of
++mappings.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M IPRewriter n ,
++.M IPAddrRewriter n ,
++.M IPAddrPairRewriter n ,
++.M IPRewriterPatterns n ,
++.M FTPPortMapper "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Tee.n click-1.6.0-27/inst/share/man/mann/Tee.n
+--- click-1.6.0/inst/share/man/mann/Tee.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Tee.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,34 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/tee.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TEE, PULLTEE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Tee, PullTee \- Click elements;
++duplicates packets
++.SH "SYNOPSIS"
++\fBTee\fR([N])
++.br
++\fBPullTee\fR([N])
++
++\fBPorts\fR: 1 input, 1 or more outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++\fBTee\fR sends a copy of each incoming packet out each output.
++.PP
++\fBPullTee\fR's input and its first output are pull; its other outputs are push.
++Each time the pull output pulls a packet, it
++sends a copy out the push outputs.
++.PP
++\fBTee\fR and \fBPullTee\fR have however many outputs are used in the configuration,
++but you can say how many outputs you expect with the optional argument
++N.
++
+diff -Nurb click-1.6.0/inst/share/man/mann/TimedSink.n click-1.6.0-27/inst/share/man/mann/TimedSink.n
+--- click-1.6.0/inst/share/man/mann/TimedSink.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/TimedSink.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,28 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/timedsink.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TIMEDSINK" n "11/Feb/2009" "Click"
++.SH "NAME"
++TimedSink \- Click element;
++periodically pulls and drops a packet
++.SH "SYNOPSIS"
++\fBTimedSink\fR([INTERVAL])
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: pull
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls one packet every INTERVAL seconds from its input.
++Discards the packet. Default INTERVAL is 500 milliseconds.
++
++.SH "SEE ALSO"
++.M Shaper "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/TimedSource.n click-1.6.0-27/inst/share/man/mann/TimedSource.n
+--- click-1.6.0/inst/share/man/mann/TimedSource.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/TimedSource.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,70 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/timedsource.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TIMEDSOURCE" n "11/Feb/2009" "Click"
++.SH "NAME"
++TimedSource \- Click element;
++periodically generates a packet
++.SH "SYNOPSIS"
++\fBTimedSource\fR([INTERVAL, DATA, \fIKEYWORDS\fR])
++
++\fBPorts\fR: no inputs, 1 output
++.br
++\fBProcessing\fR: push
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Creates packets consisting of DATA. Pushes such a packet out its single output
++about once every INTERVAL seconds. INTERVAL has millisecond precision. Default
++INTERVAL is 500 milliseconds; default DATA is at least 64 bytes long.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DATA" 8
++String. Same as the DATA argument.
++.IP "" 8
++.IP "INTERVAL" 8
++Number of seconds. Same as the INTERVAL argument.
++.IP "" 8
++.IP "LIMIT" 8
++Integer. Stops sending after LIMIT packets are generated; but if LIMIT is
++negative, sends packets forever.
++.IP "" 8
++.IP "STOP" 8
++Boolean. If true, then stop the driver once LIMIT packets are sent. Default is
++false.
++.IP "" 8
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& TimedSource(INTERVAL 0.333) -> ...
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdata\fR (read/write)" 5
++Returns or sets the DATA parameter.
++.IP "" 5
++.IP "\fBinterval\fR (read/write)" 5
++Returns or sets the INTERVAL parameter.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M InfiniteSource "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToDevice.n click-1.6.0-27/inst/share/man/mann/ToDevice.n
+--- click-1.6.0/inst/share/man/mann/ToDevice.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToDevice.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,112 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/todevice.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TODEVICE" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToDevice \- Click element;
++sends packets to network device (Linux kernel)
++.SH "SYNOPSIS"
++\fBToDevice\fR(DEVNAME [, BURST, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++This manual page describes the Linux kernel module version of the \fBToDevice\fR
++element. For the user-level element, read the
++.M ToDevice.u "n"
++manual page.
++.PP
++Pulls packets from its single input and sends them out the Linux network
++interface named DEVNAME. DEVNAME may also be an Ethernet address, in which
++case \fBToDevice\fR searches for a device with that address.
++.PP
++Sends up to BURST packets each time it is scheduled. By default, BURST is 16.
++For good performance, you should set BURST to be 8 times the number of
++elements that could generate packets for this device.
++.PP
++Packets must have a link header. For Ethernet, \fBToDevice\fR makes sure every
++packet is at least 60 bytes long (but see NO_PAD).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "BURST" 8
++Unsigned integer. Same as the BURST argument.
++.IP "" 8
++.IP "QUIET" 8
++Boolean. If true, then suppress device up/down messages. Default is false.
++.IP "" 8
++.IP "ALLOW_NONEXISTENT" 8
++Allow nonexistent devices. If true, and no device named DEVNAME exists when
++the router is initialized, then \fBToDevice\fR will report a warning (rather than an
++error). Later, while the router is running, if a device named DEVNAME appears,
++\fBToDevice\fR will seamlessly begin sending packets to it. Default is false.
++.IP "" 8
++.IP "NO_PAD" 8
++Boolean. If true, don't force packets to be at least 60 bytes (the
++minimum Ethernet packet size). This is useful because some 802.11
++cards can send shorter Ethernet format packets. Defaults false.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++The Linux networking code may also send packets out the device. If the device
++is in polling mode, Click will try to ensure that Linux eventually sends its
++packets. Linux may cause the device to be busy when a \fBToDevice\fR wants to send a
++packet. Click is not clever enough to re-queue such packets, and discards
++them.
++.PP
++In Linux 2.2, whether or not the device is running in polling mode, \fBToDevice\fR
++depends on the device driver's send operation for synchronization (e.g. tulip
++send operation uses a bit lock). In Linux 2.4, we use the device's "xmit_lock"
++to synchronize.
++.PP
++Packets sent via \fBToDevice\fR will not be received by any packet sniffers on the
++machine. Use
++.M Tee "n"
++and
++.M ToHostSniffers "n"
++to send packets to sniffers explicitly.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets \fBToDevice\fR has pulled.
++.IP "" 5
++.IP "\fBcalls\fR (read-only)" 5
++Returns a summary of \fBToDevice\fR statistics.
++.IP "" 5
++.IP "\fBdrops\fR (read-only)" 5
++Returns the number of packets \fBToDevice\fR has dropped. \fBToDevice\fR will drop
++packets because they are too short for the device, or because the device
++explicitly rejected them.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets counters to zero when written.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M FromDevice n ,
++.M PollDevice n ,
++.M FromHost n ,
++.M ToHost n ,
++.M ToDevice.u n ,
++.M Tee n ,
++.M ToHostSniffers "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToDevice.u.n click-1.6.0-27/inst/share/man/mann/ToDevice.u.n
+--- click-1.6.0/inst/share/man/mann/ToDevice.u.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToDevice.u.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,68 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/todevice.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TODEVICE.U" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToDevice.u \- Click element;
++sends packets to network device (user-level)
++.SH "SYNOPSIS"
++\fBToDevice\fR(DEVNAME [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, at most 2 outputs
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++This manual page describes the user-level version of the \fBToDevice\fR element.
++For the Linux kernel module element, read the
++.M ToDevice n
++manual page.
++.PP
++Pulls packets and sends them out the named device using
++Berkeley Packet Filters (or Linux equivalent).
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "DEBUG" 8
++Boolean. If true, print out debug messages.
++.IP "" 8
++.PP
++This element is only available at user level.
++.PP
++.SH "NOTES"
++Packets sent via \fBToDevice\fR should already have a link-level
++header prepended. This means that ARP processing,
++for example, must already have been done.
++.PP
++Under Linux, a
++.M FromDevice n
++element will not receive packets sent by a
++\fBToDevice\fR element for the same device. Under other operating systems, your
++mileage may vary.
++.PP
++Packets that are written successfully are sent on output 0, if it exists.
++Packets that fail to be written are pushed out output 1, if it exists.
++.PP
++.M KernelTun "n"
++lets you send IP packets to the host kernel's IP processing code,
++sort of like the kernel module's ToHost element.
++.PP
++
++.SH "SEE ALSO"
++.M FromDevice.u n ,
++.M FromDump n ,
++.M ToDump n ,
++.M KernelTun n ,
++\fBToDevice\fR(n)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToDump.n click-1.6.0-27/inst/share/man/mann/ToDump.n
+--- click-1.6.0/inst/share/man/mann/ToDump.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToDump.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,95 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/todump.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TODUMP" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToDump \- Click element;
++writes packets to a tcpdump file
++.SH "SYNOPSIS"
++\fBToDump\fR(FILENAME [, \fIkeywords\fR SNAPLEN, ENCAP, USE_ENCAP_FROM, EXTRA_LENGTH])
++
++\fBPorts\fR: 1 input, at most 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBDrivers\fR: userlevel, ns
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Writes incoming packets to FILENAME in `tcpdump -w' format. This file can be
++read by `tcpdump -r', or by
++.M FromDump "n"
++on a later run. FILENAME can be `-', in
++which case \fBToDump\fR writes to the standard output.
++.PP
++Writes at most SNAPLEN bytes of each packet to the file. The default SNAPLEN
++is 2000. If SNAPLEN is 0, the whole packet will be written to the file. ENCAP
++specifies the first header each packet is expected to have. This information
++is stored in the file header, and must be correct or tcpdump won't be able to
++read the file correctly. It can be \f(CWETHER\fR (Ethernet encapsulation),
++\f(CWIP\fR (raw IP packets), \f(CWFDDI\fR, \f(CWATM\fR, \f(CW802_11\fR, \f(CWSLL\fR, \f(CWAIRONET\fR, \f(CWHDLC\fR,
++\f(CWPPP_HDLC\fR, \f(CWPPP\fR, \f(CWSUNATM\fR, \f(CWPRISM\fR, or \f(CWNULL\fR; the default is \f(CWETHER\fR.
++.PP
++\fBToDump\fR may have zero or one output. If it has an output, then it emits all
++received packets on that output. \fBToDump\fR will schedule itself on the task list
++if it is used as a pull element with no outputs.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SNAPLEN" 8
++Integer. See above.
++.IP "" 8
++.IP "ENCAP" 8
++The encapsulation type to store in the dump. See above.
++.IP "" 8
++.IP "USE_ENCAP_FROM" 8
++Argument is a space-separated list of element names. At initialization time,
++\fBToDump\fR will check these elements' `encap' handlers, and parse them as ENCAP
++arguments. If all the handlers agree, \fBToDump\fR will use that encapsulation type;
++otherwise, it will report an error. You can specify at most one of ENCAP and
++USE_ENCAP_FROM.
++.M FromDump "n"
++and
++.M FromDevice.u "n"
++have `encap' handlers.
++.IP "" 8
++.IP "EXTRA_LENGTH" 8
++Boolean. Set to true if you want \fBToDump\fR to store any extra length as recorded
++in packets' extra length annotations. Default is true.
++.IP "" 8
++.PP
++This element is only available at user level.
++.PP
++.SH "NOTES"
++\fBToDump\fR stores packets' true length annotations when available.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the number of packets emitted so far.
++.IP "" 5
++.IP "\fBreset_counts\fR (write-only)" 5
++Resets "count" to 0.
++.IP "" 5
++.IP "\fBfilename\fR (read-only)" 5
++Returns the filename.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M FromDump n ,
++.M FromDevice.u n ,
++.M ToDevice.u n ,
++tcpdump(1)
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToHost.n click-1.6.0-27/inst/share/man/mann/ToHost.n
+--- click-1.6.0/inst/share/man/mann/ToHost.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToHost.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,107 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/tohost.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TOHOST" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToHost \- Click element;
++sends packets to Linux
++.SH "SYNOPSIS"
++\fBToHost\fR([DEVNAME, \fIkeywords\fR SNIFFERS, QUIET, ALLOW_NONEXISTENT])
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Hands packets to the ordinary Linux protocol stack.
++Expects packets with Ethernet headers.
++.PP
++You should probably give Linux IP packets addressed to
++the local machine (including broadcasts), and a copy
++of each ARP reply.
++.PP
++If DEVNAME is present, each packet is marked to appear as if it originated
++from that network device -- that is, its device annotation is set to that
++device. As with
++.M ToDevice "n" ,
++DEVNAME can be an Ethernet address.
++.PP
++This element is only available in the Linux kernel module.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "SNIFFERS" 8
++Boolean. If true, then \fBToHost\fR will send packets to the kernel so that only
++tcpdump(1), and other sniffer programs on the host, will receive them.
++Default is false.
++.IP "" 8
++.IP "QUIET" 8
++Boolean. If true, then suppress device up/down messages. Default is false.
++.IP "" 8
++.IP "ALLOW_NONEXISTENT" 8
++Allow nonexistent devices. If true, and no device named DEVNAME exists when
++the router is initialized, then \fBToHost\fR will report a warning (rather than
++an error). Later, while the router is running, if a device named DEVNAME
++appears, \fBToHost\fR will seamlessly begin using it. Default is false.
++.IP "" 8
++.PP
++
++.SH "NOTES"
++Linux expects packets to have valid device annotations and packet type
++annotations. \fBToHost\fR will not pass packets with null device annotations to
++Linux! Use the `\f(CWToHost(eth0)\fR' syntax to supply a device annotation. Most
++packets generated by Click will have null device annotations -- for
++example,
++.M InfiniteSource "n"
++makes packets with null device annotations.
++Exceptions include
++.M FromDevice "n"
++and
++.M PollDevice "n" .
++.PP
++Linux depends on packet type annotations as well. It will generally only
++process packets with packet type annotation HOST. (Other packets, such as
++packets originally sent to some other host, are sent only to packet
++sniffers like tcpdump(1). Linux will handle some BROADCAST and MULTICAST
++packets.) By default, packets made by Click have HOST packet type
++annotations. However, if you modified a packet that you originally got from
++some device, that packet may have some other type. Use
++.M SetPacketType "n"
++to
++reset the type appropriately.
++.PP
++Finally, IPv4 packets should have a destination IP address corresponding
++to DEVNAME, and a routable source address. Otherwise Linux will silently
++drop the packets.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Reports the number of packets \fBToHost\fR has dropped because they had a null
++device annotation.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M ToHostSniffers n ,
++.M FromHost n ,
++.M FromDevice n ,
++.M PollDevice n ,
++.M ToDevice n ,
++.M SetPacketType n ,
++.M InfiniteSource "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToHost.u.n click-1.6.0-27/inst/share/man/mann/ToHost.u.n
+--- click-1.6.0/inst/share/man/mann/ToHost.u.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToHost.u.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,54 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/tohost.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TOHOST.U" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToHost.u \- Click element;
++sends packets to Linux via Universal TUN/TAP device.
++.SH "SYNOPSIS"
++\fBToHost\fR([DEVNAME])
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Hands packets to the ordinary Linux protocol stack.
++Expects packets with Ethernet headers.
++.PP
++You should probably give Linux IP packets addressed to
++the local machine (including broadcasts), and a copy
++of each ARP reply.
++.PP
++\fBToHost\fR requires an initialized
++.M FromHost "n"
++with the same DEVNAME.
++.PP
++IPv4 packets should have a destination IP address corresponding
++to DEVNAME, and a routable source address. Otherwise Linux will silently
++drop the packets.
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBdrops\fR (read-only)" 5
++Reports the number of packets \fBToHost\fR has dropped because they had a null
++device annotation.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M FromHost.u n ,
++.M FromHost "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToHostSniffers.n click-1.6.0-27/inst/share/man/mann/ToHostSniffers.n
+--- click-1.6.0/inst/share/man/mann/ToHostSniffers.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToHostSniffers.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,51 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/linuxmodule/tohostsniffers.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TOHOSTSNIFFERS" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToHostSniffers \- Click element;
++sends packets to Linux packet sniffers
++.SH "SYNOPSIS"
++\fBToHostSniffers\fR([DEVNAME, \fIkeywords\fR SNIFFERS, QUIET, ALLOW_NONEXISTENT])
++
++\fBPorts\fR: 1 input, no outputs
++.br
++\fBProcessing\fR: push
++.br
++\fBDrivers\fR: linuxmodule
++.br
++\fBPackage\fR: linuxmodule (core)
++.br
++.SH "DESCRIPTION"
++Hands packets to any packet sniffers registered with Linux, such as packet
++sockets. Packets are not passed to the ordinary Linux networking stack.
++Expects packets with Ethernet headers.
++.PP
++If DEVNAME is present, each packet is marked to appear as if it originated
++from that network device. As with
++.M ToDevice "n" ,
++DEVNAME can be an Ethernet
++address.
++.PP
++This element is only available in the Linux kernel module.
++.PP
++
++.SH "NOTES"
++\fBToHostSniffers\fR behaves exactly like
++.M ToHost "n" ,
++except that the SNIFFERS
++keyword argument defaults to true.
++.PP
++
++.SH "SEE ALSO"
++.M ToHost n ,
++.M FromHost n ,
++.M FromDevice n ,
++.M PollDevice n ,
++.M ToDevice "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToRawSocket.n click-1.6.0-27/inst/share/man/mann/ToRawSocket.n
+--- click-1.6.0/inst/share/man/mann/ToRawSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToRawSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,60 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/torawsocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TORAWSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToRawSocket \- Click element;
++sends IP packets through a safe raw socket (user-level)
++.SH "SYNOPSIS"
++\fBToRawSocket\fR("TCP", <TCP source port number>)
++.br
++\fBToRawSocket\fR("UDP", <UDP source port number>)
++.br
++\fBToRawSocket\fR("GRE", <GRE key or PPTP call ID>)
++.br
++\fBToRawSocket\fR("ICMP", <ICMP identifier>)
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Writes data to a raw IPv4 socket. The raw IPv4 socket may optionally
++be bound to a source port number in the case of TCP/UDP, a GRE key or
++PPTP call ID in the case of GRE, or an identifier in the case of
++ICMP. Binding a port to a raw IPv4 socket to reserve it and suppress
++TCP RST and ICMP Unreachable errors, is specific to PlanetLab Linux.
++.PP
++This element exists only for backward compatibility. See the more
++general
++.M RawSocket "n"
++implementation for details, and for supported
++keyword arguments. A \fBToRawSocket\fR is equivalent to a
++.M RawSocket "n"
++with
++no outputs.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ... -> ToRawSocket(UDP, 47)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M FromRawSocket n ,
++.M RawSocket n ,
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/ToSocket.n click-1.6.0-27/inst/share/man/mann/ToSocket.n
+--- click-1.6.0/inst/share/man/mann/ToSocket.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/ToSocket.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,58 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/tosocket.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TOSOCKET" n "11/Feb/2009" "Click"
++.SH "NAME"
++ToSocket \- Click element;
++sends data to socket (user-level)
++.SH "SYNOPSIS"
++\fBToSocket\fR("TCP", IP, PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBToSocket\fR("UDP", IP, PORTNUMBER [, \fIKEYWORDS\fR])
++.br
++\fBToSocket\fR("UNIX", FILENAME [, \fIKEYWORDS\fR])
++.br
++\fBToSocket\fR("UNIX_DGRAM", FILENAME [, \fIKEYWORDS\fR])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: pull
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Sends data to the specified socket. Input packets are sent to the
++remote host or process.
++.PP
++This element exists only for backward compatibility. See the more
++general
++.M Socket "n"
++implementation for details, and for supported keyword
++arguments. A \fBToSocket\fR is equivalent to a
++.M Socket "n"
++with the CLIENT
++keyword set to TRUE or a
++.M Socket "n"
++with no outputs.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& ... -> ToSocket(1.2.3.4, UDP, 47)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M FromSocket n ,
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Truncate.n click-1.6.0-27/inst/share/man/mann/Truncate.n
+--- click-1.6.0/inst/share/man/mann/Truncate.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Truncate.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,27 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/truncate.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "TRUNCATE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Truncate \- Click element;
++limit packet length.
++.SH "SYNOPSIS"
++\fBTruncate\fR(LENGTH)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Shorten packets to at most LENGTH bytes.
++
++.SH "SEE ALSO"
++.M Strip "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/UDPIPEncap.n click-1.6.0-27/inst/share/man/mann/UDPIPEncap.n
+--- click-1.6.0/inst/share/man/mann/UDPIPEncap.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/UDPIPEncap.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,69 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/tcpudp/udpipencap.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UDPIPENCAP" n "11/Feb/2009" "Click"
++.SH "NAME"
++UDPIPEncap \- Click element;
++encapsulates packets in static UDP/IP headers
++.SH "SYNOPSIS"
++\fBUDPIPEncap\fR(SRC, SPORT, DST, DPORT [, CHECKSUM])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: tcpudp (core)
++.br
++.SH "DESCRIPTION"
++Encapsulates each incoming packet in a UDP/IP packet with source address
++SRC, source port SPORT, destination address DST, and destination port
++DPORT. The UDP checksum is calculated if CHECKSUM? is true; it is true by
++default.
++.PP
++As a special case, if DST is "DST_ANNO", then the destination address
++is set to the incoming packet's destination address annotation.
++.PP
++The \fBUDPIPEncap\fR element adds both a UDP header and an IP header.
++.PP
++The
++.M Strip "n"
++element can be used by the receiver to get rid of the
++encapsulation header.
++.PP
++
++.SH "EXAMPLES"
++
++.nf
++\& UDPIPEncap(1.0.0.1, 1234, 2.0.0.2, 1234)
++.fi
++.PP
++
++
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBsrc\fR (read/write)" 5
++Returns or sets the SRC source address argument.
++.IP "" 5
++.IP "\fBsport\fR (read/write)" 5
++Returns or sets the SPORT source port argument.
++.IP "" 5
++.IP "\fBdst\fR (read/write)" 5
++Returns or sets the DST destination address argument.
++.IP "" 5
++.IP "\fBdport\fR (read/write)" 5
++Returns or sets the DPORT destination port argument.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M Strip n ,
++.M IPEncap "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/UMLSwitch.n click-1.6.0-27/inst/share/man/mann/UMLSwitch.n
+--- click-1.6.0/inst/share/man/mann/UMLSwitch.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/UMLSwitch.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,37 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/userlevel/umlswitch.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UMLSWITCH" n "11/Feb/2009" "Click"
++.SH "NAME"
++UMLSwitch \- Click element;
++Connects to a UML switch daemon
++.SH "SYNOPSIS"
++\fBUMLSwitch\fR([FILENAME])
++
++\fBPorts\fR: at most 1 input, at most 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBDrivers\fR: userlevel
++.br
++\fBPackage\fR: userlevel (core)
++.br
++.SH "DESCRIPTION"
++Transports packets to and from a User Mode Linux switch daemon
++instance. Packets do not flow through \fBUMLSwitch\fR elements (i.e.,
++\fBUMLSwitch\fR is an "x/y" element). Instead, input packets are sent to the
++UML switch, and packets received from the UML switch are emitted on
++the output.
++.PP
++If FILENAME is not specified, "/tmp/uml.ctl" will be used as the path
++to the UML control socket.
++.PP
++
++.SH "SEE ALSO"
++.M Socket "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Unqueue.n click-1.6.0-27/inst/share/man/mann/Unqueue.n
+--- click-1.6.0/inst/share/man/mann/Unqueue.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Unqueue.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,55 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/unqueue.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UNQUEUE" n "11/Feb/2009" "Click"
++.SH "NAME"
++Unqueue \- Click element;
++pull-to-push converter
++.SH "SYNOPSIS"
++\fBUnqueue\fR([BURST, \fIKEYWORDS\fR])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets whenever they are available, then pushes them out
++its single output. Pulls a maximum of BURST packets every time
++it is scheduled. Default BURST is 1. If BURST
++is less than 0, pull until nothing comes back.
++.PP
++Keyword arguments are:
++.PP
++
++
++.IP "ACTIVE" 4
++If false, does nothing (doesn't pull packets). One possible use
++is to set ACTIVE to false in the configuration, and later
++change it to true with a handler from DriverManager element.
++The default value is true.
++.IP "" 4
++.PP
++
++.SH "ELEMENT HANDLERS"
++
++
++
++.IP "\fBcount\fR (read-only)" 5
++Returns the count of packets that have passed through \fBUnqueue\fR.
++.IP "" 5
++.IP "\fBactive\fR (read/write)" 5
++The same as ACTIVE keyword.
++.IP "" 5
++.PP
++
++.SH "SEE ALSO"
++.M RatedUnqueue n ,
++.M BandwidthRatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Unqueue2.n click-1.6.0-27/inst/share/man/mann/Unqueue2.n
+--- click-1.6.0/inst/share/man/mann/Unqueue2.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Unqueue2.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,35 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/unqueue2.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UNQUEUE2" n "11/Feb/2009" "Click"
++.SH "NAME"
++Unqueue2 \- Click element;
++pull-to-push converter
++.SH "SYNOPSIS"
++\fBUnqueue2\fR([BURSTSIZE])
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: pull inputs, push outputs
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Pulls packets whenever they are available, then pushes them out its single
++output. Pulls a maximum of BURSTSIZE packets every time it is scheduled,
++unless downstream queues are full. Default BURSTSIZE is 1. If BURSTSIZE is
++0, pull until nothing comes back. \fBUnqueue2\fR will not pull if there is a
++downstream queue that is full. It will also limit burst size to equal to
++the number of available slots in the fullest downstream queue.
++.PP
++
++.SH "SEE ALSO"
++.M Unqueue n ,
++.M RatedUnqueue n ,
++.M BandwidthRatedUnqueue "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/Unstrip.n click-1.6.0-27/inst/share/man/mann/Unstrip.n
+--- click-1.6.0/inst/share/man/mann/Unstrip.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/Unstrip.n 2009-02-11 14:08:51.000000000 -0500
+@@ -0,0 +1,39 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/standard/unstrip.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UNSTRIP" n "11/Feb/2009" "Click"
++.SH "NAME"
++Unstrip \- Click element;
++unstrips bytes from front of packets
++.SH "SYNOPSIS"
++\fBUnstrip\fR(LENGTH)
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: standard (core)
++.br
++.SH "DESCRIPTION"
++Put LENGTH bytes at the front of the packet. These LENGTH bytes may be bytes
++previously removed by Strip.
++
++.SH "EXAMPLES"
++Use this to get rid of the Ethernet header and put it back on:
++.PP
++.nf
++\& Strip(14) -> ... -> Unstrip(14)
++.fi
++.PP
++
++
++
++.SH "SEE ALSO"
++.M EtherEncap n ,
++.M IPEncap "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/UnstripIPHeader.n click-1.6.0-27/inst/share/man/mann/UnstripIPHeader.n
+--- click-1.6.0/inst/share/man/mann/UnstripIPHeader.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/UnstripIPHeader.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,36 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man' from '../elements/ip/unstripipheader.hh'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "UNSTRIPIPHEADER" n "11/Feb/2009" "Click"
++.SH "NAME"
++UnstripIPHeader \- Click element;
++restores outermost IP header
++.SH "SYNOPSIS"
++\fBUnstripIPHeader\fR()
++
++\fBPorts\fR: 1 input, 1 output
++.br
++\fBProcessing\fR: agnostic
++.br
++\fBPackage\fR: ip (core)
++.br
++.SH "DESCRIPTION"
++Put outermost IP header back onto a stripped packet, based on the IP Header
++annotation from
++.M MarkIPHeader "n"
++or
++.M CheckIPHeader "n" .
++If IP header already on,
++forwards packet unmodified.
++.PP
++
++.SH "SEE ALSO"
++.M CheckIPHeader n ,
++.M MarkIPHeader n ,
++.M StripIPHeader "n"
++
+diff -Nurb click-1.6.0/inst/share/man/mann/elements-click.n click-1.6.0-27/inst/share/man/mann/elements-click.n
+--- click-1.6.0/inst/share/man/mann/elements-click.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/elements-click.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,1323 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ELEMENTS-CLICK" n "11/Feb/2009" "Click"
++.SH "NAME"
++elements-click - documented Click element classes
++.SH "DESCRIPTION"
++This page lists all Click element classes that have manual page documentation.
++.\"html <p><a href="#BY+FUNCTION"><b>By Function</b></a>:
++.\"html <a href="#Basic+Sources+and+Sinks">Basic Sources and Sinks</a> - <a href="#Basic+Classification+and+Selection">Basic Classification and Selection</a> - <a href="#Basic+Packet+Transfer">Basic Packet Transfer</a> - <a href="#Counters">Counters</a> - <a href="#Timestamps">Timestamps</a> - <a href="#Basic+Packet+Modification">Basic Packet Modification</a> - <a href="#Packet+Storage">Packet Storage</a> - <a href="#Active+Queue+Management">Active Queue Management</a> - <a href="#Packet+Scheduling">Packet Scheduling</a> - <a href="#Traffic+Shaping">Traffic Shaping</a> - <a href="#Information+Elements">Information Elements</a> - <a href="#Network+Devices">Network Devices</a> - <a href="#Host+and+Socket+Communication">Host and Socket Communication</a> - <a href="#Ethernet">Ethernet</a> - <a href="#ARP">ARP</a> - <a href="#IPv4">IPv4</a> - <a href="#IPv4+Routing">IPv4 Routing</a> - <a href="#ICMP">ICMP</a> - <a href="#Network+Address+Translation">Network Address Translation</a> - <a href="#TCP">TCP</a> - <a href="#UDP">UDP</a> - <a href="#Trace+Manipulation">Trace Manipulation</a> - <a href="#TCP/IP+Measurement">TCP/IP Measurement</a> - <a href="#CRCs">CRCs</a> - <a href="#Paint+Annotations">Paint Annotations</a> - <a href="#Annotations">Annotations</a> - <a href="#Debugging">Debugging</a> - <a href="#Control">Control</a> - <a href="#Multithreaded+Click">Multithreaded Click</a> - <a href="#devices">devices</a><br>
++.\"html <a href="#ALPHABETICAL+LIST"><b>Alphabetical List</b></a></p>
++.SH "BY FUNCTION"
++.SS "Basic Sources and Sinks"
++.PP
++.PD 0
++.TP 20
++.M Discard n
++drops all packets
++.TP 20
++.M DiscardNoFree n
++drops all packets, but does not free any of them.
++.TP 20
++.M Idle n
++discards packets
++.TP 20
++.M InfiniteSource n
++generates packets whenever scheduled
++.TP 20
++.M RandomSource n
++generates random packets whenever scheduled
++.TP 20
++.M RatedSource n
++generates packets at specified rate
++.TP 20
++.M TimedSink n
++periodically pulls and drops a packet
++.TP 20
++.M TimedSource n
++periodically generates a packet
++.PD
++.SS "Basic Classification and Selection"
++.PP
++.PD 0
++.TP 20
++.M CheckLength n
++drops large packets
++.TP 20
++.M Classifier n
++classifies packets by contents
++.TP 20
++.M HashSwitch n
++classifies packets by hash of contents
++.TP 20
++.M RandomSample n
++samples packets with some probability
++.TP 20
++.M RandomSwitch n
++sends packets to random outputs
++.TP 20
++.M RoundRobinSwitch n
++sends packets to round-robin outputs
++.TP 20
++.M StaticSwitch n
++sends packet stream to fixed output
++.TP 20
++.M StrideSwitch n
++sends packets to stride-scheduled outputs
++.TP 20
++.M Suppressor n
++passes packets unchanged, optionally dropping some input ports
++.TP 20
++.M Switch n
++sends packet stream to settable output
++.PD
++.SS "Basic Packet Transfer"
++.PP
++.PD 0
++.TP 20
++.M Null n
++passes packets unchanged
++.TP 20
++.M Null1 n
++copy of
++.M Null "n"
++.TP 20
++.M PullNull n
++passes packets unchanged
++.TP 20
++.M PullTee n
++duplicates packets
++.TP 20
++.M PushNull n
++passes packets unchanged
++.TP 20
++.M Tee n
++duplicates packets
++.PD
++.SS "Counters"
++.PP
++.PD 0
++.TP 20
++.M AverageCounter n
++measures historical packet count and rate
++.TP 20
++.M Counter n
++measures packet count and rate
++.TP 20
++.M CycleCountAccum n
++collects differences in cycle counters
++.TP 20
++.M PerfCountAccum n
++collects differences in Pentium Pro performance metrics
++.TP 20
++.M PerfCountInfo n
++turn on Pentium Pro performance metrics
++.TP 20
++.M RoundTripCycleCount n
++measures round trip cycles on a push or pull path
++.TP 20
++.M SetCycleCount n
++stores cycle count in annotation
++.TP 20
++.M SetPerfCount n
++stores Pentium Pro performance metric in annotation
++.PD
++.SS "Timestamps"
++.PP
++.PD 0
++.TP 20
++.M SetTimestamp n
++store the time in the packet's timestamp annotation
++.PD
++.SS "Basic Packet Modification"
++.PP
++.PD 0
++.TP 20
++.M Align n
++aligns packet data
++.TP 20
++.M RandomBitErrors n
++changes packet data with some probability
++.TP 20
++.M StoreData n
++changes packet data
++.TP 20
++.M Strip n
++strips bytes from front of packets
++.TP 20
++.M StripToNetworkHeader n
++strips everything preceding network header
++.TP 20
++.M Truncate n
++limit packet length.
++.TP 20
++.M Unstrip n
++unstrips bytes from front of packets
++.PD
++.SS "Packet Storage"
++.PP
++.PD 0
++.TP 20
++.M FrontDropQueue n
++stores packets in drop-from-front FIFO queue
++.TP 20
++.M MixedQueue n
++stores packets in a FIFO/LIFO queue
++.TP 20
++.M NotifierQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Queue n
++stores packets in a FIFO queue
++.TP 20
++.M SimpleQueue n
++stores packets in a FIFO queue
++.PD
++.SS "Active Queue Management"
++.PP
++.PD 0
++.TP 20
++.M AdaptiveRED n
++drops packets according to Adaptive RED
++.TP 20
++.M RED n
++drops packets according to RED
++.PD
++.SS "Packet Scheduling"
++.PP
++.PD 0
++.TP 20
++.M DRRSched n
++pulls from inputs with deficit round robin scheduling
++.TP 20
++.M PrioSched n
++pulls from priority-scheduled inputs
++.TP 20
++.M PullSwitch n
++forwards pull requests to settable input
++.TP 20
++.M RoundRobinSched n
++pulls from round-robin inputs
++.TP 20
++.M StaticPullSwitch n
++forwards pull requests to fixed input
++.TP 20
++.M StrideSched n
++pulls from stride-scheduled inputs
++.PD
++.SS "Traffic Shaping"
++.PP
++.PD 0
++.TP 20
++.M BandwidthMeter n
++classifies packet stream by arrival rate
++.TP 20
++.M BandwidthRatedSplitter n
++splits flow of packets at specified bandwidth rate
++.TP 20
++.M BandwidthRatedUnqueue n
++pull-to-push converter
++.TP 20
++.M BandwidthShaper n
++shapes traffic to maximum rate (bytes/s)
++.TP 20
++.M Burster n
++pull-to-push converter
++.TP 20
++.M CompareBlock n
++drops packets out of rate range
++.TP 20
++.M DelayShaper n
++shapes traffic to meet delay requirements
++.TP 20
++.M DelayUnqueue n
++delay inducing pull-to-push converter
++.TP 20
++.M LinkUnqueue n
++link emulator
++.TP 20
++.M Meter n
++classifies packet stream by rate (pkt/s)
++.TP 20
++.M RatedSplitter n
++splits flow of packets at specified rate
++.TP 20
++.M RatedUnqueue n
++pull-to-push converter
++.TP 20
++.M Shaper n
++shapes traffic to maximum rate (pkt/s)
++.TP 20
++.M Unqueue n
++pull-to-push converter
++.TP 20
++.M Unqueue2 n
++pull-to-push converter
++.PD
++.SS "Information Elements"
++.PP
++.PD 0
++.TP 20
++.M AddressInfo n
++specifies address information
++.TP 20
++.M AlignmentInfo n
++specifies alignment information
++.TP 20
++.M PortInfo n
++stores named TCP/UDP port information
++.TP 20
++.M ScheduleInfo n
++specifies scheduling parameters
++.TP 20
++.M ScheduleLinux n
++returns to Linux scheduler
++.PD
++.SS "Network Devices"
++.PP
++.PD 0
++.TP 20
++.M FromDevice n
++reads packets from network device (Linux kernel)
++.TP 20
++.M FromDevice.u n
++reads packets from network device (user-level)
++.TP 20
++.M PollDevice n
++polls packets from network device (kernel)
++.TP 20
++.M ToDevice n
++sends packets to network device (Linux kernel)
++.TP 20
++.M ToDevice.u n
++sends packets to network device (user-level)
++.PD
++.SS "Host and Socket Communication"
++.PP
++.PD 0
++.TP 20
++.M FromHost n
++reads packets from Linux
++.TP 20
++.M FromHost.u n
++interface to /dev/net/tun or ethertap (user-level)
++.TP 20
++.M FromRawSocket n
++reads raw IP packets from safe raw socket (user-level)
++.TP 20
++.M FromSocket n
++reads data from socket (user-level)
++.TP 20
++.M KernelFilter n
++block kernel from handling packets
++.TP 20
++.M KernelTap n
++interface to /dev/tap or ethertap (user-level)
++.TP 20
++.M KernelTun n
++interface to /dev/tun or ethertap (user-level)
++.TP 20
++.M RawSocket n
++transports raw IP packets via safe raw sockets (user-level)
++.TP 20
++.M Socket n
++a socket transport (user-level)
++.TP 20
++.M ToHost n
++sends packets to Linux
++.TP 20
++.M ToHost.u n
++sends packets to Linux via Universal TUN/TAP device.
++.TP 20
++.M ToHostSniffers n
++sends packets to Linux packet sniffers
++.TP 20
++.M ToRawSocket n
++sends IP packets through a safe raw socket (user-level)
++.TP 20
++.M ToSocket n
++sends data to socket (user-level)
++.PD
++.SS "Ethernet"
++.PP
++.PD 0
++.TP 20
++.M EnsureEther n
++ensures that IP packets are Ethernet encapsulated
++.TP 20
++.M EtherEncap n
++encapsulates packets in Ethernet header
++.TP 20
++.M EtherMirror n
++swaps Ethernet source and destination
++.TP 20
++.M HostEtherFilter n
++drops Ethernet packets sent to other machines
++.PD
++.SS "ARP"
++.PP
++.PD 0
++.TP 20
++.M ARPFaker n
++periodically generates an ARP reply
++.TP 20
++.M ARPPrint n
++pretty-prints ARP packets a la tcpdump
++.TP 20
++.M ARPQuerier n
++encapsulates IP packets in Ethernet headers found via ARP
++.TP 20
++.M ARPResponder n
++generates responses to ARP queries
++.TP 20
++.M CheckARPHeader n
++checks ARP header
++.PD
++.SS "IPv4"
++.PP
++.PD 0
++.TP 20
++.M CheckIPHeader n
++checks IP header
++.TP 20
++.M CheckIPHeader2 n
++checks IP header, no checksum
++.TP 20
++.M DecIPTTL n
++decrements IP time-to-live, drops dead packets
++.TP 20
++.M FixIPSrc n
++sets IP source field if requested by annotation
++.TP 20
++.M GetIPAddress n
++sets destination IP address annotation from packet data
++.TP 20
++.M IPClassifier n
++classifies IP packets by contents
++.TP 20
++.M IPEncap n
++encapsulates packets in static IP header
++.TP 20
++.M IPFilter n
++filters IP packets by contents
++.TP 20
++.M IPFragmenter n
++fragments large IP packets
++.TP 20
++.M IPGWOptions n
++processes router IP options
++.TP 20
++.M IPInputCombo n
++input combo for IP routing
++.TP 20
++.M IPMirror n
++swaps IP source and destination
++.TP 20
++.M IPNameInfo n
++stores name information about IP packets
++.TP 20
++.M IPOutputCombo n
++output combo for IP routing
++.TP 20
++.M IPPrint n
++pretty-prints IP packets
++.TP 20
++.M IPReassembler n
++Reassembles fragmented IP packets
++.TP 20
++.M MarkIPCE n
++sets IP packets' ECN field to Congestion Experienced
++.TP 20
++.M MarkIPHeader n
++sets IP header annotation
++.TP 20
++.M SetIPAddress n
++sets destination IP address annotations
++.TP 20
++.M SetIPChecksum n
++sets IP packets' checksums
++.TP 20
++.M SetIPDSCP n
++sets IP packets' DSCP fields
++.TP 20
++.M SetRandIPAddress n
++sets destination IP address annotations randomly
++.TP 20
++.M StoreIPAddress n
++stores IP address in packet
++.TP 20
++.M StripIPHeader n
++strips outermost IP header
++.TP 20
++.M UnstripIPHeader n
++restores outermost IP header
++.PD
++.SS "IPv4 Routing"
++.PP
++.PD 0
++.TP 20
++.M DirectIPLookup n
++IP routing lookup using direct-indexed tables
++.TP 20
++.M IPRouteTable n
++IP routing table superclass
++.TP 20
++.M LinearIPLookup n
++simple IP routing table
++.TP 20
++.M LinuxIPLookup n
++interface to Linux's routing table
++.TP 20
++.M RadixIPLookup n
++IP lookup using a radix trie
++.TP 20
++.M RangeIPLookup n
++IP routing lookup through binary search in a very compact table
++.TP 20
++.M RIPSend n
++periodically generates specified RIP II packet
++.TP 20
++.M SortedIPLookup n " (deprecated)"
++simple IP routing table
++.TP 20
++.M StaticIPLookup n
++simple static IP routing table
++.PD
++.SS "ICMP"
++.PP
++.PD 0
++.TP 20
++.M CheckICMPHeader n
++checks ICMP header on ICMP packets
++.TP 20
++.M ICMPError n
++generates ICMP error packets
++.TP 20
++.M ICMPPingEncap n
++encapsulates packets in ICMP ping headers
++.TP 20
++.M ICMPPingResponder n
++responds to ICMP echo requests
++.TP 20
++.M ICMPPingSource n
++periodically sends ICMP echo requests
++.PD
++.SS "Network Address Translation"
++.PP
++.PD 0
++.TP 20
++.M FTPPortMapper n
++manipulates
++.M IPRewriter "n"
++for FTP
++.TP 20
++.M ICMPPingRewriter n
++rewrites ICMP echo requests and replies
++.TP 20
++.M ICMPRewriter n
++rewrites ICMP packets based on IP rewriter mappings
++.TP 20
++.M IPAddrPairRewriter n
++rewrites IP packets' addresses by address pair
++.TP 20
++.M IPAddrRewriter n
++rewrites IP packets' addresses
++.TP 20
++.M IPRewriter n
++rewrites TCP/UDP packets' addresses and ports
++.TP 20
++.M IPRewriterPatterns n
++specifies shared
++.M IPRewriter n
++patterns
++.TP 20
++.M RoundRobinIPMapper n
++round-robin mapper for
++.M IPRewriter n
++.TP 20
++.M SourceIPHashMapper n
++Source IP Hash mapper for
++.M IPRewriter n
++.TP 20
++.M TCPRewriter n
++rewrites TCP packets' addresses, ports, and sequence numbers
++.PD
++.SS "TCP"
++.PP
++.PD 0
++.TP 20
++.M CheckTCPHeader n
++checks TCP header on TCP/IP packets
++.TP 20
++.M FastTCPFlows n
++creates packets flows with static TCP/IP/Ethernet headers
++.TP 20
++.M RFC2507Comp n
++RFC2507 IPv4/TCP header compressor.
++.TP 20
++.M RFC2507Decomp n
++RFC2507 IPv4/TCP header decompressor.
++.TP 20
++.M SetTCPChecksum n
++sets TCP packets' checksums
++.PD
++.SS "UDP"
++.PP
++.PD 0
++.TP 20
++.M CheckUDPHeader n
++checks UDP header on UDP/IP packets
++.TP 20
++.M DynamicUDPIPEncap n
++encapsulates packets in dynamic UDP/IP headers
++.TP 20
++.M FastUDPFlows n
++creates packets flows with static UDP/IP/Ethernet headers
++.TP 20
++.M FastUDPSource n
++creates packets with static UDP/IP/Ethernet headers
++.TP 20
++.M SetUDPChecksum n
++sets UDP packets' checksums
++.TP 20
++.M UDPIPEncap n
++encapsulates packets in static UDP/IP headers
++.PD
++.SS "Trace Manipulation"
++.PP
++.PD 0
++.TP 20
++.M FromDump n
++reads packets from a tcpdump file
++.TP 20
++.M ToDump n
++writes packets to a tcpdump file
++.PD
++.SS "TCP/IP Measurement"
++.PP
++.PD 0
++.TP 20
++.M IPRateMonitor n
++measures coming and going IP traffic rates
++.PD
++.SS "CRCs"
++.PP
++.PD 0
++.TP 20
++.M CheckCRC32 n
++checks packet CRC32s
++.TP 20
++.M SetCRC32 n
++calculates CRC32 and prepends to packet
++.PD
++.SS "Paint Annotations"
++.PP
++.PD 0
++.TP 20
++.M CheckPaint n
++checks packets' paint annotation
++.TP 20
++.M Paint n
++sets packet paint annotations
++.TP 20
++.M PaintSwitch n
++sends packet stream to output chosen per-packet
++.TP 20
++.M PaintTee n
++duplicates packets with given paint annotation
++.PD
++.SS "Annotations"
++.PP
++.PD 0
++.TP 20
++.M DropBroadcasts n
++drops link-level broadcast and multicast packets
++.TP 20
++.M SetAnnoByte n
++sets packet user annotations
++.TP 20
++.M SetPacketType n
++sets packet type annotation
++.PD
++.SS "Debugging"
++.PP
++.PD 0
++.TP 20
++.M Error n
++always fails
++.TP 20
++.M Print n
++prints packet contents
++.PD
++.SS "Control"
++.PP
++.PD 0
++.TP 20
++.M ChangeUID n
++relinquish root privilege
++.TP 20
++.M ChatterSocket n
++reports chatter messages to connected sockets
++.TP 20
++.M ControlSocket n
++opens control sockets for other programs
++.TP 20
++.M DriverManager n
++a
++.M Script "n"
++that manages driver stop events
++.TP 20
++.M KernelHandlerProxy n
++proxies kernel module handlers at user level
++.TP 20
++.M Message n
++prints a message on configuration
++.TP 20
++.M PokeHandlers n " (deprecated)"
++calls write handlers at specified times
++.TP 20
++.M ProgressBar n
++prints a progress bar to standard error
++.TP 20
++.M QuitWatcher n
++stops router processing
++.TP 20
++.M Script n
++script a Click router configuration
++.PD
++.SS "Multithreaded Click"
++.PP
++.PD 0
++.TP 20
++.M CPUQueue n
++stores packets in FIFO queues.
++.TP 20
++.M CPUSwitch n
++classifies packets by cpu
++.TP 20
++.M LookupIPRouteMP n
++simple static IP routing table
++.TP 20
++.M MSQueue n
++stores packets in a FIFO queue
++.TP 20
++.M SpinlockAcquire n
++acquires spinlock
++.TP 20
++.M SpinlockInfo n
++specifies names of spinlocks
++.TP 20
++.M SpinlockRelease n
++releases spinlock
++.TP 20
++.M StaticThreadSched n
++specifies element and thread scheduling parameters
++.PD
++.SS "devices"
++.PP
++.PD 0
++.TP 20
++.M UMLSwitch n
++Connects to a UML switch daemon
++.PD
++.SH "ALPHABETICAL LIST"
++.PP
++.PD 0
++.TP 20
++.M AdaptiveRED n
++drops packets according to Adaptive RED
++.TP 20
++.M AddressInfo n
++specifies address information
++.TP 20
++.M Align n
++aligns packet data
++.TP 20
++.M AlignmentInfo n
++specifies alignment information
++.TP 20
++.M ARPFaker n
++periodically generates an ARP reply
++.TP 20
++.M ARPPrint n
++pretty-prints ARP packets a la tcpdump
++.TP 20
++.M ARPQuerier n
++encapsulates IP packets in Ethernet headers found via ARP
++.TP 20
++.M ARPResponder n
++generates responses to ARP queries
++.TP 20
++.M AverageCounter n
++measures historical packet count and rate
++.TP 20
++.M BandwidthMeter n
++classifies packet stream by arrival rate
++.TP 20
++.M BandwidthRatedSplitter n
++splits flow of packets at specified bandwidth rate
++.TP 20
++.M BandwidthRatedUnqueue n
++pull-to-push converter
++.TP 20
++.M BandwidthShaper n
++shapes traffic to maximum rate (bytes/s)
++.TP 20
++.M Burster n
++pull-to-push converter
++.TP 20
++.M ChangeUID n
++relinquish root privilege
++.TP 20
++.M ChatterSocket n
++reports chatter messages to connected sockets
++.TP 20
++.M CheckARPHeader n
++checks ARP header
++.TP 20
++.M CheckCRC32 n
++checks packet CRC32s
++.TP 20
++.M CheckICMPHeader n
++checks ICMP header on ICMP packets
++.TP 20
++.M CheckIPHeader n
++checks IP header
++.TP 20
++.M CheckIPHeader2 n
++checks IP header, no checksum
++.TP 20
++.M CheckLength n
++drops large packets
++.TP 20
++.M CheckPaint n
++checks packets' paint annotation
++.TP 20
++.M CheckTCPHeader n
++checks TCP header on TCP/IP packets
++.TP 20
++.M CheckUDPHeader n
++checks UDP header on UDP/IP packets
++.TP 20
++.M Classifier n
++classifies packets by contents
++.TP 20
++.M CompareBlock n
++drops packets out of rate range
++.TP 20
++.M ControlSocket n
++opens control sockets for other programs
++.TP 20
++.M Counter n
++measures packet count and rate
++.TP 20
++.M CPUQueue n
++stores packets in FIFO queues.
++.TP 20
++.M CPUSwitch n
++classifies packets by cpu
++.TP 20
++.M CycleCountAccum n
++collects differences in cycle counters
++.TP 20
++.M DecIPTTL n
++decrements IP time-to-live, drops dead packets
++.TP 20
++.M DelayShaper n
++shapes traffic to meet delay requirements
++.TP 20
++.M DelayUnqueue n
++delay inducing pull-to-push converter
++.TP 20
++.M DirectIPLookup n
++IP routing lookup using direct-indexed tables
++.TP 20
++.M Discard n
++drops all packets
++.TP 20
++.M DiscardNoFree n
++drops all packets, but does not free any of them.
++.TP 20
++.M DriverManager n
++a
++.M Script "n"
++that manages driver stop events
++.TP 20
++.M DropBroadcasts n
++drops link-level broadcast and multicast packets
++.TP 20
++.M DRRSched n
++pulls from inputs with deficit round robin scheduling
++.TP 20
++.M DynamicUDPIPEncap n
++encapsulates packets in dynamic UDP/IP headers
++.TP 20
++.M EnsureEther n
++ensures that IP packets are Ethernet encapsulated
++.TP 20
++.M Error n
++always fails
++.TP 20
++.M EtherEncap n
++encapsulates packets in Ethernet header
++.TP 20
++.M EtherMirror n
++swaps Ethernet source and destination
++.TP 20
++.M FastTCPFlows n
++creates packets flows with static TCP/IP/Ethernet headers
++.TP 20
++.M FastUDPFlows n
++creates packets flows with static UDP/IP/Ethernet headers
++.TP 20
++.M FastUDPSource n
++creates packets with static UDP/IP/Ethernet headers
++.TP 20
++.M FixIPSrc n
++sets IP source field if requested by annotation
++.TP 20
++.M FromDevice n
++reads packets from network device (Linux kernel)
++.TP 20
++.M FromDevice.u n
++reads packets from network device (user-level)
++.TP 20
++.M FromDump n
++reads packets from a tcpdump file
++.TP 20
++.M FromHost n
++reads packets from Linux
++.TP 20
++.M FromHost.u n
++interface to /dev/net/tun or ethertap (user-level)
++.TP 20
++.M FromRawSocket n
++reads raw IP packets from safe raw socket (user-level)
++.TP 20
++.M FromSocket n
++reads data from socket (user-level)
++.TP 20
++.M FrontDropQueue n
++stores packets in drop-from-front FIFO queue
++.TP 20
++.M FTPPortMapper n
++manipulates
++.M IPRewriter "n"
++for FTP
++.TP 20
++.M GetIPAddress n
++sets destination IP address annotation from packet data
++.TP 20
++.M HashSwitch n
++classifies packets by hash of contents
++.TP 20
++.M HostEtherFilter n
++drops Ethernet packets sent to other machines
++.TP 20
++.M ICMPError n
++generates ICMP error packets
++.TP 20
++.M ICMPPingEncap n
++encapsulates packets in ICMP ping headers
++.TP 20
++.M ICMPPingResponder n
++responds to ICMP echo requests
++.TP 20
++.M ICMPPingRewriter n
++rewrites ICMP echo requests and replies
++.TP 20
++.M ICMPPingSource n
++periodically sends ICMP echo requests
++.TP 20
++.M ICMPRewriter n
++rewrites ICMP packets based on IP rewriter mappings
++.TP 20
++.M Idle n
++discards packets
++.TP 20
++.M InfiniteSource n
++generates packets whenever scheduled
++.TP 20
++.M IPAddrPairRewriter n
++rewrites IP packets' addresses by address pair
++.TP 20
++.M IPAddrRewriter n
++rewrites IP packets' addresses
++.TP 20
++.M IPClassifier n
++classifies IP packets by contents
++.TP 20
++.M IPEncap n
++encapsulates packets in static IP header
++.TP 20
++.M IPFilter n
++filters IP packets by contents
++.TP 20
++.M IPFragmenter n
++fragments large IP packets
++.TP 20
++.M IPGWOptions n
++processes router IP options
++.TP 20
++.M IPInputCombo n
++input combo for IP routing
++.TP 20
++.M IPMirror n
++swaps IP source and destination
++.TP 20
++.M IPNameInfo n
++stores name information about IP packets
++.TP 20
++.M IPOutputCombo n
++output combo for IP routing
++.TP 20
++.M IPPrint n
++pretty-prints IP packets
++.TP 20
++.M IPRateMonitor n
++measures coming and going IP traffic rates
++.TP 20
++.M IPReassembler n
++Reassembles fragmented IP packets
++.TP 20
++.M IPRewriter n
++rewrites TCP/UDP packets' addresses and ports
++.TP 20
++.M IPRewriterPatterns n
++specifies shared
++.M IPRewriter n
++patterns
++.TP 20
++.M IPRouteTable n
++IP routing table superclass
++.TP 20
++.M KernelFilter n
++block kernel from handling packets
++.TP 20
++.M KernelHandlerProxy n
++proxies kernel module handlers at user level
++.TP 20
++.M KernelTap n
++interface to /dev/tap or ethertap (user-level)
++.TP 20
++.M KernelTun n
++interface to /dev/tun or ethertap (user-level)
++.TP 20
++.M LinearIPLookup n
++simple IP routing table
++.TP 20
++.M LinkUnqueue n
++link emulator
++.TP 20
++.M LinuxIPLookup n
++interface to Linux's routing table
++.TP 20
++.M LookupIPRouteMP n
++simple static IP routing table
++.TP 20
++.M MarkIPCE n
++sets IP packets' ECN field to Congestion Experienced
++.TP 20
++.M MarkIPHeader n
++sets IP header annotation
++.TP 20
++.M Message n
++prints a message on configuration
++.TP 20
++.M Meter n
++classifies packet stream by rate (pkt/s)
++.TP 20
++.M MixedQueue n
++stores packets in a FIFO/LIFO queue
++.TP 20
++.M MSQueue n
++stores packets in a FIFO queue
++.TP 20
++.M NotifierQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Null n
++passes packets unchanged
++.TP 20
++.M Null1 n
++copy of
++.M Null "n"
++.TP 20
++.M Paint n
++sets packet paint annotations
++.TP 20
++.M PaintSwitch n
++sends packet stream to output chosen per-packet
++.TP 20
++.M PaintTee n
++duplicates packets with given paint annotation
++.TP 20
++.M PerfCountAccum n
++collects differences in Pentium Pro performance metrics
++.TP 20
++.M PerfCountInfo n
++turn on Pentium Pro performance metrics
++.TP 20
++.M PokeHandlers n " (deprecated)"
++calls write handlers at specified times
++.TP 20
++.M PollDevice n
++polls packets from network device (kernel)
++.TP 20
++.M PortInfo n
++stores named TCP/UDP port information
++.TP 20
++.M Print n
++prints packet contents
++.TP 20
++.M PrioSched n
++pulls from priority-scheduled inputs
++.TP 20
++.M ProgressBar n
++prints a progress bar to standard error
++.TP 20
++.M PullNull n
++passes packets unchanged
++.TP 20
++.M PullSwitch n
++forwards pull requests to settable input
++.TP 20
++.M PullTee n
++duplicates packets
++.TP 20
++.M PushNull n
++passes packets unchanged
++.TP 20
++.M Queue n
++stores packets in a FIFO queue
++.TP 20
++.M QuitWatcher n
++stops router processing
++.TP 20
++.M RadixIPLookup n
++IP lookup using a radix trie
++.TP 20
++.M RandomBitErrors n
++changes packet data with some probability
++.TP 20
++.M RandomSample n
++samples packets with some probability
++.TP 20
++.M RandomSource n
++generates random packets whenever scheduled
++.TP 20
++.M RandomSwitch n
++sends packets to random outputs
++.TP 20
++.M RangeIPLookup n
++IP routing lookup through binary search in a very compact table
++.TP 20
++.M RatedSource n
++generates packets at specified rate
++.TP 20
++.M RatedSplitter n
++splits flow of packets at specified rate
++.TP 20
++.M RatedUnqueue n
++pull-to-push converter
++.TP 20
++.M RawSocket n
++transports raw IP packets via safe raw sockets (user-level)
++.TP 20
++.M RED n
++drops packets according to RED
++.TP 20
++.M RFC2507Comp n
++RFC2507 IPv4/TCP header compressor.
++.TP 20
++.M RFC2507Decomp n
++RFC2507 IPv4/TCP header decompressor.
++.TP 20
++.M RIPSend n
++periodically generates specified RIP II packet
++.TP 20
++.M RoundRobinIPMapper n
++round-robin mapper for
++.M IPRewriter n
++.TP 20
++.M RoundRobinSched n
++pulls from round-robin inputs
++.TP 20
++.M RoundRobinSwitch n
++sends packets to round-robin outputs
++.TP 20
++.M RoundTripCycleCount n
++measures round trip cycles on a push or pull path
++.TP 20
++.M ScheduleInfo n
++specifies scheduling parameters
++.TP 20
++.M ScheduleLinux n
++returns to Linux scheduler
++.TP 20
++.M Script n
++script a Click router configuration
++.TP 20
++.M SetAnnoByte n
++sets packet user annotations
++.TP 20
++.M SetCRC32 n
++calculates CRC32 and prepends to packet
++.TP 20
++.M SetCycleCount n
++stores cycle count in annotation
++.TP 20
++.M SetIPAddress n
++sets destination IP address annotations
++.TP 20
++.M SetIPChecksum n
++sets IP packets' checksums
++.TP 20
++.M SetIPDSCP n
++sets IP packets' DSCP fields
++.TP 20
++.M SetPacketType n
++sets packet type annotation
++.TP 20
++.M SetPerfCount n
++stores Pentium Pro performance metric in annotation
++.TP 20
++.M SetRandIPAddress n
++sets destination IP address annotations randomly
++.TP 20
++.M SetTCPChecksum n
++sets TCP packets' checksums
++.TP 20
++.M SetTimestamp n
++store the time in the packet's timestamp annotation
++.TP 20
++.M SetUDPChecksum n
++sets UDP packets' checksums
++.TP 20
++.M Shaper n
++shapes traffic to maximum rate (pkt/s)
++.TP 20
++.M SimpleQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Socket n
++a socket transport (user-level)
++.TP 20
++.M SortedIPLookup n " (deprecated)"
++simple IP routing table
++.TP 20
++.M SourceIPHashMapper n
++Source IP Hash mapper for
++.M IPRewriter n
++.TP 20
++.M SpinlockAcquire n
++acquires spinlock
++.TP 20
++.M SpinlockInfo n
++specifies names of spinlocks
++.TP 20
++.M SpinlockRelease n
++releases spinlock
++.TP 20
++.M StaticIPLookup n
++simple static IP routing table
++.TP 20
++.M StaticPullSwitch n
++forwards pull requests to fixed input
++.TP 20
++.M StaticSwitch n
++sends packet stream to fixed output
++.TP 20
++.M StaticThreadSched n
++specifies element and thread scheduling parameters
++.TP 20
++.M StoreData n
++changes packet data
++.TP 20
++.M StoreIPAddress n
++stores IP address in packet
++.TP 20
++.M StrideSched n
++pulls from stride-scheduled inputs
++.TP 20
++.M StrideSwitch n
++sends packets to stride-scheduled outputs
++.TP 20
++.M Strip n
++strips bytes from front of packets
++.TP 20
++.M StripIPHeader n
++strips outermost IP header
++.TP 20
++.M StripToNetworkHeader n
++strips everything preceding network header
++.TP 20
++.M Suppressor n
++passes packets unchanged, optionally dropping some input ports
++.TP 20
++.M Switch n
++sends packet stream to settable output
++.TP 20
++.M TCPRewriter n
++rewrites TCP packets' addresses, ports, and sequence numbers
++.TP 20
++.M Tee n
++duplicates packets
++.TP 20
++.M TimedSink n
++periodically pulls and drops a packet
++.TP 20
++.M TimedSource n
++periodically generates a packet
++.TP 20
++.M ToDevice n
++sends packets to network device (Linux kernel)
++.TP 20
++.M ToDevice.u n
++sends packets to network device (user-level)
++.TP 20
++.M ToDump n
++writes packets to a tcpdump file
++.TP 20
++.M ToHost n
++sends packets to Linux
++.TP 20
++.M ToHost.u n
++sends packets to Linux via Universal TUN/TAP device.
++.TP 20
++.M ToHostSniffers n
++sends packets to Linux packet sniffers
++.TP 20
++.M ToRawSocket n
++sends IP packets through a safe raw socket (user-level)
++.TP 20
++.M ToSocket n
++sends data to socket (user-level)
++.TP 20
++.M Truncate n
++limit packet length.
++.TP 20
++.M UDPIPEncap n
++encapsulates packets in static UDP/IP headers
++.TP 20
++.M UMLSwitch n
++Connects to a UML switch daemon
++.TP 20
++.M Unqueue n
++pull-to-push converter
++.TP 20
++.M Unqueue2 n
++pull-to-push converter
++.TP 20
++.M Unstrip n
++unstrips bytes from front of packets
++.TP 20
++.M UnstripIPHeader n
++restores outermost IP header
++.PD
+diff -Nurb click-1.6.0/inst/share/man/mann/elements.n click-1.6.0-27/inst/share/man/mann/elements.n
+--- click-1.6.0/inst/share/man/mann/elements.n 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/inst/share/man/mann/elements.n 2009-02-11 14:08:52.000000000 -0500
+@@ -0,0 +1,1323 @@
++.\" -*- mode: nroff -*-
++.\" Generated by 'click-elem2man'
++.de M
++.IR "\\$1" "(\\$2)\\$3"
++..
++.de RM
++.RI "\\$1" "\\$2" "(\\$3)\\$4"
++..
++.TH "ELEMENTS" n "11/Feb/2009" "Click"
++.SH "NAME"
++elements - documented Click element classes
++.SH "DESCRIPTION"
++This page lists all Click element classes that have manual page documentation.
++.\"html <p><a href="#BY+FUNCTION"><b>By Function</b></a>:
++.\"html <a href="#Basic+Sources+and+Sinks">Basic Sources and Sinks</a> - <a href="#Basic+Classification+and+Selection">Basic Classification and Selection</a> - <a href="#Basic+Packet+Transfer">Basic Packet Transfer</a> - <a href="#Counters">Counters</a> - <a href="#Timestamps">Timestamps</a> - <a href="#Basic+Packet+Modification">Basic Packet Modification</a> - <a href="#Packet+Storage">Packet Storage</a> - <a href="#Active+Queue+Management">Active Queue Management</a> - <a href="#Packet+Scheduling">Packet Scheduling</a> - <a href="#Traffic+Shaping">Traffic Shaping</a> - <a href="#Information+Elements">Information Elements</a> - <a href="#Network+Devices">Network Devices</a> - <a href="#Host+and+Socket+Communication">Host and Socket Communication</a> - <a href="#Ethernet">Ethernet</a> - <a href="#ARP">ARP</a> - <a href="#IPv4">IPv4</a> - <a href="#IPv4+Routing">IPv4 Routing</a> - <a href="#ICMP">ICMP</a> - <a href="#Network+Address+Translation">Network Address Translation</a> - <a href="#TCP">TCP</a> - <a href="#UDP">UDP</a> - <a href="#Trace+Manipulation">Trace Manipulation</a> - <a href="#TCP/IP+Measurement">TCP/IP Measurement</a> - <a href="#CRCs">CRCs</a> - <a href="#Paint+Annotations">Paint Annotations</a> - <a href="#Annotations">Annotations</a> - <a href="#Debugging">Debugging</a> - <a href="#Control">Control</a> - <a href="#Multithreaded+Click">Multithreaded Click</a> - <a href="#devices">devices</a> - <a href="#Basic+Sources+and+Sinks">Basic Sources and Sinks</a> - <a href="#Basic+Classification+and+Selection">Basic Classification and Selection</a> - <a href="#Basic+Packet+Transfer">Basic Packet Transfer</a> - <a href="#Counters">Counters</a> - <a href="#Timestamps">Timestamps</a> - <a href="#Basic+Packet+Modification">Basic Packet Modification</a> - <a href="#Packet+Storage">Packet Storage</a> - <a href="#Active+Queue+Management">Active Queue Management</a> - <a href="#Packet+Scheduling">Packet Scheduling</a> - <a href="#Traffic+Shaping">Traffic Shaping</a> - <a href="#Information+Elements">Information Elements</a> - <a href="#Network+Devices">Network Devices</a> - <a href="#Host+and+Socket+Communication">Host and Socket Communication</a> - <a href="#Ethernet">Ethernet</a> - <a href="#ARP">ARP</a> - <a href="#IPv4">IPv4</a> - <a href="#IPv4+Routing">IPv4 Routing</a> - <a href="#ICMP">ICMP</a> - <a href="#Network+Address+Translation">Network Address Translation</a> - <a href="#TCP">TCP</a> - <a href="#UDP">UDP</a> - <a href="#Trace+Manipulation">Trace Manipulation</a> - <a href="#TCP/IP+Measurement">TCP/IP Measurement</a> - <a href="#CRCs">CRCs</a> - <a href="#Paint+Annotations">Paint Annotations</a> - <a href="#Annotations">Annotations</a> - <a href="#Debugging">Debugging</a> - <a href="#Control">Control</a> - <a href="#Multithreaded+Click">Multithreaded Click</a> - <a href="#devices">devices</a><br>
++.\"html <a href="#ALPHABETICAL+LIST"><b>Alphabetical List</b></a></p>
++.SH "BY FUNCTION"
++.SS "Basic Sources and Sinks"
++.PP
++.PD 0
++.TP 20
++.M Discard n
++drops all packets
++.TP 20
++.M DiscardNoFree n
++drops all packets, but does not free any of them.
++.TP 20
++.M Idle n
++discards packets
++.TP 20
++.M InfiniteSource n
++generates packets whenever scheduled
++.TP 20
++.M RandomSource n
++generates random packets whenever scheduled
++.TP 20
++.M RatedSource n
++generates packets at specified rate
++.TP 20
++.M TimedSink n
++periodically pulls and drops a packet
++.TP 20
++.M TimedSource n
++periodically generates a packet
++.PD
++.SS "Basic Classification and Selection"
++.PP
++.PD 0
++.TP 20
++.M CheckLength n
++drops large packets
++.TP 20
++.M Classifier n
++classifies packets by contents
++.TP 20
++.M HashSwitch n
++classifies packets by hash of contents
++.TP 20
++.M RandomSample n
++samples packets with some probability
++.TP 20
++.M RandomSwitch n
++sends packets to random outputs
++.TP 20
++.M RoundRobinSwitch n
++sends packets to round-robin outputs
++.TP 20
++.M StaticSwitch n
++sends packet stream to fixed output
++.TP 20
++.M StrideSwitch n
++sends packets to stride-scheduled outputs
++.TP 20
++.M Suppressor n
++passes packets unchanged, optionally dropping some input ports
++.TP 20
++.M Switch n
++sends packet stream to settable output
++.PD
++.SS "Basic Packet Transfer"
++.PP
++.PD 0
++.TP 20
++.M Null n
++passes packets unchanged
++.TP 20
++.M Null1 n
++copy of
++.M Null "n"
++.TP 20
++.M PullNull n
++passes packets unchanged
++.TP 20
++.M PullTee n
++duplicates packets
++.TP 20
++.M PushNull n
++passes packets unchanged
++.TP 20
++.M Tee n
++duplicates packets
++.PD
++.SS "Counters"
++.PP
++.PD 0
++.TP 20
++.M AverageCounter n
++measures historical packet count and rate
++.TP 20
++.M Counter n
++measures packet count and rate
++.TP 20
++.M CycleCountAccum n
++collects differences in cycle counters
++.TP 20
++.M PerfCountAccum n
++collects differences in Pentium Pro performance metrics
++.TP 20
++.M PerfCountInfo n
++turn on Pentium Pro performance metrics
++.TP 20
++.M RoundTripCycleCount n
++measures round trip cycles on a push or pull path
++.TP 20
++.M SetCycleCount n
++stores cycle count in annotation
++.TP 20
++.M SetPerfCount n
++stores Pentium Pro performance metric in annotation
++.PD
++.SS "Timestamps"
++.PP
++.PD 0
++.TP 20
++.M SetTimestamp n
++store the time in the packet's timestamp annotation
++.PD
++.SS "Basic Packet Modification"
++.PP
++.PD 0
++.TP 20
++.M Align n
++aligns packet data
++.TP 20
++.M RandomBitErrors n
++changes packet data with some probability
++.TP 20
++.M StoreData n
++changes packet data
++.TP 20
++.M Strip n
++strips bytes from front of packets
++.TP 20
++.M StripToNetworkHeader n
++strips everything preceding network header
++.TP 20
++.M Truncate n
++limit packet length.
++.TP 20
++.M Unstrip n
++unstrips bytes from front of packets
++.PD
++.SS "Packet Storage"
++.PP
++.PD 0
++.TP 20
++.M FrontDropQueue n
++stores packets in drop-from-front FIFO queue
++.TP 20
++.M MixedQueue n
++stores packets in a FIFO/LIFO queue
++.TP 20
++.M NotifierQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Queue n
++stores packets in a FIFO queue
++.TP 20
++.M SimpleQueue n
++stores packets in a FIFO queue
++.PD
++.SS "Active Queue Management"
++.PP
++.PD 0
++.TP 20
++.M AdaptiveRED n
++drops packets according to Adaptive RED
++.TP 20
++.M RED n
++drops packets according to RED
++.PD
++.SS "Packet Scheduling"
++.PP
++.PD 0
++.TP 20
++.M DRRSched n
++pulls from inputs with deficit round robin scheduling
++.TP 20
++.M PrioSched n
++pulls from priority-scheduled inputs
++.TP 20
++.M PullSwitch n
++forwards pull requests to settable input
++.TP 20
++.M RoundRobinSched n
++pulls from round-robin inputs
++.TP 20
++.M StaticPullSwitch n
++forwards pull requests to fixed input
++.TP 20
++.M StrideSched n
++pulls from stride-scheduled inputs
++.PD
++.SS "Traffic Shaping"
++.PP
++.PD 0
++.TP 20
++.M BandwidthMeter n
++classifies packet stream by arrival rate
++.TP 20
++.M BandwidthRatedSplitter n
++splits flow of packets at specified bandwidth rate
++.TP 20
++.M BandwidthRatedUnqueue n
++pull-to-push converter
++.TP 20
++.M BandwidthShaper n
++shapes traffic to maximum rate (bytes/s)
++.TP 20
++.M Burster n
++pull-to-push converter
++.TP 20
++.M CompareBlock n
++drops packets out of rate range
++.TP 20
++.M DelayShaper n
++shapes traffic to meet delay requirements
++.TP 20
++.M DelayUnqueue n
++delay inducing pull-to-push converter
++.TP 20
++.M LinkUnqueue n
++link emulator
++.TP 20
++.M Meter n
++classifies packet stream by rate (pkt/s)
++.TP 20
++.M RatedSplitter n
++splits flow of packets at specified rate
++.TP 20
++.M RatedUnqueue n
++pull-to-push converter
++.TP 20
++.M Shaper n
++shapes traffic to maximum rate (pkt/s)
++.TP 20
++.M Unqueue n
++pull-to-push converter
++.TP 20
++.M Unqueue2 n
++pull-to-push converter
++.PD
++.SS "Information Elements"
++.PP
++.PD 0
++.TP 20
++.M AddressInfo n
++specifies address information
++.TP 20
++.M AlignmentInfo n
++specifies alignment information
++.TP 20
++.M PortInfo n
++stores named TCP/UDP port information
++.TP 20
++.M ScheduleInfo n
++specifies scheduling parameters
++.TP 20
++.M ScheduleLinux n
++returns to Linux scheduler
++.PD
++.SS "Network Devices"
++.PP
++.PD 0
++.TP 20
++.M FromDevice n
++reads packets from network device (Linux kernel)
++.TP 20
++.M FromDevice.u n
++reads packets from network device (user-level)
++.TP 20
++.M PollDevice n
++polls packets from network device (kernel)
++.TP 20
++.M ToDevice n
++sends packets to network device (Linux kernel)
++.TP 20
++.M ToDevice.u n
++sends packets to network device (user-level)
++.PD
++.SS "Host and Socket Communication"
++.PP
++.PD 0
++.TP 20
++.M FromHost n
++reads packets from Linux
++.TP 20
++.M FromHost.u n
++interface to /dev/net/tun or ethertap (user-level)
++.TP 20
++.M FromRawSocket n
++reads raw IP packets from safe raw socket (user-level)
++.TP 20
++.M FromSocket n
++reads data from socket (user-level)
++.TP 20
++.M KernelFilter n
++block kernel from handling packets
++.TP 20
++.M KernelTap n
++interface to /dev/tap or ethertap (user-level)
++.TP 20
++.M KernelTun n
++interface to /dev/tun or ethertap (user-level)
++.TP 20
++.M RawSocket n
++transports raw IP packets via safe raw sockets (user-level)
++.TP 20
++.M Socket n
++a socket transport (user-level)
++.TP 20
++.M ToHost n
++sends packets to Linux
++.TP 20
++.M ToHost.u n
++sends packets to Linux via Universal TUN/TAP device.
++.TP 20
++.M ToHostSniffers n
++sends packets to Linux packet sniffers
++.TP 20
++.M ToRawSocket n
++sends IP packets through a safe raw socket (user-level)
++.TP 20
++.M ToSocket n
++sends data to socket (user-level)
++.PD
++.SS "Ethernet"
++.PP
++.PD 0
++.TP 20
++.M EnsureEther n
++ensures that IP packets are Ethernet encapsulated
++.TP 20
++.M EtherEncap n
++encapsulates packets in Ethernet header
++.TP 20
++.M EtherMirror n
++swaps Ethernet source and destination
++.TP 20
++.M HostEtherFilter n
++drops Ethernet packets sent to other machines
++.PD
++.SS "ARP"
++.PP
++.PD 0
++.TP 20
++.M ARPFaker n
++periodically generates an ARP reply
++.TP 20
++.M ARPPrint n
++pretty-prints ARP packets a la tcpdump
++.TP 20
++.M ARPQuerier n
++encapsulates IP packets in Ethernet headers found via ARP
++.TP 20
++.M ARPResponder n
++generates responses to ARP queries
++.TP 20
++.M CheckARPHeader n
++checks ARP header
++.PD
++.SS "IPv4"
++.PP
++.PD 0
++.TP 20
++.M CheckIPHeader n
++checks IP header
++.TP 20
++.M CheckIPHeader2 n
++checks IP header, no checksum
++.TP 20
++.M DecIPTTL n
++decrements IP time-to-live, drops dead packets
++.TP 20
++.M FixIPSrc n
++sets IP source field if requested by annotation
++.TP 20
++.M GetIPAddress n
++sets destination IP address annotation from packet data
++.TP 20
++.M IPClassifier n
++classifies IP packets by contents
++.TP 20
++.M IPEncap n
++encapsulates packets in static IP header
++.TP 20
++.M IPFilter n
++filters IP packets by contents
++.TP 20
++.M IPFragmenter n
++fragments large IP packets
++.TP 20
++.M IPGWOptions n
++processes router IP options
++.TP 20
++.M IPInputCombo n
++input combo for IP routing
++.TP 20
++.M IPMirror n
++swaps IP source and destination
++.TP 20
++.M IPNameInfo n
++stores name information about IP packets
++.TP 20
++.M IPOutputCombo n
++output combo for IP routing
++.TP 20
++.M IPPrint n
++pretty-prints IP packets
++.TP 20
++.M IPReassembler n
++Reassembles fragmented IP packets
++.TP 20
++.M MarkIPCE n
++sets IP packets' ECN field to Congestion Experienced
++.TP 20
++.M MarkIPHeader n
++sets IP header annotation
++.TP 20
++.M SetIPAddress n
++sets destination IP address annotations
++.TP 20
++.M SetIPChecksum n
++sets IP packets' checksums
++.TP 20
++.M SetIPDSCP n
++sets IP packets' DSCP fields
++.TP 20
++.M SetRandIPAddress n
++sets destination IP address annotations randomly
++.TP 20
++.M StoreIPAddress n
++stores IP address in packet
++.TP 20
++.M StripIPHeader n
++strips outermost IP header
++.TP 20
++.M UnstripIPHeader n
++restores outermost IP header
++.PD
++.SS "IPv4 Routing"
++.PP
++.PD 0
++.TP 20
++.M DirectIPLookup n
++IP routing lookup using direct-indexed tables
++.TP 20
++.M IPRouteTable n
++IP routing table superclass
++.TP 20
++.M LinearIPLookup n
++simple IP routing table
++.TP 20
++.M LinuxIPLookup n
++interface to Linux's routing table
++.TP 20
++.M RadixIPLookup n
++IP lookup using a radix trie
++.TP 20
++.M RangeIPLookup n
++IP routing lookup through binary search in a very compact table
++.TP 20
++.M RIPSend n
++periodically generates specified RIP II packet
++.TP 20
++.M SortedIPLookup n " (deprecated)"
++simple IP routing table
++.TP 20
++.M StaticIPLookup n
++simple static IP routing table
++.PD
++.SS "ICMP"
++.PP
++.PD 0
++.TP 20
++.M CheckICMPHeader n
++checks ICMP header on ICMP packets
++.TP 20
++.M ICMPError n
++generates ICMP error packets
++.TP 20
++.M ICMPPingEncap n
++encapsulates packets in ICMP ping headers
++.TP 20
++.M ICMPPingResponder n
++responds to ICMP echo requests
++.TP 20
++.M ICMPPingSource n
++periodically sends ICMP echo requests
++.PD
++.SS "Network Address Translation"
++.PP
++.PD 0
++.TP 20
++.M FTPPortMapper n
++manipulates
++.M IPRewriter "n"
++for FTP
++.TP 20
++.M ICMPPingRewriter n
++rewrites ICMP echo requests and replies
++.TP 20
++.M ICMPRewriter n
++rewrites ICMP packets based on IP rewriter mappings
++.TP 20
++.M IPAddrPairRewriter n
++rewrites IP packets' addresses by address pair
++.TP 20
++.M IPAddrRewriter n
++rewrites IP packets' addresses
++.TP 20
++.M IPRewriter n
++rewrites TCP/UDP packets' addresses and ports
++.TP 20
++.M IPRewriterPatterns n
++specifies shared
++.M IPRewriter n
++patterns
++.TP 20
++.M RoundRobinIPMapper n
++round-robin mapper for
++.M IPRewriter n
++.TP 20
++.M SourceIPHashMapper n
++Source IP Hash mapper for
++.M IPRewriter n
++.TP 20
++.M TCPRewriter n
++rewrites TCP packets' addresses, ports, and sequence numbers
++.PD
++.SS "TCP"
++.PP
++.PD 0
++.TP 20
++.M CheckTCPHeader n
++checks TCP header on TCP/IP packets
++.TP 20
++.M FastTCPFlows n
++creates packets flows with static TCP/IP/Ethernet headers
++.TP 20
++.M RFC2507Comp n
++RFC2507 IPv4/TCP header compressor.
++.TP 20
++.M RFC2507Decomp n
++RFC2507 IPv4/TCP header decompressor.
++.TP 20
++.M SetTCPChecksum n
++sets TCP packets' checksums
++.PD
++.SS "UDP"
++.PP
++.PD 0
++.TP 20
++.M CheckUDPHeader n
++checks UDP header on UDP/IP packets
++.TP 20
++.M DynamicUDPIPEncap n
++encapsulates packets in dynamic UDP/IP headers
++.TP 20
++.M FastUDPFlows n
++creates packets flows with static UDP/IP/Ethernet headers
++.TP 20
++.M FastUDPSource n
++creates packets with static UDP/IP/Ethernet headers
++.TP 20
++.M SetUDPChecksum n
++sets UDP packets' checksums
++.TP 20
++.M UDPIPEncap n
++encapsulates packets in static UDP/IP headers
++.PD
++.SS "Trace Manipulation"
++.PP
++.PD 0
++.TP 20
++.M FromDump n
++reads packets from a tcpdump file
++.TP 20
++.M ToDump n
++writes packets to a tcpdump file
++.PD
++.SS "TCP/IP Measurement"
++.PP
++.PD 0
++.TP 20
++.M IPRateMonitor n
++measures coming and going IP traffic rates
++.PD
++.SS "CRCs"
++.PP
++.PD 0
++.TP 20
++.M CheckCRC32 n
++checks packet CRC32s
++.TP 20
++.M SetCRC32 n
++calculates CRC32 and prepends to packet
++.PD
++.SS "Paint Annotations"
++.PP
++.PD 0
++.TP 20
++.M CheckPaint n
++checks packets' paint annotation
++.TP 20
++.M Paint n
++sets packet paint annotations
++.TP 20
++.M PaintSwitch n
++sends packet stream to output chosen per-packet
++.TP 20
++.M PaintTee n
++duplicates packets with given paint annotation
++.PD
++.SS "Annotations"
++.PP
++.PD 0
++.TP 20
++.M DropBroadcasts n
++drops link-level broadcast and multicast packets
++.TP 20
++.M SetAnnoByte n
++sets packet user annotations
++.TP 20
++.M SetPacketType n
++sets packet type annotation
++.PD
++.SS "Debugging"
++.PP
++.PD 0
++.TP 20
++.M Error n
++always fails
++.TP 20
++.M Print n
++prints packet contents
++.PD
++.SS "Control"
++.PP
++.PD 0
++.TP 20
++.M ChangeUID n
++relinquish root privilege
++.TP 20
++.M ChatterSocket n
++reports chatter messages to connected sockets
++.TP 20
++.M ControlSocket n
++opens control sockets for other programs
++.TP 20
++.M DriverManager n
++a
++.M Script "n"
++that manages driver stop events
++.TP 20
++.M KernelHandlerProxy n
++proxies kernel module handlers at user level
++.TP 20
++.M Message n
++prints a message on configuration
++.TP 20
++.M PokeHandlers n " (deprecated)"
++calls write handlers at specified times
++.TP 20
++.M ProgressBar n
++prints a progress bar to standard error
++.TP 20
++.M QuitWatcher n
++stops router processing
++.TP 20
++.M Script n
++script a Click router configuration
++.PD
++.SS "Multithreaded Click"
++.PP
++.PD 0
++.TP 20
++.M CPUQueue n
++stores packets in FIFO queues.
++.TP 20
++.M CPUSwitch n
++classifies packets by cpu
++.TP 20
++.M LookupIPRouteMP n
++simple static IP routing table
++.TP 20
++.M MSQueue n
++stores packets in a FIFO queue
++.TP 20
++.M SpinlockAcquire n
++acquires spinlock
++.TP 20
++.M SpinlockInfo n
++specifies names of spinlocks
++.TP 20
++.M SpinlockRelease n
++releases spinlock
++.TP 20
++.M StaticThreadSched n
++specifies element and thread scheduling parameters
++.PD
++.SS "devices"
++.PP
++.PD 0
++.TP 20
++.M UMLSwitch n
++Connects to a UML switch daemon
++.PD
++.SH "ALPHABETICAL LIST"
++.PP
++.PD 0
++.TP 20
++.M AdaptiveRED n
++drops packets according to Adaptive RED
++.TP 20
++.M AddressInfo n
++specifies address information
++.TP 20
++.M Align n
++aligns packet data
++.TP 20
++.M AlignmentInfo n
++specifies alignment information
++.TP 20
++.M ARPFaker n
++periodically generates an ARP reply
++.TP 20
++.M ARPPrint n
++pretty-prints ARP packets a la tcpdump
++.TP 20
++.M ARPQuerier n
++encapsulates IP packets in Ethernet headers found via ARP
++.TP 20
++.M ARPResponder n
++generates responses to ARP queries
++.TP 20
++.M AverageCounter n
++measures historical packet count and rate
++.TP 20
++.M BandwidthMeter n
++classifies packet stream by arrival rate
++.TP 20
++.M BandwidthRatedSplitter n
++splits flow of packets at specified bandwidth rate
++.TP 20
++.M BandwidthRatedUnqueue n
++pull-to-push converter
++.TP 20
++.M BandwidthShaper n
++shapes traffic to maximum rate (bytes/s)
++.TP 20
++.M Burster n
++pull-to-push converter
++.TP 20
++.M ChangeUID n
++relinquish root privilege
++.TP 20
++.M ChatterSocket n
++reports chatter messages to connected sockets
++.TP 20
++.M CheckARPHeader n
++checks ARP header
++.TP 20
++.M CheckCRC32 n
++checks packet CRC32s
++.TP 20
++.M CheckICMPHeader n
++checks ICMP header on ICMP packets
++.TP 20
++.M CheckIPHeader n
++checks IP header
++.TP 20
++.M CheckIPHeader2 n
++checks IP header, no checksum
++.TP 20
++.M CheckLength n
++drops large packets
++.TP 20
++.M CheckPaint n
++checks packets' paint annotation
++.TP 20
++.M CheckTCPHeader n
++checks TCP header on TCP/IP packets
++.TP 20
++.M CheckUDPHeader n
++checks UDP header on UDP/IP packets
++.TP 20
++.M Classifier n
++classifies packets by contents
++.TP 20
++.M CompareBlock n
++drops packets out of rate range
++.TP 20
++.M ControlSocket n
++opens control sockets for other programs
++.TP 20
++.M Counter n
++measures packet count and rate
++.TP 20
++.M CPUQueue n
++stores packets in FIFO queues.
++.TP 20
++.M CPUSwitch n
++classifies packets by cpu
++.TP 20
++.M CycleCountAccum n
++collects differences in cycle counters
++.TP 20
++.M DecIPTTL n
++decrements IP time-to-live, drops dead packets
++.TP 20
++.M DelayShaper n
++shapes traffic to meet delay requirements
++.TP 20
++.M DelayUnqueue n
++delay inducing pull-to-push converter
++.TP 20
++.M DirectIPLookup n
++IP routing lookup using direct-indexed tables
++.TP 20
++.M Discard n
++drops all packets
++.TP 20
++.M DiscardNoFree n
++drops all packets, but does not free any of them.
++.TP 20
++.M DriverManager n
++a
++.M Script "n"
++that manages driver stop events
++.TP 20
++.M DropBroadcasts n
++drops link-level broadcast and multicast packets
++.TP 20
++.M DRRSched n
++pulls from inputs with deficit round robin scheduling
++.TP 20
++.M DynamicUDPIPEncap n
++encapsulates packets in dynamic UDP/IP headers
++.TP 20
++.M EnsureEther n
++ensures that IP packets are Ethernet encapsulated
++.TP 20
++.M Error n
++always fails
++.TP 20
++.M EtherEncap n
++encapsulates packets in Ethernet header
++.TP 20
++.M EtherMirror n
++swaps Ethernet source and destination
++.TP 20
++.M FastTCPFlows n
++creates packets flows with static TCP/IP/Ethernet headers
++.TP 20
++.M FastUDPFlows n
++creates packets flows with static UDP/IP/Ethernet headers
++.TP 20
++.M FastUDPSource n
++creates packets with static UDP/IP/Ethernet headers
++.TP 20
++.M FixIPSrc n
++sets IP source field if requested by annotation
++.TP 20
++.M FromDevice n
++reads packets from network device (Linux kernel)
++.TP 20
++.M FromDevice.u n
++reads packets from network device (user-level)
++.TP 20
++.M FromDump n
++reads packets from a tcpdump file
++.TP 20
++.M FromHost n
++reads packets from Linux
++.TP 20
++.M FromHost.u n
++interface to /dev/net/tun or ethertap (user-level)
++.TP 20
++.M FromRawSocket n
++reads raw IP packets from safe raw socket (user-level)
++.TP 20
++.M FromSocket n
++reads data from socket (user-level)
++.TP 20
++.M FrontDropQueue n
++stores packets in drop-from-front FIFO queue
++.TP 20
++.M FTPPortMapper n
++manipulates
++.M IPRewriter "n"
++for FTP
++.TP 20
++.M GetIPAddress n
++sets destination IP address annotation from packet data
++.TP 20
++.M HashSwitch n
++classifies packets by hash of contents
++.TP 20
++.M HostEtherFilter n
++drops Ethernet packets sent to other machines
++.TP 20
++.M ICMPError n
++generates ICMP error packets
++.TP 20
++.M ICMPPingEncap n
++encapsulates packets in ICMP ping headers
++.TP 20
++.M ICMPPingResponder n
++responds to ICMP echo requests
++.TP 20
++.M ICMPPingRewriter n
++rewrites ICMP echo requests and replies
++.TP 20
++.M ICMPPingSource n
++periodically sends ICMP echo requests
++.TP 20
++.M ICMPRewriter n
++rewrites ICMP packets based on IP rewriter mappings
++.TP 20
++.M Idle n
++discards packets
++.TP 20
++.M InfiniteSource n
++generates packets whenever scheduled
++.TP 20
++.M IPAddrPairRewriter n
++rewrites IP packets' addresses by address pair
++.TP 20
++.M IPAddrRewriter n
++rewrites IP packets' addresses
++.TP 20
++.M IPClassifier n
++classifies IP packets by contents
++.TP 20
++.M IPEncap n
++encapsulates packets in static IP header
++.TP 20
++.M IPFilter n
++filters IP packets by contents
++.TP 20
++.M IPFragmenter n
++fragments large IP packets
++.TP 20
++.M IPGWOptions n
++processes router IP options
++.TP 20
++.M IPInputCombo n
++input combo for IP routing
++.TP 20
++.M IPMirror n
++swaps IP source and destination
++.TP 20
++.M IPNameInfo n
++stores name information about IP packets
++.TP 20
++.M IPOutputCombo n
++output combo for IP routing
++.TP 20
++.M IPPrint n
++pretty-prints IP packets
++.TP 20
++.M IPRateMonitor n
++measures coming and going IP traffic rates
++.TP 20
++.M IPReassembler n
++Reassembles fragmented IP packets
++.TP 20
++.M IPRewriter n
++rewrites TCP/UDP packets' addresses and ports
++.TP 20
++.M IPRewriterPatterns n
++specifies shared
++.M IPRewriter n
++patterns
++.TP 20
++.M IPRouteTable n
++IP routing table superclass
++.TP 20
++.M KernelFilter n
++block kernel from handling packets
++.TP 20
++.M KernelHandlerProxy n
++proxies kernel module handlers at user level
++.TP 20
++.M KernelTap n
++interface to /dev/tap or ethertap (user-level)
++.TP 20
++.M KernelTun n
++interface to /dev/tun or ethertap (user-level)
++.TP 20
++.M LinearIPLookup n
++simple IP routing table
++.TP 20
++.M LinkUnqueue n
++link emulator
++.TP 20
++.M LinuxIPLookup n
++interface to Linux's routing table
++.TP 20
++.M LookupIPRouteMP n
++simple static IP routing table
++.TP 20
++.M MarkIPCE n
++sets IP packets' ECN field to Congestion Experienced
++.TP 20
++.M MarkIPHeader n
++sets IP header annotation
++.TP 20
++.M Message n
++prints a message on configuration
++.TP 20
++.M Meter n
++classifies packet stream by rate (pkt/s)
++.TP 20
++.M MixedQueue n
++stores packets in a FIFO/LIFO queue
++.TP 20
++.M MSQueue n
++stores packets in a FIFO queue
++.TP 20
++.M NotifierQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Null n
++passes packets unchanged
++.TP 20
++.M Null1 n
++copy of
++.M Null "n"
++.TP 20
++.M Paint n
++sets packet paint annotations
++.TP 20
++.M PaintSwitch n
++sends packet stream to output chosen per-packet
++.TP 20
++.M PaintTee n
++duplicates packets with given paint annotation
++.TP 20
++.M PerfCountAccum n
++collects differences in Pentium Pro performance metrics
++.TP 20
++.M PerfCountInfo n
++turn on Pentium Pro performance metrics
++.TP 20
++.M PokeHandlers n " (deprecated)"
++calls write handlers at specified times
++.TP 20
++.M PollDevice n
++polls packets from network device (kernel)
++.TP 20
++.M PortInfo n
++stores named TCP/UDP port information
++.TP 20
++.M Print n
++prints packet contents
++.TP 20
++.M PrioSched n
++pulls from priority-scheduled inputs
++.TP 20
++.M ProgressBar n
++prints a progress bar to standard error
++.TP 20
++.M PullNull n
++passes packets unchanged
++.TP 20
++.M PullSwitch n
++forwards pull requests to settable input
++.TP 20
++.M PullTee n
++duplicates packets
++.TP 20
++.M PushNull n
++passes packets unchanged
++.TP 20
++.M Queue n
++stores packets in a FIFO queue
++.TP 20
++.M QuitWatcher n
++stops router processing
++.TP 20
++.M RadixIPLookup n
++IP lookup using a radix trie
++.TP 20
++.M RandomBitErrors n
++changes packet data with some probability
++.TP 20
++.M RandomSample n
++samples packets with some probability
++.TP 20
++.M RandomSource n
++generates random packets whenever scheduled
++.TP 20
++.M RandomSwitch n
++sends packets to random outputs
++.TP 20
++.M RangeIPLookup n
++IP routing lookup through binary search in a very compact table
++.TP 20
++.M RatedSource n
++generates packets at specified rate
++.TP 20
++.M RatedSplitter n
++splits flow of packets at specified rate
++.TP 20
++.M RatedUnqueue n
++pull-to-push converter
++.TP 20
++.M RawSocket n
++transports raw IP packets via safe raw sockets (user-level)
++.TP 20
++.M RED n
++drops packets according to RED
++.TP 20
++.M RFC2507Comp n
++RFC2507 IPv4/TCP header compressor.
++.TP 20
++.M RFC2507Decomp n
++RFC2507 IPv4/TCP header decompressor.
++.TP 20
++.M RIPSend n
++periodically generates specified RIP II packet
++.TP 20
++.M RoundRobinIPMapper n
++round-robin mapper for
++.M IPRewriter n
++.TP 20
++.M RoundRobinSched n
++pulls from round-robin inputs
++.TP 20
++.M RoundRobinSwitch n
++sends packets to round-robin outputs
++.TP 20
++.M RoundTripCycleCount n
++measures round trip cycles on a push or pull path
++.TP 20
++.M ScheduleInfo n
++specifies scheduling parameters
++.TP 20
++.M ScheduleLinux n
++returns to Linux scheduler
++.TP 20
++.M Script n
++script a Click router configuration
++.TP 20
++.M SetAnnoByte n
++sets packet user annotations
++.TP 20
++.M SetCRC32 n
++calculates CRC32 and prepends to packet
++.TP 20
++.M SetCycleCount n
++stores cycle count in annotation
++.TP 20
++.M SetIPAddress n
++sets destination IP address annotations
++.TP 20
++.M SetIPChecksum n
++sets IP packets' checksums
++.TP 20
++.M SetIPDSCP n
++sets IP packets' DSCP fields
++.TP 20
++.M SetPacketType n
++sets packet type annotation
++.TP 20
++.M SetPerfCount n
++stores Pentium Pro performance metric in annotation
++.TP 20
++.M SetRandIPAddress n
++sets destination IP address annotations randomly
++.TP 20
++.M SetTCPChecksum n
++sets TCP packets' checksums
++.TP 20
++.M SetTimestamp n
++store the time in the packet's timestamp annotation
++.TP 20
++.M SetUDPChecksum n
++sets UDP packets' checksums
++.TP 20
++.M Shaper n
++shapes traffic to maximum rate (pkt/s)
++.TP 20
++.M SimpleQueue n
++stores packets in a FIFO queue
++.TP 20
++.M Socket n
++a socket transport (user-level)
++.TP 20
++.M SortedIPLookup n " (deprecated)"
++simple IP routing table
++.TP 20
++.M SourceIPHashMapper n
++Source IP Hash mapper for
++.M IPRewriter n
++.TP 20
++.M SpinlockAcquire n
++acquires spinlock
++.TP 20
++.M SpinlockInfo n
++specifies names of spinlocks
++.TP 20
++.M SpinlockRelease n
++releases spinlock
++.TP 20
++.M StaticIPLookup n
++simple static IP routing table
++.TP 20
++.M StaticPullSwitch n
++forwards pull requests to fixed input
++.TP 20
++.M StaticSwitch n
++sends packet stream to fixed output
++.TP 20
++.M StaticThreadSched n
++specifies element and thread scheduling parameters
++.TP 20
++.M StoreData n
++changes packet data
++.TP 20
++.M StoreIPAddress n
++stores IP address in packet
++.TP 20
++.M StrideSched n
++pulls from stride-scheduled inputs
++.TP 20
++.M StrideSwitch n
++sends packets to stride-scheduled outputs
++.TP 20
++.M Strip n
++strips bytes from front of packets
++.TP 20
++.M StripIPHeader n
++strips outermost IP header
++.TP 20
++.M StripToNetworkHeader n
++strips everything preceding network header
++.TP 20
++.M Suppressor n
++passes packets unchanged, optionally dropping some input ports
++.TP 20
++.M Switch n
++sends packet stream to settable output
++.TP 20
++.M TCPRewriter n
++rewrites TCP packets' addresses, ports, and sequence numbers
++.TP 20
++.M Tee n
++duplicates packets
++.TP 20
++.M TimedSink n
++periodically pulls and drops a packet
++.TP 20
++.M TimedSource n
++periodically generates a packet
++.TP 20
++.M ToDevice n
++sends packets to network device (Linux kernel)
++.TP 20
++.M ToDevice.u n
++sends packets to network device (user-level)
++.TP 20
++.M ToDump n
++writes packets to a tcpdump file
++.TP 20
++.M ToHost n
++sends packets to Linux
++.TP 20
++.M ToHost.u n
++sends packets to Linux via Universal TUN/TAP device.
++.TP 20
++.M ToHostSniffers n
++sends packets to Linux packet sniffers
++.TP 20
++.M ToRawSocket n
++sends IP packets through a safe raw socket (user-level)
++.TP 20
++.M ToSocket n
++sends data to socket (user-level)
++.TP 20
++.M Truncate n
++limit packet length.
++.TP 20
++.M UDPIPEncap n
++encapsulates packets in static UDP/IP headers
++.TP 20
++.M UMLSwitch n
++Connects to a UML switch daemon
++.TP 20
++.M Unqueue n
++pull-to-push converter
++.TP 20
++.M Unqueue2 n
++pull-to-push converter
++.TP 20
++.M Unstrip n
++unstrips bytes from front of packets
++.TP 20
++.M UnstripIPHeader n
++restores outermost IP header
++.PD
+Files click-1.6.0/inst.tar.gz and click-1.6.0-27/inst.tar.gz differ
+diff -Nurb click-1.6.0/installch click-1.6.0-27/installch
+--- click-1.6.0/installch 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/installch 2009-01-28 16:15:43.000000000 -0500
+@@ -0,0 +1,66 @@
++#! /bin/sh
++#
++# installch - install a program, script, or datafile if changed
++#
++# Copyright (c) 2006 Mazu Networks, Inc.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the "Software"),
++# to deal in the Software without restriction, subject to the conditions
++# listed in the Click LICENSE file. These conditions include: you must
++# preserve this copyright notice, and you cannot mention the copyright
++# holders in advertising related to the Software without their permission.
++# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++# notice is a summary of the Click LICENSE file; the license in that file is
++# legally binding.
++
++install=${INSTALL-/usr/bin/install -c}
++src=
++dst=
++multi=
++mode=0755
++user=`id -u`
++group=`id -g`
++
++while [ x"$1" != x ]; do
++ case $1 in
++ -m)
++ mode="$2"; install="$install -m $2"; shift; shift; continue;;
++ -*)
++ echo "installch: unknown option $1" 1>&2; exit 1;;
++ *)
++ if [ x"$src" = x ]; then
++ src="$1"
++ elif [ x"$dst" = x ]; then
++ dst="$1"
++ else
++ multi=1; src="$src $dst"; dst="$1"
++ fi
++ shift; continue;;
++ esac
++done
++
++if [ x"$dst" = x ]; then
++ echo "installch: too few arguments" 1>&2; exit 1
++fi
++
++if [ x"$multi" = 1 -a ! -d "$dst" ]; then
++ echo "installch: last argument must be directory" 1>&2; exit 1
++fi
++
++doinstall () {
++ while [ x"$1" != x ]; do
++ if [ -d "$dst" ]; then d="$dst/"`basename "$1"`; else d="$dst"; fi
++ if [ -r "$d" ] && cmp "$1" "$d" >/dev/null; then
++ chmod $mode "$d" || exit 1
++ chgrp $group "$d" || exit 1
++ else
++ $install "$1" "$d" || exit 1
++ fi
++ shift
++ done
++}
++
++doinstall $src
++
++exit 0
+diff -Nurb click-1.6.0/lib/bitvector.cc.orig click-1.6.0-27/lib/bitvector.cc.orig
+--- click-1.6.0/lib/bitvector.cc.orig 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/lib/bitvector.cc.orig 2007-07-16 19:47:50.000000000 -0400
+@@ -0,0 +1,216 @@
++// -*- c-basic-offset: 4; related-file-name: "../include/click/bitvector.hh" -*-
++/*
++ * bitvector.{cc,hh} -- generic bit vector class
++ * Eddie Kohler
++ *
++ * Copyright (c) 1999-2000 Massachusetts Institute of Technology
++ * Copyright (c) 2002 International Computer Science Institute
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, subject to the conditions
++ * listed in the Click LICENSE file. These conditions include: you must
++ * preserve this copyright notice, and you cannot mention the copyright
++ * holders in advertising related to the Software without their permission.
++ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
++ * notice is a summary of the Click LICENSE file; the license in that file is
++ * legally binding.
++ */
++
++#include <click/config.h>
++#include <click/bitvector.hh>
++CLICK_DECLS
++
++void
++Bitvector::finish_copy_constructor(const Bitvector &o)
++{
++ int nn = max_word();
++ _data = new uint32_t[nn + 1];
++ for (int i = 0; i <= nn; i++)
++ _data[i] = o._data[i];
++}
++
++void
++Bitvector::clear()
++{
++ int nn = max_word();
++ for (int i = 0; i <= nn; i++)
++ _data[i] = 0;
++}
++
++bool
++Bitvector::zero() const
++{
++ int nn = max_word();
++ for (int i = 0; i <= nn; i++)
++ if (_data[i])
++ return false;
++ return true;
++}
++
++void
++Bitvector::resize_to_max(int new_max, bool valid_n)
++{
++ int want_u = (new_max >> 5) + 1;
++ int have_u = (valid_n ? max_word() : MAX_INLINE_WORD) + 1;
++ if (have_u < MAX_INLINE_WORD + 1)
++ have_u = MAX_INLINE_WORD + 1;
++ if (want_u <= have_u)
++ return;
++
++ uint32_t *new_data = new uint32_t[want_u];
++ memcpy(new_data, _data, have_u * sizeof(uint32_t));
++ memset(new_data + have_u, 0, (want_u - have_u) * sizeof(uint32_t));
++ if (_data != &_f0)
++ delete[] _data;
++ _data = new_data;
++}
++
++void
++Bitvector::clear_last()
++{
++ if ((_max&0x1F) != 0x1F) {
++ uint32_t mask = (1U << ((_max&0x1F)+1)) - 1;
++ _data[_max>>5] &= mask;
++ } else if (_max < 0)
++ _data[0] = 0;
++}
++
++Bitvector &
++Bitvector::operator=(const Bitvector &o)
++{
++#if CLICK_LINUXMODULE || CLICK_BSDMODULE
++ // We might not have been initialized properly.
++ if (!_data)
++ _max = -1, _data = &_f0;
++#endif
++ if (&o == this)
++ /* nada */;
++ else if (o.max_word() <= MAX_INLINE_WORD)
++ memcpy(_data, o._data, 8);
++ else {
++ if (_data != &_f0)
++ delete[] _data;
++ _data = new uint32_t[o.max_word() + 1];
++ memcpy(_data, o._data, (o.max_word() + 1) * sizeof(uint32_t));
++ }
++ _max = o._max;
++ return *this;
++}
++
++Bitvector &
++Bitvector::assign(int n, bool value)
++{
++ resize(n);
++ uint32_t bits = (value ? 0xFFFFFFFFU : 0U);
++ int copy = max_word();
++ for (int i = 0; i <= copy; i++)
++ _data[i] = bits;
++ if (value)
++ clear_last();
++ return *this;
++}
++
++void
++Bitvector::negate()
++{
++ int nn = max_word();
++ uint32_t *data = _data;
++ for (int i = 0; i <= nn; i++)
++ data[i] = ~data[i];
++ clear_last();
++}
++
++Bitvector &
++Bitvector::operator&=(const Bitvector &o)
++{
++ assert(o._max == _max);
++ int nn = max_word();
++ uint32_t *data = _data, *o_data = o._data;
++ for (int i = 0; i <= nn; i++)
++ data[i] &= o_data[i];
++ return *this;
++}
++
++Bitvector &
++Bitvector::operator|=(const Bitvector &o)
++{
++ if (o._max > _max)
++ resize(o._max + 1);
++ int nn = max_word();
++ uint32_t *data = _data, *o_data = o._data;
++ for (int i = 0; i <= nn; i++)
++ data[i] |= o_data[i];
++ return *this;
++}
++
++Bitvector &
++Bitvector::operator^=(const Bitvector &o)
++{
++ assert(o._max == _max);
++ int nn = max_word();
++ uint32_t *data = _data, *o_data = o._data;
++ for (int i = 0; i <= nn; i++)
++ data[i] ^= o_data[i];
++ return *this;
++}
++
++void
++Bitvector::or_at(const Bitvector &o, int offset)
++{
++ assert(offset >= 0 && offset + o._max <= _max);
++ uint32_t bits_1st = offset&0x1F;
++ int my_pos = offset>>5;
++ int o_pos = 0;
++ int my_max_word = max_word();
++ int o_max_word = o.max_word();
++ uint32_t *data = _data;
++ uint32_t *o_data = o._data;
++
++ while (true) {
++ uint32_t val = o_data[o_pos];
++ data[my_pos] |= (val << bits_1st);
++
++ my_pos++;
++ if (my_pos > my_max_word)
++ break;
++
++ if (bits_1st)
++ data[my_pos] |= (val >> (32 - bits_1st));
++
++ o_pos++;
++ if (o_pos > o_max_word)
++ break;
++ }
++}
++
++void
++Bitvector::or_with_difference(const Bitvector &o, Bitvector &diff)
++{
++ if (o._max > _max)
++ resize(o._max + 1);
++ if (diff._max > _max)
++ diff.resize(o._max + 1);
++ int nn = max_word();
++ uint32_t *data = _data, *diff_data = diff._data;
++ const uint32_t *o_data = o._data;
++ for (int i = 0; i <= nn; i++) {
++ diff_data[i] = o_data[i] & ~data[i];
++ data[i] |= o_data[i];
++ }
++}
++
++bool
++Bitvector::nonzero_intersection(const Bitvector &o) const
++{
++ int nn = o.max_word();
++ if (nn > max_word())
++ nn = max_word();
++ const uint32_t *data = _data, *o_data = o._data;
++ for (int i = 0; i <= nn; i++)
++ if (data[i] & o_data[i])
++ return true;
++ return false;
++}
++
++CLICK_ENDDECLS
+diff -Nurb click-1.6.0/lib/in_cksum.c.orig click-1.6.0-27/lib/in_cksum.c.orig
+--- click-1.6.0/lib/in_cksum.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ click-1.6.0-27/lib/in_cksum.c.orig 2007-07-16 19:47:50.000000000 -0400
+@@ -0,0 +1,111 @@
++/* -*- c-basic-offset: 4 -*-
++ *
++ * in_cksum.c -- Internet checksum
++ * borrowed, with bug fixes, from one of the BSDs
++ */
++
++#include <click/config.h>
++#if CLICK_BSDMODULE
++# include <sys/param.h>
++# include <sys/proc.h>
++#endif
++#include <clicknet/ip.h>
++#if CLICK_LINUXMODULE
++# include <linux/string.h>
++#else
++# include <string.h>
++#endif
++
++#if !CLICK_LINUXMODULE
++uint16_t
++click_in_cksum(const unsigned char *addr, int len)
++{
++ int nleft = len;
++ const uint16_t *w = (const uint16_t *)addr;
++ uint32_t sum = 0;
++ uint16_t answer = 0;
++
++ /*
++ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
++ * sequential 16 bit words to it, and at the end, fold back all the
++ * carry bits from the top 16 bits into the lower 16 bits.
++ */
++ while (nleft > 1) {
++ sum += *w++;
++ nleft -= 2;
++ }
++
++ /* mop up an odd byte, if necessary */
++ if (nleft == 1) {
++ *(unsigned char *)(&answer) = *(const unsigned char *)w ;
++ sum += answer;
++ }
++
++ /* add back carry outs from top 16 bits to low 16 bits */
++ sum = (sum & 0xffff) + (sum >> 16);
++ sum += (sum >> 16);
++ /* guaranteed now that the lower 16 bits of sum are correct */
++
++ answer = ~sum; /* truncate to 16 bits */
++ return answer;
++}
++
++uint16_t
++click_in_cksum_pseudohdr_raw(uint32_t csum, uint32_t src, uint32_t dst, int proto, int packet_len)
++{
++ assert(csum <= 0xFFFF);
++ csum = ~csum & 0xFFFF;
++# ifdef __i386__
++ // borrowed from Linux
++ __asm__("\n\
++ addl %1, %0\n\
++ adcl %2, %0\n\
++ adcl %3, %0\n\
++ adcl $0, %0\n"
++ : "=r" (csum)
++ : "g" (src), "g" (dst), "g" ((htons(packet_len) << 16) + (proto << 8)), "0" (csum));
++ __asm__("\n\
++ addl %1, %0\n\
++ adcl $0xffff, %0\n"
++ : "=r" (csum)
++ : "r" (csum << 16), "0" (csum & 0xFFFF0000));
++ return (~csum) >> 16;
++# else
++ csum += (src & 0xffff) + (src >> 16);
++ csum += (dst & 0xffff) + (dst >> 16);
++ csum += htons(packet_len) + htons(proto);
++ csum = (csum & 0xffff) + (csum >> 16);
++ return ~(csum + (csum >> 16)) & 0xFFFF;
++# endif
++}
++#endif
++
++uint16_t
++click_in_cksum_pseudohdr_hard(uint32_t csum, const struct click_ip *iph, int packet_len)
++{
++ const uint8_t *opt = (const uint8_t *)(iph + 1);
++ const uint8_t *end_opt = ((const uint8_t *)iph) + (iph->ip_hl << 2);
++ while (opt < end_opt) {
++ /* check one-byte options */
++ if (*opt == IPOPT_NOP) {
++ opt++;
++ continue;
++ } else if (*opt == IPOPT_EOL)
++ break;
++
++ /* check option length */
++ if (opt + 1 >= end_opt || opt[1] < 2 || opt + opt[1] > end_opt)
++ break;
++
++ /* grab correct final destination from source routing option */
++ if ((*opt == IPOPT_SSRR || *opt == IPOPT_LSRR) && opt[1] >= 7) {
++ uint32_t daddr;
++ memcpy(&daddr, opt + opt[1] - 4, 4);
++ return click_in_cksum_pseudohdr_raw(csum, iph->ip_src.s_addr, daddr, iph->ip_p, packet_len);
++ }
++
++ opt += opt[1];
++ }
++
++ return click_in_cksum_pseudohdr_raw(csum, iph->ip_src.s_addr, iph->ip_dst.s_addr, iph->ip_p, packet_len);
++}
+diff -Nurb click-1.6.0/lib/ino.cc click-1.6.0-27/lib/ino.cc
+--- click-1.6.0/lib/ino.cc 2007-09-11 15:39:22.000000000 -0400
++++ click-1.6.0-27/lib/ino.cc 2009-01-20 22:34:50.000000000 -0500
+@@ -34,6 +34,16 @@
+ _generation = 0;
+ }