📄 2
字号:
#include <click/config.h>#include <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/timestamp.hh>#include <clicknet/ether.h>#include <elements/wifi/sr/srpacket.hh>#include "listenmanager.hh"#include "recpheader.hh"ListenManager::ListenManager() : Element(0, 0), _recp_timeout(5), _expire_timeout(200000), _max_recps(5), _enable_recps(true), _enc_ethtype(0){ click_chatter("init listen manager");}ListenManager::~ListenManager(){}void *ListenManager::cast(const char *n){ if (strcmp(n, "ListenManager") == 0) return (ListenManager *) this; else return 0;}intListenManager::configure(Vector<String> &conf, ErrorHandler *errh){ click_chatter("starting listen manager"); int res; unsigned t_recp_timeout(0); res = cp_va_parse(conf, this, errh, cpKeywords, "ETH", cpEtherAddress, "Ethernet address", &_myea, "RECPTIMEOUT", cpUnsigned, "Recepton Report timeout", &t_recp_timeout, "ENCETHTYPE", cpUnsigned, "Ethtype for encoded packets", &_enc_ethtype, cpEnd); if (!_myea) return errh->error("ETH not specified"); if (t_recp_timeout) { _recp_timeout = t_recp_timeout; } if (!_enc_ethtype) { return errh->error("ENCETHTYPE not specified"); } click_chatter("listen manager done"); return res;}intListenManager::enable_recps(const String &arg, Element *e, void *, ErrorHandler *errh){ ListenManager *rm = static_cast<ListenManager *>(e); bool x; if (!cp_bool(arg, &x)) return errh->error("`enable_recps' must be a boolean"); rm->set_enable_recps(x); if (x) click_chatter("%{element}: reception reports enabled", rm); else click_chatter("%{element}: reception reprots disabled", rm); return 0;}voidListenManager::add_handlers(){ add_write_handler("enable_recps", enable_recps, 0); }voidListenManager::add_new_packet(Packet *p, uint32_t now){ click_ether *eth_h = (click_ether *)p->data(); EtherAddress nbr = EtherAddress(eth_h->ether_shost); PacketRID pid = PacketRID(p); StringAccum sa; StringAccum sa1; sa1 << pid._src; sa << "add_new_packet() called with PID (" << sa1.c_str() << ", " << pid._id << ")"; click_chatter("%s: %s", id().cc(), sa.c_str()); PacketState *ps = new PacketState(p->clone()); _ovhdpacks.insert(pid, ps); click_chatter("adding done"); //Register guess for this neighbor source // Register timeouts to delete this packet eventually uint32_t exp_time = now + _expire_timeout; Event e(EVENT_EXPIRE, pid); EventMap::iterator i = _eventmap.find(exp_time); if (i == _eventmap.end()) { EventList *el = new EventList; el->push_front(e); _eventmap[exp_time] = el; click_chatter("%s: add_new_packet() created new EventList entry for expire", id().cc()); } else { EventList *el = (*i).second; el->push_front(e); click_chatter("%s: add_new_packet() added event to existing EventList for expire", id().cc()); }}Packet*ListenManager::get_packet(PacketRID pid){ PacketState *ps = _ovhdpacks.find(pid); if (ps == NULL) { click_chatter("%s dont have the packet ", id().cc()); return NULL; } return ps->_p->clone();} boolListenManager::register_packet_to_recp(Packet *p, uint32_t now){ PacketRID pid = PacketRID(p); PacketState *ps = _ovhdpacks.find(pid); if (ps != NULL) { click_chatter("%s already have the packet ", id().cc()); return false; } add_new_packet(p, now); //get the ip header and parameters const click_ip *iph = p->ip_header(); IPAddress src = IPAddress(iph->ip_src); uint16_t ipid = ntohs(iph->ip_id); StringAccum src_str; src_str << IPAddress(iph->ip_src); StringAccum dst_str; dst_str << IPAddress(iph->ip_dst); click_chatter("%s 12346 srcipaddress:%s dstipaddress:%s seq:%u", id().cc(), src_str.c_str(), dst_str.c_str(), ntohs(iph->ip_id)); if (!_enable_recps) { return true; } // reception reports are enabled at this point //Put entry into the corresponding source's data structure RecpStateList *rsl = _pending.find(src, 0); if (!rsl) { click_chatter("%s register_packet_to_recp empty recptatelist for src %u, timedout size is %u", id().cc(), src_str.c_str(), _timedout.size()); rsl = new RecpStateList; _pending.insert(src, rsl); } // reception reports are stored in sorted order of sequence number RecpStateList::iterator prev = rsl->begin(); RecpStateList::iterator next = prev; bool toinsert = 1; while (next != rsl->end()) { if ((*next)->_id >= ipid) { click_chatter("%s register_packet_to_recp found boundary element in RecpStateList with prev %u, next %u, timedout size is %u", id().cc(), (*prev)->_id, (*next)->_id, _timedout.size()); if ((*next)->_id == ipid) { toinsert = 0; } break; } prev = next++; } // this is a duplicate, packet was already received if (toinsert == 0) { click_chatter("%s register_packet_to_recp skipping insert, duplicate, timedout size is %u", id().cc(), _timedout.size()); return false; } RecpState *rs = new RecpState(ipid, now + _recp_timeout); if (prev == next) { rsl->push_front(rs); } else { rsl->insert_after(prev, rs); } // HANDLE TIMEOUT FUNCTIONS // at this point, this is a new seq, set up a timeout for the recp // also insert into the timeout array if it is not already there click_chatter("%s register_packet_to_recp adding %s to timedout neighbors for time %u, timedout size is %u", id().cc(), src_str.c_str(), rs->_timeout, _timedout.size()); SrcStateList *nsl = _timedout[rs->_timeout]; click_chatter("%s register_packet_to_recp SrcStateList entry is %x, timedout size is %u", id().cc(), nsl, _timedout.size()); if (!nsl) { nsl = new SrcStateList; _timedout[rs->_timeout] = nsl; click_chatter("%s register_packet_to_recp had to insert new SrcStateList entry %x for %u, timedoutsize is %u", id().cc(), nsl, rs->_timeout, _timedout.size()); } // neighbors are stored in sorted order for easy searching SrcStateList::iterator prevn = nsl->begin(); SrcStateList::iterator nextn = prevn; bool exists = 0; while (nextn != nsl->end()){ if ((*nextn)->_src == src) { click_chatter("%s register_packet_to_recp found source entry in SrcStateList with src %s, timedout size is %u", id().cc(), src_str.c_str(), _timedout.size()); exists = 1; break; } prevn = nextn++; } if (exists) { (*nextn)->_nrecps++; } else { SrcState *ns = new SrcState(src); if (prevn == nextn) { nsl->push_front(ns); } else { nsl->insert_after(prevn, ns); } } return true;}//updating the timeout entry for <timeout> and source <src>voidListenManager::update_timeout_list(uint32_t timeout, IPAddress src) { TimeoutList::iterator x = _timedout.find(timeout); SrcStateList *nsl = (*x).second; SrcStateList::iterator prev = nsl->begin(); SrcStateList::iterator next = prev; while (next != nsl->end()) { if ((*next)->_src == src) { click_chatter("%s get_recps_timeout updating nrecps for src %u nrecps is %u, timedout size is %u", id().cc(), src.addr(), (*next)->_nrecps, _timedout.size()); --(*next)->_nrecps; if ((*next)->_nrecps == 0) { click_chatter("%s get_recps_timeout deleting NbrStateList entry for src %u timedout size is %u", id().cc(), src.addr(), _timedout.size()); if (prev == next) { nsl->pop_front(); } else { nsl->erase_after(prev); } } break; } prev = next++; } if (nsl->empty()) { // delete the entire timeout entry
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -