📄 radixiplookup.cc
字号:
// -*- c-basic-offset: 4 -*-/* * radixiplookup.{cc,hh} -- looks up next-hop address in radix table * Eddie Kohler (earlier versions: Thomer M. Gil, Benjie Chen) * * Copyright (c) 1999-2001 Massachusetts Institute of Technology * Copyright (c) 2002 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. */#include <click/config.h>#include <click/ipaddress.hh>#include <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/straccum.hh>#include "radixiplookup.hh"CLICK_DECLSRadixIPLookup::Radix*RadixIPLookup::Radix::make_radix(int bitshift, int n){ if (Radix* r = (Radix*) new unsigned char[sizeof(Radix) + n * sizeof(Child)]) { r->_route_index = -1; r->_bitshift = bitshift; r->_n = n; r->_nchildren = 0; memset(r->_children, 0, n * sizeof(Child)); for (int i = 0; i < n; i++) r->_children[i].key = -1; return r; } else return 0;}voidRadixIPLookup::Radix::free_radix(Radix* r){ if (r->_nchildren) for (int i = 0; i < r->_n; i++) if (r->_children[i].child) free_radix(r->_children[i].child); delete[] (unsigned char *)r;}RadixIPLookup::Radix*RadixIPLookup::Radix::change(uint32_t addr, uint32_t naddr, int key, uint32_t key_priority){ if (naddr == 0) { for (int i = 0; i < _n; i++) if (_children[i].key_priority <= key_priority) { _children[i].key = key; _children[i].key_priority = (key < 0 ? 0 : key_priority); } } else { int i1 = addr >> _bitshift; int i2 = i1 + (naddr >> _bitshift); addr &= (1 << _bitshift) - 1; naddr &= (1 << _bitshift) - 1; if (i1 == i2) { if (!_children[i1].child) { if ((_children[i1].child = make_radix(_bitshift - 4, 16))) _nchildren++; } if (_children[i1].child) return _children[i1].child->change(addr, naddr, key, key_priority); } while (i1 < i2) { if (_children[i1].key_priority <= key_priority) { if ((_children[i1].key >= 0) != (key >= 0)) _nchildren += (key >= 0 ? 1 : -1); _children[i1].key = key; _children[i1].key_priority = (key < 0 ? 0 : key_priority); } i1++; } } return this;}RadixIPLookup::RadixIPLookup() : _vfree(-1), _default_key(-1), _radix(Radix::make_radix(24, 256)){}RadixIPLookup::~RadixIPLookup(){}voidRadixIPLookup::cleanup(CleanupStage){ _v.clear(); Radix::free_radix(_radix); _radix = 0;}StringRadixIPLookup::dump_routes(){ StringAccum sa; for (int j = _vfree; j >= 0; j = _v[j].extra) _v[j].kill(); for (int i = 0; i < _v.size(); i++) if (_v[i].real()) _v[i].unparse(sa, true) << '\n'; return sa.take_string();}intRadixIPLookup::add_route(const IPRoute& route, bool set, IPRoute* old_route, ErrorHandler *){ int found; if (_vfree < 0) { found = _v.size(); _v.push_back(IPRoute()); } else { found = _vfree; _vfree = _v[found].extra; } _v[found] = route; _v[found].extra = -1; int32_t* pprev; uint32_t hmask = ntohl(route.mask.addr()); if (hmask) { Radix* r = _radix->change(ntohl(route.addr.addr()), ~hmask + 1, found, hmask); pprev = &r->_route_index; } else { _default_key = found; pprev = &_default_key; } for (int32_t j = *pprev; j >= 0; j = *pprev) if (route.addr == _v[j].addr && route.mask == _v[j].mask) { int r; if (old_route) *old_route = _v[j]; if (!set && found != j) { _v[found] = _v[j]; r = -EEXIST; } else { _v[found].extra = _v[j].extra; r = 0; } *pprev = found; _v[j].extra = _vfree; _vfree = j; return r; } else pprev = &_v[j].extra; *pprev = found; return 0;}intRadixIPLookup::remove_route(const IPRoute& route, IPRoute* old_route, ErrorHandler*){ int32_t* pprev; uint32_t hmask = ntohl(route.mask.addr()); if (hmask) { Radix* r = _radix->change(ntohl(route.addr.addr()), ~hmask + 1, -1, hmask); pprev = &r->_route_index; } else { // no need to set _default_key; will happen, or not, below pprev = &_default_key; } int r = -ENOENT; for (int32_t j = *pprev; j >= 0; j = *pprev) if (route.match(_v[j])) { if (old_route) *old_route = _v[j]; *pprev = _v[j].extra; _v[j].extra = _vfree; _vfree = j; r = 0; } else { if (_v[j].contains(route) && (hmask = ntohl(_v[j].mask.addr()))) (void) _radix->change(ntohl(_v[j].addr.addr()), ~hmask + 1, j, hmask); pprev = &_v[j].extra; } return r;}intRadixIPLookup::lookup_route(IPAddress addr, IPAddress &gw) const{ int key = Radix::lookup(_radix, _default_key, ntohl(addr.addr())); if (key >= 0 && _v[key].contains(addr)) { gw = _v[key].gw; return _v[key].port; } else { gw = 0; return -1; }}CLICK_ENDDECLSELEMENT_REQUIRES(IPRouteTable)EXPORT_ELEMENT(RadixIPLookup)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -