// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- // vim:set sts=4 ts=8: // Copyright (c) 2001-2007 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 XORP 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 XORP LICENSE file; the license in that file is // legally binding. #ident "$XORP: xorp/rip/route_entry.cc,v 1.15 2007/02/16 22:47:16 pavlin Exp $" #include "rip_module.h" #include "libxorp/ipv4.hh" #include "libxorp/ipv6.hh" #include "libxorp/xlog.h" #include "route_entry.hh" template inline void RouteEntry::dissociate() { RouteEntryOrigin* o = _origin; _origin = 0; if (o) { o->dissociate(this); } } template inline void RouteEntry::associate(Origin* o) { if (o) o->associate(this); _origin = o; } template RouteEntry::RouteEntry(const Net& n, const Addr& nh, uint16_t cost, Origin*& o, uint16_t tag) : _net(n), _nh(nh), _cost(cost), _tag(tag), _ref_cnt(0), _filtered(false) { associate(o); } template RouteEntry::RouteEntry(const Net& n, const Addr& nh, uint16_t cost, Origin*& o, uint16_t tag, const PolicyTags& policytags) : _net(n), _nh(nh), _cost(cost), _tag(tag), _ref_cnt(0), _policytags(policytags), _filtered(false) { associate(o); } template RouteEntry::~RouteEntry() { Origin* o = _origin; _origin = 0; if (o) { o->dissociate(this); } } template bool RouteEntry::set_nexthop(const A& nh) { if (nh != _nh) { _nh = nh; return true; } return false; } template bool RouteEntry::set_cost(uint16_t cost) { if (cost != _cost) { _cost = cost; return true; } return false; } template bool RouteEntry::set_origin(Origin* o) { if (o != _origin) { dissociate(); associate(o); return true; } return false; } template bool RouteEntry::set_tag(uint16_t tag) { if (tag != _tag) { _tag = tag; return true; } return false; } template bool RouteEntry::set_policytags(const PolicyTags& ptags) { if (ptags != _policytags) { _policytags = ptags; return true; } return false; } /** * A comparitor for the purposes of sorting containers of RouteEntry objects. * It examines the data rather than using the address of pointers. The * latter approach makes testing difficult on different platforms since the * tests may inadvertantly make assumptions about the memory layout. The * comparison is arbitrary, it just has to be consistent and reversible. * * IFF speed proves to be an issue, RouteEntry can be changed to be an element * in an intrusive linked list that has a sentinel embedded in the * RouteEntryOrigin. */ template struct NetCmp { bool operator() (const IPNet& l, const IPNet& r) const { if (l.prefix_len() < r.prefix_len()) return true; if (l.prefix_len() > r.prefix_len()) return false; return l.masked_addr() < r.masked_addr(); } }; // ---------------------------------------------------------------------------- // RouteEntryOrigin::RouteEntryStore and related // // RouteEntryStore is a private class that is used by Route Origin's to store // their associated routes. // #include template struct RouteEntryOrigin::RouteEntryStore { public: typedef map, RouteEntry*, NetCmp > Container; Container routes; }; // ---------------------------------------------------------------------------- // RouteEntryOrigin template RouteEntryOrigin::RouteEntryOrigin(bool is_rib_origin) : _is_rib_origin(is_rib_origin) { _rtstore = new RouteEntryStore(); } template RouteEntryOrigin::~RouteEntryOrigin() { // XXX store should be empty XLOG_ASSERT(_rtstore->routes.empty()); delete _rtstore; } template bool RouteEntryOrigin::associate(Route* r) { XLOG_ASSERT(r != 0); if (_rtstore->routes.find(r->net()) != _rtstore->routes.end()) { XLOG_FATAL("entry already exists"); return false; } _rtstore->routes.insert(typename RouteEntryStore::Container::value_type(r->net(), r)); return true; } template bool RouteEntryOrigin::dissociate(Route* r) { typename RouteEntryStore::Container::iterator i = _rtstore->routes.find(r->net()); if (i == _rtstore->routes.end()) { XLOG_FATAL("entry does not exist"); return false; } _rtstore->routes.erase(i); return true; } template uint32_t RouteEntryOrigin::route_count() const { return static_cast(_rtstore->routes.size()); } template void RouteEntryOrigin::clear() { typename RouteEntryStore::Container::iterator i = _rtstore->routes.begin(); while (i != _rtstore->routes.end()) { Route* r = i->second; delete r; i = _rtstore->routes.begin(); } } template void RouteEntryOrigin::dump_routes(vector& routes) const { typename RouteEntryStore::Container::const_iterator i = _rtstore->routes.begin(); typename RouteEntryStore::Container::const_iterator end = _rtstore->routes.end(); while (i != end) { routes.push_back(i->second); ++i; } } template RouteEntry* RouteEntryOrigin::find_route(const Net& n) const { typename RouteEntryStore::Container::const_iterator i = _rtstore->routes.find(n); if (i == _rtstore->routes.end()) return 0; return i->second; } // ---------------------------------------------------------------------------- // Instantiations #ifdef INSTANTIATE_IPV4 template class RouteEntryOrigin; template class RouteEntry; #endif #ifdef INSTANTIATE_IPV6 template class RouteEntryOrigin; template class RouteEntry; #endif