📄 directiplookup.cc
字号:
_vport[vport_i].ll_prev = -1; _vport[vport_i].ll_next = _vport_head; if (_vport_head >= 0) _vport[_vport_head].ll_prev = vport_i; _vport_head = vport_i; } ++_vport[vport_i].refcount; _rtable[rt_i].vport = vport_i; for (int i = start; i < end; i++) { if (_tbl_0_23[i] & 0x8000) { // Entries with plen > 24 already there in _tbl_24_31[]! int sec_i = (_tbl_0_23[i] & 0x7fff) << 8, sec_start, sec_end; if (plen > 24) { sec_start = prefix & 0xFF; sec_end = sec_start + (1 << (32 - plen)); } else { sec_start = 0; sec_end = 256; } for (int j = sec_i + sec_start; j < sec_i + sec_end; j++) { if (plen > _tbl_24_31_plen[j]) { _tbl_24_31[j] = vport_i; _tbl_24_31_plen[j] = plen; } else if (plen < _tbl_24_31_plen[j]) { // Skip a sequence of more-specific entries if (_tbl_24_31_plen[j] > 24) { j |= 0x000000ff >> (_tbl_24_31_plen[j] - 24); } else { i |= 0x00ffffff >> _tbl_24_31_plen[j]; break; } } else if (allow_replace) { _tbl_24_31[j] = vport_i; } else { // plen == _tbl_24_31_plen[j] -> damn! return errh->error("BUG: _tbl_24_31[%08X] collision", j); } } } else { if (plen > _tbl_0_23_plen[i]) { if (plen > 24) { // Allocate a new _tbl_24_31[] entry and populate it assert(!(_tbl_24_31_empty_head & 0x8000)); int sec_i = _tbl_24_31_empty_head << 8; _tbl_24_31_empty_head = _tbl_24_31[sec_i]; int sec_start = prefix & 0xFF; int sec_end = sec_start + (1 << (32 - plen)); for (int j = 0; j < 256; j++) { if (j >= sec_start && j < sec_end) { _tbl_24_31[sec_i + j] = vport_i; _tbl_24_31_plen[sec_i + j] = plen; } else { _tbl_24_31[sec_i + j] = _tbl_0_23[i]; _tbl_24_31_plen[sec_i + j] = _tbl_0_23_plen[i]; } } _tbl_0_23[i] = (sec_i >> 8) | 0x8000; } else { _tbl_0_23[i] = vport_i; _tbl_0_23_plen[i] = plen; } } else if (plen < _tbl_0_23_plen[i]) { // Skip a sequence of more-specific entries i |= 0x00ffffff >> _tbl_0_23_plen[i]; } else if (allow_replace) { _tbl_0_23[i] = vport_i; } else { // plen == _tbl_0_23_plen[i] - must never happen!!! return errh->error("BUG: _tbl_0_23[%08X] collision", i); } } } return 0;}intDirectIPLookup::Table::remove_route(const IPRoute& route, IPRoute* old_route, ErrorHandler *errh){ uint32_t prefix = ntohl(route.addr.addr()); uint32_t plen = route.prefix_len(); int rt_i = find_entry(prefix, plen); IPRoute found_route; if (rt_i < 0 || (rt_i == 0 && _vport[0].port == DISCARD_PORT)) return -ENOENT; found_route = IPRoute(IPAddress(htonl(_rtable[rt_i].prefix)), IPAddress::make_prefix(_rtable[rt_i].plen), _vport[_rtable[rt_i].vport].gw, _vport[_rtable[rt_i].vport].port); if (!route.match(found_route)) return -ENOENT; if (old_route) *old_route = found_route; if (plen == 0) { // Default route is a special case. We never remove it from lookup // tables, but instead only point it to the "discard port". if (rt_i > 0) // Must never happen, checking it just in case... return errh->error("BUG: default route rt_i=%d, should be 0", rt_i); _vport[0].port = DISCARD_PORT; } else { uint32_t start, end, i, j, sec_i, sec_start, sec_end; int newent = -1; int newmask, prev, next; vport_unref(_rtable[rt_i].vport); // Prune our entry from the prefix/len hashtable prev = _rtable[rt_i].ll_prev; next = _rtable[rt_i].ll_next; if (prev >= 0) _rtable[prev].ll_next = next; else _rt_hashtbl[prefix_hash(prefix, plen)] = next; if (next >= 0) _rtable[next].ll_prev = prev; // Add entry to the list of empty _rtable entries _rtable[rt_i].ll_next = _rt_empty_head; _rt_empty_head = rt_i; // Find an entry covering current prefix/len with the longest prefix. for (newmask = plen - 1 ; newmask >= 0 ; newmask--) if (newmask == 0) { newent = 0; // rtable[0] is always the default route break; } else { newent = find_entry(prefix & (0xffffffff << (32 - newmask)), newmask); if (newent > 0) break; } // Replace prefix/plen with newent/mask in lookup tables start = prefix >> 8; if (plen >= 24) end = start + 1; else end = start + (1 << (24 - plen)); for (i = start; i < end; i++) { if (_tbl_0_23[i] & 0x8000) { sec_i = (_tbl_0_23[i] & 0x7fff) << 8; if (plen > 24) { sec_start = prefix & 0xFF; sec_end = sec_start + (1 << (32 - plen)); } else { sec_start = 0; sec_end = 256; } for (j = sec_i + sec_start; j < sec_i + sec_end; j++) { if (plen == _tbl_24_31_plen[j]) { _tbl_24_31[j] = _rtable[newent].vport; _tbl_24_31_plen[j] = newmask; } else if (plen < _tbl_24_31_plen[j]) { // Skip a sequence of more-specific entries if (_tbl_24_31_plen[j] > 24) { j |= 0x000000ff >> (_tbl_24_31_plen[j] - 24); } else { i |= 0x00ffffff >> _tbl_24_31_plen[j]; break; } } else { // plen > _tbl_24_31_plen[j] -> damn! return errh->error("BUG: _tbl_24_31[%08X] inconsistency", j); } } // Check if we can prune the entire secondary table range? for (j = sec_i ; j < sec_i + 255; j++) if (_tbl_24_31_plen[j] != _tbl_24_31_plen[j+1]) break; if (j == sec_i + 255) { // Yup, adjust entries in primary tables... _tbl_0_23[i] = _tbl_24_31[sec_i]; _tbl_0_23_plen[i] = _tbl_24_31_plen[sec_i]; // ... and free up the entry (adding it to free space list) _tbl_24_31[sec_i] = _tbl_24_31_empty_head; _tbl_24_31_empty_head = sec_i >> 8; } } else { if (plen == _tbl_0_23_plen[i]) { _tbl_0_23[i] = _rtable[newent].vport; _tbl_0_23_plen[i] = newmask; } else if (plen < _tbl_0_23_plen[i]) { // Skip a sequence of more-specific entries i |= 0x00ffffff >> _tbl_0_23_plen[i]; } } } } return 0;}// DIRECTIPLOOKUPDirectIPLookup::DirectIPLookup(){}DirectIPLookup::~DirectIPLookup(){}intDirectIPLookup::configure(Vector<String> &conf, ErrorHandler *errh){ int r; if ((r = _t.initialize()) < 0) return r; _t.flush(); return IPRouteTable::configure(conf, errh);}voidDirectIPLookup::cleanup(CleanupStage){ _t.cleanup();}voidDirectIPLookup::push(int, Packet *p){ IPAddress gw; int port = lookup_route(p->dst_ip_anno(), gw); if (port >= 0) { if (gw) p->set_dst_ip_anno(gw); output(port).push(p); } else p->kill();}intDirectIPLookup::lookup_route(IPAddress dest, IPAddress &gw) const{ uint32_t ip_addr = ntohl(dest.addr()); uint16_t vport_i = _t._tbl_0_23[ip_addr >> 8]; if (vport_i & 0x8000) vport_i = _t._tbl_24_31[((vport_i & 0x7fff) << 8) | (ip_addr & 0xff)]; gw = _t._vport[vport_i].gw; return _t._vport[vport_i].port;}intDirectIPLookup::add_route(const IPRoute& route, bool allow_replace, IPRoute* old_route, ErrorHandler *errh){ return _t.add_route(route, allow_replace, old_route, errh);}intDirectIPLookup::remove_route(const IPRoute& route, IPRoute* old_route, ErrorHandler *errh){ return _t.remove_route(route, old_route, errh);}intDirectIPLookup::flush_handler(const String &, Element *e, void *, ErrorHandler *){ DirectIPLookup *t = static_cast<DirectIPLookup *>(e); t->_t.flush(); return 0;}StringDirectIPLookup::dump_routes(){ return _t.dump();}voidDirectIPLookup::add_handlers(){ IPRouteTable::add_handlers(); add_write_handler("flush", flush_handler, 0, Handler::BUTTON);}CLICK_ENDDECLSELEMENT_REQUIRES(IPRouteTable userlevel|bsdmodule)EXPORT_ELEMENT(DirectIPLookup)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -