📄 gridlogger.hh
字号:
#ifndef GRIDLOGGER_HH#define GRIDLOGGER_HH#include <sys/types.h>#include <sys/uio.h>#include <unistd.h>#include <fcntl.h>#include <clicknet/ether.h>#include <clicknet/ip.h>#include <clicknet/udp.h>#include <click/string.hh>#include <click/element.hh>#include "grid.hh"#include "gridgenericrt.hh"#include "gridgenericlogger.hh"CLICK_DECLS/* * =c * GridLogger(I<KEYWORDS>) * * =s Grid * Log Grid-related events. * * =d * * This element provides methods which other Grid components can call * to log significant protocol events. * * Multiple GridLogger elements can co-exist. * * Keyword arguments are: * * =over 8 * * =item LOGFILE * * String. Filename of binary format log file. If this argument is * supplied, the element starts logging to the specified file as soon * as the element is initialized. Otherwise, no logging takes place * until the start_log handler is called. * * =item SHORT_IP * * Boolean. Defaults to true. If true, only log the last byte of IP * Addresses. * * =back * * =h start_log write-only * * When a filename is written, starts logging to that file. Any existing logfile is closed. * * =h stop_log write-only * * Stop logging and close any open logfile. * * =h logfile read-only * * Return the filename of the current logfile, if any. May return the empty string. * * =a * GridRouteTable, DSDVRouteTable, GridTxError, LookupLocalGridRoute */class GridLogger : public GridGenericLogger { enum state_t { WAITING, RECV_AD, EXPIRE_HANDLER }; state_t _state; int _fd; String _fn; bool _log_full_ip; unsigned char _buf[1024]; size_t _bufptr; // index of next byte available in buf bool check_state(state_t s) { assert(_state == s); return _state == s; } bool check_space(size_t needed) { size_t avail = sizeof(_buf) - _bufptr; if (avail < needed) { click_chatter("GridLogger %s: log buffer is too small. total buf size: %u, needed at least %u", id().cc(), sizeof(_buf), needed + _bufptr); return false; } return true; } void write_buf() { if (!log_is_open()) { _bufptr = 0; return; // no log active now } int res = write(_fd, _buf, _bufptr); if (res < 0) click_chatter("GridLogger %s: error writing log buffer: %s", id().cc(), strerror(errno)); else if (res != (int) _bufptr) click_chatter("GridLogger %s: bad write to log buffer, had %u bytes in buffer but wrote %d bytes", id().cc(), (unsigned) _bufptr, res); _bufptr = 0; } void clear_buf() { _bufptr = 0; } size_t bufsz() { return _bufptr; } void add_bytes(void *bytes, size_t n) { if (!check_space(n)) return; memcpy(_buf + _bufptr, bytes, n); _bufptr += n; } void add_one_byte(unsigned char c) { add_bytes(&c, 1); } void add_ip(unsigned ip) { if (_log_full_ip) add_bytes(&ip, sizeof(ip)); else add_one_byte(ntohl(ip) & 0xff); } void add_long(unsigned long v) { v = htonl(v); add_bytes(&v, sizeof(v)); } void dump_buf() { for (size_t i = 0; i < _bufptr; i++) click_chatter("XXXX %x ", (unsigned) _buf[i]); } void add_timeval(struct timeval tv) { tv.tv_sec = htonl(tv.tv_sec); tv.tv_usec = htonl(tv.tv_usec); add_bytes(&tv, sizeof(tv)); } void log_pkt(struct click_ether *eh) { struct grid_hdr *gh = (struct grid_hdr *) (eh + 1); add_one_byte(gh->type); switch (gh->type) { case grid_hdr::GRID_LR_HELLO: case grid_hdr::GRID_HELLO: { struct grid_hello *hlo = (struct grid_hello *) (gh + 1); add_long(ntohl(hlo->seq_no)); break; } case grid_hdr::GRID_NBR_ENCAP: { struct grid_nbr_encap *nbr = (struct grid_nbr_encap *) (gh + 1); add_ip(gh->ip); add_ip(nbr->dst_ip); add_bytes(eh->ether_dhost, 6); log_special_pkt((struct click_ip *) (nbr + 1)); break; } default: ; /* nothing */ } } void log_special_pkt(struct click_ip *ip) { bool special = false; if (ip->ip_p == IP_PROTO_UDP) { struct click_udp *udp = (struct click_udp *) (ip + 1); if (udp->uh_dport == htons(8021)) { // ahh, it's an experiment packet, get the seqno special = true; unsigned char *data = (unsigned char *) (udp + 1); int num_sent = 0; memcpy(&num_sent, data, 4); add_one_byte(SPECIAL_PKT_CODE); add_long(num_sent); } } if (!special) add_one_byte(BORING_PKT_CODE); }public: GridLogger(); ~GridLogger(); const char *class_name() const { return "GridLogger"; } int configure(Vector<String> &, ErrorHandler *); bool can_live_reconfigure() const { return false; } void *cast(const char *); void add_handlers(); // handlers static String read_logfile(Element *, void *); static int write_start_log(const String &, Element *, void *, ErrorHandler *); static int write_stop_log(const String &, Element *, void *, ErrorHandler *); bool open_log(const String &); void close_log(); bool log_is_open() { return _fd >= 0; } private: // these must be distinct from the inherited reason_t values static const unsigned char SENT_AD_CODE = 0x01; static const unsigned char BEGIN_RECV_CODE = 0x02; static const unsigned char END_RECV_CODE = 0x03; static const unsigned char BEGIN_EXPIRE_CODE = 0x04; static const unsigned char END_EXPIRE_CODE = 0x05; static const unsigned char TRUNCATED_CODE = 0x06; static const unsigned char RECV_ADD_ROUTE_CODE = 0x07; static const unsigned char RECV_TRIGGER_ROUTE_CODE = 0x08; static const unsigned char RECV_EXPIRE_ROUTE_CODE = 0x09; static const unsigned char ROUTE_DUMP_CODE = 0x0A; static const unsigned char TX_ERR_CODE = 0x0B; static const unsigned char NO_ROUTE_CODE = 0x0C; static const unsigned char SPECIAL_PKT_CODE = 0x0D; static const unsigned char BORING_PKT_CODE = 0x0E; static const unsigned char RECV_ADD_ROUTE_CODE_EXTRA = 0x0F;public: void log_sent_advertisement(unsigned seq_no, const Timestamp &when) { if (!check_state(WAITING)) return; if (!check_space(1 + sizeof(seq_no) + sizeof(when))) return; add_one_byte(SENT_AD_CODE); add_long(seq_no); add_timeval(when.to_timeval()); write_buf(); } void log_start_recv_advertisement(unsigned seq_no, unsigned ip, const Timestamp &when) { if (!check_state(WAITING)) return; _state = RECV_AD; add_one_byte(BEGIN_RECV_CODE); add_ip(ip); add_long(seq_no); add_timeval(when.to_timeval()); } void log_added_route(reason_t why, const GridGenericRouteTable::RouteEntry &r) { if (!check_state(RECV_AD)) return; add_one_byte(RECV_ADD_ROUTE_CODE); add_one_byte(why); add_ip(r.dest_ip); add_ip(r.next_hop_ip); add_one_byte(r.num_hops()); add_long(r.seq_no()); } void log_added_route(reason_t why, const GridGenericRouteTable::RouteEntry &r, const unsigned extra) { if (!check_state(RECV_AD)) return; add_one_byte(RECV_ADD_ROUTE_CODE_EXTRA); add_one_byte(why); add_ip(r.dest_ip); add_ip(r.next_hop_ip); add_one_byte(r.num_hops()); add_long(r.seq_no()); add_long(extra); } void log_expired_route(reason_t why, unsigned ip) { if (_state != RECV_AD && _state != EXPIRE_HANDLER) { assert(0); return; } if (_state == RECV_AD) { add_one_byte(RECV_EXPIRE_ROUTE_CODE); add_ip(ip); } else { add_one_byte(why); add_ip(ip); } } void log_triggered_route(unsigned ip) { if (!check_state(RECV_AD)) return; add_one_byte(RECV_TRIGGER_ROUTE_CODE); add_ip(ip); } void log_end_recv_advertisement() { if (!check_state(RECV_AD)) return; _state = WAITING; add_one_byte(END_RECV_CODE); write_buf(); } void log_start_expire_handler(const Timestamp &when) { if (!check_state(WAITING)) return; _state = EXPIRE_HANDLER; add_one_byte(BEGIN_EXPIRE_CODE); add_timeval(when.to_timeval()); } void log_end_expire_handler() { if (!check_state(EXPIRE_HANDLER)) return; _state = WAITING; add_one_byte(END_EXPIRE_CODE); if (bufsz() <= 2 + sizeof(struct timeval)) clear_buf(); // don't log if nothing actually expired else write_buf(); } void log_route_dump(const Vector<GridGenericRouteTable::RouteEntry> &rt, const Timestamp &when) { if (!check_state(WAITING)) return; add_one_byte(ROUTE_DUMP_CODE); add_timeval(when.to_timeval()); int n = rt.size(); add_long(n); for (int i = 0; i < rt.size(); i++) { const GridGenericRouteTable::RouteEntry &r = rt[i]; add_ip(r.dest_ip); add_ip(r.next_hop_ip); add_one_byte(r.num_hops()); add_long(r.seq_no()); } write_buf(); } // assumes Grid packet void log_tx_err(const Packet *p, int err, const Timestamp &when) { if (!check_state(WAITING)) return; struct click_ether *eh = (click_ether *) (p->data()); if (eh->ether_type != htons(ETHERTYPE_GRID)) return; add_one_byte(TX_ERR_CODE); add_timeval(when.to_timeval()); add_long((unsigned long) err); log_pkt(eh); write_buf(); } void log_no_route(const Packet *p, const Timestamp &when) { if (!check_state(WAITING)) return; struct click_ether *eh = (click_ether *) (p->data()); if (eh->ether_type != htons(ETHERTYPE_GRID)) return; add_one_byte(NO_ROUTE_CODE); add_timeval(when.to_timeval()); log_pkt(eh); write_buf(); }};CLICK_ENDDECLS#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -