From 0d8b0897657af6acb41849407a3f6584969ae77a Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 15 Jun 2012 16:31:20 +0200 Subject: [PATCH 01/38] trivial: ws fixes --- xorp/libxorp/tests/test_trie.cc | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/xorp/libxorp/tests/test_trie.cc b/xorp/libxorp/tests/test_trie.cc index a3a85358a..ff164be53 100644 --- a/xorp/libxorp/tests/test_trie.cc +++ b/xorp/libxorp/tests/test_trie.cc @@ -9,13 +9,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -124,7 +124,7 @@ void test_upper_bound(IPv4 test_addr, IPv4 test_answer) { print_passed(result.str()); } else { print_failed(""); - printf("answer should be %s, result was %s\n", + printf("answer should be %s, result was %s\n", test_answer.str().c_str(), result.str().c_str()); trie.print(); abort(); @@ -142,7 +142,7 @@ void test_lower_bound(IPv4 test_addr, IPv4 test_answer) { print_passed(result.str()); } else { print_failed(""); - printf("Fail: answer should be %s, result was %s\n", + printf("Fail: answer should be %s, result was %s\n", test_answer.str().c_str(), result.str().c_str()); trie.print(); abort(); @@ -202,7 +202,7 @@ void test_upper_bound6(IPv6 test_addr, IPv6 test_answer) { print_passed(result.str()); } else { print_failed(""); - printf("Fail: answer should be %s, result was %s\n", + printf("Fail: answer should be %s, result was %s\n", test_answer.str().c_str(), result.str().c_str()); trie.print(); abort(); @@ -216,13 +216,13 @@ test_find_subtree() printf("Find subtree\n"); Trie trie_subtree; - + IPv4Net n1(IPv4("169.229.0.136"), 29); trie_subtree.insert(n1, "169.229.0.136/29"); IPv4Net n2(IPv4("192.150.187.0"), 25); trie_subtree.insert(n2, "192.150.187.0/25"); - + IPv4Net n3(IPv4("192.168.254.2"), 32); trie_subtree.insert(n3, "192.168.254.2/32"); @@ -407,7 +407,7 @@ int main() { IPv4Net n9(IPv4("1.2.2.0"), 24); trie.insert(n9, &d9); trie.print(); - + trie.erase(n9); trie.erase(n2); @@ -460,7 +460,7 @@ int main() { test_lower_bound(IPv4("1.0.0.1"), IPv4("0.0.0.0")); test_upper_bound(IPv4("1.3.128.1"), IPv4("255.255.255.255")); test_upper_bound(IPv4("1.2.2.1"), IPv4("1.2.2.255")); - + trie.print(); Trie::iterator iter; IPv4Net subroot(IPv4("1.2.0.0"), 21); @@ -498,7 +498,7 @@ int main() { iter++; } - + trie.insert(n10, &d10); trie.insert(n1, &d1); trie.insert(n9, &d9); @@ -516,7 +516,7 @@ int main() { iter++; } - //------------------------------------------------------- + //------------------------------------------------------- printf("Test replacement of interior node\n"); @@ -525,13 +525,13 @@ int main() { trie.insert(n13, &d13); trie.print(); - //------------------------------------------------------- + //------------------------------------------------------- printf("==================\nTest of begin()\n"); trie.erase(n11); trie.erase(n10); trie.print(); - //------------------------------------------------------- + //------------------------------------------------------- printf("==================\nTest of lower_bound()\n"); trie.print(); iter = trie.lower_bound(n1); /*1.2.1.0/24*/ @@ -543,23 +543,23 @@ int main() { iter = trie.lower_bound(n13); /*1.2.2.0/23*/ assert(iter.key() == n13); - iter = trie.lower_bound(IPNet("1.2.1.128/25")); + iter = trie.lower_bound(IPNet("1.2.1.128/25")); assert(iter.key() == n1); /*1.2.1.0/24*/ - iter = trie.lower_bound(IPNet("1.2.4.128/25")); + iter = trie.lower_bound(IPNet("1.2.4.128/25")); assert(iter == trie.end()); - iter = trie.lower_bound(IPNet("1.2.1.0/23")); + iter = trie.lower_bound(IPNet("1.2.1.0/23")); assert(iter.key() == n9); /*1.2.2.0/24*/ - iter = trie.lower_bound(IPNet("1.0.0.0/24")); + iter = trie.lower_bound(IPNet("1.0.0.0/24")); if (iter != trie.end()) printf("iter.key = %s\n", iter.key().str().c_str()); else printf("iter = end\n"); assert(iter.key() == n1); /*1.2.1.0/24*/ - //------------------------------------------------------- + //------------------------------------------------------- printf("Test /32 prefix works\n"); @@ -579,7 +579,7 @@ int main() { // inserting a list of unsorted subnets and check that the iterator // retrieves them in the proper order. - Trie > + Trie > preotrie; const char * subnets[] = { "1.2.0.0/16", "1.2.0.0/20", @@ -611,7 +611,7 @@ int main() { printf("adding n20: %s route: %p\n", n20.str().c_str(), &d20); preotrie.insert(n20, &d20); - //------------------------------------------------------- + //------------------------------------------------------- printf("-----------\n"); printf("Test of prefix increment (++ti)\n"); printf("-----------\n"); @@ -636,11 +636,11 @@ int main() { } print_passed(""); - //------------------------------------------------------- + //------------------------------------------------------- printf("-----------\n"); printf("Test of postfix increment (ti++)\n"); printf("-----------\n"); - subnetidx = 0; + subnetidx = 0; for (ti = preotrie.begin() ; ti != preotrie.end() ; ++ti) { printf("*** node: %-26s %s\n", ti.cur()->k().str().c_str(), From 78dd3bfb34a7ab613ea72b0429a004edc32a630d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 15 Jun 2012 15:23:05 +0200 Subject: [PATCH 02/38] xorp: libxorp: Fix find_subtree function of TrieNode Problem was that it was going unconditionaly right, if the left branch didn't contain network we were looking for. That is wrong, because it is posible that left branch is contained in the network that we're looking for. Because of that it's possible that it's our candidate. Added checks for the left and right branches. Added test that really test if we found correct subtree. Passed trie test. --- xorp/libxorp/tests/test_trie.cc | 71 ++++++++++++++++++++++++++++++++- xorp/libxorp/trie.hh | 19 +++++++-- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/xorp/libxorp/tests/test_trie.cc b/xorp/libxorp/tests/test_trie.cc index ff164be53..a0a4f394c 100644 --- a/xorp/libxorp/tests/test_trie.cc +++ b/xorp/libxorp/tests/test_trie.cc @@ -229,6 +229,9 @@ test_find_subtree() IPv4Net n4(IPv4("192.168.254.3"), 32); trie_subtree.insert(n4, "192.168.254.3/32"); + IPv4Net n5(IPv4("192.168.254.4"), 32); + trie_subtree.insert(n5, "192.168.254.4/32"); + trie_subtree.print(); IPv4Net nsearch1(IPv4("192.150.187.248"), 29); @@ -241,8 +244,8 @@ test_find_subtree() abort(); } - IPv4Net n5(IPv4("192.150.187.248"), 29); - trie_subtree.insert(n5, "192.150.187.248/29"); + IPv4Net n6(IPv4("192.150.187.248"), 29); + trie_subtree.insert(n6, "192.150.187.248/29"); IPv4Net nsearch2(IPv4("192.150.187.0"), 25); trie_subtree.erase(n2); @@ -256,6 +259,70 @@ test_find_subtree() abort(); } + IPv4Net nsearchReally(IPv4("192.168.254.0"), 24); + iter = trie_subtree.search_subtree(nsearchReally); + int i = 0; + printf("--- Results for %s\n", nsearchReally.str().c_str()); + for( ; iter != trie_subtree.end(); iter++) { + i++; + printf("subtree = %s\n", iter.payload().c_str()); + } + printf("---\n"); + + if (i != 3) { + print_failed(""); + printf("We expected three entries to be found and we found %d", i); + abort(); + } + + IPv4Net nsearchReally2(IPv4("192.0.0.0"), 8); + iter = trie_subtree.search_subtree(nsearchReally2); + + printf("--- Results for %s\n", nsearchReally2.str().c_str()); + for(i = 0; iter != trie_subtree.end(); iter++) { + i++; + printf("subtree = %s\n", iter.payload().c_str()); + } + printf("---\n"); + + if (i != 4) { + print_failed(""); + printf("We expected four entries to be found and we found %d", i); + abort(); + } + + IPv4Net nsearchReally3(IPv4("192.168.254.0"), 30); + iter = trie_subtree.search_subtree(nsearchReally3); + + printf("--- Results for %s\n", nsearchReally3.str().c_str()); + for(i = 0; iter != trie_subtree.end(); iter++) { + i++; + printf("subtree = %s\n", iter.payload().c_str()); + } + printf("---\n"); + + if (i != 2) { + print_failed(""); + printf("We expected two entries to be found and we found %d", i); + abort(); + } + + IPv4Net nsearchReally4(IPv4("192.168.254.4"), 31); + iter = trie_subtree.search_subtree(nsearchReally4); + + printf("--- Results for %s\n", nsearchReally4.str().c_str()); + for(i = 0; iter != trie_subtree.end(); iter++) { + i++; + printf("subtree = %s\n", iter.payload().c_str()); + } + printf("---\n"); + + if (i != 1) { + print_failed(""); + printf("We expected one entrie to be found and we found %d", i); + abort(); + } + print_passed(""); } diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index b2048533c..2c7b8964d 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -930,13 +930,24 @@ TrieNode::find_subtree(const Key &key) TrieNode *cand = r && key.contains(r->_k) ? r : NULL; for ( ; r && r->_k.contains(key) ; ) { - if (key.contains(r->_k)) - cand = r; // we have a candidate. + if (key.contains(r->_k)) { + cand = r; // we have a candidate. + break; // and we don't need to search any more! + } if (r->_left && r->_left->_k.contains(key)) r = r->_left; - else // should check that right contains(key), but - r = r->_right; // the loop condition will do it for us. + else if (r->_right && r->_right->_k.contains(key)) + r = r->_right; + else if (r->_left && key.contains(r->_left->_k)) { + cand = r->_left; + break; + } else if (r->_right && key.contains(r->_right->_k)) { + cand = r->_right; + break; + } else + break; } + return cand; } From 5ee82f1fdff40e39ee3e5558903eecb195f3b4c2 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Wed, 13 Jun 2012 13:36:29 +0200 Subject: [PATCH 03/38] xorp: libxorp: Add operator!= to the Trie iterators --- xorp/libxorp/trie.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index 2c7b8964d..a54fe78dd 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -384,6 +384,10 @@ public: return (_cur == x._cur); } + bool operator!=(const TriePostOrderIterator & x) const { + return (_cur != x._cur); + } + bool has_payload() const { return _cur->has_payload(); } Payload & payload() { return _cur->p(); }; const Payload & payload() const { return _cur->p(); }; @@ -483,6 +487,10 @@ public: return (_cur == x._cur); } + bool operator!=(const TriePreOrderIterator & x) const { + return (_cur != x._cur); + } + bool has_payload() const { return _cur->has_payload(); } Payload & payload() { return _cur->p(); }; const Payload & payload() const { return _cur->p(); }; From 4901d2409eb1ec3a4412f48c090ab02ffa95ff49 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 14 Jun 2012 11:28:10 +0200 Subject: [PATCH 04/38] xorp: libxorp: Add size() method, and change payload_count type to size_t --- xorp/libxorp/trie.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index a54fe78dd..af6920db8 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -669,7 +669,8 @@ public: } #endif // compatibility - int route_count() const { return _payload_count; } + int route_count() const { return static_cast(_payload_count); } + size_t size() const { return _payload_count; } bool empty() const { return (_payload_count == 0); } @@ -682,7 +683,7 @@ private: } Node *_root; - int _payload_count; + size_t _payload_count; }; From 47ccb4d096122e68ef46ff2e1203e00daf96e3fc Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 14 Jun 2012 13:13:13 +0200 Subject: [PATCH 05/38] xorp: rib: Register for the max_specific subnet Register for the max_specific subnet, when registering for non resolvable address. That way listener can be notified when the address become resolvable. --- xorp/rib/rt_tab_register.cc | 14 +++++++++----- xorp/rib/tests/test_register.cc | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/xorp/rib/rt_tab_register.cc b/xorp/rib/rt_tab_register.cc index 31c444c03..33c07937a 100644 --- a/xorp/rib/rt_tab_register.cc +++ b/xorp/rib/rt_tab_register.cc @@ -423,16 +423,20 @@ RegisterTable::register_route_range(const A& addr, { debug_msg("*****\nRRR: register_route_range: %s\n", addr.str().c_str()); RouteRange* rrange; + RouteRegister* rreg; + IPNet subnet; rrange = lookup_route_range(addr); - IPNet subnet = rrange->minimal_subnet(); - debug_msg("RRR: minimal subnet = %s\n", subnet.str().c_str()); - if (rrange->route() == NULL) + + if (rrange->route() == NULL) { + subnet = IPNet(addr, (uint8_t)addr.addr_bitlen()); debug_msg("RRR: no matching route\n"); - else + } else { + subnet = rrange->minimal_subnet(); debug_msg("RRR: route = %s\n", rrange->route()->str().c_str()); + } - RouteRegister* rreg; + debug_msg("RRR: minimal subnet = %s\n", subnet.str().c_str()); rreg = add_registration(subnet, rrange->route(), module); delete rrange; return rreg; diff --git a/xorp/rib/tests/test_register.cc b/xorp/rib/tests/test_register.cc index 05a56fb52..121272af3 100644 --- a/xorp/rib/tests/test_register.cc +++ b/xorp/rib/tests/test_register.cc @@ -346,10 +346,13 @@ main (int /* argc */, char* argv[]) abort(); // Register interest in all three non-existent ranges - rreg = rib.route_register(IPv4("1.0.0.1"), string("foo")); + rreg = rib.route_register(IPv4("1.0.6.1"), string("foo")); if (verbose) printf("%s\n", rreg->str().c_str()); - rreg = rib.route_register(IPv4("1.0.6.1"), string("foo")); + rreg = rib.route_register(IPv4("1.0.6.128"), string("foo")); + if (verbose) + printf("%s\n", rreg->str().c_str()); + rreg = rib.route_register(IPv4("1.0.0.1"), string("foo")); if (verbose) printf("%s\n", rreg->str().c_str()); rreg = rib.route_register(IPv4("1.0.7.1"), string("foo2")); @@ -359,12 +362,15 @@ main (int /* argc */, char* argv[]) if (verbose) printf("%s\n", rreg->str().c_str()); - rib.add_route("ospf", IPv4Net("1.0.6.0", 24), IPv4("10.0.2.2"), + rib.add_route("ospf", IPv4Net("1.0.6.0", 23), IPv4("10.0.2.2"), "", "", 3, PolicyTags()); - if (!register_server.verify_invalidated("foo 1.0.6.0/23 mcast:false")) - abort(); - if (!register_server.verify_invalidated("foo2 1.0.6.0/23 mcast:false")) + if (!register_server.verify_invalidated("foo 1.0.6.1/32 mcast:false")) abort(); + if (!register_server.verify_invalidated("foo 1.0.6.128/32 mcast:false")) + abort(); + if (!register_server.verify_invalidated("foo2 1.0.7.1/32 mcast:false")) + abort(); + // There shouldn't be any more invalidated or changed entries if (!register_server.verify_no_info()) abort(); // From 186ff790da4c66adc04d6c276975d331a4c26444 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 14 Jun 2012 13:06:26 +0200 Subject: [PATCH 06/38] xorp: rib: Add str() method for RouteRange --- xorp/rib/rt_tab_base.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index f0dddb920..dbf8c6363 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -78,6 +78,14 @@ public: const IPRouteEntry* route() const { return _route; } const IPNet& net() const { return _route->net(); } + string str() const { + ostringstream oss; + oss << "RouteRange: " << endl; + oss << "Top - " << _top.str() << endl; + oss << "Bottom - " << _bottom.str() << endl; + return oss.str(); + } + /** * Merge this entry with another entry. * From 95a070ce62c7c1a98abab52eac52c77957830928 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 15 Jun 2012 16:04:51 +0200 Subject: [PATCH 07/38] xorp: rib: Dynamicly allocate memory for nexthop, instead of saving them in map This is a lot safer, because each IPRouteEntry is now the real owner of nexthop! Updated IPRouteEntry to approprietly delete nexthop, and added copy constructor. Nexthop pointer, which is passed to IPRouteEntry shouldn't be freed by the callers of IPRouteEntry constructor. Passed all rib tests. --- xorp/libxorp/nexthop.hh | 19 ++++++++++++ xorp/rib/rib.cc | 54 +++++---------------------------- xorp/rib/rib.hh | 30 ++++++------------ xorp/rib/route.cc | 13 ++++---- xorp/rib/route.hh | 13 +++----- xorp/rib/rt_tab_extint.cc | 5 ++- xorp/rib/tests/test_deletion.cc | 6 ++-- xorp/rib/tests/test_redist.cc | 40 ++++++++++++------------ 8 files changed, 73 insertions(+), 107 deletions(-) diff --git a/xorp/libxorp/nexthop.hh b/xorp/libxorp/nexthop.hh index 81fb3f84e..87470beb0 100644 --- a/xorp/libxorp/nexthop.hh +++ b/xorp/libxorp/nexthop.hh @@ -115,6 +115,8 @@ public: */ IPNextHop(const A &from_ipaddr); + virtual ~IPNextHop() { } + #ifdef XORP_USE_USTL IPNextHop() { } #endif @@ -134,6 +136,13 @@ public: */ string str() const; + /** + * Returns pointer to copy of IPNextHop + * + * Callers ARE RESPONSIBLE for freeing the memory + */ + virtual IPNextHop* get_copy() = 0; + protected: const A _addr; }; @@ -171,6 +180,8 @@ public: */ int type() const { return PEER_NEXTHOP; } + IPPeerNextHop* get_copy() { return new IPPeerNextHop(*this); } + private: }; @@ -204,6 +215,8 @@ public: */ int type() const { return ENCAPS_NEXTHOP; } + IPEncapsNextHop* get_copy() { return new IPEncapsNextHop(*this); } + private: //_cached_peer is the cached copy of the local peer we send the //encapsulated packet to. @@ -248,6 +261,8 @@ public: */ int type() const { return EXTERNAL_NEXTHOP; } + IPExternalNextHop* get_copy() { return new IPExternalNextHop(*this); } + private: }; @@ -277,6 +292,8 @@ public: */ int type() const { return DISCARD_NEXTHOP; } + DiscardNextHop* get_copy() { return new DiscardNextHop(*this); } + private: }; @@ -302,6 +319,8 @@ public: */ int type() const { return UNREACHABLE_NEXTHOP; } + UnreachableNextHop* get_copy() { return new UnreachableNextHop(*this); } + private: }; diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index 7294bdd59..a82f2982a 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -252,56 +252,16 @@ RIB::get_protocol_admin_distance(const string& protocol_name) template inline IPExternalNextHop* -RIB::find_external_nexthop(const A& addr) +RIB::create_external_nexthop(const A& addr) { - typename map >::iterator mi; - - mi = _external_nexthops.find(addr); - if (mi == _external_nexthops.end()) - return NULL; - return &mi->second; -} - -template -inline IPPeerNextHop* -RIB::find_peer_nexthop(const A& addr) -{ - typename map >::iterator mi; - - mi = _peer_nexthops.find(addr); - if (mi == _peer_nexthops.end()) - return NULL; - return &mi->second; -} - -template -inline IPExternalNextHop* -RIB::find_or_create_external_nexthop(const A& addr) -{ - IPExternalNextHop* nexthop = find_external_nexthop(addr); - if (nexthop != NULL) - return nexthop; - - typedef map > C; // for convenience - typename C::value_type vt(addr, IPExternalNextHop(addr)); - typename C::iterator iter; - iter = _external_nexthops.insert(_external_nexthops.end(), vt); - return &iter->second; + return new IPExternalNextHop(addr); } template inline IPPeerNextHop* -RIB::find_or_create_peer_nexthop(const A& addr) +RIB::create_peer_nexthop(const A& addr) { - IPPeerNextHop* nexthop = find_peer_nexthop(addr); - if (nexthop != NULL) - return nexthop; - - typedef map > C; // for convenience - typename C::value_type vt(addr, addr); - typename C::iterator iter; - iter = _peer_nexthops.insert(_peer_nexthops.end(), vt); - return &iter->second; + return new IPPeerNextHop(addr); } // ---------------------------------------------------------------------------- @@ -909,7 +869,7 @@ RIB::add_route(const string& tablename, return XORP_ERROR; } - IPNextHop* nexthop = find_or_create_peer_nexthop(nexthop_addr); + IPNextHop* nexthop = create_peer_nexthop(nexthop_addr); ot->add_route(new IPRouteEntry(net, vif, nexthop, protocol, metric, policytags)); flush(); @@ -925,7 +885,7 @@ RIB::add_route(const string& tablename, vif = re->vif(); if (vif != NULL) - nexthop = find_or_create_peer_nexthop(nexthop_addr); + nexthop = create_peer_nexthop(nexthop_addr); else if (vif == NULL && protocol->protocol_type() == IGP) { debug_msg("**not directly connected route found for nexthop\n"); // @@ -937,7 +897,7 @@ RIB::add_route(const string& tablename, "interface toward the next-hop router", tablename.c_str(), net.str().c_str(), nexthop_addr.str().c_str()); return XORP_ERROR; } else - nexthop = find_or_create_external_nexthop(nexthop_addr); + nexthop = create_external_nexthop(nexthop_addr); XLOG_ASSERT(nexthop->addr() == nexthop_addr); // diff --git a/xorp/rib/rib.hh b/xorp/rib/rib.hh index d9cd0480e..86abdfb97 100644 --- a/xorp/rib/rib.hh +++ b/xorp/rib/rib.hh @@ -753,40 +753,28 @@ private: RibVif* find_vif(const string& vifname); /** - * Find the IP External Nexthop class instance associated with an IP - * address. - * - * @param addr the IP address of the nexthop router. - * @return pointer to external next hop if it exists, NULL otherwise. - */ - IPExternalNextHop* find_external_nexthop(const A& addr); - - /** - * Find the IP Peer Nexthop class instance associated with an IP - * address. - * - * @param addr the IP address of the nexthop router. - * @return pointer to peer next hop if it exists, NULL otherwise. - */ - IPPeerNextHop* find_peer_nexthop(const A& addr); - - /** - * Find or create the IP External Nexthop class instance + * Create the IP External Nexthop class instance * associated with an IP address. * + * IPRouteEntry IS RESPONSIBLE for freeing + * allocated memory for IPExternalNextHop. + * * @param addr the IP address of the nexthop router. * @return the IPExternalNextHop class instance for @ref addr */ - IPExternalNextHop* find_or_create_external_nexthop(const A& addr); + IPExternalNextHop* create_external_nexthop(const A& addr); /** * Find or create the IP Peer Nexthop class instance * associated with an IP address. * + * IPRouteEntry IS RESPONSIBLE for freeing + * allocated memory for IPPeerNextHop. + * * @param addr the IP address of the nexthop router. * @return the IPPeerNextHop class instance for @ref addr. */ - IPPeerNextHop* find_or_create_peer_nexthop(const A& addr); + IPPeerNextHop* create_peer_nexthop(const A& addr); /** * Flush out routing table changes to other processes. diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index 554d0f4c7..17777275b 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -90,6 +90,10 @@ RouteEntry::~RouteEntry() template class RouteEntry; template class RouteEntry; +template +IPRouteEntry::IPRouteEntry(const IPRouteEntry& ipr) + : RouteEntry(ipr), _nexthop(ipr.nexthop()->get_copy()) { } + template string IPRouteEntry::str() const @@ -97,23 +101,18 @@ IPRouteEntry::str() const string dst = (RouteEntry::_net.is_valid()) ? RouteEntry::_net.str() : string("NULL"); string vif = (RouteEntry::_vif) ? string(RouteEntry::_vif->name()) : string("NULL"); return string("Dst: ") + dst + string(" Vif: ") + vif + - string(" NextHop: ") + _nexthop->str() + + string(" NextHop: ") + (_nexthop ? _nexthop->str() : "no next hop") + string(" Metric: ") + c_format("%d", RouteEntry::_metric) + string(" Protocol: ") + RouteEntry::_protocol->name() + string(" PolicyTags: ") + RouteEntry::_policytags.str(); } -template -IPRouteEntry::IPRouteEntry(const IPRouteEntry& r) : RouteEntry(r) { - _nexthop = r._nexthop; -} - template IPRouteEntry& IPRouteEntry::operator=(const IPRouteEntry& r) { if (this == &r) return *this; RouteEntry::operator=(r); - _nexthop = r._nexthop; + _nexthop = r._nexthop->get_copy(); return *this; } diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index a54970392..f2e8b6db2 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -196,15 +196,15 @@ public: IPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, Protocol* protocol, uint32_t metric, const PolicyTags& policytags) - : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) {} + : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) { } IPRouteEntry(const IPRouteEntry& r); - IPRouteEntry& operator=(const IPRouteEntry& r); + IPRouteEntry& operator=(const IPRouteEntry& rhs); /** * Destructor for Routing Table Entry */ - virtual ~IPRouteEntry() {} + virtual ~IPRouteEntry() { delete _nexthop; } /** * Get the NextHop router. @@ -214,8 +214,6 @@ public: */ IPNextHop* nexthop() const { return _nexthop; } - void set_nexthop(IPNextHop* v) { _nexthop = v; } - /** * Get the route entry's next-hop router address. * @@ -223,9 +221,8 @@ public: * next-hop router, then the return value is IPv4#ZERO() or IPv6#ZERO(). */ const A& nexthop_addr() const { - IPNextHop* nh = nexthop(); - if (nh != NULL) - return nh->addr(); + if (_nexthop != NULL) + return _nexthop->addr(); else return A::ZERO(); } diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index a8afef8a8..d7aa75804 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -221,7 +221,10 @@ ExtIntTable::resolve_and_store_route(const IPRouteEntry& route, ResolvedIPRouteEntry* resolved_route; resolved_route = new ResolvedIPRouteEntry(route.net(), nexthop_route->vif(), - nexthop_route->nexthop(), + // IPRouteEntry will free memory for the nexthop. + // That's why we pass copy of NextHop pointer + // instead of pointer! + nexthop_route->nexthop()->get_copy(), route.protocol(), route.metric(), nexthop_route, diff --git a/xorp/rib/tests/test_deletion.cc b/xorp/rib/tests/test_deletion.cc index fd352f691..eaf39d374 100644 --- a/xorp/rib/tests/test_deletion.cc +++ b/xorp/rib/tests/test_deletion.cc @@ -57,8 +57,8 @@ main(int /* argc */, char* argv[]) IPv4Net net1("10.0.1.0/24"); IPv4Net net2("10.0.2.0/24"); - IPRouteEntry route1(net1, &vif1, &nh1, &protocol, 100); - IPRouteEntry route2(net2, &vif1, &nh1, &protocol, 100); + IPRouteEntry route1(net1, &vif1, nh1.get_copy(), &protocol, 100); + IPRouteEntry route2(net2, &vif1, nh1.get_copy(), &protocol, 100); dt.expect_add(route1); dt.expect_add(route2); @@ -113,7 +113,7 @@ main(int /* argc */, char* argv[]) ot.routing_protocol_shutdown(); XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); - IPRouteEntry route3(net1, &vif2, &nh2, &protocol, 101); + IPRouteEntry route3(net1, &vif2, nh2.get_copy(), &protocol, 101); dt.expect_delete(route1); dt.expect_add(route3); diff --git a/xorp/rib/tests/test_redist.cc b/xorp/rib/tests/test_redist.cc index 38bbf579e..dfd1fb824 100644 --- a/xorp/rib/tests/test_redist.cc +++ b/xorp/rib/tests/test_redist.cc @@ -290,17 +290,17 @@ test_deterministic() // Add some initial routes origin.add_route(new IPRouteEntry("10.0.0.0/8", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); origin.add_route(new IPRouteEntry("10.3.0.0/16", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); origin.add_route(new IPRouteEntry("10.5.0.0/16", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); origin.add_route(new IPRouteEntry("10.6.0.0/16", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); origin.add_route(new IPRouteEntry("10.3.128.0/17", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); origin.add_route(new IPRouteEntry("10.3.192.0/18", - &vif, &nh, &protocol, 10)); + &vif, nh.get_copy(), &protocol, 10)); verbose_log("RedistTable index size = %u\n", XORP_UINT_CAST(redist_table.route_index().size())); @@ -315,38 +315,38 @@ test_deterministic() XorpTimer a0 = e.new_oneoff_after_ms(1250, callback(&add_route_after_current, &origin, output, - new IPRouteEntry("10.4.0.0/16", &vif, &nh, - &protocol, 10))); + new IPRouteEntry("10.4.0.0/16", &vif, nh.get_copy(), + &protocol, 10))); // And two routes before XorpTimer a1 = e.new_oneoff_after_ms(1500, callback(&add_route_before_current, &origin, output, - new IPRouteEntry("10.1.0.0/16", &vif, &nh, - &protocol, 10))); + new IPRouteEntry("10.1.0.0/16", &vif, nh.get_copy(), + &protocol, 10))); XorpTimer a2 = e.new_oneoff_after_ms(1750, callback(&add_route_before_current, &origin, output, - new IPRouteEntry("10.2.0.0/16", &vif, &nh, - &protocol, 10))); + new IPRouteEntry("10.2.0.0/16", &vif, nh.get_copy(), + &protocol, 10))); // Delete first route XorpTimer d1 = e.new_oneoff_after_ms(2250, callback(&delete_route_before_current, &origin, output, - IPRouteEntry("10.0.0.0/8", &vif, &nh, + IPRouteEntry("10.0.0.0/8", &vif, nh.get_copy(), &protocol, 10))); // Delete current route XorpTimer d2 = e.new_oneoff_after_ms(2500, callback(&delete_route_before_current, &origin, output, - IPRouteEntry("10.4.0.0/16", &vif, &nh, + IPRouteEntry("10.4.0.0/16", &vif, nh.get_copy(), &protocol, 10))); // Delete last route XorpTimer d3 = e.new_oneoff_after_ms(2750, callback(&delete_route_before_current, &origin, output, - IPRouteEntry("10.3.192.0/18", &vif, &nh, + IPRouteEntry("10.3.192.0/18", &vif, nh.get_copy(), &protocol, 10))); bool done = false; @@ -364,16 +364,16 @@ test_deterministic() // Expect updates after dump to be propagated immediately. add_route_before_current(&origin, output, - new IPRouteEntry("1.1.0.0/9", &vif, &nh, - &protocol, 10)); + new IPRouteEntry("1.1.0.0/9", &vif, nh.get_copy(), + &protocol, 10)); add_route_before_current(&origin, output, - new IPRouteEntry("20.1.127.0/24", &vif, &nh, - &protocol, 10)); + new IPRouteEntry("20.1.127.0/24", &vif, nh.get_copy(), + &protocol, 10)); delete_route_before_current(&origin, output, IPRouteEntry("20.1.127.0/24", - &vif, &nh, + &vif, nh.get_copy(), &protocol, 10)); // Expect output route index to still match the redist table index. From 969f95c67aba08f90fa9be54cbe1fed34e626690 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 18 Jun 2012 12:47:17 +0200 Subject: [PATCH 08/38] xorp: rib: Print parent name of RedistTable in str() --- xorp/rib/rt_tab_redist.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xorp/rib/rt_tab_redist.cc b/xorp/rib/rt_tab_redist.cc index 143224096..ec26fbc6c 100644 --- a/xorp/rib/rt_tab_redist.cc +++ b/xorp/rib/rt_tab_redist.cc @@ -510,6 +510,11 @@ RedistTable::str() const } } + if (this->parent()) + s += "parent = " + this->parent()->tablename() + "\n"; + else + s += "no parent table\n"; + if (this->next_table() == NULL) { s += "no next table\n"; } else { From d4423225e56f3973bb0181c8a8f04f5831f20c9d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 18 Jun 2012 12:51:40 +0200 Subject: [PATCH 09/38] xorp: rib: Add constified method for geting parent from RouteTable classes --- xorp/rib/rt_tab_base.hh | 1 + xorp/rib/rt_tab_deletion.hh | 1 + xorp/rib/rt_tab_log.hh | 1 + xorp/rib/rt_tab_pol_conn.hh | 1 + xorp/rib/rt_tab_pol_redist.hh | 1 + xorp/rib/rt_tab_redist.hh | 1 + xorp/rib/rt_tab_register.hh | 1 + xorp/rib/tests/rt_tab_expect.hh | 1 + 8 files changed, 8 insertions(+) diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index dbf8c6363..df091e05c 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -181,6 +181,7 @@ public: // parent is only supposed to be called on single-parent tables virtual RouteTable* parent() { XLOG_UNREACHABLE(); return NULL; } + virtual const RouteTable* parent() const { XLOG_UNREACHABLE(); return NULL; } virtual TableType type() const = 0; virtual void replumb(RouteTable* old_parent, RouteTable* new_parent) = 0; diff --git a/xorp/rib/rt_tab_deletion.hh b/xorp/rib/rt_tab_deletion.hh index 6691a2c43..25e478d5f 100644 --- a/xorp/rib/rt_tab_deletion.hh +++ b/xorp/rib/rt_tab_deletion.hh @@ -143,6 +143,7 @@ public: string str() const; RouteTable* parent() { return _parent; } + const RouteTable* parent() const { return _parent; } private: RouteTable* _parent; diff --git a/xorp/rib/rt_tab_log.hh b/xorp/rib/rt_tab_log.hh index 680110bf7..e28c73da0 100644 --- a/xorp/rib/rt_tab_log.hh +++ b/xorp/rib/rt_tab_log.hh @@ -53,6 +53,7 @@ public: RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return LOG_TABLE; } RouteTable* parent() { return _parent; } + const RouteTable* parent() const { return _parent; } void replumb(RouteTable* old_parent, RouteTable* new_parent); string str() const; diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index 679d38266..e44122d3f 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -58,6 +58,7 @@ public: const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return POLICY_CONNECTED_TABLE; } + const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } void replumb(RouteTable* old_parent, RouteTable* new_parent); string str() const; diff --git a/xorp/rib/rt_tab_pol_redist.hh b/xorp/rib/rt_tab_pol_redist.hh index 973f71c08..ae592d3a8 100644 --- a/xorp/rib/rt_tab_pol_redist.hh +++ b/xorp/rib/rt_tab_pol_redist.hh @@ -134,6 +134,7 @@ public: const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return POLICY_REDIST_TABLE; } + const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } void replumb(RouteTable* old_parent, RouteTable* new_parent); string str() const; diff --git a/xorp/rib/rt_tab_redist.hh b/xorp/rib/rt_tab_redist.hh index 747b1d1cc..8b155ff51 100644 --- a/xorp/rib/rt_tab_redist.hh +++ b/xorp/rib/rt_tab_redist.hh @@ -116,6 +116,7 @@ public: const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return REDIST_TABLE; } + const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } void replumb(RouteTable* old_parent, RouteTable* new_parent); string str() const; diff --git a/xorp/rib/rt_tab_register.hh b/xorp/rib/rt_tab_register.hh index acf4a6a83..fe7ba1b05 100644 --- a/xorp/rib/rt_tab_register.hh +++ b/xorp/rib/rt_tab_register.hh @@ -349,6 +349,7 @@ public: /** * @return the parent @ref RouteTable of this RegisterTable. */ + const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } /** diff --git a/xorp/rib/tests/rt_tab_expect.hh b/xorp/rib/tests/rt_tab_expect.hh index b7e37d667..2b2c949d8 100644 --- a/xorp/rib/tests/rt_tab_expect.hh +++ b/xorp/rib/tests/rt_tab_expect.hh @@ -58,6 +58,7 @@ public: RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return EXPECT_TABLE; } RouteTable* parent() { return _parent; } + const RouteTable* parent() const { return _parent; } void replumb(RouteTable* old_parent, RouteTable* new_parent); string str() const; From ee5ebe5cd1b02795290be7f0e9c44bea71cce2ad Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 18 Jun 2012 13:19:13 +0200 Subject: [PATCH 10/38] xorp: rib: ExtInt table can now be initialized with NULL parents Added necesary checks, everywhere where it's possible to call, _ext_table or _int_table. Now they can take NULL values. This will enable us to uncoditionally plumb ExtInt table. When it's unconditionally plumbed we can add some route caching to it. Passed all tests. --- xorp/rib/rt_tab_extint.cc | 291 ++++++++++++++++++++------------------ xorp/rib/rt_tab_extint.hh | 16 ++- 2 files changed, 166 insertions(+), 141 deletions(-) diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index d7aa75804..88deaf89b 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -32,7 +32,7 @@ template inline static string make_extint_name(const RouteTable* e, const RouteTable* i) { - return string("Ext:(" + e->tablename() + ")Int:(" + i->tablename() + ")"); + return string("Ext:(" + (e ? e->tablename() : "NULL") + ")Int:(" + (i ? i->tablename() : "NULL") + ")"); } template @@ -40,8 +40,10 @@ ExtIntTable::ExtIntTable(RouteTable* ext_table, RouteTable* int_table) : RouteTable(make_extint_name(ext_table, int_table)), _ext_table(ext_table), _int_table(int_table) { - _ext_table->set_next_table(this); - _int_table->set_next_table(this); + if (_ext_table) + _ext_table->set_next_table(this); + if (_int_table) + _int_table->set_next_table(this); debug_msg("New ExtInt: %s\n", this->tablename().c_str()); } @@ -66,83 +68,83 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) { debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); - if (caller == _int_table) { + if (_int_table && caller == _int_table) { // The new route comes from the IGP table debug_msg("route comes from IGP\n"); - const IPRouteEntry* found_egp; - const IPRouteEntry* found_resolved; - - if (route.nexthop()->type() == EXTERNAL_NEXTHOP) { - // An IGP route must have a local nexthop. - XLOG_ERROR("Received route from IGP that contains " - "a non-local nexthop: %s", - route.str().c_str()); - return XORP_ERROR; - } + if (_ext_table) { + const IPRouteEntry* found_egp; + const IPRouteEntry* found_resolved; - found_egp = lookup_route_in_egp_parent(route.net()); - if (found_egp != NULL) { - if (found_egp->admin_distance() < route.admin_distance()) { - // The admin distance of the existing EGP route is better - return XORP_ERROR; - } - } + XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); - found_resolved = lookup_in_resolved_table(route.net()); - if (found_resolved != NULL) { - if (found_resolved->admin_distance() < route.admin_distance()) { - // The admin distance of the existing route is better - return XORP_ERROR; + found_egp = lookup_route_in_egp_parent(route.net()); + if (found_egp != NULL) { + if (found_egp->admin_distance() < route.admin_distance()) { + // The admin distance of the existing EGP route is better + return XORP_ERROR; + } } - } - // - // If necessary, from delete the route that came from the Ext table - // - do { + found_resolved = lookup_in_resolved_table(route.net()); if (found_resolved != NULL) { - bool is_delete_propagated = false; - this->delete_ext_route(found_resolved, is_delete_propagated); - break; + if (found_resolved->admin_distance() < route.admin_distance()) { + // The admin distance of the existing route is better + return XORP_ERROR; + } } - if (found_egp == NULL) - break; // - // If the nexthop of the route from the Ext table was directly - // connected, then it was propagated when the route was added, - // so delete it first. + // If necessary, from delete the route that came from the Ext table // - IPNextHop* rt_nexthop; - rt_nexthop = found_egp->nexthop(); - const A& nexthop_addr = rt_nexthop->addr(); - const IPRouteEntry* nexthop_route; - nexthop_route = lookup_route_in_igp_parent(nexthop_addr); - if (nexthop_route != NULL) { - RibVif* vif = nexthop_route->vif(); - if ((vif != NULL) - && (vif->is_same_subnet(IPvXNet(nexthop_route->net())) - || vif->is_same_p2p(IPvX(nexthop_addr)))) { - if (this->next_table() != NULL) - this->next_table()->delete_route(found_egp, this); + do { + if (found_resolved != NULL) { + bool is_delete_propagated = false; + this->delete_ext_route(found_resolved, + is_delete_propagated); + break; } - } - break; - } while (false); + + if (found_egp == NULL) + break; + // + // If the nexthop of the route from the Ext table was directly + // connected, then it was propagated when the route was added, + // so delete it first. + // + IPNextHop* rt_nexthop; + rt_nexthop = found_egp->nexthop(); + const A& nexthop_addr = rt_nexthop->addr(); + const IPRouteEntry* nexthop_route; + nexthop_route = lookup_route_in_igp_parent(nexthop_addr); + if (nexthop_route != NULL) { + RibVif* vif = nexthop_route->vif(); + if ((vif != NULL) + && (vif->is_same_subnet( + IPvXNet(nexthop_route->net())) + || vif->is_same_p2p(IPvX(nexthop_addr)))) { + if (this->next_table() != NULL) + this->next_table()->delete_route(found_egp, this); + } + } + break; + } while (false); + } if (this->next_table() != NULL) this->next_table()->add_route(route, this); - // Does this cause any previously resolved nexthops to resolve - // differently? - recalculate_nexthops(route); + if (_ext_table) { + // Does this cause any previously resolved nexthops to resolve + // differently? + recalculate_nexthops(route); - // Does this new route cause any unresolved nexthops to be resolved? - resolve_unresolved_nexthops(route); + // Does this new route cause any unresolved nexthops to be resolved? + resolve_unresolved_nexthops(route); + } return XORP_OK; - } else if (caller == _ext_table) { + } else if (_ext_table && caller == _ext_table) { // The new route comes from the EGP table debug_msg("route comes from EGP\n"); IPNextHop* rt_nexthop; @@ -251,58 +253,59 @@ ExtIntTable::delete_route(const IPRouteEntry* route, { debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); - if (caller == _int_table) { + if (_int_table && caller == _int_table) { debug_msg(" called from _int_table\n"); - const IPRouteEntry* egp_parent; - - if (route->nexthop()->type() == EXTERNAL_NEXTHOP) { - // We didn't propagate the add_route, so also ignore the deletion - return XORP_ERROR; - } - const IPRouteEntry* found_egp_route; - found_egp_route = lookup_route_in_egp_parent(route->net()); - if (found_egp_route != NULL) { - if (found_egp_route->admin_distance() < route->admin_distance()) { - // The admin distance of the existing EGP route is better - return XORP_ERROR; + if (_ext_table) { + const IPRouteEntry* egp_parent; + const IPRouteEntry* found_egp_route; + found_egp_route = lookup_route_in_egp_parent(route->net()); + if (found_egp_route != NULL) { + if (found_egp_route->admin_distance() + < route->admin_distance()) { + // The admin distance of the existing EGP route is better + return XORP_ERROR; + } } - } - const ResolvedIPRouteEntry* found; - found = lookup_by_igp_parent(route->net()); - if (found != NULL) { - _resolving_routes.erase(route->net()); - } + const ResolvedIPRouteEntry* found; + found = lookup_by_igp_parent(route->net()); - while (found != NULL) { - debug_msg("found route using this nexthop:\n %s\n", - found->str().c_str()); - // Erase from table first to prevent lookups on this entry - _ip_route_table.erase(found->net()); - _ip_igp_parents.erase(found->backlink()); + if (found != NULL) { + _resolving_routes.erase(route->net()); + } - // Propagate the delete next - if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + while (found != NULL) { + debug_msg("found route using this nexthop:\n %s\n", found->str().c_str()); + // Erase from table first to prevent lookups on this entry + _ip_route_table.erase(found->net()); + _ip_igp_parents.erase(found->backlink()); - // Now delete the local resolved copy, and reinstantiate it - egp_parent = found->egp_parent(); - delete found; - add_route(*egp_parent, _ext_table); - found = lookup_by_igp_parent(route->net()); + // Propagate the delete next + if (this->next_table() != NULL) + this->next_table()->delete_route(found, this); + + // Now delete the local resolved copy, and reinstantiate it + egp_parent = found->egp_parent(); + delete found; + add_route(*egp_parent, _ext_table); + found = lookup_by_igp_parent(route->net()); + } } // Propagate the original delete this->next_table()->delete_route(route, this); - // It is possible the internal route had masked an external one. - const IPRouteEntry* masked_route; - masked_route = _ext_table->lookup_route(route->net()); - if (masked_route != NULL) - add_route(*masked_route, _ext_table); - } else if (caller == _ext_table) { + if (_ext_table) { + // It is possible the internal route had masked an external one. + const IPRouteEntry* masked_route; + masked_route = _ext_table->lookup_route(route->net()); + if (masked_route != NULL) + add_route(*masked_route, _ext_table); + } + + } else if (_ext_table && caller == _ext_table) { debug_msg(" called from _ext_table\n"); const IPRouteEntry* found_igp_route; @@ -316,7 +319,7 @@ ExtIntTable::delete_route(const IPRouteEntry* route, bool is_delete_propagated = false; this->delete_ext_route(route, is_delete_propagated); - if (is_delete_propagated) { + if (is_delete_propagated && _int_table) { // It is possible the external route had masked an internal one. const IPRouteEntry* masked_route; masked_route = _int_table->lookup_route(route->net()); @@ -392,6 +395,7 @@ template void ExtIntTable::resolve_unresolved_nexthops(const IPRouteEntry& nexthop_route) { + XLOG_ASSERT(_ext_table); typename multimap* >::iterator rpair, nextpair; A unresolved_nexthop, new_subnet; @@ -501,6 +505,7 @@ template void ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) { + XLOG_ASSERT(_ext_table); debug_msg("recalculate_nexthops: %s\n", new_route.str().c_str()); const IPRouteEntry* old_route; @@ -583,7 +588,7 @@ ExtIntTable::lookup_route(const IPNet& ipv4net) const // Local version failed, so try the parent tables. int_found = lookup_route_in_igp_parent(ipv4net); - ext_found = _ext_table->lookup_route(ipv4net); + ext_found = lookup_route_in_egp_parent(ipv4net); if (ext_found == NULL) { return int_found; @@ -620,7 +625,7 @@ ExtIntTable::lookup_route(const A& addr) const if (int_found != NULL) found.push_back(int_found); - ext_found = _ext_table->lookup_route(addr); + ext_found = lookup_route_in_egp_parent(addr); // Check that the external route has a local nexthop (if it doesn't // we expect the version in local_found to have a local nexthop) if (ext_found != NULL @@ -684,15 +689,11 @@ template const IPRouteEntry* ExtIntTable::lookup_route_in_igp_parent(const IPNet& ipnet) const { - const IPRouteEntry* found; + const IPRouteEntry* found = NULL; - found = _int_table->lookup_route(ipnet); + if (_int_table) + found = _int_table->lookup_route(ipnet); - // Sanity check that the answer is good - if (found != NULL) { - if (found->nexthop()->type() == EXTERNAL_NEXTHOP) - found = NULL; - } return found; } @@ -700,15 +701,11 @@ template const IPRouteEntry* ExtIntTable::lookup_route_in_igp_parent(const A& addr) const { - const IPRouteEntry* found; + const IPRouteEntry* found = NULL; - found = _int_table->lookup_route(addr); + if (_int_table) + found = _int_table->lookup_route(addr); - // Sanity check that the answer is good - if (found != NULL) { - if (found->nexthop()->type() == EXTERNAL_NEXTHOP) - found = NULL; - } return found; } @@ -716,9 +713,9 @@ template const IPRouteEntry* ExtIntTable::lookup_route_in_egp_parent(const IPNet& ipnet) const { - const IPRouteEntry* found; - - found = _ext_table->lookup_route(ipnet); + const IPRouteEntry* found = NULL; + if (_ext_table) + found = _ext_table->lookup_route(ipnet); return found; } @@ -727,30 +724,42 @@ template const IPRouteEntry* ExtIntTable::lookup_route_in_egp_parent(const A& addr) const { - const IPRouteEntry* found; - - found = _ext_table->lookup_route(addr); + const IPRouteEntry* found = NULL; + if (_ext_table) + found = _ext_table->lookup_route(addr); return found; } template void -ExtIntTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +ExtIntTable::replumb(RouteTable* old_parent, RouteTable* new_parent) { - debug_msg("ExtIntTable::replumb replacing %s with %s\n", - old_parent->tablename().c_str(), - new_parent->tablename().c_str()); - - if (_ext_table == old_parent) { - _ext_table = new_parent; - } else if (_int_table == old_parent) { - _int_table = new_parent; - } else { - // Shouldn't be possible - XLOG_UNREACHABLE(); - } + XLOG_ASSERT(old_parent); + if (old_parent == _int_table) + replumb_internal(new_parent); + else if (old_parent == _ext_table) + replumb_external(new_parent); +} + +template +void +ExtIntTable::replumb_external(RouteTable* new_ext_parent) +{ + debug_msg("ExtIntTable::replumb_external\n"); + _ext_table = new_ext_parent; + _ext_table->set_next_table(this); + this->set_tablename(make_extint_name(_ext_table, _int_table)); + debug_msg("ExtIntTable: now called \"%s\"\n", this->tablename().c_str()); +} + +template +void +ExtIntTable::replumb_internal(RouteTable* new_int_parent) +{ + debug_msg("ExtIntTable::replumb_internal\n"); + _int_table = new_int_parent; + _int_table->set_next_table(this); this->set_tablename(make_extint_name(_ext_table, _int_table)); debug_msg("ExtIntTable: now called \"%s\"\n", this->tablename().c_str()); } @@ -760,8 +769,10 @@ RouteRange* ExtIntTable::lookup_route_range(const A& addr) const { // What do the parents think the answer is? - RouteRange* int_rr = _int_table->lookup_route_range(addr); - RouteRange* ext_rr = _ext_table->lookup_route_range(addr); + RouteRange* int_rr = (_int_table ? _int_table->lookup_route_range(addr) : + new RouteRange(addr, NULL, A::ZERO(), A::ALL_ONES())); + RouteRange* ext_rr = (_ext_table ? _ext_table->lookup_route_range(addr) : + new RouteRange(addr, NULL, A::ZERO(), A::ALL_ONES())); // What do we think the answer is? const IPRouteEntry* route; @@ -800,8 +811,8 @@ ExtIntTable::str() const string s; s = "-------\nExtIntTable: " + this->tablename() + "\n"; - s += "_ext_table = " + _ext_table->tablename() + "\n"; - s += "_int_table = " + _int_table->tablename() + "\n"; + s += "_ext_table = " + (_ext_table ? _ext_table->tablename() : "NULL") + "\n"; + s += "_int_table = " + (_int_table ? _int_table->tablename() : "NULL") + "\n"; if (this->next_table() == NULL) s += "no next table\n"; else diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index 401b568e4..dd32466c4 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -152,13 +152,27 @@ public: TableType type() const { return EXTINT_TABLE; } /** - * replumb the parent tables, so that new_parent replaces old_parent + * Set new parent * * @param old_parent the old parent table. * @param new_parent the new parent table. */ void replumb(RouteTable* old_parent, RouteTable* new_parent); + /** + * Set new external parent + * + * @param new_ext_parent the new external parent table. + */ + void replumb_external(RouteTable* new_ext_parent); + + /** + * Set new internal parent + * + * @param new_int_parent the new external parent table. + */ + void replumb_internal(RouteTable* new_int_parent); + /** * Render this ExtIntTable as a string for debugging purposes. */ From d7744e663b36d280839b1f4b9257b1f1e04aa577 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 18 Jun 2012 13:21:58 +0200 Subject: [PATCH 11/38] xorp: rib: Uncoditionally plumb ExtInt table Now we uncoditionally plumb ExtInt table in front of Register table. Also, in intialize functions, instead of checking with if statement, use XLOG_ASSERTS. All checks MUST pass, so we shouldn't waste our performances on those checks. Passed all tests. --- xorp/rib/rib.cc | 183 ++++++++++++++++-------------------------------- xorp/rib/rib.hh | 26 +++---- 2 files changed, 70 insertions(+), 139 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index a82f2982a..385631ee3 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -395,15 +395,14 @@ template void RIB::initialize(RegisterServer& register_server) { - if (initialize_register(register_server) != XORP_OK) { - XLOG_FATAL("Could not initialize register table for %s", - name().c_str()); - } + // Unconditionally plumb ExtInt table if it doesn't exist + // All wining IGP, EGP and overall routes are cached in ExtInt table, + // so we could perform faster lookup + initialize_ext_int(); - if (initialize_policy_redist() != XORP_OK) { - XLOG_FATAL("Could not initialize policy redistribution table for %s", - name().c_str()); - } + initialize_register(register_server); + + initialize_policy_redist(); // // XXX: we must initialize the final RedistTable after the @@ -428,22 +427,15 @@ template int RIB::initialize_policy_redist() { - if (_register_table == NULL) { - XLOG_ERROR("Register table is not yet initialized"); - return XORP_ERROR; - } - - if (_policy_redist_table != NULL) { - return XORP_OK; // done already - } + XLOG_ASSERT(_register_table != NULL && _policy_redist_table == NULL); _policy_redist_table = new PolicyRedistTable(_register_table, _rib_manager.xrl_router(), _rib_manager.policy_redist_map(), _multicast); - if (_final_table == NULL || _final_table == _register_table) - _final_table = _policy_redist_table; + XLOG_ASSERT(_final_table == _register_table); + _final_table = _policy_redist_table; return XORP_OK; } @@ -452,17 +444,12 @@ template int RIB::initialize_redist_all(const string& all) { - if (_policy_redist_table == NULL) { - XLOG_ERROR("Policy redist table is not yet initialized"); - return XORP_ERROR; - } + XLOG_ASSERT(_policy_redist_table != NULL); - if (find_redist_table(redist_tablename(all)) != NULL) { - return XORP_OK; // RedistTable already exists, no sweat - } + XLOG_ASSERT(find_redist_table(redist_tablename(all)) == NULL); + + RedistTable* r = new RedistTable(redist_tablename(all), _policy_redist_table); - RedistTable* r; - r = new RedistTable(redist_tablename(all), _policy_redist_table); if (add_table(r) != XORP_OK) { delete r; return XORP_ERROR; @@ -471,8 +458,24 @@ RIB::initialize_redist_all(const string& all) // // Set the RedistTable as the final table // - if (_final_table == NULL || _final_table == _policy_redist_table) - _final_table = r; + XLOG_ASSERT(_final_table == _policy_redist_table); + _final_table = r; + + return XORP_OK; +} + + +template +int +RIB::initialize_ext_int() +{ + XLOG_ASSERT(!_ext_int_table); + + _ext_int_table = new ExtIntTable(NULL, NULL); + + XLOG_ASSERT(_final_table == NULL); + + _final_table = _ext_int_table; return XORP_OK; } @@ -481,22 +484,16 @@ template int RIB::initialize_register(RegisterServer& register_server) { - if (_register_table != NULL) { - XLOG_WARNING("Register table already initialized."); - return XORP_ERROR; - } + XLOG_ASSERT(!_register_table); - RegisterTable* rt; - rt = new RegisterTable("RegisterTable", register_server, _multicast); + _register_table = new RegisterTable("RegisterTable", register_server, _multicast); - _register_table = rt; + XLOG_ASSERT(_final_table == _ext_int_table); + + _register_table->replumb(NULL, _final_table); + _final_table->set_next_table(_register_table); + _final_table = _register_table; - if (_final_table == NULL) { - _final_table = _register_table; - } else { - _final_table->replumb(NULL, _register_table); - _register_table->set_next_table(_final_table); - } return XORP_OK; } @@ -516,9 +513,7 @@ RIB::new_origin_table(const string& tablename, return XORP_ERROR; } - if (_final_table == NULL) { - _final_table = ot; - } + XLOG_ASSERT(_final_table); // // Store the XRL target instance, so we know which OriginTable to @@ -1229,30 +1224,22 @@ RIB::add_redist_table(RouteTable* parent) template int -RIB::plumb_ahead_of_ext_int(OriginTable*& ot) +RIB::plumb_ahead_of_ext_int(OriginTable*& ot, const ProtocolType& type) { - // - // We are going to need to create an ExtInt table. - // - // Find the appropriate existng table to be a parent - // of the ExtIntTable. - // - RouteTable* next_table = track_back(_final_table, - REDIST_TABLE | POLICY_REDIST_TABLE | REGISTER_TABLE); - RouteTable* existing_table = next_table->parent(); - if (ot->protocol_type() == IGP) { - _ext_int_table = new ExtIntTable(existing_table, ot); - } else { - _ext_int_table = new ExtIntTable(ot, existing_table); - } + XLOG_ASSERT(_ext_int_table); - if (_final_table->type() - & (REDIST_TABLE | POLICY_REDIST_TABLE | REGISTER_TABLE)) { - _ext_int_table->set_next_table(next_table); - next_table->replumb(existing_table, _ext_int_table); - } else { - _final_table = _ext_int_table; + switch (type) { + case IGP: + _ext_int_table->replumb_internal(ot); + break; + case EGP: + _ext_int_table->replumb_external(ot); + break; + default: + XLOG_UNREACHABLE(); + break; } + return XORP_OK; } @@ -1296,38 +1283,6 @@ RIB::plumb_ahead_of_merged(OriginTable*& ot, } -template -int -RIB::plumb_ahead_of_first(OriginTable*& ot) -{ - // - // There are tables, but neither IGP or EGP origin tables - // Therefore the final table must be a RedistTable - // or a RegisterTable. - // - if ((_final_table->type() & (REDIST_TABLE | POLICY_REDIST_TABLE | REGISTER_TABLE)) == 0) - XLOG_UNREACHABLE(); - - // - // There may be existing single-parent tables before the - // final table such as RegisterTable - track back to be - // first of them. - // - RouteTable* rt = track_back(_final_table, - REDIST_TABLE - | POLICY_REDIST_TABLE - | REGISTER_TABLE); - - // - // Plumb our new table in ahead of the first single-parent - // table. - // - rt->replumb(NULL, ot); - ot->set_next_table(rt); - return XORP_OK; - -} - template int RIB::plumb_origin_table(OriginTable*& ot, @@ -1335,29 +1290,19 @@ RIB::plumb_origin_table(OriginTable*& ot, OriginTable* existing_egp_table) { // XXX: the table was created by new_origin_table() above, so it must exist - XLOG_ASSERT(ot != NULL); - if (_final_table == ot) { - // - // This is the first table, so no need to plumb anything. - // - debug_msg("first table\n"); - return XORP_OK; - } + XLOG_ASSERT(ot != NULL && _final_table != ot); // // There are existing tables, so we need to do some plumbing // - // Three possibilities: + // Two possibilities: // 1. There are no existing tables of the same protocol type as the protocol type // of the table that we're plumbing // - // -> Add ExtInt table and plumb the origin table ahead of ext int table + // -> Plumb the origin table ahead of ext int table // 2. There are both existing EGP and existing IGP tables // // -> Add Merged table and plumb the origin table ahead of merged table - // 3. there aren't existing IGP and existing EGP tables - // - // -> Plumb origin table ahead of currently first table // // @@ -1366,18 +1311,9 @@ RIB::plumb_origin_table(OriginTable*& ot, // ProtocolType protocol_type = (ProtocolType) ot->protocol_type(); if ((!existing_igp_table && (protocol_type == IGP)) || - (!existing_egp_table && (protocol_type == EGP))) { - // - // Sanity check: we've found an ExtIntTable, when there - // weren't both IGP and EGP tables. - // - XLOG_ASSERT(!_ext_int_table); - - if (!existing_egp_table && !existing_igp_table) - return plumb_ahead_of_first(ot); - else - return plumb_ahead_of_ext_int(ot); - } else + (!existing_egp_table && (protocol_type == EGP))) + return plumb_ahead_of_ext_int(ot, protocol_type); + else return plumb_ahead_of_merged(ot, (protocol_type == IGP) ? existing_igp_table : existing_egp_table); } @@ -1442,7 +1378,6 @@ RIB::add_origin_table(const string& tablename, OriginTable* existing_igp_table = !_igp_origin_tables.empty() ? _igp_origin_tables.begin()->second : NULL; OriginTable* existing_egp_table = !_egp_origin_tables.empty() ? _egp_origin_tables.begin()->second : NULL; - if (new_origin_table(tablename, target_class, target_instance, get_protocol_admin_distance(tablename), protocol_type) != XORP_OK) { debug_msg("new_origin_table failed\n"); diff --git a/xorp/rib/rib.hh b/xorp/rib/rib.hh index 86abdfb97..72667cba1 100644 --- a/xorp/rib/rib.hh +++ b/xorp/rib/rib.hh @@ -151,6 +151,13 @@ public: */ int initialize_register(RegisterServer& register_server); + /** + * Initialize the RIB's ExtIntTable. + * + * @return XORP_OK on success, otherwise XORP_ERROR. + */ + int initialize_ext_int(); + /** * Add a new OriginTable. Use is deprecated, except in test suites. * @@ -548,15 +555,14 @@ private: OriginTable* existing_egp_table); /** - * Creates ExtInt table and plumbs OriginTable @ot ahead of it. - * It should be called ONLY if are adding EGP table and there are - * existing IGP tables but no existing EGP table, or if we're adding - * IGP table and there are existing EGP tables but no existing IGP tables + * Plumbs OriginTable @ot ahead of ExtInt table. + * It should be called ONLY if are adding first origin table of some + * protocol type (IGP or EGP) * * @param ot OriginTable to plumb in * @return XORP_OK on success, otherwise XORP_ERROR. */ - int plumb_ahead_of_ext_int(OriginTable*& ot); + int plumb_ahead_of_ext_int(OriginTable*& ot, const ProtocolType& type); /** * Creates Merged table and plumbs OriginTable @ot ahead of it. @@ -569,16 +575,6 @@ private: */ int plumb_ahead_of_merged(OriginTable*& ot, RouteTable* existing_table); - /** - * Plumbs OriginTable @ot ahead of the currently first RouteTable. - * It should be called ONLY if if there aren't existing EGP tables and - * existing IGP tables. - * - * @param ot OriginTable to plumb in - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int plumb_ahead_of_first(OriginTable*& ot); - /** * Used to implement @ref add_igp_table and @ref add_egp_table. * From bf926a0a44ba2e34279ac2d4578c5a9bc6e18e5d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 18 Jun 2012 13:25:42 +0200 Subject: [PATCH 12/38] xorp: rib: Pretify print_rib function --- xorp/rib/rib.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index 385631ee3..04e72f590 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -1516,12 +1516,13 @@ RIB::track_forward(RouteTable* rt, int typemask) const #ifdef DEBUG_LOGGING template struct print_from_pair { - print_from_pair() {} + print_from_pair(string s = "###"): _separator(s) {} void operator() (const pair& table_pair) const { - cout << table_pair.second->str() << "###" << endl; + cout << table_pair.second->str() << _separator << endl; } +protected: + string _separator; }; - #endif template @@ -1569,7 +1570,7 @@ RIB::print_rib() const cout << "Protocols: " << endl; for_each(_protocols.begin(), _protocols.end(), - print_from_pair()); + print_from_pair(",")); cout << endl; cout << "**************************************************************" << endl; #endif // DEBUG_LOGGING From e1eae71879003804bc4faacae70594fbc1c12086 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 13:51:11 +0200 Subject: [PATCH 13/38] xorp: libxorp: trie: Print warning only if debugging Don't print warning if we're overwriting node. Assume that programmer knows what it's doing. Print the warning only in debug mode! --- xorp/libxorp/trie.hh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index af6920db8..9f4725785 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -540,11 +540,14 @@ public: iterator insert(const Key & net, const Payload& p) { bool replaced = false; Node *out = Node::insert(&_root, net, p, replaced); - if (replaced) { - fprintf(stderr, "overwriting a full node"); //XXX - } else { + if (!replaced) { _payload_count++; } +#ifdef DEBUG_LOGGING + else { + fprintf(stderr, "overwriting a full node"); //XXX + } +#endif return iterator(out); } From 0ffc52689982b2f87eb94868a26e83415760a726 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 15:05:16 +0200 Subject: [PATCH 14/38] xorp: rib: Don't propagate route copy from PolicyConnectedTable All routes are saved in trie, as pointers to non const objects. That way they can be modified. All routes will be cached in subsequent tables, and because of that, we must pass pointers to objects that won't be destroyed. This table is responsible of freeing the memory of route objects. Passed all rib tests. --- xorp/rib/rt_tab_pol_conn.cc | 51 ++++++++++--------------------------- xorp/rib/rt_tab_pol_conn.hh | 2 +- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index 48c04414b..f33c40a73 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -78,16 +78,13 @@ PolicyConnectedTable::add_route(const IPRouteEntry& route, IPRouteEntry* original = new IPRouteEntry(route); _route_table.insert(original->net(), original); - // make a copy so we may modify it - IPRouteEntry route_copy(*original); - do_filtering(route_copy); - + do_filtering(*original); RouteTable* next = this->next_table(); XLOG_ASSERT(next); // Send the possibly modified route down - return next->add_route(route_copy, this); + return next->add_route(*original, this); } template @@ -107,19 +104,19 @@ PolicyConnectedTable::delete_route(const IPRouteEntry* route, XLOG_ASSERT(i != _route_table.end()); - const IPRouteEntry* re = *i; + IPRouteEntry* re = *i; _route_table.erase(route->net()); - delete re; RouteTable* next = this->next_table(); XLOG_ASSERT(next); - // make a copy so we may modify it (e.g., by setting its policy tags) - IPRouteEntry route_copy(*route); - do_filtering(route_copy); + do_filtering(*re); // propagate the delete - return next->delete_route(&route_copy, this); + int ret = next->delete_route(re, this); + delete re; + + return ret; } template @@ -133,7 +130,7 @@ PolicyConnectedTable::lookup_route(const IPNet& net) const // check if we have route [we should have same routes as origin table]. if (i == _route_table.end()) - return _parent->lookup_route(net); // should return null probably + return NULL; return *i; } @@ -150,7 +147,7 @@ PolicyConnectedTable::lookup_route(const A& addr) const // same as above if (i == _route_table.end()) - return _parent->lookup_route(addr); // return null + return NULL; return *i; } @@ -202,39 +199,17 @@ PolicyConnectedTable::push_routes() RouteTable* next = this->next_table(); XLOG_ASSERT(next); - vector*> new_routes; - // XXX: not a background task // go through original routes and refilter them for (typename RouteContainer::iterator i = _route_table.begin(); i != _route_table.end(); ++i) { - const IPRouteEntry* prev = *i; - - // make a copy so filter may [possibly] modify it - const IPRouteEntry* orig = _parent->lookup_route(prev->net()); - IPRouteEntry* copy = new IPRouteEntry(*orig); + IPRouteEntry* prev = *i; - do_filtering(*copy); + do_filtering(*prev); // only policytags may change - next->replace_policytags(*copy, prev->policytags(), this); - - // delete old route - delete prev; - - // keep the new route so we may re-store it after this iteration - new_routes.push_back(copy); - } - - // store all new routes - for (typename vector*>::iterator i = new_routes.begin(); - i != new_routes.end(); ++i) { - - // replace route - IPRouteEntry* route = *i; - _route_table.erase(route->net()); - _route_table.insert(route->net(), route); + next->replace_policytags(*prev, prev->policytags(), this); } } diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index e44122d3f..c8d47833a 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -79,7 +79,7 @@ private: void do_filtering(IPRouteEntry& r); - typedef Trie*> RouteContainer; + typedef Trie* > RouteContainer; RouteTable* _parent; From d886a7ef42b040b6929d10e2b725c7bdd4ae01e6 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 17:41:45 +0200 Subject: [PATCH 15/38] xorp: libxorp: Fix finding of bounds in trie Problem was when we're in right intermidiate node, and there is existing left node. Just set the lo to the highest address of the right node and continue. Passed all trie tests. --- xorp/libxorp/trie.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index 9f4725785..57bbc1b91 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -244,6 +244,8 @@ public: lo = x->high(); ++lo; hi = n->_right->low(); --hi; } else if (a <= n->_right->_k.top_addr()) { // case 4: + if (n->_left && a > n->_left->_k.top_addr()) + lo = n->_left->high(); ++lo; n = n->_right; // and continue } else { // case 5: lo = n->_right->high(); ++lo; From d7fa4a603cbb5a94b1dfff300bea48e781bed62b Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 15:14:01 +0200 Subject: [PATCH 16/38] xorp: rib: Cache routes in ExtInt table Now we cache wining IGP, EGP and overall routes. All functions are updated to use this cached routes. Wining IGP routes are added/deleted to _wining_igp_routes only in function add_route/delete_route, if we're adding/deleting route from IGP parent. Wining EGP routes are added/deleted to/from _wining_egp_routes only in function add_route/delete_route, if we're adding/deleting route from EGP parent. It's possible that the same route is added to _wining_{igp, egp}_routes only when we're recursively call the add_route() method. That's not the problem because it overwrites pointer with the existing pointer. _wining_routes are updated always when we propagate add or delete routes. All lookups are performed on this tries. Passed all rib tests. --- xorp/rib/rt_tab_extint.cc | 473 ++++++++++++++------------------------ xorp/rib/rt_tab_extint.hh | 11 +- 2 files changed, 184 insertions(+), 300 deletions(-) diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 88deaf89b..cf566b5cb 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -56,9 +56,9 @@ ExtIntTable::~ExtIntTable() _ip_unresolved_table.erase(_ip_unresolved_table.begin()); } - while (! _ip_route_table.empty()) { - delete *_ip_route_table.begin(); - _ip_route_table.erase(_ip_route_table.begin()); + while (! _ip_resolved_table.empty()) { + delete *_ip_resolved_table.begin(); + _ip_resolved_table.erase(_ip_resolved_table.begin()); } } @@ -69,67 +69,35 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); if (_int_table && caller == _int_table) { + XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); // The new route comes from the IGP table debug_msg("route comes from IGP\n"); - if (_ext_table) { - const IPRouteEntry* found_egp; - const IPRouteEntry* found_resolved; - - XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); - - found_egp = lookup_route_in_egp_parent(route.net()); - if (found_egp != NULL) { - if (found_egp->admin_distance() < route.admin_distance()) { - // The admin distance of the existing EGP route is better - return XORP_ERROR; - } - } + // If it came here, it must be the wining IGP route. + // Insert it in wining IGP trie + _wining_igp_routes.insert(route.net(), &route); - found_resolved = lookup_in_resolved_table(route.net()); - if (found_resolved != NULL) { - if (found_resolved->admin_distance() < route.admin_distance()) { - // The admin distance of the existing route is better + if (_ext_table) { + // Try to find existing EGP routes, that are installed + // We're looking for EGP route in all wining routes. + // We can look here, because no IGP route that matches this subnet + // can't be in wining routes, because we're currently adding it. + // If it would be there, then some error has occurred. + // It should have been deleted. We check for that in the XLOG_ASSERT + const IPRouteEntry* found = lookup_route(route.net()); + if (found != NULL) { + if (found->admin_distance() < route.admin_distance()) { + // The admin distance of the existing IGP route is better return XORP_ERROR; + } else { + XLOG_ASSERT(found->admin_distance() != route.admin_distance()); + bool delete_is_propagated(false); + this->delete_ext_route(found, delete_is_propagated); } } - - // - // If necessary, from delete the route that came from the Ext table - // - do { - if (found_resolved != NULL) { - bool is_delete_propagated = false; - this->delete_ext_route(found_resolved, - is_delete_propagated); - break; - } - - if (found_egp == NULL) - break; - // - // If the nexthop of the route from the Ext table was directly - // connected, then it was propagated when the route was added, - // so delete it first. - // - IPNextHop* rt_nexthop; - rt_nexthop = found_egp->nexthop(); - const A& nexthop_addr = rt_nexthop->addr(); - const IPRouteEntry* nexthop_route; - nexthop_route = lookup_route_in_igp_parent(nexthop_addr); - if (nexthop_route != NULL) { - RibVif* vif = nexthop_route->vif(); - if ((vif != NULL) - && (vif->is_same_subnet( - IPvXNet(nexthop_route->net())) - || vif->is_same_p2p(IPvX(nexthop_addr)))) { - if (this->next_table() != NULL) - this->next_table()->delete_route(found_egp, this); - } - } - break; - } while (false); } + _wining_routes.insert(route.net(), &route); + if (this->next_table() != NULL) this->next_table()->add_route(route, this); @@ -147,7 +115,10 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) } else if (_ext_table && caller == _ext_table) { // The new route comes from the EGP table debug_msg("route comes from EGP\n"); - IPNextHop* rt_nexthop; + // If it came here, it must be the wining EGP route. + // Insert it in wining EGP trie + _wining_egp_routes.insert(route.net(), &route); + const IPRouteEntry* found = lookup_route_in_igp_parent(route.net()); if (found != NULL) { @@ -157,54 +128,66 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) } } - rt_nexthop = route.nexthop(); - A nexthop_addr = rt_nexthop->addr(); - const IPRouteEntry* nexthop_route; - nexthop_route = lookup_route_in_igp_parent(nexthop_addr); - if (nexthop_route == NULL) { - // Store the fact that this was unresolved for later - debug_msg("nexthop %s was unresolved\n", - nexthop_addr.str().c_str()); - UnresolvedIPRouteEntry* unresolved_route; - unresolved_route = new UnresolvedIPRouteEntry(&route); - _ip_unresolved_table.insert(make_pair(route.net(), - unresolved_route)); - typename UnresolvedRouteBackLink::iterator backlink; - backlink = _ip_unresolved_nexthops.insert( - make_pair(rt_nexthop->addr(), unresolved_route)); - unresolved_route->set_backlink(backlink); - return XORP_ERROR; - } else { - // The EGP route is resolvable + if (route.nexthop()->type() == PEER_NEXTHOP) { + // + // Despite it coming from the Ext table, the nexthop is + // directly connected. Just propagate it. + // + + debug_msg("nexthop %s was directly connected\n", route.nexthop()->addr().str().c_str()); + if (found != NULL) { // Delete the IGP route that has worse admin distance + _wining_routes.erase(found->net()); + if (this->next_table() != NULL) this->next_table()->delete_route(found, this); } - RibVif* vif = nexthop_route->vif(); - if ((vif != NULL) - && (vif->is_same_subnet(IPvXNet(nexthop_route->net())) - || vif->is_same_p2p(IPvX(nexthop_addr)))) { - // - // Despite it coming from the Ext table, the nexthop is - // directly connected. Just propagate it. - // - debug_msg("nexthop %s was directly connected\n", - nexthop_addr.str().c_str()); - if (this->next_table() != NULL) - this->next_table()->add_route(route, this); - return XORP_OK; + _wining_routes.insert(route.net(), &route); + + if (this->next_table() != NULL) + this->next_table()->add_route(route, this); + return XORP_OK; + } else { + IPNextHop* rt_nexthop = route.nexthop(); + + const IPRouteEntry* nexthop_route = + lookup_route_in_igp_parent(rt_nexthop->addr()); + if (nexthop_route == NULL) { + // Store the fact that this was unresolved for later + debug_msg("nexthop %s was unresolved\n", rt_nexthop->addr().str().c_str()); + UnresolvedIPRouteEntry* unresolved_route = + new UnresolvedIPRouteEntry(&route); + + _ip_unresolved_table.insert(make_pair(route.net(), unresolved_route)); + typename UnresolvedRouteBackLink::iterator backlink = + _ip_unresolved_nexthops.insert(make_pair(rt_nexthop->addr(), unresolved_route)); + + unresolved_route->set_backlink(backlink); + return XORP_ERROR; } else { - debug_msg("nexthop resolved to \n %s\n", - nexthop_route->str().c_str()); + // The EGP route is resolvable + if (found != NULL) { + // Delete the IGP route that has worse admin distance + _wining_routes.erase(found->net()); + + if (this->next_table() != NULL) + this->next_table()->delete_route(found, this); + } + + debug_msg("nexthop resolved to \n %s\n", nexthop_route->str().c_str()); + // Resolve the nexthop for non-directly connected nexthops - const ResolvedIPRouteEntry* resolved_route; - resolved_route = resolve_and_store_route(route, nexthop_route); + const ResolvedIPRouteEntry* resolved_route = + resolve_and_store_route(route, nexthop_route); + + _wining_routes.insert(resolved_route->net(), resolved_route); if (this->next_table() != NULL) this->next_table()->add_route(*resolved_route, this); + return XORP_OK; } } @@ -232,14 +215,15 @@ ExtIntTable::resolve_and_store_route(const IPRouteEntry& route, nexthop_route, &route); resolved_route->set_admin_distance(route.admin_distance()); - _ip_route_table.insert(resolved_route->net(), resolved_route); + _ip_resolved_table.insert(resolved_route->net(), resolved_route); if (_resolving_routes.lookup_node(nexthop_route->net()) == _resolving_routes.end()) { _resolving_routes.insert(nexthop_route->net(), nexthop_route); } - typename ResolvedRouteBackLink::iterator backlink; - backlink = _ip_igp_parents.insert(make_pair(nexthop_route->net(), + + typename ResolvedRouteBackLink::iterator backlink + = _ip_igp_parents.insert(make_pair(nexthop_route->net(), resolved_route)); resolved_route->set_backlink(backlink); @@ -255,22 +239,22 @@ ExtIntTable::delete_route(const IPRouteEntry* route, if (_int_table && caller == _int_table) { debug_msg(" called from _int_table\n"); + // If it came here, than we're certainly deleting wining IGP route + _wining_igp_routes.erase(route->net()); + const IPRouteEntry* found_egp_route = NULL; if (_ext_table) { - const IPRouteEntry* egp_parent; - const IPRouteEntry* found_egp_route; found_egp_route = lookup_route_in_egp_parent(route->net()); + if (found_egp_route != NULL) { - if (found_egp_route->admin_distance() - < route->admin_distance()) { + if (found_egp_route->admin_distance() < route->admin_distance()) { // The admin distance of the existing EGP route is better return XORP_ERROR; } } - - const ResolvedIPRouteEntry* found; - found = lookup_by_igp_parent(route->net()); + const ResolvedIPRouteEntry* found + = lookup_by_igp_parent(route->net()); if (found != NULL) { _resolving_routes.erase(route->net()); @@ -279,37 +263,54 @@ ExtIntTable::delete_route(const IPRouteEntry* route, while (found != NULL) { debug_msg("found route using this nexthop:\n %s\n", found->str().c_str()); // Erase from table first to prevent lookups on this entry - _ip_route_table.erase(found->net()); + _ip_resolved_table.erase(found->net()); _ip_igp_parents.erase(found->backlink()); // Propagate the delete next + _wining_routes.erase(found->net()); + if (this->next_table() != NULL) this->next_table()->delete_route(found, this); // Now delete the local resolved copy, and reinstantiate it - egp_parent = found->egp_parent(); + const IPRouteEntry* egp_parent = found->egp_parent(); delete found; + + // egp_parent route is one of the wining EGP routes. + // Re-adding will overwrite it the in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + add_route(*egp_parent, _ext_table); found = lookup_by_igp_parent(route->net()); } } // Propagate the original delete + _wining_routes.erase(route->net()); + this->next_table()->delete_route(route, this); - if (_ext_table) { + if (_ext_table && found_egp_route) { // It is possible the internal route had masked an external one. - const IPRouteEntry* masked_route; - masked_route = _ext_table->lookup_route(route->net()); - if (masked_route != NULL) - add_route(*masked_route, _ext_table); + + // found_egp_route route is one of the wining EGP routes. + // Re-adding will overwrite it the in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + + add_route(*found_egp_route, _ext_table); } } else if (_ext_table && caller == _ext_table) { debug_msg(" called from _ext_table\n"); + // If it came here, than we're certainly deleting wining EGP route + _wining_egp_routes.erase(route->net()); + const IPRouteEntry* found_igp_route = + lookup_route_in_igp_parent(route->net()); - const IPRouteEntry* found_igp_route; - found_igp_route = lookup_route_in_igp_parent(route->net()); if (found_igp_route != NULL) { if (found_igp_route->admin_distance() < route->admin_distance()) { // The admin distance of the existing IGP route is better @@ -319,12 +320,16 @@ ExtIntTable::delete_route(const IPRouteEntry* route, bool is_delete_propagated = false; this->delete_ext_route(route, is_delete_propagated); - if (is_delete_propagated && _int_table) { + if (is_delete_propagated && found_igp_route) { // It is possible the external route had masked an internal one. - const IPRouteEntry* masked_route; - masked_route = _int_table->lookup_route(route->net()); - if (masked_route != NULL) - add_route(*masked_route, _int_table); + + // found_igp_route route is one of the wining IGP routes. + // Re-adding will overwrite it the in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + + add_route(*found_igp_route, _int_table); } } else { XLOG_FATAL("ExtIntTable::delete_route called from a class that " @@ -345,7 +350,7 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, found = lookup_in_resolved_table(route->net()); if (found != NULL) { // Erase from table first to prevent lookups on this entry - _ip_route_table.erase(found->net()); + _ip_resolved_table.erase(found->net()); _ip_igp_parents.erase(found->backlink()); // Delete the route's IGP parent from _resolving_routes if @@ -355,6 +360,8 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, } // Propagate the delete next + _wining_routes.erase(found->net()); + if (this->next_table() != NULL) { this->next_table()->delete_route(found, this); is_delete_propagated = true; @@ -366,6 +373,8 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, // Propagate the delete only if the route wasn't found in // the unresolved nexthops table. if (delete_unresolved_nexthop(route) == false) { + _wining_routes.erase(route->net()); + if (this->next_table() != NULL) { this->next_table()->delete_route(route, this); is_delete_propagated = true; @@ -384,11 +393,8 @@ ExtIntTable::lookup_in_resolved_table(const IPNet& net) this->tablename().c_str()); typename Trie* >::iterator iter; - iter = _ip_route_table.lookup_node(net); - if (iter == _ip_route_table.end()) - return NULL; - else - return *iter; + iter = _ip_resolved_table.lookup_node(net); + return ((iter == _ip_resolved_table.end()) ? NULL : *iter); } template @@ -426,6 +432,12 @@ ExtIntTable::resolve_unresolved_nexthops(const IPRouteEntry& nexthop_route _ip_unresolved_table.erase(unresolved_route->net()); delete unresolved_entry; + // Unresolved routes are also wining EGP routes + // Re-adding them will overwrite them in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + // Reinstantiate the resolved route add_route(*unresolved_route, _ext_table); @@ -509,7 +521,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) debug_msg("recalculate_nexthops: %s\n", new_route.str().c_str()); const IPRouteEntry* old_route; - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _resolving_routes.find_less_specific(new_route.net()); if (iter == _resolving_routes.end()) { @@ -527,13 +539,12 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) egp_parent = found->egp_parent(); XLOG_ASSERT(egp_parent->nexthop()->type() != DISCARD_NEXTHOP); XLOG_ASSERT(egp_parent->nexthop()->type() != UNREACHABLE_NEXTHOP); - A nexthop = (egp_parent->nexthop())->addr(); - if (new_route.net().contains(nexthop)) { + if (new_route.net().contains((egp_parent->nexthop())->addr())) { debug_msg("found route using this nexthop:\n %s\n", found->str().c_str()); // Erase from table first to prevent lookups on this entry - _ip_route_table.erase(found->net()); + _ip_resolved_table.erase(found->net()); _ip_igp_parents.erase(found->backlink()); // Delete the route's IGP parent from _resolving_routes if @@ -543,15 +554,24 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) } // Propagate the delete next + _wining_routes.erase(found->net()); + if (this->next_table() != NULL) this->next_table()->delete_route(found, this); // Now delete the local resolved copy, and reinstantiate it delete found; + + // egp_parent route is one of the wining EGP routes. + // Re-adding will overwrite it the in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + add_route(*egp_parent, _ext_table); } else { debug_msg("route matched but nexthop didn't: nexthop: %s\n %s\n", - nexthop.str().c_str(), + (egp_parent->nexthop())->addr().str().c_str(), found->str().c_str()); last_not_deleted = found->backlink(); } @@ -566,169 +586,51 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route(const IPNet& ipv4net) const { - const IPRouteEntry* int_found; - const IPRouteEntry* ext_found; - - // First try our local version - debug_msg("------------------\nlookup_route in resolved table %s\n", - this->tablename().c_str()); - typename Trie* >::iterator iter; - - iter = _ip_route_table.lookup_node(ipv4net); - if (iter != _ip_route_table.end()) { - return *iter; - } - debug_msg("Not found in resolved table\n"); -#ifdef DEBUG_LOGGING - _ip_route_table.print(); -#endif - - // Local version failed, so try the parent tables. - int_found = lookup_route_in_igp_parent(ipv4net); - ext_found = lookup_route_in_egp_parent(ipv4net); - - if (ext_found == NULL) { - return int_found; - } - if (int_found == NULL) { - return ext_found; - } - - if (int_found->admin_distance() <= ext_found->admin_distance()) { - return int_found; - } else { - return ext_found; - } + typename RouteTrie::iterator iter = _wining_routes.lookup_node(ipv4net); + return ((iter == _wining_routes.end()) ? NULL : *iter); } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route(const A& addr) const { - const IPRouteEntry* ext_found = NULL; - const IPRouteEntry* int_found; - list* > found; - - debug_msg("ExtIntTable::lookup_route\n"); - - // Lookup locally, and in both internal and external tables - typename Trie* >::iterator trie_iter; - trie_iter = _ip_route_table.find(addr); - if (trie_iter != _ip_route_table.end()) { - found.push_back(*trie_iter); - } - - int_found = lookup_route_in_igp_parent(addr); - if (int_found != NULL) - found.push_back(int_found); - - ext_found = lookup_route_in_egp_parent(addr); - // Check that the external route has a local nexthop (if it doesn't - // we expect the version in local_found to have a local nexthop) - if (ext_found != NULL - && ext_found->nexthop()->type() == EXTERNAL_NEXTHOP) { - ext_found = NULL; - } - if (ext_found != NULL) - found.push_back(ext_found); - - if (found.empty()) - return NULL; - - // Retain only the routes with the longest prefix length - uint32_t longest_prefix_len = 0; - typename list* >::iterator iter, iter2; - for (iter = found.begin(); iter != found.end(); ++iter) { - if ((*iter)->net().prefix_len() > longest_prefix_len) { - longest_prefix_len = (*iter)->net().prefix_len(); - } - } - for (iter = found.begin(); iter != found.end(); ) { - iter2 = iter; - ++iter2; - if ((*iter)->net().prefix_len() < longest_prefix_len) { - found.erase(iter); - } - iter = iter2; - } - - if (found.size() == 1) { - return found.front(); - } - - // Retain only the routes with the lowest admin_distance - uint32_t lowest_admin_distance = MAX_ADMIN_DISTANCE; - for (iter = found.begin(); iter != found.end(); ++iter) { - if ((*iter)->admin_distance() < lowest_admin_distance) { - lowest_admin_distance = (*iter)->admin_distance(); - } - } - for (iter = found.begin(); iter != found.end(); ) { - iter2 = iter; - ++iter2; - if ((*iter)->admin_distance() > lowest_admin_distance) { - found.erase(iter); - } - iter = iter2; - } - - if (found.size() == 1) { - return found.front(); - } - - // This shouldn't happen. - XLOG_ERROR("ExtIntTable has multiple routes with same prefix_len " - "and same admin_distance"); - return found.front(); + typename RouteTrie::iterator iter = _wining_routes.find(addr); + return ((iter == _wining_routes.end()) ? NULL : *iter); } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route_in_igp_parent(const IPNet& ipnet) const { - const IPRouteEntry* found = NULL; - - if (_int_table) - found = _int_table->lookup_route(ipnet); - - return found; + typename RouteTrie::iterator iter = _wining_igp_routes.lookup_node(ipnet); + return ((iter == _wining_igp_routes.end()) ? NULL : *iter); } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route_in_igp_parent(const A& addr) const { - const IPRouteEntry* found = NULL; - - if (_int_table) - found = _int_table->lookup_route(addr); - - return found; + typename RouteTrie::iterator iter = _wining_igp_routes.find(addr); + return ((iter == _wining_igp_routes.end()) ? NULL : *iter); } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route_in_egp_parent(const IPNet& ipnet) const { - const IPRouteEntry* found = NULL; - if (_ext_table) - found = _ext_table->lookup_route(ipnet); - - return found; + typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(ipnet); + return ((iter == _wining_egp_routes.end()) ? NULL : *iter); } template -const IPRouteEntry* +inline const IPRouteEntry* ExtIntTable::lookup_route_in_egp_parent(const A& addr) const { - const IPRouteEntry* found = NULL; - if (_ext_table) - found = _ext_table->lookup_route(addr); - - return found; + typename RouteTrie::iterator iter = _wining_egp_routes.find(addr); + return ((iter == _wining_egp_routes.end()) ? NULL : *iter); } template @@ -743,7 +645,7 @@ ExtIntTable::replumb(RouteTable* old_parent, RouteTable* new_parent) } template -void +inline void ExtIntTable::replumb_external(RouteTable* new_ext_parent) { debug_msg("ExtIntTable::replumb_external\n"); @@ -754,7 +656,7 @@ ExtIntTable::replumb_external(RouteTable* new_ext_parent) } template -void +inline void ExtIntTable::replumb_internal(RouteTable* new_int_parent) { debug_msg("ExtIntTable::replumb_internal\n"); @@ -768,40 +670,15 @@ template RouteRange* ExtIntTable::lookup_route_range(const A& addr) const { - // What do the parents think the answer is? - RouteRange* int_rr = (_int_table ? _int_table->lookup_route_range(addr) : - new RouteRange(addr, NULL, A::ZERO(), A::ALL_ONES())); - RouteRange* ext_rr = (_ext_table ? _ext_table->lookup_route_range(addr) : - new RouteRange(addr, NULL, A::ZERO(), A::ALL_ONES())); - - // What do we think the answer is? - const IPRouteEntry* route; - typename Trie* >::iterator iter; - iter = _ip_route_table.find(addr); - if (iter == _ip_route_table.end()) - route = NULL; - else - route = *iter; - - A bottom_addr, top_addr; - _ip_route_table.find_bounds(addr, bottom_addr, top_addr); - RouteRange* rr = new RouteRange(addr, route, top_addr, bottom_addr); + typename RouteTrie::iterator iter; + iter = _wining_routes.find(addr); - // - // If there's a matching routing in _ip_route_table, there'll also - // be one in _ext_table. But our version has the correct nexthop. - // We still need to merge in the result of lookup_route_range on - // _ext_table though, because the upper and lower bounds there may - // be tighter than the ones we'd find ourselves. - // + const IPRouteEntry* route = + (iter == _wining_routes.end()) ? NULL : *iter; - rr->merge(int_rr); - delete(int_rr); - - rr->merge(ext_rr); - delete(ext_rr); - - return rr; + A bottom_addr, top_addr; + _wining_routes.find_bounds(addr, bottom_addr, top_addr); + return (new RouteRange(addr, route, top_addr, bottom_addr)); } template diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index dd32466c4..4de078739 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -183,6 +183,7 @@ private: typedef typename UnresolvedIPRouteEntry::RouteBackLink UnresolvedRouteBackLink; typedef multimap, ResolvedIPRouteEntry* > IGPParentMultiMap; typedef map, UnresolvedIPRouteEntry* > IpUnresolvedTableMap; + typedef Trie* > RouteTrie; int delete_ext_route(const IPRouteEntry* route, bool& is_delete_propagated); @@ -217,7 +218,7 @@ private: RouteTable* _ext_table; RouteTable* _int_table; - Trie* > _ip_route_table; + Trie* > _ip_resolved_table; multimap* > _ip_unresolved_nexthops; IpUnresolvedTableMap _ip_unresolved_table; @@ -227,7 +228,13 @@ private: // _resolving_routes is a Trie of all the routes that are used to // resolve external routes - Trie* > _resolving_routes; + RouteTrie _resolving_routes; + + // Tries where we cache wining IGP, EGP and overall routes + RouteTrie _wining_igp_routes; + RouteTrie _wining_egp_routes; // Here, all wining EGP routes will be stored + //(resolved, unresolved and connected) + RouteTrie _wining_routes; // Overall wining routes! }; #endif // __RIB_RT_TAB_EXTINT_HH__ From 7ddd862090ccde650454b131542afe072c450ba6 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 15:26:55 +0200 Subject: [PATCH 17/38] xorp: rib: Don't check for next_table in ExtInt table Don't waste CPU on unecessary checks, because next_table must not be NULL if we have initialized RIB. --- xorp/rib/rt_tab_extint.cc | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index cf566b5cb..6410bddbc 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -68,6 +68,8 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) { debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); + XLOG_ASSERT(this->next_table()); + if (_int_table && caller == _int_table) { XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); // The new route comes from the IGP table @@ -98,8 +100,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) _wining_routes.insert(route.net(), &route); - if (this->next_table() != NULL) - this->next_table()->add_route(route, this); + this->next_table()->add_route(route, this); if (_ext_table) { // Does this cause any previously resolved nexthops to resolve @@ -140,14 +141,12 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) // Delete the IGP route that has worse admin distance _wining_routes.erase(found->net()); - if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found, this); } _wining_routes.insert(route.net(), &route); - if (this->next_table() != NULL) - this->next_table()->add_route(route, this); + this->next_table()->add_route(route, this); return XORP_OK; } else { IPNextHop* rt_nexthop = route.nexthop(); @@ -172,8 +171,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) // Delete the IGP route that has worse admin distance _wining_routes.erase(found->net()); - if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found, this); } debug_msg("nexthop resolved to \n %s\n", nexthop_route->str().c_str()); @@ -185,8 +183,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) _wining_routes.insert(resolved_route->net(), resolved_route); - if (this->next_table() != NULL) - this->next_table()->add_route(*resolved_route, this); + this->next_table()->add_route(*resolved_route, this); return XORP_OK; } @@ -236,6 +233,7 @@ ExtIntTable::delete_route(const IPRouteEntry* route, RouteTable* caller) { debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); + XLOG_ASSERT(this->next_table()); if (_int_table && caller == _int_table) { debug_msg(" called from _int_table\n"); @@ -269,8 +267,7 @@ ExtIntTable::delete_route(const IPRouteEntry* route, // Propagate the delete next _wining_routes.erase(found->net()); - if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found, this); // Now delete the local resolved copy, and reinstantiate it const IPRouteEntry* egp_parent = found->egp_parent(); @@ -362,10 +359,8 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, // Propagate the delete next _wining_routes.erase(found->net()); - if (this->next_table() != NULL) { - this->next_table()->delete_route(found, this); - is_delete_propagated = true; - } + this->next_table()->delete_route(found, this); + is_delete_propagated = true; // Now delete the locally modified copy delete found; @@ -375,10 +370,8 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, if (delete_unresolved_nexthop(route) == false) { _wining_routes.erase(route->net()); - if (this->next_table() != NULL) { - this->next_table()->delete_route(route, this); - is_delete_propagated = true; - } + this->next_table()->delete_route(route, this); + is_delete_propagated = true; } } @@ -556,8 +549,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) // Propagate the delete next _wining_routes.erase(found->net()); - if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found, this); // Now delete the local resolved copy, and reinstantiate it delete found; From 0dffdf5a004a57fc9943f6309b953f9f119b5678 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 29 Jun 2012 19:43:43 +0200 Subject: [PATCH 18/38] xorp: libxorp: Make trie lookup faster Lookup is made faster by avoiding creation of temporary objects in functions, that are in fast path. --- xorp/libxorp/ipnet.hh | 58 +++++++++++++++++++++------------ xorp/libxorp/ipv4.cc | 26 ++------------- xorp/libxorp/ipv4.hh | 42 ++++++++++++++++++++++-- xorp/libxorp/ipv6.cc | 65 ++----------------------------------- xorp/libxorp/ipv6.hh | 74 +++++++++++++++++++++++++++++++++++++++++-- xorp/libxorp/trie.hh | 4 +-- 6 files changed, 156 insertions(+), 113 deletions(-) diff --git a/xorp/libxorp/ipnet.hh b/xorp/libxorp/ipnet.hh index 8a8c9d2ea..f112663e3 100644 --- a/xorp/libxorp/ipnet.hh +++ b/xorp/libxorp/ipnet.hh @@ -9,13 +9,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -104,8 +104,8 @@ public: * right-hand operand. */ bool operator==(const IPNet& other) const { - return ((prefix_len() == other.prefix_len()) && - (masked_addr() == other.masked_addr())); + return ((_prefix_len == other._prefix_len) && + (_masked_addr == other._masked_addr)); } /** @@ -456,7 +456,8 @@ private: /* ------------------------------------------------------------------------- */ /* Deferred method definitions */ -template bool +template +inline bool IPNet::operator<(const IPNet& other) const { #if 1 @@ -548,23 +549,38 @@ IPNet::is_overlap(const IPNet& other) const return (other.masked_addr() == masked_addr()); } -template bool -IPNet::contains(const IPNet& other) const +template <> +inline bool +IPNet::contains(const IPv4& addr) const { - if (masked_addr().af() != other.masked_addr().af()) - return (false); + return addr.mask_by_prefix_len_uint(_prefix_len) == _masked_addr.addr(); +} - if (prefix_len() > other.prefix_len()) { +template <> +inline bool +IPNet::contains(const IPv6& addr) const +{ + uint32_t prefixed_addr[4]; + addr.mask_by_prefix_len_uint(_prefix_len, prefixed_addr); + return ((prefixed_addr[0] == _masked_addr.addr()[0]) + && (prefixed_addr[1] == _masked_addr.addr()[1]) + && (prefixed_addr[2] == _masked_addr.addr()[2]) + && (prefixed_addr[3] == _masked_addr.addr()[3])); +} + +template +inline bool +IPNet::contains(const IPNet& other) const +{ + if (_prefix_len > other._prefix_len) // I have smaller prefix size, hence I don't contain other. return (false); - } - if (prefix_len() < other.prefix_len()) { - // I have bigger prefix size - IPNet other_masked(other.masked_addr(), prefix_len()); - return (other_masked.masked_addr() == masked_addr()); - } - // Same prefix size - return (other.masked_addr() == masked_addr()); + + if (_prefix_len == other._prefix_len) + return (other._masked_addr == _masked_addr); + + // I have bigger prefix size + return (contains(other._masked_addr)); } template void @@ -591,7 +607,8 @@ IPNet::initialize_from_string(const char *cp) _masked_addr = A(addr.c_str()).mask_by_prefix_len(_prefix_len); } -template IPNet& +template +inline IPNet& IPNet::operator--() { _masked_addr = _masked_addr >> (_masked_addr.addr_bitlen() - _prefix_len); @@ -600,7 +617,8 @@ IPNet::operator--() return (*this); } -template IPNet& +template +inline IPNet& IPNet::operator++() { _masked_addr = _masked_addr >> (_masked_addr.addr_bitlen() - _prefix_len); diff --git a/xorp/libxorp/ipv4.cc b/xorp/libxorp/ipv4.cc index 857aa8fdb..aabfb19b3 100644 --- a/xorp/libxorp/ipv4.cc +++ b/xorp/libxorp/ipv4.cc @@ -8,13 +8,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -219,12 +219,6 @@ IPv4::operator>>(uint32_t right_shift) const return IPv4(htonl(tmp_addr)); } -bool -IPv4::operator<(const IPv4& other) const -{ - return ntohl(_addr) < ntohl(other._addr); -} - IPv4 IPv4::make_prefix(uint32_t mask_len) throw (InvalidNetmaskLength) { @@ -251,22 +245,6 @@ IPv4::mask_len() const return ctr; } -IPv4& -IPv4::operator--() -{ - uint32_t tmp_addr = ntohl(_addr) - 1; - _addr = htonl(tmp_addr); - return *this; -} - -IPv4& -IPv4::operator++() -{ - uint32_t tmp_addr = ntohl(_addr) + 1; - _addr = htonl(tmp_addr); - return *this; -} - string IPv4::str() const { diff --git a/xorp/libxorp/ipv4.hh b/xorp/libxorp/ipv4.hh index aa3e33259..cfb42e73c 100644 --- a/xorp/libxorp/ipv4.hh +++ b/xorp/libxorp/ipv4.hh @@ -9,13 +9,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -612,6 +612,8 @@ public: */ static IPv4 make_prefix(uint32_t mask_len) throw (InvalidNetmaskLength); + static uint32_t make_prefix_uint(uint32_t mask_len) throw (InvalidNetmaskLength); + /** * Make an IPv4 address prefix. * @@ -624,6 +626,11 @@ public: return (*this) & make_prefix(mask_len); } + uint32_t mask_by_prefix_len_uint(uint32_t mask_len) const + throw (InvalidNetmaskLength) { + return this->_addr & make_prefix_uint(mask_len); + } + /** * Get the mask length. * @@ -747,6 +754,31 @@ IPv4::bits(uint32_t lsb, uint32_t len) const return (ntohl(_addr) >> lsb) & mask; } +inline uint32_t +IPv4::make_prefix_uint(uint32_t mask_len) throw (InvalidNetmaskLength) +{ + if (mask_len > 32) + xorp_throw(InvalidNetmaskLength, mask_len); + uint32_t m = (mask_len == 0) ? 0 : ((~0U) << (32 - mask_len)); + return htonl(m); +} + +inline IPv4& +IPv4::operator--() +{ + uint32_t tmp_addr = ntohl(_addr) - 1; + _addr = htonl(tmp_addr); + return *this; +} + +inline IPv4& +IPv4::operator++() +{ + uint32_t tmp_addr = ntohl(_addr) + 1; + _addr = htonl(tmp_addr); + return *this; +} + inline uint32_t IPv4::bit_count() const { @@ -760,6 +792,12 @@ IPv4::leading_zero_count() const return (xorp_leading_zero_count_uint32(ntohl(_addr))); } +inline bool +IPv4::operator<(const IPv4& other) const +{ + return ntohl(_addr) < ntohl(other._addr); +} + struct IPv4Constants { static const IPv4 zero, any, diff --git a/xorp/libxorp/ipv6.cc b/xorp/libxorp/ipv6.cc index 6a3bfc793..daaaaca44 100644 --- a/xorp/libxorp/ipv6.cc +++ b/xorp/libxorp/ipv6.cc @@ -8,13 +8,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -329,67 +329,6 @@ IPv6::operator>>(uint32_t rs) const return IPv6(tmp_addr); } -bool -IPv6::operator<(const IPv6& other) const -{ - int i; - x_static_assert(sizeof(_addr) == 16); - - for (i = 0; i < 3; i++) { // XXX: Loop ends intentionally at 3 not 4 - if (_addr[i] != other._addr[i]) - break; - } - return ntohl(_addr[i]) < ntohl(other._addr[i]); -} - -bool -IPv6::operator==(const IPv6& other) const -{ - return ((_addr[0] == other._addr[0]) - && (_addr[1] == other._addr[1]) - && (_addr[2] == other._addr[2]) - && (_addr[3] == other._addr[3])); -} - -bool -IPv6::operator!=(const IPv6& other) const -{ - return ((_addr[0] != other._addr[0]) - || (_addr[1] != other._addr[1]) - || (_addr[2] != other._addr[2]) - || (_addr[3] != other._addr[3])); -} - -IPv6& -IPv6::operator--() -{ - for (int i = 3; i >= 0; i--) { - if (_addr[i] == 0) { - _addr[i] = 0xffffffffU; - } else { - uint32_t tmp_addr = ntohl(_addr[i]) - 1; - _addr[i] = htonl(tmp_addr); - return *this; - } - } - return *this; -} - -IPv6& -IPv6::operator++() -{ - for (int i = 3; i >= 0; i--) { - if (_addr[i] == 0xffffffffU) { - _addr[i] = 0; - } else { - uint32_t tmp_addr = ntohl(_addr[i]) + 1; - _addr[i] = htonl(tmp_addr); - return *this; - } - } - return *this; -} - static uint32_t init_prefixes(IPv6* v6prefix) { diff --git a/xorp/libxorp/ipv6.hh b/xorp/libxorp/ipv6.hh index 3ee3fefcd..66d347836 100644 --- a/xorp/libxorp/ipv6.hh +++ b/xorp/libxorp/ipv6.hh @@ -9,13 +9,13 @@ // Redistribution and/or modification of this program under the terms of // any other version of the GNU Lesser General Public License is not // permitted. -// +// // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, // see the GNU Lesser General Public License, Version 2.1, a copy of // which can be found in the XORP LICENSE.lgpl file. -// +// // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net @@ -514,6 +514,15 @@ public: return (*this) & make_prefix(prefix_len); } + void mask_by_prefix_len_uint(uint32_t prefix_len, uint32_t* masked_addr) const + throw (InvalidNetmaskLength) { + const IPv6& other = make_prefix(prefix_len); + masked_addr[0] = _addr[0] & other._addr[0]; + masked_addr[1] = _addr[1] & other._addr[1]; + masked_addr[2] = _addr[2] & other._addr[2]; + masked_addr[3] = _addr[3] & other._addr[3]; + } + /** * Get the mask length. * @@ -661,6 +670,67 @@ IPv6::leading_zero_count() const return (r); } +inline bool +IPv6::operator<(const IPv6& other) const +{ + int i; + x_static_assert(sizeof(_addr) == 16); + + for (i = 0; i < 3; i++) { // XXX: Loop ends intentionally at 3 not 4 + if (_addr[i] != other._addr[i]) + break; + } + return ntohl(_addr[i]) < ntohl(other._addr[i]); +} + +inline bool +IPv6::operator==(const IPv6& other) const +{ + return ((_addr[0] == other._addr[0]) + && (_addr[1] == other._addr[1]) + && (_addr[2] == other._addr[2]) + && (_addr[3] == other._addr[3])); +} + +inline bool +IPv6::operator!=(const IPv6& other) const +{ + return ((_addr[0] != other._addr[0]) + || (_addr[1] != other._addr[1]) + || (_addr[2] != other._addr[2]) + || (_addr[3] != other._addr[3])); +} + +inline IPv6& +IPv6::operator--() +{ + for (int i = 3; i >= 0; i--) { + if (_addr[i] == 0) { + _addr[i] = 0xffffffffU; + } else { + uint32_t tmp_addr = ntohl(_addr[i]) - 1; + _addr[i] = htonl(tmp_addr); + return *this; + } + } + return *this; +} + +inline IPv6& +IPv6::operator++() +{ + for (int i = 3; i >= 0; i--) { + if (_addr[i] == 0xffffffffU) { + _addr[i] = 0; + } else { + uint32_t tmp_addr = ntohl(_addr[i]) + 1; + _addr[i] = htonl(tmp_addr); + return *this; + } + } + return *this; +} + struct IPv6Constants { static const IPv6 zero, any, diff --git a/xorp/libxorp/trie.hh b/xorp/libxorp/trie.hh index 57bbc1b91..516c76b15 100644 --- a/xorp/libxorp/trie.hh +++ b/xorp/libxorp/trie.hh @@ -867,13 +867,13 @@ TrieNode::erase() * that contains the desired key and has a Payload */ template -TrieNode * +inline TrieNode * TrieNode::find(const Key &key) { TrieNode * cand = NULL; TrieNode * r = this; - for ( ; r && r->_k.contains(key) ; ) { + while(r && r->_k.contains(key)) { if (r->_p) cand = r; // we have a candidate. if (r->_left && r->_left->_k.contains(key)) From 56d90e5657d26c4ae0313c7dafe2297ffd5d2d5d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 19 Jun 2012 15:11:37 +0200 Subject: [PATCH 19/38] xorp: rib: tests: Add some additional tests, to better test RIB --- xorp/rib/tests/commands | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/xorp/rib/tests/commands b/xorp/rib/tests/commands index d2395b447..390b1ba80 100644 --- a/xorp/rib/tests/commands +++ b/xorp/rib/tests/commands @@ -98,6 +98,27 @@ route verify ip 192.150.187.1 de1 10.0.1.2 5 #delete the static and check it reverts to the ospf route route delete static 192.150.187.0/24 route verify ip 192.150.187.1 de0 10.0.0.2 5 + +route add ebgp 176.16.128.0/28 10.0.0.100 10 +route verify ip 176.16.128.1 de0 10.0.0.100 10 + +vif Ethernet de3 176.16.128.2 28 +route verify ip 176.16.128.1 de3 176.16.128.2 0 + +route delete ebgp 176.16.128.0/28 +route verify ip 176.16.128.1 de3 176.16.128.2 0 + +route add rip 147.91.8.0/24 176.16.128.1 10 +route verify ip 147.91.8.1 de3 176.16.128.1 10 + +route add ebgp 147.91.8.0/24 192.150.187.1 7 +route verify ip 147.91.8.1 de0 10.0.0.2 7 + +route delete ebgp 147.91.8.0/24 +route verify ip 147.91.8.1 de3 176.16.128.1 10 + +route delete rip 147.91.8.0/24 +route verify miss 147.91.8.1 lo0 0.0.0.0 0 # #------------------------------------------------------------------- #Now add an EBGP route From c4695b50ec178ae466822362483ab5033049c766 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 3 Jul 2012 17:24:42 +0200 Subject: [PATCH 20/38] xorp: policy: backend: Fix memory leak in PolicyredistMap --- xorp/policy/backend/policy_redist_map.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xorp/policy/backend/policy_redist_map.cc b/xorp/policy/backend/policy_redist_map.cc index ffb90749f..df596ea7a 100644 --- a/xorp/policy/backend/policy_redist_map.cc +++ b/xorp/policy/backend/policy_redist_map.cc @@ -35,6 +35,9 @@ PolicyRedistMap::~PolicyRedistMap() { void PolicyRedistMap::remove(const string& protocol) { + Map::iterator i = _map.find(protocol); + if (i != _map.end()) + delete i->second; _map.erase(protocol); } From e8f7ada8d1fc32712f1f5e6537aa11ae79a00974 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 3 Jul 2012 17:08:05 +0200 Subject: [PATCH 21/38] xorp: rtrmgr: Fix memory leaks in template.ll --- xorp/rtrmgr/template.ll | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/xorp/rtrmgr/template.ll b/xorp/rtrmgr/template.ll index 354268f79..d9f918408 100644 --- a/xorp/rtrmgr/template.ll +++ b/xorp/rtrmgr/template.ll @@ -268,102 +268,82 @@ RE_URL_SUBDELIMS "!"|"$"|"&"|"'"|"("|")"|"*"|"+"|","|";"|"=" } "->" { - tpltlval = strdup(tplttext); return RETURN; } "txt" { - tpltlval = strdup(tplttext); return TEXT_TYPE; } "i32" { - tpltlval = strdup(tplttext); return INT_TYPE; } "u32range" { - tpltlval = strdup(tplttext); return UINTRANGE_TYPE; } "u32" { - tpltlval = strdup(tplttext); return UINT_TYPE; } "u64range" { - tpltlval = strdup(tplttext); return ULONGRANGE_TYPE; } "u64" { - tpltlval = strdup(tplttext); return ULONG_TYPE; } "bool" { - tpltlval = strdup(tplttext); return BOOL_TYPE; } "toggle" { - tpltlval = strdup(tplttext); return TOGGLE_TYPE; } "ipv4range" { - tpltlval = strdup(tplttext); return IPV4RANGE_TYPE; } "ipv4" { - tpltlval = strdup(tplttext); return IPV4_TYPE; } "ipv4net" { - tpltlval = strdup(tplttext); return IPV4NET_TYPE; } "ipv6range" { - tpltlval = strdup(tplttext); return IPV6RANGE_TYPE; } "ipv6" { - tpltlval = strdup(tplttext); return IPV6_TYPE; } "ipv6net" { - tpltlval = strdup(tplttext); return IPV6NET_TYPE; } "macaddr" { - tpltlval = strdup(tplttext); return MACADDR_TYPE; } "url_file" { - tpltlval = strdup(tplttext); return URL_FILE_TYPE; } "url_ftp" { - tpltlval = strdup(tplttext); return URL_FTP_TYPE; } "url_http" { - tpltlval = strdup(tplttext); return URL_HTTP_TYPE; } "url_tftp" { - tpltlval = strdup(tplttext); return URL_TFTP_TYPE; } From ffb94a467b2fbc09773844faaa0eba3b8043530c Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 5 Jul 2012 10:02:11 +0200 Subject: [PATCH 22/38] xorp: rib: Enlarge max word limit, and set it via static variable --- xorp/rib/parser.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xorp/rib/parser.cc b/xorp/rib/parser.cc index b3dc7ba10..fa766f975 100644 --- a/xorp/rib/parser.cc +++ b/xorp/rib/parser.cc @@ -30,6 +30,7 @@ #include "parser.hh" +static uint32_t MAX_WORDS = 20; // ---------------------------------------------------------------------------- // Argument Parsing methods @@ -275,14 +276,14 @@ Parser::parse(const string& s) const debug_msg("Best match: %s\n", rpair->first.c_str()); Command* cmd = rpair->second; - vector words(10); + vector words(MAX_WORDS); int wcount = split_into_words(str, words); // Accept empty lines if (wcount == 0) return XORP_OK; - vector template_words(10); + vector template_words(MAX_WORDS); int twcount = split_into_words(rpair->first, template_words); try { @@ -355,6 +356,7 @@ Parser::split_into_words(const string& str, vector& words) const break; } } catch (out_of_range) { + throw Parse_error("Max Word limit is reached\n"); } return word; } From 4c30bf376fa588f1d05adda632b23da3875bbd8b Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 6 Jul 2012 11:11:53 +0200 Subject: [PATCH 23/38] xorp: rib: Change variable and function names in ExtInt table and ResolvedIPRouteEntry _ip_igp_parent and similar names were misleading. Changed them to _ip_resolving_parent and similar. --- xorp/rib/route.cc | 4 ++-- xorp/rib/route.hh | 10 +++++----- xorp/rib/rt_tab_extint.cc | 30 +++++++++++++++--------------- xorp/rib/rt_tab_extint.hh | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index 17777275b..249781e6c 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -119,7 +119,7 @@ IPRouteEntry& IPRouteEntry::operator=(const IPRouteEntry& r) { template ResolvedIPRouteEntry::ResolvedIPRouteEntry(const ResolvedIPRouteEntry& r) : IPRouteEntry(r) { - _igp_parent = r._igp_parent; + _resolving_parent = r._resolving_parent; _egp_parent = r._egp_parent; _backlink = r._backlink; } @@ -129,7 +129,7 @@ ResolvedIPRouteEntry& ResolvedIPRouteEntry::operator=(const ResolvedIPRout if (this == &r) return *this; IPRouteEntry::operator=(r); - _igp_parent = r._igp_parent; + _resolving_parent = r._resolving_parent; _egp_parent = r._egp_parent; _backlink = r._backlink; return *this; diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index f2e8b6db2..5ce968634 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -276,11 +276,11 @@ public: */ ResolvedIPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, Protocol* protocol, uint32_t metric, - const IPRouteEntry* igp_parent, + const IPRouteEntry* resolving_parent, const IPRouteEntry* egp_parent) : IPRouteEntry(net, vif, nexthop, protocol, metric, PolicyTags()), - _igp_parent(igp_parent), - _egp_parent(egp_parent) { } + _resolving_parent(resolving_parent), + _egp_parent(egp_parent) { } ResolvedIPRouteEntry(const ResolvedIPRouteEntry& r); ResolvedIPRouteEntry& operator=(const ResolvedIPRouteEntry& r); @@ -291,7 +291,7 @@ public: * @return the IGP parent route entry that was used to resolve the * EGP parent route entry's non-local nexthop into a local nexthop. */ - const IPRouteEntry* igp_parent() const { return _igp_parent; } + const IPRouteEntry* resolving_parent() const { return _resolving_parent; } /** * Get the EGP parent. @@ -323,7 +323,7 @@ public: typename RouteBackLink::iterator backlink() const { return _backlink; } private: - const IPRouteEntry* _igp_parent; + const IPRouteEntry* _resolving_parent; const IPRouteEntry* _egp_parent; // _backlink is used for removing the corresponding entry from the diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 6410bddbc..3a05a9f2b 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -220,7 +220,7 @@ ExtIntTable::resolve_and_store_route(const IPRouteEntry& route, typename ResolvedRouteBackLink::iterator backlink - = _ip_igp_parents.insert(make_pair(nexthop_route->net(), + = _ip_resolving_parents.insert(make_pair(nexthop_route->net(), resolved_route)); resolved_route->set_backlink(backlink); @@ -262,7 +262,7 @@ ExtIntTable::delete_route(const IPRouteEntry* route, debug_msg("found route using this nexthop:\n %s\n", found->str().c_str()); // Erase from table first to prevent lookups on this entry _ip_resolved_table.erase(found->net()); - _ip_igp_parents.erase(found->backlink()); + _ip_resolving_parents.erase(found->backlink()); // Propagate the delete next _wining_routes.erase(found->net()); @@ -348,12 +348,12 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, if (found != NULL) { // Erase from table first to prevent lookups on this entry _ip_resolved_table.erase(found->net()); - _ip_igp_parents.erase(found->backlink()); + _ip_resolving_parents.erase(found->backlink()); // Delete the route's IGP parent from _resolving_routes if // no-one is using it anymore - if (lookup_by_igp_parent(found->igp_parent()->net()) == NULL) { - _resolving_routes.erase(found->igp_parent()->net()); + if (lookup_by_igp_parent(found->resolving_parent()->net()) == NULL) { + _resolving_routes.erase(found->resolving_parent()->net()); } // Propagate the delete next @@ -473,8 +473,8 @@ ExtIntTable::lookup_by_igp_parent(const IPNet& route_net) route_net.str().c_str()); typename ResolvedRouteBackLink::iterator iter; - iter = _ip_igp_parents.find(route_net); - if (iter == _ip_igp_parents.end()) { + iter = _ip_resolving_parents.find(route_net); + if (iter == _ip_resolving_parents.end()) { debug_msg("Found no routes with this IGP parent\n"); return NULL; } else { @@ -487,14 +487,14 @@ ExtIntTable::lookup_by_igp_parent(const IPNet& route_net) template const ResolvedIPRouteEntry* ExtIntTable::lookup_next_by_igp_parent(const IPNet& route_net, - const typename IGPParentMultiMap::iterator& previous) + const typename ResolvingParentMultiMap::iterator& previous) { debug_msg("lookup_next_by_igp_parent %s, starting from %p -> %s\n", route_net.str().c_str(), previous->second, previous->second->net().str().c_str()); - pair route_range = _ip_igp_parents.equal_range(route_net); - typename IGPParentMultiMap::iterator iter = previous; + pair route_range = _ip_resolving_parents.equal_range(route_net); + typename ResolvingParentMultiMap::iterator iter = previous; if (iter++ == route_range.second || iter == route_range.second) { debug_msg("Found no more routes with this IGP parent\n"); @@ -525,7 +525,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) debug_msg("old route was: %s\n", old_route->str().c_str()); const ResolvedIPRouteEntry* found; - typename IGPParentMultiMap::iterator last_not_deleted = _ip_igp_parents.end(); + typename ResolvingParentMultiMap::iterator last_not_deleted = _ip_resolving_parents.end(); const IPRouteEntry* egp_parent; found = lookup_by_igp_parent(old_route->net()); while (found != NULL) { @@ -538,12 +538,12 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) found->str().c_str()); // Erase from table first to prevent lookups on this entry _ip_resolved_table.erase(found->net()); - _ip_igp_parents.erase(found->backlink()); + _ip_resolving_parents.erase(found->backlink()); // Delete the route's IGP parent from _resolving_routes if // no-one's using it anymore - if (lookup_by_igp_parent(found->igp_parent()->net()) == NULL) { - _resolving_routes.erase(found->igp_parent()->net()); + if (lookup_by_igp_parent(found->resolving_parent()->net()) == NULL) { + _resolving_routes.erase(found->resolving_parent()->net()); } // Propagate the delete next @@ -568,7 +568,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) last_not_deleted = found->backlink(); } - if (last_not_deleted == _ip_igp_parents.end()) { + if (last_not_deleted == _ip_resolving_parents.end()) { found = lookup_by_igp_parent(old_route->net()); } else { found = lookup_next_by_igp_parent(old_route->net(), last_not_deleted); diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index 4de078739..b81ba9276 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -181,7 +181,7 @@ public: private: typedef typename ResolvedIPRouteEntry::RouteBackLink ResolvedRouteBackLink; typedef typename UnresolvedIPRouteEntry::RouteBackLink UnresolvedRouteBackLink; - typedef multimap, ResolvedIPRouteEntry* > IGPParentMultiMap; + typedef multimap, ResolvedIPRouteEntry* > ResolvingParentMultiMap; typedef map, UnresolvedIPRouteEntry* > IpUnresolvedTableMap; typedef Trie* > RouteTrie; @@ -206,7 +206,7 @@ private: const ResolvedIPRouteEntry* lookup_next_by_igp_parent( const IPNet& route_net, - const typename IGPParentMultiMap::iterator& previous); + const typename ResolvingParentMultiMap::iterator& previous); const IPRouteEntry* lookup_route_in_igp_parent( const IPNet& subnet) const; @@ -224,7 +224,7 @@ private: // _ip_igp_parents gives us a fast way of finding a route // affected by a change in an igp parent route - IGPParentMultiMap _ip_igp_parents; + ResolvingParentMultiMap _ip_resolving_parents; // _resolving_routes is a Trie of all the routes that are used to // resolve external routes From fb35ac274f105fb56141499c5d01305e31d876ca Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 6 Jul 2012 12:10:35 +0200 Subject: [PATCH 24/38] xorp: rib: Don't make copies in PolicyConnected RouteTable Save original routes in own route trie. --- xorp/rib/rt_tab_pol_conn.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index f33c40a73..7facc3804 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -55,11 +55,6 @@ PolicyConnectedTable::PolicyConnectedTable (RouteTable* parent, template PolicyConnectedTable::~PolicyConnectedTable () { - for (typename RouteContainer::iterator i = _route_table.begin(); - i != _route_table.end(); ++i) { - delete *i; - } - _route_table.delete_all_nodes(); } @@ -75,7 +70,7 @@ PolicyConnectedTable::add_route(const IPRouteEntry& route, // store original - IPRouteEntry* original = new IPRouteEntry(route); + IPRouteEntry* original = const_cast* >(&route); _route_table.insert(original->net(), original); do_filtering(*original); @@ -114,7 +109,6 @@ PolicyConnectedTable::delete_route(const IPRouteEntry* route, // propagate the delete int ret = next->delete_route(re, this); - delete re; return ret; } From 37791570d501eaef5d6bcc28b410c7960d6517f4 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 11:33:46 +0200 Subject: [PATCH 25/38] xorp: rib: Drop merged tables from RIB tree Merged tables aren't used any more. Now all origin tables, with their Redist tables if any, are directly connected to ExtIntTable. ExtInt table has taken the role of finding the route with best admin distance. This way, adding and finding routes in RIB is more efficient. --- xorp/rib/SConscript | 2 - xorp/rib/rib.cc | 216 +-------------- xorp/rib/rib.hh | 77 +----- xorp/rib/rt_tab_base.hh | 13 +- xorp/rib/rt_tab_deletion.cc | 25 +- xorp/rib/rt_tab_deletion.hh | 6 +- xorp/rib/rt_tab_extint.cc | 467 ++++++++++++++++++++------------ xorp/rib/rt_tab_extint.hh | 60 ++-- xorp/rib/rt_tab_log.cc | 46 ++-- xorp/rib/rt_tab_log.hh | 22 +- xorp/rib/rt_tab_origin.cc | 29 +- xorp/rib/rt_tab_origin.hh | 23 +- xorp/rib/rt_tab_pol_conn.cc | 22 +- xorp/rib/rt_tab_pol_conn.hh | 6 +- xorp/rib/rt_tab_pol_redist.cc | 21 +- xorp/rib/rt_tab_pol_redist.hh | 6 +- xorp/rib/rt_tab_redist.cc | 44 +-- xorp/rib/rt_tab_redist.hh | 12 +- xorp/rib/rt_tab_register.cc | 18 +- xorp/rib/rt_tab_register.hh | 15 +- xorp/rib/tests/commands | 1 + xorp/rib/tests/rt_tab_expect.cc | 12 +- xorp/rib/tests/rt_tab_expect.hh | 6 +- 23 files changed, 447 insertions(+), 702 deletions(-) diff --git a/xorp/rib/SConscript b/xorp/rib/SConscript index 466ae9cb0..71c7044ef 100644 --- a/xorp/rib/SConscript +++ b/xorp/rib/SConscript @@ -110,8 +110,6 @@ libxorp_rib_srcs = [ 'rt_tab_base.cc', 'rt_tab_deletion.cc', 'rt_tab_extint.cc', - 'rt_tab_log.cc', - 'rt_tab_merged.cc', 'rt_tab_origin.cc', 'rt_tab_pol_conn.cc', 'rt_tab_pol_redist.cc', diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index 04e72f590..c84ec93ba 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -102,20 +102,6 @@ RIB::find_egp_origin_table(const string& tablename) return NULL; } -template -inline MergedTable* -RIB::find_merged_table(const string& tablename) -{ - typename MergedTableMap::iterator li; - - li = _merged_tables.find(tablename); - - if (li == _merged_tables.end()) - return NULL; - - return li->second; -} - template inline RedistTable* RIB::find_redist_table(const string& tablename) @@ -201,19 +187,6 @@ RIB::add_table(RedistTable* table) return XORP_OK; } -template -inline int -RIB::add_table(MergedTable* table) -{ - const string& tablename = table->tablename(); - if (find_merged_table(tablename) != NULL) { - XLOG_WARNING("add_table: table %s already exists", tablename.c_str()); - return XORP_ERROR; - } - _merged_tables[tablename] = table; - return XORP_OK; -} - template int RIB::set_protocol_admin_distance(const string& protocol_name, @@ -228,7 +201,10 @@ RIB::set_protocol_admin_distance(const string& protocol_name, protocol_name.c_str()); return XORP_ERROR; } else if (NULL != ot && ot->route_count() == 0) { - ot->change_admin_distance(admin_distance); + int ret; + ret = _ext_int_table->change_admin_distance(ot, admin_distance); + if (ret == XORP_ERROR) + return XORP_ERROR; } } _admin_distances[protocol_name] = admin_distance; @@ -329,6 +305,9 @@ RIB::~RIB() // Just set the pointer to NULL here _connected_origin_table = NULL; + delete _ext_int_table; + _ext_int_table = NULL; + while (! _igp_origin_tables.empty()) { delete _igp_origin_tables.begin()->second; _igp_origin_tables.erase(_igp_origin_tables.begin()); @@ -344,11 +323,6 @@ RIB::~RIB() _redist_tables.erase(_redist_tables.begin()); } - while (! _merged_tables.empty()) { - delete _merged_tables.begin()->second; - _merged_tables.erase(_merged_tables.begin()); - } - delete _register_table; _register_table = NULL; @@ -358,9 +332,6 @@ RIB::~RIB() delete _policy_redist_table; _policy_redist_table = NULL; - delete _ext_int_table; - _ext_int_table = NULL; - while (! _protocols.empty()) { delete _protocols.begin()->second; _protocols.erase(_protocols.begin()); @@ -471,7 +442,7 @@ RIB::initialize_ext_int() { XLOG_ASSERT(!_ext_int_table); - _ext_int_table = new ExtIntTable(NULL, NULL); + _ext_int_table = new ExtIntTable(); XLOG_ASSERT(_final_table == NULL); @@ -490,7 +461,7 @@ RIB::initialize_register(RegisterServer& register_server) XLOG_ASSERT(_final_table == _ext_int_table); - _register_table->replumb(NULL, _final_table); + _register_table->set_parent(_final_table); _final_table->set_next_table(_register_table); _final_table = _register_table; @@ -502,7 +473,7 @@ int RIB::new_origin_table(const string& tablename, const string& target_class, const string& target_instance, - uint32_t admin_distance, + uint16_t admin_distance, ProtocolType protocol_type) { OriginTable* ot = new OriginTable(tablename, admin_distance, @@ -1135,10 +1106,10 @@ RIB::add_igp_table(const string& tablename, delete_origin_table(tablename, target_class, target_instance); return r; } - RedistTable* rt = find_redist_table(redist_tablename(tablename)); - XLOG_ASSERT(rt != NULL); if (tablename == "connected") { + RedistTable* rt = find_redist_table(redist_tablename(tablename)); + XLOG_ASSERT(rt != NULL); r = add_policy_connected_table(rt); if (r != XORP_OK) { delete_origin_table(tablename, target_class, target_instance); @@ -1164,19 +1135,6 @@ RIB::add_egp_table(const string& tablename, return r; } -#if 0 - // XXX For now we unconditionally plumb a RedistTable behind each - // OriginTable. We need this because the RedistTable needs to - // track the routes within the OriginTable in order to be able to - // render a dump when another protocol requests redistribution. - r = add_redist_table(tablename); - if (r != XORP_OK) { - delete_origin_table(tablename, target_class, target_instance); - return r; - } - RouteTable* rt = find_table(redist_tablename(tablename)); - XLOG_ASSERT(rt != NULL); -#endif return r; } @@ -1224,98 +1182,12 @@ RIB::add_redist_table(RouteTable* parent) template int -RIB::plumb_ahead_of_ext_int(OriginTable*& ot, const ProtocolType& type) -{ - XLOG_ASSERT(_ext_int_table); - - switch (type) { - case IGP: - _ext_int_table->replumb_internal(ot); - break; - case EGP: - _ext_int_table->replumb_external(ot); - break; - default: - XLOG_UNREACHABLE(); - break; - } - - return XORP_OK; -} - -template -int -RIB::plumb_ahead_of_merged(OriginTable*& ot, - RouteTable* existing_table) -{ - // - // We're going to need to create a MergedTable - // - RouteTable* next_table = existing_table->next_table(); - - // Skip past any RedistTables - RouteTable* new_prev_table = track_forward(existing_table, - (REDIST_TABLE | - POLICY_CONNECTED_TABLE)); - if (new_prev_table != existing_table) { - existing_table = new_prev_table; - next_table = existing_table->next_table(); - } - - MergedTable* merged_table = new MergedTable(existing_table, ot); - if (merged_table == NULL || add_table(merged_table) != XORP_OK) { - delete merged_table; - return XORP_ERROR; - } - - merged_table->set_next_table(next_table); - if (next_table != NULL) - next_table->replumb(existing_table, merged_table); - - // - // It's possible existing_table was the last table - if so, then it - // isn't anymore. - // - if (_final_table == existing_table) - _final_table = merged_table; - - return XORP_OK; - -} - -template -int -RIB::plumb_origin_table(OriginTable*& ot, - OriginTable* existing_igp_table, - OriginTable* existing_egp_table) +RIB::plumb_origin_table(OriginTable*& ot) { // XXX: the table was created by new_origin_table() above, so it must exist XLOG_ASSERT(ot != NULL && _final_table != ot); - // - // There are existing tables, so we need to do some plumbing - // - // Two possibilities: - // 1. There are no existing tables of the same protocol type as the protocol type - // of the table that we're plumbing - // - // -> Plumb the origin table ahead of ext int table - // 2. There are both existing EGP and existing IGP tables - // - // -> Add Merged table and plumb the origin table ahead of merged table - // - - // - // Depending on which tables already exist, we may need to create - // a MergedTable or an ExtInt table. - // - ProtocolType protocol_type = (ProtocolType) ot->protocol_type(); - if ((!existing_igp_table && (protocol_type == IGP)) || - (!existing_egp_table && (protocol_type == EGP))) - return plumb_ahead_of_ext_int(ot, protocol_type); - else - return plumb_ahead_of_merged(ot, (protocol_type == IGP) ? - existing_igp_table : existing_egp_table); + return _ext_int_table->add_protocol_table(ot); } // @@ -1371,13 +1243,6 @@ RIB::add_origin_table(const string& tablename, return XORP_OK; } - // - // Find first IGP and EGP origin table - // This is needed for plumbing new origin table - // - OriginTable* existing_igp_table = !_igp_origin_tables.empty() ? _igp_origin_tables.begin()->second : NULL; - OriginTable* existing_egp_table = !_egp_origin_tables.empty() ? _egp_origin_tables.begin()->second : NULL; - if (new_origin_table(tablename, target_class, target_instance, get_protocol_admin_distance(tablename), protocol_type) != XORP_OK) { debug_msg("new_origin_table failed\n"); @@ -1396,7 +1261,7 @@ RIB::add_origin_table(const string& tablename, break; } - return plumb_origin_table(ot, existing_igp_table, existing_egp_table); + return plumb_origin_table(ot); } template @@ -1467,52 +1332,6 @@ RIB::target_death(const string& target_class, } } -// -// Given a single-parent table, track back to the last matching table -// before this one. -// -template -RouteTable* -RIB::track_back(RouteTable* rt, int typemask) const -{ - if (rt == NULL || (rt->type() & typemask) == 0) { - return rt; - } - - for (RouteTable* parent = rt->parent(); - parent && (parent->type() & typemask); - parent = rt->parent()) { - rt = parent; - } - return rt; -} - -// -// Track forward to the last matching table, or return this table if -// the next table doesn't match. -// -template -RouteTable* -RIB::track_forward(RouteTable* rt, int typemask) const -{ - RouteTable* next; - if (NULL == rt) - // XXX: not the same test as track back (deliberate ?) - return rt; - - next = rt->next_table(); - - while (next != NULL) { - if ((next->type() & typemask) != 0) { - rt = next; - next = rt->next_table(); - } else - return rt; - } - - return rt; -} - #ifdef DEBUG_LOGGING template struct print_from_pair { @@ -1535,11 +1354,6 @@ RIB::print_rib() const for_each(_redist_tables.begin(), _redist_tables.end(), print_from_pair >()); - cout << "==============================================================" << endl; - cout << "Merged table count " << _merged_tables.size() << endl; - for_each(_merged_tables.begin(), _merged_tables.end(), - print_from_pair >()); - cout << "==============================================================" << endl; cout << "IGP table count " << _igp_origin_tables.size() << endl; for_each(_igp_origin_tables.begin(), _igp_origin_tables.end(), diff --git a/xorp/rib/rib.hh b/xorp/rib/rib.hh index 72667cba1..a4643bc2b 100644 --- a/xorp/rib/rib.hh +++ b/xorp/rib/rib.hh @@ -33,7 +33,6 @@ #include "route.hh" #include "rt_tab_base.hh" #include "rt_tab_origin.hh" -#include "rt_tab_merged.hh" #include "rt_tab_extint.hh" #include "rt_tab_redist.hh" #include "rt_tab_pol_redist.hh" @@ -176,7 +175,7 @@ public: int new_origin_table(const string& tablename, const string& target_class, const string& target_instance, - uint32_t admin_distance, + uint16_t admin_distance, ProtocolType protocol_type); /** @@ -550,30 +549,7 @@ private: * @param existing_egp_table first occurrence of EGP origin table in tree * @return XORP_OK on success, otherwise XORP_ERROR. */ - int plumb_origin_table(OriginTable*& ot, - OriginTable* existing_igp_table, - OriginTable* existing_egp_table); - - /** - * Plumbs OriginTable @ot ahead of ExtInt table. - * It should be called ONLY if are adding first origin table of some - * protocol type (IGP or EGP) - * - * @param ot OriginTable to plumb in - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int plumb_ahead_of_ext_int(OriginTable*& ot, const ProtocolType& type); - - /** - * Creates Merged table and plumbs OriginTable @ot ahead of it. - * It should be called ONLY if there are both existing EGP table and - * existing IGP table. - * - * @param ot OriginTable to plumb in - * @param existing_table existing origin table of the same type - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int plumb_ahead_of_merged(OriginTable*& ot, RouteTable* existing_table); + int plumb_origin_table(OriginTable*& ot); /** * Used to implement @ref add_igp_table and @ref add_egp_table. @@ -624,33 +600,6 @@ private: */ int add_redist_table(RouteTable* parent); - /** - * track_back trough the RouteTables' parent pointers to find the - * last (i.e, nearest the OriginTable) table that matches the mask - * in @ref typemask. If the table given by @ref rt doesn't match - * the mask, return it anyway. If a table has more than one - * parent, then this is an error. - * - * @param rt the routing table to start with. - * @param typemask the bitwise-or of the routing table types that - * we may track back through. - * @return the last matching table, or @ref rt if rt itself doesn't match. - */ - RouteTable* track_back(RouteTable* rt, int typemask) const; - - /** - * track_forward trough the RouteTables' child pointers to find - * the last able that matches the mask in @ref typemask. - * Unlike track_back, if @ref rt doesn't match, but the next does, - * the track forward anyway. - * - * @param rt the routing table to start with. - * @param typemask the bitwise-or of the routing table types that - * we may track forward through. - * @return the last matching table. - */ - RouteTable* track_forward(RouteTable* rt, int typemask) const; - /** * Find a origin routing table, given its table name * @@ -675,14 +624,6 @@ private: */ OriginTable* find_egp_origin_table(const string& tablename); - /** - * Find a merged routing table, given its table name - * - * @param tablename the name of the table to search for. - * @return pointer to table if exists, NULL otherwise. - */ - MergedTable* find_merged_table(const string& tablename); - /** * Find a redist routing table, given its table name * @@ -716,18 +657,6 @@ private: */ int add_table(OriginTable* table); - /** - * Add merged table to RIB, but don't do any plumbing. - * - * It is an error to add the same table twice or multiple tables - * with the same name. - * - * @param table the table to be added. - * - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int add_table(MergedTable* table); - /** * Add redist table to RIB, but don't do any plumbing. * @@ -780,7 +709,6 @@ private: protected: typedef map* > OriginTableMap; typedef map* > RedistTableMap; - typedef map* > MergedTableMap; typedef map ProtocolMap; RibManager& _rib_manager; @@ -794,7 +722,6 @@ protected: OriginTableMap _igp_origin_tables; OriginTableMap _egp_origin_tables; - MergedTableMap _merged_tables; RedistTableMap _redist_tables; OriginTable* _connected_origin_table; // Helper to faster resolve if route, that we're adding, is diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index df091e05c..fe692258d 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -165,11 +165,9 @@ public: RouteTable(const string& name) : _tablename(name), _next_table(NULL) {} virtual ~RouteTable(); - virtual int add_route(const IPRouteEntry& route, - RouteTable* caller) = 0; + virtual int add_route(const IPRouteEntry& route) = 0; - virtual int delete_route(const IPRouteEntry* route, - RouteTable* caller) = 0; + virtual int delete_route(const IPRouteEntry* route) = 0; virtual const IPRouteEntry* lookup_route(const IPNet& net) const = 0; @@ -179,15 +177,12 @@ public: virtual void set_next_table(RouteTable* next_table); - // parent is only supposed to be called on single-parent tables - virtual RouteTable* parent() { XLOG_UNREACHABLE(); return NULL; } - virtual const RouteTable* parent() const { XLOG_UNREACHABLE(); return NULL; } - virtual TableType type() const = 0; - virtual void replumb(RouteTable* old_parent, RouteTable* new_parent) = 0; virtual string str() const = 0; virtual void flush() {} + virtual void set_parent(RouteTable*) {} + const string& tablename() const { return _tablename; } RouteTable* next_table() { return _next_table; } const RouteTable* next_table() const { return _next_table; } diff --git a/xorp/rib/rt_tab_deletion.cc b/xorp/rib/rt_tab_deletion.cc index f790a099b..f332b47bb 100644 --- a/xorp/rib/rt_tab_deletion.cc +++ b/xorp/rib/rt_tab_deletion.cc @@ -44,7 +44,7 @@ DeletionTable::DeletionTable(const string& tablename, { XLOG_ASSERT(_parent != NULL); this->set_next_table(_parent->next_table()); - this->next_table()->replumb(parent, this); + this->next_table()->set_parent(this); parent->set_next_table(this); // Callback immediately, but after network events or expired timers @@ -63,11 +63,8 @@ DeletionTable::~DeletionTable() template int -DeletionTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +DeletionTable::add_route(const IPRouteEntry& route) { - XLOG_ASSERT(caller == _parent); - typename Trie* >::iterator iter; iter = _ip_route_table->lookup_node(route.net()); if (iter != _ip_route_table->end()) { @@ -79,26 +76,23 @@ DeletionTable::add_route(const IPRouteEntry& route, // const IPRouteEntry* our_route = *iter; _ip_route_table->erase(route.net()); - this->next_table()->delete_route(our_route, this); + this->next_table()->delete_route(our_route); delete our_route; } - return this->next_table()->add_route(route, this); + return this->next_table()->add_route(route); } template int -DeletionTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +DeletionTable::delete_route(const IPRouteEntry* route) { - XLOG_ASSERT(caller == _parent); - // The route MUST NOT be in our trie. typename Trie* >::iterator iter; iter = _ip_route_table->lookup_node(route->net()); XLOG_ASSERT(iter == _ip_route_table->end()); - return this->next_table()->delete_route(route, this); + return this->next_table()->delete_route(route); } template @@ -223,7 +217,7 @@ DeletionTable::background_deletion_pass() iter = _ip_route_table->begin(); const IPRouteEntry* our_route = *iter; _ip_route_table->erase(our_route->net()); - this->next_table()->delete_route(our_route, this); + this->next_table()->delete_route(our_route); delete our_route; // Callback immediately, but after network events or expired timers @@ -237,15 +231,14 @@ void DeletionTable::unplumb_self() { _parent->set_next_table(this->next_table()); - this->next_table()->replumb(this, _parent); + this->next_table()->set_parent(_parent); delete this; } template void -DeletionTable::replumb(RouteTable* old_parent, RouteTable* new_parent) +DeletionTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(_parent == old_parent); _parent = new_parent; } diff --git a/xorp/rib/rt_tab_deletion.hh b/xorp/rib/rt_tab_deletion.hh index 25e478d5f..d5361d660 100644 --- a/xorp/rib/rt_tab_deletion.hh +++ b/xorp/rib/rt_tab_deletion.hh @@ -64,7 +64,7 @@ public: * @param caller the caller route table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(const IPRouteEntry& route, RouteTable* caller); + int add_route(const IPRouteEntry& route); /** * Delete a route. This route MUST NOT be in the DeletionTable trie. @@ -73,7 +73,7 @@ public: * @param caller the caller route table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int delete_route(const IPRouteEntry* route); /** * Delete all the routes that are in this DeletionTable. The @@ -135,7 +135,7 @@ public: /** * Change the parent of this route table. */ - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent); /** * Render the DeletionTable as a string for debugging purposes. diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 3a05a9f2b..142fcbce7 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -28,23 +28,18 @@ #include "rib.hh" #include "rt_tab_extint.hh" -template -inline static string -make_extint_name(const RouteTable* e, const RouteTable* i) +template +inline const string& +ExtIntTable::ext_int_name() { - return string("Ext:(" + (e ? e->tablename() : "NULL") + ")Int:(" + (i ? i->tablename() : "NULL") + ")"); + static string EXT_INT_NAME(c_format("ExtInt Table IPv%d", A::ip_version())); + return EXT_INT_NAME; } template -ExtIntTable::ExtIntTable(RouteTable* ext_table, RouteTable* int_table) - : RouteTable(make_extint_name(ext_table, int_table)), - _ext_table(ext_table), _int_table(int_table) +ExtIntTable::ExtIntTable() + : RouteTable(ext_int_name()) { - if (_ext_table) - _ext_table->set_next_table(this); - if (_int_table) - _int_table->set_next_table(this); - debug_msg("New ExtInt: %s\n", this->tablename().c_str()); } @@ -60,25 +55,125 @@ ExtIntTable::~ExtIntTable() delete *_ip_resolved_table.begin(); _ip_resolved_table.erase(_ip_resolved_table.begin()); } + + _igp_ad_set.clear(); + _egp_ad_set.clear(); + + _all_tables.clear(); +} + +template +int +ExtIntTable::change_admin_distance(OriginTable* ot, uint32_t ad) +{ + XLOG_ASSERT(ot && ot->route_count() == 0); + switch (ot->protocol_type()) { + case IGP: + if (_igp_ad_set.find(ot->admin_distance()) == _igp_ad_set.end()) { + return XORP_ERROR; + } + _igp_ad_set.erase(ot->admin_distance()); + _igp_ad_set.insert(ad); + break; + case EGP: + if (_egp_ad_set.find(ot->admin_distance()) == _egp_ad_set.end()) { + return XORP_ERROR; + } + _egp_ad_set.erase(ot->admin_distance()); + _egp_ad_set.insert(ad); + break; + default: + XLOG_ERROR("OriginTable for unrecognized protocol received!\n"); + return XORP_ERROR; + } + XLOG_ASSERT(_all_tables.find(ot->admin_distance()) != _all_tables.end() && + _all_tables.find(ot->admin_distance())->second == ot); + _all_tables.erase(ot->admin_distance()); + _all_tables[ad] = ot; + + /* Change the AD of OriginTable */ + ot->change_admin_distance(ad); + return XORP_OK; +} + +template +int +ExtIntTable::add_protocol_table(OriginTable* new_table) +{ + switch (new_table->protocol_type()) { + case IGP: + XLOG_ASSERT(_igp_ad_set.find(new_table->admin_distance()) == _igp_ad_set.end()); + _igp_ad_set.insert(new_table->admin_distance()); + break; + case EGP: + XLOG_ASSERT(_egp_ad_set.find(new_table->admin_distance()) == _egp_ad_set.end()); + _egp_ad_set.insert(new_table->admin_distance()); + break; + default: + XLOG_ERROR("OriginTable for unrecognized protocol received!\n"); + return XORP_ERROR; + } + XLOG_ASSERT(_all_tables.find(new_table->admin_distance()) == _all_tables.end()); + _all_tables[new_table->admin_distance()] = new_table; + new_table->set_next_table(this); + return XORP_OK; +} + +template +bool +ExtIntTable::best_igp_route(const IPRouteEntry& route) +{ + typename RouteTrie::iterator iter = _wining_igp_routes.lookup_node(route.net()); + if (iter == _wining_igp_routes.end()) { + _wining_igp_routes.insert(route.net(), &route); + return true; + } else if ((*iter)->admin_distance() > route.admin_distance()) { + this->delete_route(*iter); + _wining_igp_routes.insert(route.net(), &route); + return true; + } else if ((*iter)->admin_distance() == route.admin_distance()) { + // It's best IGP Route, but it wasn't overall best route when we added it first time + return true; + } + return false; +} + +template +bool +ExtIntTable::best_egp_route(const IPRouteEntry& route) +{ + typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(route.net()); + if (iter == _wining_egp_routes.end()) { + _wining_egp_routes.insert(route.net(), &route); + return true; + } else if ((*iter)->admin_distance() > route.admin_distance()) { + this->delete_route(*iter); + _wining_egp_routes.insert(route.net(), &route); + return true; + } else if ((*iter)->admin_distance() == route.admin_distance()) { + // It's best EGP Route, but it wasn't overall best route when we added it first time + return true; + } + return false; } template int -ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) +ExtIntTable::add_route(const IPRouteEntry& route) { debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); - XLOG_ASSERT(this->next_table()); - if (_int_table && caller == _int_table) { + if (_igp_ad_set.find(route.admin_distance()) != _igp_ad_set.end()) { XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); // The new route comes from the IGP table debug_msg("route comes from IGP\n"); - // If it came here, it must be the wining IGP route. - // Insert it in wining IGP trie - _wining_igp_routes.insert(route.net(), &route); - if (_ext_table) { + // Is it the best IGP route? + if (!best_igp_route(route)) + return XORP_ERROR; + + if (!_egp_ad_set.empty()) { // Try to find existing EGP routes, that are installed // We're looking for EGP route in all wining routes. // We can look here, because no IGP route that matches this subnet @@ -87,22 +182,21 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) // It should have been deleted. We check for that in the XLOG_ASSERT const IPRouteEntry* found = lookup_route(route.net()); if (found != NULL) { - if (found->admin_distance() < route.admin_distance()) { - // The admin distance of the existing IGP route is better + if (found->admin_distance() < route.admin_distance()) + // The admin distance of the existing EGP route is better return XORP_ERROR; - } else { - XLOG_ASSERT(found->admin_distance() != route.admin_distance()); - bool delete_is_propagated(false); - this->delete_ext_route(found, delete_is_propagated); - } + + XLOG_ASSERT(found->admin_distance() != route.admin_distance()); + + this->delete_ext_route(found); } } _wining_routes.insert(route.net(), &route); - this->next_table()->add_route(route, this); + this->next_table()->add_route(route); - if (_ext_table) { + if (!_egp_ad_set.empty()) { // Does this cause any previously resolved nexthops to resolve // differently? recalculate_nexthops(route); @@ -113,46 +207,45 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) return XORP_OK; - } else if (_ext_table && caller == _ext_table) { + } else if (_egp_ad_set.find(route.admin_distance()) != _egp_ad_set.end()) { // The new route comes from the EGP table debug_msg("route comes from EGP\n"); - // If it came here, it must be the wining EGP route. - // Insert it in wining EGP trie - _wining_egp_routes.insert(route.net(), &route); - const IPRouteEntry* found = lookup_route_in_igp_parent(route.net()); + // Is it the best EGP route? + if (!best_egp_route(route)) + return XORP_ERROR; - if (found != NULL) { - if (found->admin_distance() < route.admin_distance()) { - // The admin distance of the existing IGP route is better - return XORP_ERROR; - } - } + const IPRouteEntry* found = lookup_route(route.net()); + + if (found && (found->admin_distance() < route.admin_distance())) + return XORP_ERROR; + + XLOG_ASSERT(found ? (found->admin_distance() != route.admin_distance()) : true); if (route.nexthop()->type() == PEER_NEXTHOP) { // // Despite it coming from the Ext table, the nexthop is // directly connected. Just propagate it. // - debug_msg("nexthop %s was directly connected\n", route.nexthop()->addr().str().c_str()); if (found != NULL) { // Delete the IGP route that has worse admin distance _wining_routes.erase(found->net()); - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found); } _wining_routes.insert(route.net(), &route); - this->next_table()->add_route(route, this); + this->next_table()->add_route(route); + return XORP_OK; } else { IPNextHop* rt_nexthop = route.nexthop(); const IPRouteEntry* nexthop_route = - lookup_route_in_igp_parent(rt_nexthop->addr()); + lookup_winning_igp_route(rt_nexthop->addr()); if (nexthop_route == NULL) { // Store the fact that this was unresolved for later debug_msg("nexthop %s was unresolved\n", rt_nexthop->addr().str().c_str()); @@ -171,7 +264,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) // Delete the IGP route that has worse admin distance _wining_routes.erase(found->net()); - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found); } debug_msg("nexthop resolved to \n %s\n", nexthop_route->str().c_str()); @@ -183,7 +276,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) _wining_routes.insert(resolved_route->net(), resolved_route); - this->next_table()->add_route(*resolved_route, this); + this->next_table()->add_route(*resolved_route); return XORP_OK; } @@ -192,6 +285,7 @@ ExtIntTable::add_route(const IPRouteEntry& route, RouteTable* caller) XLOG_FATAL("ExtIntTable::add_route called from a class that " "isn't a component of this override table"); } + return XORP_OK; } @@ -227,69 +321,131 @@ ExtIntTable::resolve_and_store_route(const IPRouteEntry& route, return resolved_route; } +template +bool +ExtIntTable::deleting_best_igp_route(const IPRouteEntry* route) +{ + typename RouteTrie::iterator iter = _wining_igp_routes.lookup_node(route->net()); + if (iter != _wining_igp_routes.end()) { + if ((*iter)->admin_distance() != route->admin_distance()) + return false; + else { + _wining_igp_routes.erase(route->net()); + return true; + } + } + return false; +} + +template +bool +ExtIntTable::deleting_best_egp_route(const IPRouteEntry* route) +{ + typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(route->net()); + if (iter != _wining_egp_routes.end()) { + if ((*iter)->admin_distance() != route->admin_distance()) + return false; + else { + _wining_egp_routes.erase(route->net()); + return true; + } + } + return false; +} + +template +const IPRouteEntry* +ExtIntTable::masked_route(const IPRouteEntry* route) +{ + typename RouteTableMap::iterator border = _all_tables.find(route->admin_distance()); + const IPRouteEntry* found = NULL; + XLOG_ASSERT(border != _all_tables.end()); + for (typename RouteTableMap::iterator iter = border; iter != _all_tables.end(); ++iter) { + found = iter->second->lookup_route(route->net()); + if (found) + return found; + } + return found; +} + +template +void +ExtIntTable::delete_resolved_routes(const IPRouteEntry* route) +{ + const ResolvedIPRouteEntry* found_resolved + = lookup_by_igp_parent(route->net()); + + if (found_resolved) + _resolving_routes.erase(route->net()); + + while (found_resolved) { + debug_msg("found route using this nexthop:\n %s\n", found_resolved->str().c_str()); + // Erase from table first to prevent lookups on this entry + _ip_resolved_table.erase(found_resolved->net()); + _ip_resolving_parents.erase(found_resolved->backlink()); + + // Propagate the delete next + _wining_routes.erase(found_resolved->net()); + + this->next_table()->delete_route(found_resolved); + + // Now delete the local resolved copy, and reinstantiate it + const IPRouteEntry* egp_parent = found_resolved->egp_parent(); + delete found_resolved; + + // egp_parent route is one of the wining EGP routes. + // Re-adding will overwrite it the in trie + // That's no problem because we're overwriting + // old pointer with the existing pointer. + // That way we don't have any memory leaking. + + add_route(*egp_parent); + found_resolved = lookup_by_igp_parent(route->net()); + } +} + template int -ExtIntTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +ExtIntTable::delete_route(const IPRouteEntry* route) { + debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); XLOG_ASSERT(this->next_table()); - if (_int_table && caller == _int_table) { + if (_igp_ad_set.find(route->admin_distance()) != _igp_ad_set.end()) { debug_msg(" called from _int_table\n"); // If it came here, than we're certainly deleting wining IGP route - _wining_igp_routes.erase(route->net()); - const IPRouteEntry* found_egp_route = NULL; - if (_ext_table) { - found_egp_route = lookup_route_in_egp_parent(route->net()); + if (!deleting_best_igp_route(route)) + return XORP_ERROR; - if (found_egp_route != NULL) { - if (found_egp_route->admin_distance() < route->admin_distance()) { - // The admin distance of the existing EGP route is better - return XORP_ERROR; - } - } + const IPRouteEntry* found_route = NULL; - const ResolvedIPRouteEntry* found - = lookup_by_igp_parent(route->net()); + if (!_egp_ad_set.empty()) { + found_route = lookup_route(route->net()); - if (found != NULL) { - _resolving_routes.erase(route->net()); + if (found_route != NULL) { + if (found_route->admin_distance() == route->admin_distance()) + // This route was the best route overall + found_route = NULL; + else { + // Our route wasn't the best route overall + XLOG_ASSERT(found_route->admin_distance() < route->admin_distance()); + return XORP_ERROR; + } } - while (found != NULL) { - debug_msg("found route using this nexthop:\n %s\n", found->str().c_str()); - // Erase from table first to prevent lookups on this entry - _ip_resolved_table.erase(found->net()); - _ip_resolving_parents.erase(found->backlink()); - - // Propagate the delete next - _wining_routes.erase(found->net()); - - this->next_table()->delete_route(found, this); - - // Now delete the local resolved copy, and reinstantiate it - const IPRouteEntry* egp_parent = found->egp_parent(); - delete found; - - // egp_parent route is one of the wining EGP routes. - // Re-adding will overwrite it the in trie - // That's no problem because we're overwriting - // old pointer with the existing pointer. - // That way we don't have any memory leaking. - - add_route(*egp_parent, _ext_table); - found = lookup_by_igp_parent(route->net()); - } + delete_resolved_routes(route); } // Propagate the original delete _wining_routes.erase(route->net()); - this->next_table()->delete_route(route, this); + this->next_table()->delete_route(route); + + found_route = masked_route(route); - if (_ext_table && found_egp_route) { + if (!_egp_ad_set.empty() && found_route) { // It is possible the internal route had masked an external one. // found_egp_route route is one of the wining EGP routes. @@ -297,27 +453,30 @@ ExtIntTable::delete_route(const IPRouteEntry* route, // That's no problem because we're overwriting // old pointer with the existing pointer. // That way we don't have any memory leaking. - - add_route(*found_egp_route, _ext_table); + add_route(*found_route); } - } else if (_ext_table && caller == _ext_table) { + } else if (_egp_ad_set.find(route->admin_distance()) != _egp_ad_set.end()) { debug_msg(" called from _ext_table\n"); - // If it came here, than we're certainly deleting wining EGP route - _wining_egp_routes.erase(route->net()); - const IPRouteEntry* found_igp_route = - lookup_route_in_igp_parent(route->net()); - - if (found_igp_route != NULL) { - if (found_igp_route->admin_distance() < route->admin_distance()) { - // The admin distance of the existing IGP route is better - return XORP_ERROR; + + if (!deleting_best_egp_route(route)) + return XORP_ERROR; + + const IPRouteEntry* found_route = lookup_route(route->net()); + + if (found_route != NULL) { + if (found_route->admin_distance() == route->admin_distance()) + found_route = NULL; + else if (found_route->admin_distance() < route->admin_distance()) { + //Our route wasn't the best overall + delete_ext_route(route, false); + return XORP_OK; } } - bool is_delete_propagated = false; - this->delete_ext_route(route, is_delete_propagated); - if (is_delete_propagated && found_igp_route) { + found_route = masked_route(route); + + if (this->delete_ext_route(route) && found_route) { // It is possible the external route had masked an internal one. // found_igp_route route is one of the wining IGP routes. @@ -325,24 +484,23 @@ ExtIntTable::delete_route(const IPRouteEntry* route, // That's no problem because we're overwriting // old pointer with the existing pointer. // That way we don't have any memory leaking. - - add_route(*found_igp_route, _int_table); + add_route(*found_route); } } else { XLOG_FATAL("ExtIntTable::delete_route called from a class that " "isn't a component of this override table\n"); } + return XORP_OK; } template -int -ExtIntTable::delete_ext_route(const IPRouteEntry* route, - bool& is_delete_propagated) +bool +ExtIntTable::delete_ext_route(const IPRouteEntry* route, bool winning_route) { const ResolvedIPRouteEntry* found; - is_delete_propagated = false; + bool is_delete_propagated = false; found = lookup_in_resolved_table(route->net()); if (found != NULL) { @@ -352,30 +510,30 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, // Delete the route's IGP parent from _resolving_routes if // no-one is using it anymore - if (lookup_by_igp_parent(found->resolving_parent()->net()) == NULL) { + if (lookup_by_igp_parent(found->resolving_parent()->net()) == NULL) _resolving_routes.erase(found->resolving_parent()->net()); - } - // Propagate the delete next - _wining_routes.erase(found->net()); + if (winning_route == true) { + // Propagate the delete next + _wining_routes.erase(found->net()); - this->next_table()->delete_route(found, this); - is_delete_propagated = true; + this->next_table()->delete_route(found); + is_delete_propagated = true; + } // Now delete the locally modified copy delete found; - } else { + } else if (!delete_unresolved_nexthop(route) && winning_route) { // Propagate the delete only if the route wasn't found in - // the unresolved nexthops table. - if (delete_unresolved_nexthop(route) == false) { - _wining_routes.erase(route->net()); + // the unresolved nexthops table and if it was the winning route. + // Propagate the delete next + _wining_routes.erase(route->net()); - this->next_table()->delete_route(route, this); - is_delete_propagated = true; - } + this->next_table()->delete_route(route); + is_delete_propagated = true; } - return XORP_OK; + return is_delete_propagated; } template @@ -394,7 +552,6 @@ template void ExtIntTable::resolve_unresolved_nexthops(const IPRouteEntry& nexthop_route) { - XLOG_ASSERT(_ext_table); typename multimap* >::iterator rpair, nextpair; A unresolved_nexthop, new_subnet; @@ -432,7 +589,7 @@ ExtIntTable::resolve_unresolved_nexthops(const IPRouteEntry& nexthop_route // That way we don't have any memory leaking. // Reinstantiate the resolved route - add_route(*unresolved_route, _ext_table); + add_route(*unresolved_route); rpair = nextpair; } else { @@ -510,7 +667,6 @@ template void ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) { - XLOG_ASSERT(_ext_table); debug_msg("recalculate_nexthops: %s\n", new_route.str().c_str()); const IPRouteEntry* old_route; @@ -549,7 +705,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) // Propagate the delete next _wining_routes.erase(found->net()); - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found); // Now delete the local resolved copy, and reinstantiate it delete found; @@ -560,7 +716,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) // old pointer with the existing pointer. // That way we don't have any memory leaking. - add_route(*egp_parent, _ext_table); + add_route(*egp_parent); } else { debug_msg("route matched but nexthop didn't: nexthop: %s\n %s\n", (egp_parent->nexthop())->addr().str().c_str(), @@ -595,7 +751,7 @@ ExtIntTable::lookup_route(const A& addr) const template inline const IPRouteEntry* -ExtIntTable::lookup_route_in_igp_parent(const IPNet& ipnet) const +ExtIntTable::lookup_winning_igp_route(const IPNet& ipnet) const { typename RouteTrie::iterator iter = _wining_igp_routes.lookup_node(ipnet); return ((iter == _wining_igp_routes.end()) ? NULL : *iter); @@ -603,7 +759,7 @@ ExtIntTable::lookup_route_in_igp_parent(const IPNet& ipnet) const template inline const IPRouteEntry* -ExtIntTable::lookup_route_in_igp_parent(const A& addr) const +ExtIntTable::lookup_winning_igp_route(const A& addr) const { typename RouteTrie::iterator iter = _wining_igp_routes.find(addr); return ((iter == _wining_igp_routes.end()) ? NULL : *iter); @@ -611,7 +767,7 @@ ExtIntTable::lookup_route_in_igp_parent(const A& addr) const template inline const IPRouteEntry* -ExtIntTable::lookup_route_in_egp_parent(const IPNet& ipnet) const +ExtIntTable::lookup_winning_egp_route(const IPNet& ipnet) const { typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(ipnet); return ((iter == _wining_egp_routes.end()) ? NULL : *iter); @@ -619,45 +775,12 @@ ExtIntTable::lookup_route_in_egp_parent(const IPNet& ipnet) const template inline const IPRouteEntry* -ExtIntTable::lookup_route_in_egp_parent(const A& addr) const +ExtIntTable::lookup_winning_egp_route(const A& addr) const { typename RouteTrie::iterator iter = _wining_egp_routes.find(addr); return ((iter == _wining_egp_routes.end()) ? NULL : *iter); } -template -void -ExtIntTable::replumb(RouteTable* old_parent, RouteTable* new_parent) -{ - XLOG_ASSERT(old_parent); - if (old_parent == _int_table) - replumb_internal(new_parent); - else if (old_parent == _ext_table) - replumb_external(new_parent); -} - -template -inline void -ExtIntTable::replumb_external(RouteTable* new_ext_parent) -{ - debug_msg("ExtIntTable::replumb_external\n"); - _ext_table = new_ext_parent; - _ext_table->set_next_table(this); - this->set_tablename(make_extint_name(_ext_table, _int_table)); - debug_msg("ExtIntTable: now called \"%s\"\n", this->tablename().c_str()); -} - -template -inline void -ExtIntTable::replumb_internal(RouteTable* new_int_parent) -{ - debug_msg("ExtIntTable::replumb_internal\n"); - _int_table = new_int_parent; - _int_table->set_next_table(this); - this->set_tablename(make_extint_name(_ext_table, _int_table)); - debug_msg("ExtIntTable: now called \"%s\"\n", this->tablename().c_str()); -} - template RouteRange* ExtIntTable::lookup_route_range(const A& addr) const @@ -680,8 +803,18 @@ ExtIntTable::str() const string s; s = "-------\nExtIntTable: " + this->tablename() + "\n"; - s += "_ext_table = " + (_ext_table ? _ext_table->tablename() : "NULL") + "\n"; - s += "_int_table = " + (_int_table ? _int_table->tablename() : "NULL") + "\n"; + s += "_int_tables:\n"; + for (typename AdminDistanceSet::const_iterator iter = _igp_ad_set.begin(); iter != _igp_ad_set.end(); ++iter) { + s += c_format("AD: %d \n", *iter); + typename RouteTableMap::const_iterator rt_iter = _all_tables.find(*iter); + s += rt_iter->second->str() + "\n"; + } + s += "_ext_tables:\n"; + for (typename AdminDistanceSet::const_iterator iter = _egp_ad_set.begin(); iter != _egp_ad_set.end(); ++iter) { + s += c_format("AD: %d \n", *iter); + typename RouteTableMap::const_iterator rt_iter = _all_tables.find(*iter); + s += rt_iter->second->str() + "\n"; + } if (this->next_table() == NULL) s += "no next table\n"; else diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index b81ba9276..31a14d08d 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -63,11 +63,8 @@ public: /** * ExtIntTable Constructor. * - * @param ext_table parent RouteTables supplying EGP routes. - * @param int_table parent RouteTables supplying IGP routes. */ - ExtIntTable(RouteTable* ext_table, - RouteTable* int_table); + ExtIntTable(); /** * ExtInt Destructor @@ -84,7 +81,7 @@ public: * @param caller the parent table sending the new route. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(const IPRouteEntry& route, RouteTable* caller); + int add_route(const IPRouteEntry& route); /** * An delete_route request from a parent table also causes a @@ -98,7 +95,7 @@ public: * @param caller the parent table sending the delete_route. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int delete_route(const IPRouteEntry* route); /** * Lookup a specific subnet. The lookup will first look in the @@ -152,26 +149,18 @@ public: TableType type() const { return EXTINT_TABLE; } /** - * Set new parent + * Changes the admin distance of the OriginTable and replumbs it. * - * @param old_parent the old parent table. - * @param new_parent the new parent table. + * @return XORP_OK on success, otherwise XORP_ERROR */ - void replumb(RouteTable* old_parent, RouteTable* new_parent); + int change_admin_distance(OriginTable* ot, uint32_t ad); /** - * Set new external parent + * Adds new RouteTable to the map * - * @param new_ext_parent the new external parent table. - */ - void replumb_external(RouteTable* new_ext_parent); - - /** - * Set new internal parent - * - * @param new_int_parent the new external parent table. + * @return XORP_OK on success, otherwise XORP_ERROR. */ - void replumb_internal(RouteTable* new_int_parent); + int add_protocol_table(OriginTable* new_table); /** * Render this ExtIntTable as a string for debugging purposes. @@ -184,9 +173,10 @@ private: typedef multimap, ResolvedIPRouteEntry* > ResolvingParentMultiMap; typedef map, UnresolvedIPRouteEntry* > IpUnresolvedTableMap; typedef Trie* > RouteTrie; + typedef map* > RouteTableMap; + typedef set AdminDistanceSet; - int delete_ext_route(const IPRouteEntry* route, - bool& is_delete_propagated); + bool delete_ext_route(const IPRouteEntry* route, bool winning_route = true); const ResolvedIPRouteEntry* lookup_in_resolved_table( const IPNet& ipv4net); @@ -208,16 +198,28 @@ private: const IPNet& route_net, const typename ResolvingParentMultiMap::iterator& previous); - const IPRouteEntry* lookup_route_in_igp_parent( + const IPRouteEntry* lookup_winning_igp_route( const IPNet& subnet) const; - const IPRouteEntry* lookup_route_in_igp_parent(const A& addr) const; + const IPRouteEntry* lookup_winning_igp_route(const A& addr) const; - const IPRouteEntry* lookup_route_in_egp_parent( + const IPRouteEntry* lookup_winning_egp_route( const IPNet& subnet) const; - const IPRouteEntry* lookup_route_in_egp_parent(const A& addr) const; + const IPRouteEntry* lookup_winning_egp_route(const A& addr) const; + + bool best_igp_route(const IPRouteEntry& route); + bool best_egp_route(const IPRouteEntry& route); - RouteTable* _ext_table; - RouteTable* _int_table; + bool deleting_best_igp_route(const IPRouteEntry* route); + bool deleting_best_egp_route(const IPRouteEntry* route); + + const IPRouteEntry* masked_route(const IPRouteEntry* route); + + void delete_resolved_routes(const IPRouteEntry* route); + + AdminDistanceSet _igp_ad_set; + AdminDistanceSet _egp_ad_set; + + RouteTableMap _all_tables; Trie* > _ip_resolved_table; multimap* > _ip_unresolved_nexthops; IpUnresolvedTableMap _ip_unresolved_table; @@ -235,6 +237,8 @@ private: RouteTrie _wining_egp_routes; // Here, all wining EGP routes will be stored //(resolved, unresolved and connected) RouteTrie _wining_routes; // Overall wining routes! + + static const string& ext_int_name(); }; #endif // __RIB_RT_TAB_EXTINT_HH__ diff --git a/xorp/rib/rt_tab_log.cc b/xorp/rib/rt_tab_log.cc index fcf21db8f..092932c28 100644 --- a/xorp/rib/rt_tab_log.cc +++ b/xorp/rib/rt_tab_log.cc @@ -51,25 +51,23 @@ LogTable::update_number() const template int -LogTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +LogTable::add_route(const IPRouteEntry& route) { _update_number++; RouteTable* n = this->next_table(); if (n != NULL) { - return n->add_route(route, caller); + return n->add_route(route); } return XORP_OK; } template int -LogTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +LogTable::delete_route(const IPRouteEntry* route) { RouteTable* n = this->next_table(); if (n != NULL) { - return n->delete_route(route, caller); + return n->delete_route(route); } _update_number++; return XORP_OK; @@ -91,13 +89,9 @@ LogTable::lookup_route(const A& addr) const template void -LogTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +LogTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(_parent == old_parent); _parent = new_parent; - - // XXX _parent->set_next_table??? } template @@ -129,27 +123,25 @@ OstreamLogTable::OstreamLogTable(const string& tablename, template int -OstreamLogTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +OstreamLogTable::add_route(const IPRouteEntry& route) { _o << this->update_number() << (const char*)(" Add: ") << route.str() << (const char*)(" Return: "); - int s = LogTable::add_route(route, caller); + int s = LogTable::add_route(route); _o << s << endl; return s; } template int -OstreamLogTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +OstreamLogTable::delete_route(const IPRouteEntry* route) { if (route != NULL) { _o << this->update_number() << (const char*)(" Delete: ") << route->str() << (const char*)(" Return: "); } - int s = LogTable::delete_route(route, caller); + int s = LogTable::delete_route(route); if (route != NULL) { _o << s << endl; @@ -182,13 +174,12 @@ XLogTraceTable::XLogTraceTable(const string& tablename, template int -XLogTraceTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +XLogTraceTable::add_route(const IPRouteEntry& route) { string msg = c_format("%u Add: %s Return: ", XORP_UINT_CAST(this->update_number()), route.str().c_str()); - int s = LogTable::add_route(route, caller); + int s = LogTable::add_route(route); msg += c_format("%d\n", s); XLOG_TRACE(true, "%s", msg.c_str()); @@ -197,8 +188,7 @@ XLogTraceTable::add_route(const IPRouteEntry& route, template int -XLogTraceTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +XLogTraceTable::delete_route(const IPRouteEntry* route) { string msg; @@ -208,7 +198,7 @@ XLogTraceTable::delete_route(const IPRouteEntry* route, route->str().c_str()); } - int s = LogTable::delete_route(route, caller); + int s = LogTable::delete_route(route); if (route != NULL) { msg += c_format("%d\n", s); @@ -246,13 +236,12 @@ DebugMsgLogTable::DebugMsgLogTable(const string& tablename, template int -DebugMsgLogTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +DebugMsgLogTable::add_route(const IPRouteEntry& route) { string msg = c_format("%u Add: %s Return: ", XORP_UINT_CAST(this->update_number()), route.str().c_str()); - int s = LogTable::add_route(route, caller); + int s = LogTable::add_route(route); msg += c_format("%d\n", s); debug_msg("%s", msg.c_str()); @@ -261,8 +250,7 @@ DebugMsgLogTable::add_route(const IPRouteEntry& route, template int -DebugMsgLogTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +DebugMsgLogTable::delete_route(const IPRouteEntry* route) { string msg; @@ -272,7 +260,7 @@ DebugMsgLogTable::delete_route(const IPRouteEntry* route, route->str().c_str()); } - int s = LogTable::delete_route(route, caller); + int s = LogTable::delete_route(route); if (route != NULL) { msg += c_format("%d\n", s); diff --git a/xorp/rib/rt_tab_log.hh b/xorp/rib/rt_tab_log.hh index e28c73da0..b5e9f3220 100644 --- a/xorp/rib/rt_tab_log.hh +++ b/xorp/rib/rt_tab_log.hh @@ -46,15 +46,15 @@ public: LogTable(const string& tablename, RouteTable* parent); ~LogTable(); - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* , RouteTable* caller); + int add_route(const IPRouteEntry& route); + int delete_route(const IPRouteEntry*); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return LOG_TABLE; } RouteTable* parent() { return _parent; } const RouteTable* parent() const { return _parent; } - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent); string str() const; uint32_t update_number() const; @@ -79,8 +79,8 @@ public: OstreamLogTable(const string& tablename, RouteTable* parent, ostream& out); - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* , RouteTable* caller); + int add_route(const IPRouteEntry& route); + int delete_route(const IPRouteEntry*); string str() const; private: @@ -100,11 +100,9 @@ public: XLogTraceTable(const string& tablename, RouteTable* parent); - int add_route(const IPRouteEntry& route, - RouteTable* caller); + int add_route(const IPRouteEntry& route); - int delete_route(const IPRouteEntry* proute, - RouteTable* caller); + int delete_route(const IPRouteEntry* proute); string str() const; }; @@ -121,11 +119,9 @@ public: DebugMsgLogTable(const string& tablename, RouteTable* parent); - int add_route(const IPRouteEntry& route, - RouteTable* caller); + int add_route(const IPRouteEntry& route); - int delete_route(const IPRouteEntry* proute, - RouteTable* caller); + int delete_route(const IPRouteEntry* proute); string str() const; }; diff --git a/xorp/rib/rt_tab_origin.cc b/xorp/rib/rt_tab_origin.cc index 0dd6c3e14..604a71453 100644 --- a/xorp/rib/rt_tab_origin.cc +++ b/xorp/rib/rt_tab_origin.cc @@ -34,7 +34,7 @@ // template OriginTable::OriginTable(const string& tablename, - uint32_t admin_distance, + uint16_t admin_distance, ProtocolType protocol_type, EventLoop& eventloop) : RouteTable(tablename), @@ -64,10 +64,10 @@ int OriginTable::add_route(IPRouteEntry* route) { debug_msg("OT[%s]: Adding route %s\n", this->tablename().c_str(), - route->str().c_str()); + route->str().c_str()); if (lookup_route(route->net()) != NULL) { - delete route; + delete (route); return XORP_ERROR; } @@ -81,12 +81,9 @@ OriginTable::add_route(IPRouteEntry* route) _ip_route_table->insert(route->net(), route); - - - // Propagate to next table if (this->next_table() != NULL) - this->next_table()->add_route(*route, this); + this->next_table()->add_route(*route); #ifdef DEBUG_LOGGING debug_msg("AFTER:\n"); @@ -95,14 +92,6 @@ OriginTable::add_route(IPRouteEntry* route) return XORP_OK; } -template -int -OriginTable::add_route(const IPRouteEntry&, RouteTable*) -{ - XLOG_UNREACHABLE(); - return XORP_ERROR; -} - template int OriginTable::delete_route(const IPNet& net) @@ -120,7 +109,7 @@ OriginTable::delete_route(const IPNet& net) _ip_route_table->erase(net); // Propagate to next table if (this->next_table() != NULL) - this->next_table()->delete_route(found, this); + this->next_table()->delete_route(found); // Finally we're done, and can cleanup delete found; @@ -131,14 +120,6 @@ OriginTable::delete_route(const IPNet& net) return XORP_ERROR; } -template -int -OriginTable::delete_route(const IPRouteEntry*, RouteTable*) -{ - XLOG_UNREACHABLE(); - return XORP_ERROR; -} - template void OriginTable::delete_all_routes() diff --git a/xorp/rib/rt_tab_origin.hh b/xorp/rib/rt_tab_origin.hh index eb6df6be2..5e0c8e715 100644 --- a/xorp/rib/rt_tab_origin.hh +++ b/xorp/rib/rt_tab_origin.hh @@ -58,7 +58,7 @@ public: * @param protocol_type the routing protocol type (@ref ProtocolType). * @param eventloop the main event loop. */ - OriginTable(const string& tablename, uint32_t admin_distance, + OriginTable(const string& tablename, uint16_t admin_distance, ProtocolType protocol_type, EventLoop& eventloop); /** @@ -79,11 +79,7 @@ public: */ int add_route(IPRouteEntry* route); - /** - * Generic @ref RouteTable method that is not used on OriginTable. - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int add_route(const IPRouteEntry&, RouteTable* ); + int add_route(const IPRouteEntry&) { return XORP_ERROR; } /** * Delete a route from the OriginTable. @@ -93,11 +89,7 @@ public: */ int delete_route(const IPNet& net); - /** - * Generic @ref RouteTable method that is not used on OriginTable. - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int delete_route(const IPRouteEntry* , RouteTable* ); + int delete_route(const IPRouteEntry*) { return XORP_ERROR; } /** * Delete all the routes that are in this OriginTable. The @@ -152,7 +144,7 @@ public: /** * @return the default administrative distance for this OriginTable */ - uint32_t admin_distance() const { return _admin_distance; } + uint16_t admin_distance() const { return _admin_distance; } /** * @return the routing protocol type (@ref ProtocolType). @@ -164,11 +156,6 @@ public: */ TableType type() const { return ORIGIN_TABLE; } - /** - * Generic @ref RouteTable method that is not used on OriginTable. - */ - void replumb(RouteTable* , RouteTable* ) {} - /** * Render the OriginTable as a string for debugging purposes */ @@ -191,7 +178,7 @@ public: const RouteContainer& route_container() const; private: - uint32_t _admin_distance; // 0 .. 255 + uint16_t _admin_distance; // 0 .. 255 ProtocolType _protocol_type; // IGP or EGP EventLoop& _eventloop; RouteContainer* _ip_route_table; diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index 7facc3804..39ee5485d 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -46,8 +46,7 @@ PolicyConnectedTable::PolicyConnectedTable (RouteTable* parent, { if (_parent->next_table()) { this->set_next_table(_parent->next_table()); - - this->next_table()->replumb(_parent, this); + this->next_table()->set_parent(this); } _parent->set_next_table(this); } @@ -60,15 +59,11 @@ PolicyConnectedTable::~PolicyConnectedTable () template int -PolicyConnectedTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +PolicyConnectedTable::add_route(const IPRouteEntry& route) { - XLOG_ASSERT(caller == _parent); - debug_msg("[RIB] PolicyConnectedTable ADD ROUTE: %s\n", route.str().c_str()); - // store original IPRouteEntry* original = const_cast* >(&route); _route_table.insert(original->net(), original); @@ -79,15 +74,13 @@ PolicyConnectedTable::add_route(const IPRouteEntry& route, XLOG_ASSERT(next); // Send the possibly modified route down - return next->add_route(*original, this); + return next->add_route(*original); } template int -PolicyConnectedTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +PolicyConnectedTable::delete_route(const IPRouteEntry* route) { - XLOG_ASSERT(caller == _parent); XLOG_ASSERT(route != NULL); debug_msg("[RIB] PolicyConnectedTable DELETE ROUTE: %s\n", @@ -108,7 +101,7 @@ PolicyConnectedTable::delete_route(const IPRouteEntry* route, do_filtering(*re); // propagate the delete - int ret = next->delete_route(re, this); + int ret = next->delete_route(re); return ret; } @@ -160,11 +153,8 @@ PolicyConnectedTable::lookup_route_range(const A& addr) const template void -PolicyConnectedTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +PolicyConnectedTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(old_parent == _parent); - _parent = new_parent; } diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index c8d47833a..e9bcd18dc 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -52,15 +52,15 @@ public: PolicyConnectedTable(RouteTable* parent, PolicyFilters& pfs); ~PolicyConnectedTable(); - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int add_route(const IPRouteEntry& route); + int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return POLICY_CONNECTED_TABLE; } const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent); string str() const; /** diff --git a/xorp/rib/rt_tab_pol_redist.cc b/xorp/rib/rt_tab_pol_redist.cc index b0b543e5e..31a6805e8 100644 --- a/xorp/rib/rt_tab_pol_redist.cc +++ b/xorp/rib/rt_tab_pol_redist.cc @@ -50,19 +50,15 @@ PolicyRedistTable::PolicyRedistTable(RouteTable* parent, XrlRouter& rtr, { if (_parent->next_table() != NULL) { this->set_next_table(_parent->next_table()); - - this->next_table()->replumb(_parent, this); + this->next_table()->set_parent(this); } _parent->set_next_table(this); } template int -PolicyRedistTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +PolicyRedistTable::add_route(const IPRouteEntry& route) { - XLOG_ASSERT(caller == _parent); - debug_msg("[RIB] PolicyRedistTable ADD ROUTE: %s\n", route.str().c_str()); @@ -77,15 +73,13 @@ PolicyRedistTable::add_route(const IPRouteEntry& route, RouteTable* next = this->next_table(); XLOG_ASSERT(next != NULL); - return next->add_route(route, this); + return next->add_route(route); } template int -PolicyRedistTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +PolicyRedistTable::delete_route(const IPRouteEntry* route) { - XLOG_ASSERT(caller == _parent); XLOG_ASSERT(route != NULL); debug_msg("[RIB] PolicyRedistTable DELETE ROUTE: %s\n", @@ -102,7 +96,7 @@ PolicyRedistTable::delete_route(const IPRouteEntry* route, RouteTable* next = this->next_table(); XLOG_ASSERT(next != NULL); - return next->delete_route(route, this); + return next->delete_route(route); } template @@ -137,11 +131,8 @@ PolicyRedistTable::lookup_route_range(const A& addr) const template void -PolicyRedistTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +PolicyRedistTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(old_parent == _parent); - _parent = new_parent; } diff --git a/xorp/rib/rt_tab_pol_redist.hh b/xorp/rib/rt_tab_pol_redist.hh index ae592d3a8..eaf27802c 100644 --- a/xorp/rib/rt_tab_pol_redist.hh +++ b/xorp/rib/rt_tab_pol_redist.hh @@ -128,15 +128,15 @@ public: PolicyRedistTable(RouteTable* parent, XrlRouter& rtr, PolicyRedistMap&, bool multicast); - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int add_route(const IPRouteEntry& router); + int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return POLICY_REDIST_TABLE; } const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent); string str() const; void xrl_cb(const XrlError&, string); diff --git a/xorp/rib/rt_tab_redist.cc b/xorp/rib/rt_tab_redist.cc index ec26fbc6c..1cec7915b 100644 --- a/xorp/rib/rt_tab_redist.cc +++ b/xorp/rib/rt_tab_redist.cc @@ -349,7 +349,7 @@ RedistTable::RedistTable(const string& tablename, { if (_parent->next_table()) { this->set_next_table(_parent->next_table()); - this->next_table()->replumb(_parent, this); + this->next_table()->set_parent(this); } _parent->set_next_table(this); } @@ -399,10 +399,8 @@ RedistTable::redistributor(const string& name) template int -RedistTable::add_route(const IPRouteEntry& route, RouteTable* caller) +RedistTable::add_route(const IPRouteEntry& route) { - XLOG_ASSERT(caller == _parent); - typename RouteIndex::iterator rci = _rt_index.find(route.net()); XLOG_ASSERT(rci == _rt_index.end()); @@ -416,17 +414,14 @@ RedistTable::add_route(const IPRouteEntry& route, RouteTable* caller) } if (this->next_table()) - return this->next_table()->add_route(route, this); + return this->next_table()->add_route(route); return XORP_OK; } template int -RedistTable::delete_route(const IPRouteEntry* r, - RouteTable* caller) +RedistTable::delete_route(const IPRouteEntry* r) { - XLOG_ASSERT(caller == _parent); - const IPRouteEntry& route = *r; debug_msg("delete_route for %s\n", route.net().str().c_str()); @@ -455,7 +450,7 @@ RedistTable::delete_route(const IPRouteEntry* r, } if (this->next_table()) - return this->next_table()->delete_route(r, this); + return this->next_table()->delete_route(r); return XORP_OK; } @@ -464,35 +459,6 @@ RedistTable::delete_route(const IPRouteEntry* r, // ---------------------------------------------------------------------------- // Standard RouteTable methods, RedistTable punts everything to parent. -template -const IPRouteEntry* -RedistTable::lookup_route(const IPNet& net) const -{ - return _parent->lookup_route(net); -} - -template -const IPRouteEntry* -RedistTable::lookup_route(const A& addr) const -{ - return _parent->lookup_route(addr); -} - -template -RouteRange* -RedistTable::lookup_route_range(const A& addr) const -{ - return _parent->lookup_route_range(addr); -} - -template -void -RedistTable::replumb(RouteTable* old_parent, RouteTable* new_parent) -{ - XLOG_ASSERT(old_parent == _parent); - _parent = new_parent; -} - template string RedistTable::str() const diff --git a/xorp/rib/rt_tab_redist.hh b/xorp/rib/rt_tab_redist.hh index 8b155ff51..2371cd042 100644 --- a/xorp/rib/rt_tab_redist.hh +++ b/xorp/rib/rt_tab_redist.hh @@ -110,15 +110,15 @@ public: // // Standard RouteTable methods // - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* route, RouteTable* caller); - const IPRouteEntry* lookup_route(const IPNet& net) const; - const IPRouteEntry* lookup_route(const A& addr) const; - RouteRange* lookup_route_range(const A& addr) const; + int add_route(const IPRouteEntry& route); + int delete_route(const IPRouteEntry* route); + const IPRouteEntry* lookup_route(const IPNet& net) const { return _parent->lookup_route(net); } + const IPRouteEntry* lookup_route(const A& addr) const { return _parent->lookup_route(addr); } + RouteRange* lookup_route_range(const A& addr) const { return _parent->lookup_route_range(addr); } TableType type() const { return REDIST_TABLE; } const RouteTable* parent() const { return _parent; } RouteTable* parent() { return _parent; } - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent) { _parent = new_parent; } string str() const; /** diff --git a/xorp/rib/rt_tab_register.cc b/xorp/rib/rt_tab_register.cc index 33c07937a..3369c5f50 100644 --- a/xorp/rib/rt_tab_register.cc +++ b/xorp/rib/rt_tab_register.cc @@ -94,10 +94,8 @@ RegisterTable::~RegisterTable() template void -RegisterTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +RegisterTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(_parent == old_parent); _parent = new_parent; } @@ -252,16 +250,14 @@ RegisterTable::notify_relevant_modules(bool add, template int -RegisterTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +RegisterTable::add_route(const IPRouteEntry& route) { debug_msg("RegisterTable::add_route %s\n", route.str().c_str()); debug_msg("Before:\n"); print(); - XLOG_ASSERT(caller == _parent); if (this->next_table() != NULL) - this->next_table()->add_route(route, this); + this->next_table()->add_route(route); notify_relevant_modules(true /* it's an add */, route); @@ -272,16 +268,14 @@ RegisterTable::add_route(const IPRouteEntry& route, template int -RegisterTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +RegisterTable::delete_route(const IPRouteEntry* route) { debug_msg("[REGT]: delete_route: %p\n%s\n", route, route->str().c_str()); debug_msg("Before:\n"); print(); - XLOG_ASSERT(caller == _parent); if (this->next_table() != NULL) - this->next_table()->delete_route(route, this); + this->next_table()->delete_route(route); notify_relevant_modules(false /* it's a delete */, *route); debug_msg("Delete route called on register table\n"); @@ -469,7 +463,7 @@ RegisterTable::str() const } template -void +inline void RegisterTable::print() { #ifdef DEBUG_LOGGING diff --git a/xorp/rib/rt_tab_register.hh b/xorp/rib/rt_tab_register.hh index fe7ba1b05..5680ad38e 100644 --- a/xorp/rib/rt_tab_register.hh +++ b/xorp/rib/rt_tab_register.hh @@ -298,7 +298,7 @@ public: * @param caller this must be this table's parent table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(const IPRouteEntry& route, RouteTable* caller); + int add_route(const IPRouteEntry& route); /** * Delete a route from the RIB. This will be propagated @@ -310,7 +310,7 @@ public: * @param caller this must be this table's parent table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int delete_route(const IPRouteEntry* route); /** * Lookup a route in the RIB. This request will be propagated to @@ -337,15 +337,6 @@ public: return _parent->lookup_route_range(addr); } - /** - * Replumb to replace the old parent of this table with a new parent. - * - * @param old_parent the parent RouteTable being replaced (must be - * the same as the existing parent). - * @param new_parent the new parent RouteTable. - */ - void replumb(RouteTable* old_parent, RouteTable* new_parent); - /** * @return the parent @ref RouteTable of this RegisterTable. */ @@ -398,6 +389,8 @@ public: */ TableType type() const { return REGISTER_TABLE; } + void set_parent(RouteTable* new_parent); + /** * Cause the register server to push out queued changes to the * routing protocols. diff --git a/xorp/rib/tests/commands b/xorp/rib/tests/commands index 390b1ba80..f79194e08 100644 --- a/xorp/rib/tests/commands +++ b/xorp/rib/tests/commands @@ -451,3 +451,4 @@ route add rip 10.20.30.0/24 10.0.0.2 2 route add ebgp 10.20.30.0/24 9.9.9.9 0 route delete ebgp 10.20.30.0/24 route add ebgp 10.20.30.0/24 9.9.9.9 0 +route verify ip 10.20.30.1 de0 10.0.0.2 2 diff --git a/xorp/rib/tests/rt_tab_expect.cc b/xorp/rib/tests/rt_tab_expect.cc index 960481529..ff1352ca9 100644 --- a/xorp/rib/tests/rt_tab_expect.cc +++ b/xorp/rib/tests/rt_tab_expect.cc @@ -126,10 +126,8 @@ ExpectTable::expect_delete(const IPRouteEntry& route) template int -ExpectTable::add_route(const IPRouteEntry& route, - RouteTable* caller) +ExpectTable::add_route(const IPRouteEntry& route) { - XLOG_ASSERT(caller == _parent); debug_msg("DT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); if (_expected_route_changes.empty()) { @@ -148,10 +146,8 @@ ExpectTable::add_route(const IPRouteEntry& route, template int -ExpectTable::delete_route(const IPRouteEntry* route, - RouteTable* caller) +ExpectTable::delete_route(const IPRouteEntry* route) { - XLOG_ASSERT(caller == _parent); debug_msg("DT[%s]: Deleting route %s\n", this->tablename().c_str(), route->str().c_str()); if (_expected_route_changes.empty()) { @@ -184,10 +180,8 @@ ExpectTable::lookup_route(const A& addr) const template void -ExpectTable::replumb(RouteTable* old_parent, - RouteTable* new_parent) +ExpectTable::set_parent(RouteTable* new_parent) { - XLOG_ASSERT(_parent == old_parent); _parent = new_parent; } diff --git a/xorp/rib/tests/rt_tab_expect.hh b/xorp/rib/tests/rt_tab_expect.hh index 2b2c949d8..4da385d28 100644 --- a/xorp/rib/tests/rt_tab_expect.hh +++ b/xorp/rib/tests/rt_tab_expect.hh @@ -51,15 +51,15 @@ public: void expect_add(const IPRouteEntry& route); void expect_delete(const IPRouteEntry& route); - int add_route(const IPRouteEntry& route, RouteTable* caller); - int delete_route(const IPRouteEntry* route, RouteTable* caller); + int add_route(const IPRouteEntry& route); + int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return EXPECT_TABLE; } RouteTable* parent() { return _parent; } const RouteTable* parent() const { return _parent; } - void replumb(RouteTable* old_parent, RouteTable* new_parent); + void set_parent(RouteTable* new_parent); string str() const; private: From e28b4201960bbf57298b824625b83d8778c3d369 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 16:15:32 +0200 Subject: [PATCH 26/38] xorp: rib: Split add_route to add_igp_route and add_egp_route This way we're avoiding unecessary branching in ExtIntTable. --- xorp/rib/rib.cc | 14 +- xorp/rib/rt_tab_base.hh | 6 +- xorp/rib/rt_tab_deletion.cc | 72 ++++--- xorp/rib/rt_tab_deletion.hh | 77 ++++++- xorp/rib/rt_tab_extint.cc | 357 +++++++++++++++++--------------- xorp/rib/rt_tab_extint.hh | 11 +- xorp/rib/rt_tab_origin.cc | 63 +++--- xorp/rib/rt_tab_origin.hh | 69 ++++-- xorp/rib/rt_tab_pol_conn.cc | 61 ++++-- xorp/rib/rt_tab_pol_conn.hh | 9 +- xorp/rib/rt_tab_pol_redist.cc | 52 ++++- xorp/rib/rt_tab_pol_redist.hh | 10 +- xorp/rib/rt_tab_redist.cc | 47 ++++- xorp/rib/rt_tab_redist.hh | 10 +- xorp/rib/rt_tab_register.cc | 67 ++++-- xorp/rib/rt_tab_register.hh | 46 ++-- xorp/rib/tests/rt_tab_expect.hh | 4 + xorp/rib/tests/test_deletion.cc | 2 +- xorp/rib/tests/test_redist.cc | 3 +- 19 files changed, 649 insertions(+), 331 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index c84ec93ba..a36a5dabe 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -476,8 +476,18 @@ RIB::new_origin_table(const string& tablename, uint16_t admin_distance, ProtocolType protocol_type) { - OriginTable* ot = new OriginTable(tablename, admin_distance, - protocol_type, _eventloop); + OriginTable* ot = NULL; + switch (protocol_type) { + case IGP: + ot = new TypedOriginTable(tablename, admin_distance, _eventloop); + break; + case EGP: + ot = new TypedOriginTable(tablename, admin_distance, _eventloop); + break; + default: + XLOG_UNREACHABLE(); + break; + } if (ot == NULL || add_table(ot) != XORP_OK) { XLOG_WARNING("Could not add origin table %s", tablename.c_str()); delete ot; diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index fe692258d..d769986f3 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -165,9 +165,11 @@ public: RouteTable(const string& name) : _tablename(name), _next_table(NULL) {} virtual ~RouteTable(); - virtual int add_route(const IPRouteEntry& route) = 0; + virtual int add_igp_route(const IPRouteEntry& route) = 0; + virtual int add_egp_route(const IPRouteEntry& route) = 0; - virtual int delete_route(const IPRouteEntry* route) = 0; + virtual int delete_igp_route(const IPRouteEntry* route) = 0; + virtual int delete_egp_route(const IPRouteEntry* route) = 0; virtual const IPRouteEntry* lookup_route(const IPNet& net) const = 0; diff --git a/xorp/rib/rt_tab_deletion.cc b/xorp/rib/rt_tab_deletion.cc index f332b47bb..b58994214 100644 --- a/xorp/rib/rt_tab_deletion.cc +++ b/xorp/rib/rt_tab_deletion.cc @@ -35,7 +35,7 @@ template DeletionTable::DeletionTable(const string& tablename, RouteTable* parent, - Trie* >* ip_route_trie, + RouteTrie* ip_route_trie, EventLoop& eventloop) : RouteTable(tablename), _parent(parent), @@ -46,11 +46,6 @@ DeletionTable::DeletionTable(const string& tablename, this->set_next_table(_parent->next_table()); this->next_table()->set_parent(this); parent->set_next_table(this); - - // Callback immediately, but after network events or expired timers - _background_deletion_timer = _eventloop.new_oneoff_after_ms( - 0, - callback(this, &DeletionTable::background_deletion_pass)); } template @@ -63,9 +58,31 @@ DeletionTable::~DeletionTable() template int -DeletionTable::add_route(const IPRouteEntry& route) +DeletionTable::add_igp_route(const IPRouteEntry& route) +{ + typename RouteTrie::iterator iter; + iter = _ip_route_table->lookup_node(route.net()); + if (iter != _ip_route_table->end()) { + // + // We got an add route for a route that was waiting to be + // deleted. Process this now - pass the deletion downstream, + // remove the route from our trie, then pass the new route + // downstream. + // + const IPRouteEntry* our_route = *iter; + _ip_route_table->erase(route.net()); + this->next_table()->delete_igp_route(our_route); + delete our_route; + } + + return this->next_table()->add_igp_route(route); +} + +template +int +DeletionTable::add_egp_route(const IPRouteEntry& route) { - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->lookup_node(route.net()); if (iter != _ip_route_table->end()) { // @@ -76,30 +93,38 @@ DeletionTable::add_route(const IPRouteEntry& route) // const IPRouteEntry* our_route = *iter; _ip_route_table->erase(route.net()); - this->next_table()->delete_route(our_route); + this->next_table()->delete_egp_route(our_route); delete our_route; } - return this->next_table()->add_route(route); + return this->next_table()->add_egp_route(route); +} + +template +int +DeletionTable::delete_igp_route(const IPRouteEntry* route) +{ + // The route MUST NOT be in our trie. + XLOG_ASSERT(_ip_route_table->lookup_node(route->net()) == _ip_route_table->end()); + + return this->next_table()->delete_igp_route(route); } template int -DeletionTable::delete_route(const IPRouteEntry* route) +DeletionTable::delete_egp_route(const IPRouteEntry* route) { // The route MUST NOT be in our trie. - typename Trie* >::iterator iter; - iter = _ip_route_table->lookup_node(route->net()); - XLOG_ASSERT(iter == _ip_route_table->end()); + XLOG_ASSERT(_ip_route_table->lookup_node(route->net()) == _ip_route_table->end()); - return this->next_table()->delete_route(route); + return this->next_table()->delete_egp_route(route); } template void DeletionTable::delete_all_routes() { - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; for (iter = _ip_route_table->begin(); iter != _ip_route_table->end(); ++iter) { @@ -114,7 +139,7 @@ DeletionTable::lookup_route(const IPNet& net) const { const IPRouteEntry* parent_route = _parent->lookup_route(net); - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->lookup_node(net); if (parent_route != NULL) { @@ -141,7 +166,7 @@ DeletionTable::lookup_route(const A& addr) const { const IPRouteEntry* parent_route = _parent->lookup_route(addr); - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->find(addr); if (parent_route != NULL) { @@ -179,7 +204,7 @@ RouteRange* DeletionTable::lookup_route_range(const A& addr) const { const IPRouteEntry* route; - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->find(addr); if (iter == _ip_route_table->end()) @@ -213,17 +238,14 @@ DeletionTable::background_deletion_pass() return; } - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->begin(); const IPRouteEntry* our_route = *iter; _ip_route_table->erase(our_route->net()); - this->next_table()->delete_route(our_route); + this->generic_delete_route(our_route); delete our_route; - // Callback immediately, but after network events or expired timers - _background_deletion_timer = _eventloop.new_oneoff_after_ms( - 0, - callback(this, &DeletionTable::background_deletion_pass)); + this->set_background_timer(); } template diff --git a/xorp/rib/rt_tab_deletion.hh b/xorp/rib/rt_tab_deletion.hh index d5361d660..527345059 100644 --- a/xorp/rib/rt_tab_deletion.hh +++ b/xorp/rib/rt_tab_deletion.hh @@ -38,6 +38,7 @@ class EventLoop; template class DeletionTable : public RouteTable { public: + typedef Trie* > RouteTrie; /** * DeletionTable constructor. * @@ -48,13 +49,13 @@ public: */ DeletionTable(const string& tablename, RouteTable* parent, - Trie* >* ip_route_trie, + RouteTrie* ip_route_trie, EventLoop& eventloop); /** * DeletionTable destructor. */ - ~DeletionTable(); + virtual ~DeletionTable(); /** * Add a route. If the route was stored in the DeletionTable, @@ -64,7 +65,8 @@ public: * @param caller the caller route table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(const IPRouteEntry& route); + int add_igp_route(const IPRouteEntry& route); + int add_egp_route(const IPRouteEntry& route); /** * Delete a route. This route MUST NOT be in the DeletionTable trie. @@ -73,7 +75,8 @@ public: * @param caller the caller route table. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route); + int delete_egp_route(const IPRouteEntry* route); /** * Delete all the routes that are in this DeletionTable. The @@ -120,7 +123,7 @@ public: * Delete a route, and reschedule background_deletion_pass again * on a zero-second timer until all the routes have been deleted */ - void background_deletion_pass(); + virtual void background_deletion_pass(); /** * Remove ourself from the plumbing and delete ourself. @@ -145,10 +148,70 @@ public: RouteTable* parent() { return _parent; } const RouteTable* parent() const { return _parent; } -private: +protected: + virtual int generic_add_route(const IPRouteEntry& route) = 0; + virtual int generic_delete_route(const IPRouteEntry* route) = 0; + virtual void set_background_timer() = 0; + RouteTable* _parent; EventLoop& _eventloop; - Trie* >* _ip_route_table; + RouteTrie* _ip_route_table; +}; + +template +class TypedDeletionTable { }; + +template +class TypedDeletionTable : public DeletionTable { +public: + TypedDeletionTable(const string& tablename, RouteTable* parent, + typename DeletionTable::RouteTrie* ip_route_trie, EventLoop& eventloop) : + DeletionTable(tablename, parent, ip_route_trie, eventloop), + _background_deletion_timer(this->_eventloop.new_oneoff_after_ms( + 0, callback(this, &TypedDeletionTable::background_deletion_pass))) {} + + ~TypedDeletionTable() {} + + int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_igp_route(route); } + int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_igp_route(route); } + + //XXX This is hack, because callback can't register call + // to function from base class from the derived class + void background_deletion_pass() { DeletionTable::background_deletion_pass(); } +protected: + void set_background_timer() { + // Callback immediately, but after network events or expired timers + _background_deletion_timer = this->_eventloop.new_oneoff_after_ms(0, + callback(this, &TypedDeletionTable::background_deletion_pass)); + } + + XorpTimer _background_deletion_timer; +}; + +template +class TypedDeletionTable : public DeletionTable { +public: + TypedDeletionTable(const string& tablename, RouteTable* parent, + typename DeletionTable::RouteTrie* ip_route_trie, EventLoop& eventloop) : + DeletionTable(tablename, parent, ip_route_trie, eventloop), + _background_deletion_timer(this->_eventloop.new_oneoff_after_ms( + 0, callback(this, &TypedDeletionTable::background_deletion_pass))) {} + + ~TypedDeletionTable() {} + + int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_egp_route(route); } + int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_egp_route(route); } + + //XXX This is hack, because callback can't register call + // to function from base class from the derived class + void background_deletion_pass() { DeletionTable::background_deletion_pass(); } +protected: + void set_background_timer() { + // Callback immediately, but after network events or expired timers + _background_deletion_timer = this->_eventloop.new_oneoff_after_ms(0, + callback(this, &TypedDeletionTable::background_deletion_pass)); + } + XorpTimer _background_deletion_timer; }; diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 142fcbce7..049aaaca1 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -17,8 +17,6 @@ // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; // http://xorp.net - - #include "rib_module.h" #include "libxorp/xorp.h" @@ -128,7 +126,7 @@ ExtIntTable::best_igp_route(const IPRouteEntry& route) _wining_igp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() > route.admin_distance()) { - this->delete_route(*iter); + this->delete_igp_route(*iter); _wining_igp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() == route.admin_distance()) { @@ -147,7 +145,7 @@ ExtIntTable::best_egp_route(const IPRouteEntry& route) _wining_egp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() > route.admin_distance()) { - this->delete_route(*iter); + this->delete_egp_route(*iter); _wining_egp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() == route.admin_distance()) { @@ -159,134 +157,150 @@ ExtIntTable::best_egp_route(const IPRouteEntry& route) template int -ExtIntTable::add_route(const IPRouteEntry& route) +ExtIntTable::add_igp_route(const IPRouteEntry& route) { - debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), - route.str().c_str()); + XLOG_ASSERT(_igp_ad_set.find(route.admin_distance()) != _igp_ad_set.end()); + XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); + // The new route comes from the IGP table + debug_msg("route comes from IGP %s\n", route.str().c_str()); - if (_igp_ad_set.find(route.admin_distance()) != _igp_ad_set.end()) { - XLOG_ASSERT(route.nexthop()->type() != EXTERNAL_NEXTHOP); - // The new route comes from the IGP table - debug_msg("route comes from IGP\n"); + // Is it the best IGP route? + if (!best_igp_route(route)) + return XORP_ERROR; - // Is it the best IGP route? - if (!best_igp_route(route)) - return XORP_ERROR; + if (!_egp_ad_set.empty()) { + // Try to find existing EGP routes, that are installed + // We're looking for EGP route in all wining routes. + // We can look here, because no IGP route that matches this subnet + // can't be in wining routes, because we're currently adding it. + // If it would be there, then some error has occurred. + // It should have been deleted. We check for that in the XLOG_ASSERT + const IPRouteEntry* found = lookup_route(route.net()); + if (found != NULL) { + if (found->admin_distance() < route.admin_distance()) + // The admin distance of the existing EGP route is better + return XORP_ERROR; - if (!_egp_ad_set.empty()) { - // Try to find existing EGP routes, that are installed - // We're looking for EGP route in all wining routes. - // We can look here, because no IGP route that matches this subnet - // can't be in wining routes, because we're currently adding it. - // If it would be there, then some error has occurred. - // It should have been deleted. We check for that in the XLOG_ASSERT - const IPRouteEntry* found = lookup_route(route.net()); - if (found != NULL) { - if (found->admin_distance() < route.admin_distance()) - // The admin distance of the existing EGP route is better - return XORP_ERROR; - - XLOG_ASSERT(found->admin_distance() != route.admin_distance()); - - this->delete_ext_route(found); - } + XLOG_ASSERT(found->admin_distance() != route.admin_distance()); + + this->delete_ext_route(found); } + } - _wining_routes.insert(route.net(), &route); + _wining_routes.insert(route.net(), &route); - this->next_table()->add_route(route); + this->next_table()->add_igp_route(route); - if (!_egp_ad_set.empty()) { - // Does this cause any previously resolved nexthops to resolve - // differently? - recalculate_nexthops(route); + if (!_egp_ad_set.empty()) { + // Does this cause any previously resolved nexthops to resolve + // differently? + recalculate_nexthops(route); - // Does this new route cause any unresolved nexthops to be resolved? - resolve_unresolved_nexthops(route); - } + // Does this new route cause any unresolved nexthops to be resolved? + resolve_unresolved_nexthops(route); + } - return XORP_OK; + return XORP_OK; +} - } else if (_egp_ad_set.find(route.admin_distance()) != _egp_ad_set.end()) { - // The new route comes from the EGP table - debug_msg("route comes from EGP\n"); +template +int +ExtIntTable::add_direct_egp_route(const IPRouteEntry& route) +{ + const IPRouteEntry* found = lookup_route(route.net()); - // Is it the best EGP route? - if (!best_egp_route(route)) - return XORP_ERROR; + if (found && (found->admin_distance() < route.admin_distance())) + return XORP_ERROR; - const IPRouteEntry* found = lookup_route(route.net()); + XLOG_ASSERT(found ? (found->admin_distance() != route.admin_distance()) : true); - if (found && (found->admin_distance() < route.admin_distance())) - return XORP_ERROR; + // + // Despite it coming from the Ext table, the nexthop is + // directly connected. Just propagate it. + // + debug_msg("nexthop %s was directly connected\n", route.nexthop()->addr().str().c_str()); - XLOG_ASSERT(found ? (found->admin_distance() != route.admin_distance()) : true); + if (found != NULL) { + // Delete the IGP route that has worse admin distance + _wining_routes.erase(found->net()); + + this->next_table()->delete_igp_route(found); + } - if (route.nexthop()->type() == PEER_NEXTHOP) { - // - // Despite it coming from the Ext table, the nexthop is - // directly connected. Just propagate it. - // - debug_msg("nexthop %s was directly connected\n", route.nexthop()->addr().str().c_str()); + _wining_routes.insert(route.net(), &route); - if (found != NULL) { - // Delete the IGP route that has worse admin distance - _wining_routes.erase(found->net()); + this->next_table()->add_egp_route(route); + return XORP_OK; +} - this->next_table()->delete_route(found); - } +template +int +ExtIntTable::add_indirect_egp_route(const IPRouteEntry& route) +{ + IPNextHop* rt_nexthop = route.nexthop(); - _wining_routes.insert(route.net(), &route); + const IPRouteEntry* nexthop_route = lookup_winning_igp_route(rt_nexthop->addr()); - this->next_table()->add_route(route); + if (nexthop_route == NULL) { + // Store the fact that this was unresolved for later + debug_msg("nexthop %s was unresolved\n", rt_nexthop->addr().str().c_str()); + UnresolvedIPRouteEntry* unresolved_route = + new UnresolvedIPRouteEntry(&route); - return XORP_OK; - } else { - IPNextHop* rt_nexthop = route.nexthop(); + _ip_unresolved_table.insert(make_pair(route.net(), unresolved_route)); + typename UnresolvedRouteBackLink::iterator backlink = + _ip_unresolved_nexthops.insert(make_pair(rt_nexthop->addr(), unresolved_route)); - const IPRouteEntry* nexthop_route = - lookup_winning_igp_route(rt_nexthop->addr()); - if (nexthop_route == NULL) { - // Store the fact that this was unresolved for later - debug_msg("nexthop %s was unresolved\n", rt_nexthop->addr().str().c_str()); - UnresolvedIPRouteEntry* unresolved_route = - new UnresolvedIPRouteEntry(&route); + unresolved_route->set_backlink(backlink); + return XORP_ERROR; + } else { + const IPRouteEntry* found = lookup_route(route.net()); - _ip_unresolved_table.insert(make_pair(route.net(), unresolved_route)); - typename UnresolvedRouteBackLink::iterator backlink = - _ip_unresolved_nexthops.insert(make_pair(rt_nexthop->addr(), unresolved_route)); + if (found && (found->admin_distance() < route.admin_distance())) + return XORP_ERROR; - unresolved_route->set_backlink(backlink); - return XORP_ERROR; - } else { - // The EGP route is resolvable - if (found != NULL) { - // Delete the IGP route that has worse admin distance - _wining_routes.erase(found->net()); + XLOG_ASSERT(found ? (found->admin_distance() != route.admin_distance()) : true); - this->next_table()->delete_route(found); - } + // The EGP route is resolvable + if (found != NULL) { + // Delete the IGP route that has worse admin distance + _wining_routes.erase(found->net()); - debug_msg("nexthop resolved to \n %s\n", nexthop_route->str().c_str()); + this->next_table()->delete_igp_route(found); + } - // Resolve the nexthop for non-directly connected nexthops + debug_msg("nexthop resolved to \n %s\n", nexthop_route->str().c_str()); - const ResolvedIPRouteEntry* resolved_route = - resolve_and_store_route(route, nexthop_route); + // Resolve the nexthop for non-directly connected nexthops - _wining_routes.insert(resolved_route->net(), resolved_route); + const ResolvedIPRouteEntry* resolved_route = resolve_and_store_route(route, nexthop_route); - this->next_table()->add_route(*resolved_route); + _wining_routes.insert(resolved_route->net(), resolved_route); - return XORP_OK; - } - } - } else { - XLOG_FATAL("ExtIntTable::add_route called from a class that " - "isn't a component of this override table"); + this->next_table()->add_egp_route(*resolved_route); + + return XORP_OK; } +} - return XORP_OK; +template +int +ExtIntTable::add_egp_route(const IPRouteEntry& route) +{ + XLOG_ASSERT(_egp_ad_set.find(route.admin_distance()) != _egp_ad_set.end()); + debug_msg("EIT[%s]: Adding route %s\n", this->tablename().c_str(), route.str().c_str()); + + // The new route comes from the EGP table + debug_msg("route comes from EGP %s\n", route.str().c_str()); + + // Is it the best EGP route? + if (!best_egp_route(route)) + return XORP_ERROR; + + if (route.nexthop()->type() == PEER_NEXTHOP) + return add_direct_egp_route(route); + else + return add_indirect_egp_route(route); } template @@ -360,7 +374,7 @@ ExtIntTable::masked_route(const IPRouteEntry* route) typename RouteTableMap::iterator border = _all_tables.find(route->admin_distance()); const IPRouteEntry* found = NULL; XLOG_ASSERT(border != _all_tables.end()); - for (typename RouteTableMap::iterator iter = border; iter != _all_tables.end(); ++iter) { + for (typename RouteTableMap::iterator iter = ++border; iter != _all_tables.end(); ++iter) { found = iter->second->lookup_route(route->net()); if (found) return found; @@ -387,7 +401,7 @@ ExtIntTable::delete_resolved_routes(const IPRouteEntry* route) // Propagate the delete next _wining_routes.erase(found_resolved->net()); - this->next_table()->delete_route(found_resolved); + this->next_table()->delete_egp_route(found_resolved); // Now delete the local resolved copy, and reinstantiate it const IPRouteEntry* egp_parent = found_resolved->egp_parent(); @@ -399,96 +413,94 @@ ExtIntTable::delete_resolved_routes(const IPRouteEntry* route) // old pointer with the existing pointer. // That way we don't have any memory leaking. - add_route(*egp_parent); + add_egp_route(*egp_parent); found_resolved = lookup_by_igp_parent(route->net()); } } template int -ExtIntTable::delete_route(const IPRouteEntry* route) +ExtIntTable::delete_igp_route(const IPRouteEntry* route) { + XLOG_ASSERT(_igp_ad_set.find(route->admin_distance()) != _igp_ad_set.end()); + debug_msg(" called from _int_table\n"); + debug_msg("route comes from IGP %s\n", route->str().c_str()); + // If it came here, than we're certainly deleting wining IGP route - debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); - XLOG_ASSERT(this->next_table()); - - if (_igp_ad_set.find(route->admin_distance()) != _igp_ad_set.end()) { - debug_msg(" called from _int_table\n"); - // If it came here, than we're certainly deleting wining IGP route - - if (!deleting_best_igp_route(route)) - return XORP_ERROR; + if (!deleting_best_igp_route(route)) + return XORP_ERROR; - const IPRouteEntry* found_route = NULL; + const IPRouteEntry* found_route = NULL; - if (!_egp_ad_set.empty()) { - found_route = lookup_route(route->net()); + if (!_egp_ad_set.empty()) { + found_route = lookup_route(route->net()); - if (found_route != NULL) { - if (found_route->admin_distance() == route->admin_distance()) - // This route was the best route overall - found_route = NULL; - else { - // Our route wasn't the best route overall - XLOG_ASSERT(found_route->admin_distance() < route->admin_distance()); - return XORP_ERROR; - } + if (found_route != NULL) { + if (found_route->admin_distance() == route->admin_distance()) + // This route was the best route overall + found_route = NULL; + else { + // Our route wasn't the best route overall + XLOG_ASSERT(found_route->admin_distance() < route->admin_distance()); + return XORP_ERROR; } - - delete_resolved_routes(route); } - // Propagate the original delete - _wining_routes.erase(route->net()); + delete_resolved_routes(route); + } - this->next_table()->delete_route(route); + // Propagate the original delete + _wining_routes.erase(route->net()); - found_route = masked_route(route); + this->next_table()->delete_igp_route(route); - if (!_egp_ad_set.empty() && found_route) { - // It is possible the internal route had masked an external one. + found_route = masked_route(route); - // found_egp_route route is one of the wining EGP routes. - // Re-adding will overwrite it the in trie - // That's no problem because we're overwriting - // old pointer with the existing pointer. - // That way we don't have any memory leaking. - add_route(*found_route); - } + if (found_route) { + if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) + add_igp_route(*found_route); + else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) + add_egp_route(*found_route); + else + XLOG_UNREACHABLE(); + } + return XORP_OK; +} - } else if (_egp_ad_set.find(route->admin_distance()) != _egp_ad_set.end()) { - debug_msg(" called from _ext_table\n"); +template +int +ExtIntTable::delete_egp_route(const IPRouteEntry* route) +{ + XLOG_ASSERT(_egp_ad_set.find(route->admin_distance()) != _egp_ad_set.end()); + debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); + XLOG_ASSERT(this->next_table()); - if (!deleting_best_egp_route(route)) - return XORP_ERROR; + debug_msg("route comes from EGP %s\n", route->str().c_str()); - const IPRouteEntry* found_route = lookup_route(route->net()); + if (!deleting_best_egp_route(route)) + return XORP_ERROR; - if (found_route != NULL) { - if (found_route->admin_distance() == route->admin_distance()) - found_route = NULL; - else if (found_route->admin_distance() < route->admin_distance()) { - //Our route wasn't the best overall - delete_ext_route(route, false); - return XORP_OK; - } - } + const IPRouteEntry* found_route = lookup_route(route->net()); - found_route = masked_route(route); + if (found_route != NULL) { + if (found_route->admin_distance() == route->admin_distance()) + found_route = NULL; + else if (found_route->admin_distance() < route->admin_distance()) { + //Our route wasn't the best overall + delete_ext_route(found_route, false); + return XORP_OK; + } + } - if (this->delete_ext_route(route) && found_route) { - // It is possible the external route had masked an internal one. + found_route = masked_route(route); - // found_igp_route route is one of the wining IGP routes. - // Re-adding will overwrite it the in trie - // That's no problem because we're overwriting - // old pointer with the existing pointer. - // That way we don't have any memory leaking. - add_route(*found_route); - } - } else { - XLOG_FATAL("ExtIntTable::delete_route called from a class that " - "isn't a component of this override table\n"); + if (this->delete_ext_route(route) && found_route) { + if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) + add_igp_route(*found_route); + else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) + add_egp_route(*found_route); + else + XLOG_UNREACHABLE(); } return XORP_OK; @@ -517,7 +529,7 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, bool winning_rout // Propagate the delete next _wining_routes.erase(found->net()); - this->next_table()->delete_route(found); + this->next_table()->delete_egp_route(found); is_delete_propagated = true; } @@ -529,7 +541,10 @@ ExtIntTable::delete_ext_route(const IPRouteEntry* route, bool winning_rout // Propagate the delete next _wining_routes.erase(route->net()); - this->next_table()->delete_route(route); + if (_egp_ad_set.find(route->admin_distance()) != _egp_ad_set.end()) + this->next_table()->delete_egp_route(route); + else if (_igp_ad_set.find(route->admin_distance()) != _igp_ad_set.end()) + this->next_table()->delete_igp_route(route); is_delete_propagated = true; } @@ -589,7 +604,7 @@ ExtIntTable::resolve_unresolved_nexthops(const IPRouteEntry& nexthop_route // That way we don't have any memory leaking. // Reinstantiate the resolved route - add_route(*unresolved_route); + add_egp_route(*unresolved_route); rpair = nextpair; } else { @@ -705,7 +720,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) // Propagate the delete next _wining_routes.erase(found->net()); - this->next_table()->delete_route(found); + this->next_table()->delete_egp_route(found); // Now delete the local resolved copy, and reinstantiate it delete found; @@ -716,7 +731,7 @@ ExtIntTable::recalculate_nexthops(const IPRouteEntry& new_route) // old pointer with the existing pointer. // That way we don't have any memory leaking. - add_route(*egp_parent); + add_egp_route(*egp_parent); } else { debug_msg("route matched but nexthop didn't: nexthop: %s\n %s\n", (egp_parent->nexthop())->addr().str().c_str(), diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index 31a14d08d..de2461abb 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -81,7 +81,9 @@ public: * @param caller the parent table sending the new route. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(const IPRouteEntry& route); + int add_igp_route(const IPRouteEntry& route); + + int add_egp_route(const IPRouteEntry& route); /** * An delete_route request from a parent table also causes a @@ -95,7 +97,9 @@ public: * @param caller the parent table sending the delete_route. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route); + + int delete_egp_route(const IPRouteEntry* route); /** * Lookup a specific subnet. The lookup will first look in the @@ -216,6 +220,9 @@ private: void delete_resolved_routes(const IPRouteEntry* route); + int add_direct_egp_route(const IPRouteEntry& route); + int add_indirect_egp_route(const IPRouteEntry& route); + AdminDistanceSet _igp_ad_set; AdminDistanceSet _egp_ad_set; diff --git a/xorp/rib/rt_tab_origin.cc b/xorp/rib/rt_tab_origin.cc index 604a71453..f0c296016 100644 --- a/xorp/rib/rt_tab_origin.cc +++ b/xorp/rib/rt_tab_origin.cc @@ -35,18 +35,15 @@ template OriginTable::OriginTable(const string& tablename, uint16_t admin_distance, - ProtocolType protocol_type, EventLoop& eventloop) : RouteTable(tablename), _admin_distance(admin_distance), - _protocol_type(protocol_type), _eventloop(eventloop), _gen(0) { XLOG_ASSERT(admin_distance <= 255); - XLOG_ASSERT((protocol_type == IGP) || (protocol_type == EGP)); - _ip_route_table = new Trie* >(); + _ip_route_table = new RouteTrie(); _gen++; } @@ -73,22 +70,12 @@ OriginTable::add_route(IPRouteEntry* route) route->set_admin_distance(_admin_distance); - // Now add the route to this table -#ifdef DEBUG_LOGGING - debug_msg("BEFORE:\n"); - _ip_route_table->print(); -#endif - _ip_route_table->insert(route->net(), route); // Propagate to next table - if (this->next_table() != NULL) - this->next_table()->add_route(*route); + XLOG_ASSERT(this->next_table() != NULL); + this->generic_add_route(*route); -#ifdef DEBUG_LOGGING - debug_msg("AFTER:\n"); - _ip_route_table->print(); -#endif return XORP_OK; } @@ -102,14 +89,14 @@ OriginTable::delete_route(const IPNet& net) _ip_route_table->print(); #endif - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->lookup_node(net); if (iter != _ip_route_table->end()) { const IPRouteEntry* found = *iter; _ip_route_table->erase(net); // Propagate to next table - if (this->next_table() != NULL) - this->next_table()->delete_route(found); + XLOG_ASSERT(this->next_table() != NULL); + this->generic_delete_route(found); // Finally we're done, and can cleanup delete found; @@ -124,7 +111,7 @@ template void OriginTable::delete_all_routes() { - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; for (iter = _ip_route_table->begin(); iter != _ip_route_table->end(); ++iter) { @@ -143,16 +130,15 @@ OriginTable::routing_protocol_shutdown() // upstream tables to query whether trie has changed. // - Trie* >* old_ip_route_table = _ip_route_table; - _ip_route_table = new Trie* >(); + RouteTrie* old_ip_route_table = _ip_route_table; + _ip_route_table = new RouteTrie(); // // Pass our entire routing table into a DeletionTable, which will // handle the background deletion task. The DeletionTable will // plumb itself in. // - new DeletionTable("Delete(" + this->tablename() + ")", - this, old_ip_route_table, _eventloop); + this->allocate_deletion_table(old_ip_route_table); } template @@ -162,7 +148,7 @@ OriginTable::lookup_route(const IPNet& net) const debug_msg("------------------\nlookup_route in table %s\n", this->tablename().c_str()); debug_msg("OriginTable: Looking up route %s\n", net.str().c_str()); - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->lookup_node(net); return (iter == _ip_route_table->end()) ? NULL : *iter; } @@ -176,7 +162,7 @@ OriginTable::lookup_route(const A& addr) const debug_msg("OriginTable (%u): Looking up route for addr %s\n", XORP_UINT_CAST(_admin_distance), addr.str().c_str()); - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->find(addr); if (iter == _ip_route_table->end()) { debug_msg("No match found\n"); @@ -189,7 +175,7 @@ RouteRange* OriginTable::lookup_route_range(const A& addr) const { const IPRouteEntry* route; - typename Trie* >::iterator iter; + typename RouteTrie::iterator iter; iter = _ip_route_table->find(addr); route = (iter == _ip_route_table->end()) ? NULL : *iter; @@ -213,7 +199,7 @@ OriginTable::str() const string s; s = "-------\nOriginTable: " + this->tablename() + "\n" + - ( _protocol_type == IGP ? "IGP\n" : "EGP\n" ) ; + ( this->protocol_type() == IGP ? "IGP\n" : "EGP\n" ) ; if (this->next_table() == NULL) s += "no next table\n"; else @@ -221,8 +207,29 @@ OriginTable::str() const return s; } +template +void +TypedOriginTable::allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie) +{ + new TypedDeletionTable("Delete(" + this->tablename() + ")", this, + ip_route_trie, this->_eventloop); +} + +template +void +TypedOriginTable::allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie) +{ + new TypedDeletionTable("Delete(" + this->tablename() + ")", this, + ip_route_trie, this->_eventloop); +} + template class OriginTable; typedef OriginTable IPv4OriginTable; template class OriginTable; typedef OriginTable IPv6OriginTable; + +template class TypedOriginTable; +template class TypedOriginTable; +template class TypedOriginTable; +template class TypedOriginTable; diff --git a/xorp/rib/rt_tab_origin.hh b/xorp/rib/rt_tab_origin.hh index 5e0c8e715..f150b7bc6 100644 --- a/xorp/rib/rt_tab_origin.hh +++ b/xorp/rib/rt_tab_origin.hh @@ -42,7 +42,7 @@ template class OriginTable : public RouteTable { public: - typedef Trie*> RouteContainer; + typedef Trie*> RouteTrie; public: /** @@ -59,12 +59,12 @@ public: * @param eventloop the main event loop. */ OriginTable(const string& tablename, uint16_t admin_distance, - ProtocolType protocol_type, EventLoop& eventloop); + EventLoop& eventloop); /** * OriginTable destructor. */ - ~OriginTable(); + virtual ~OriginTable(); /** * Add a route to the OriginTable. The route must not already be @@ -77,9 +77,10 @@ public: * @param route the pointer to route entry to be added. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int add_route(IPRouteEntry* route); + virtual int add_route(IPRouteEntry* route); - int add_route(const IPRouteEntry&) { return XORP_ERROR; } + int add_egp_route(const IPRouteEntry&) { return XORP_ERROR; }; + int add_igp_route(const IPRouteEntry&) { return XORP_ERROR; }; /** * Delete a route from the OriginTable. @@ -87,9 +88,10 @@ public: * @param net the subnet of the route entry to be deleted. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_route(const IPNet& net); + virtual int delete_route(const IPNet& net); - int delete_route(const IPRouteEntry*) { return XORP_ERROR; } + int delete_igp_route(const IPRouteEntry*) { return XORP_ERROR; }; + int delete_egp_route(const IPRouteEntry*) { return XORP_ERROR; }; /** * Delete all the routes that are in this OriginTable. The @@ -149,7 +151,7 @@ public: /** * @return the routing protocol type (@ref ProtocolType). */ - int protocol_type() const { return _protocol_type; } + virtual int protocol_type() const = 0; /** * @return the table type (@ref TableType). @@ -175,16 +177,57 @@ public: /** * Get the trie. */ - const RouteContainer& route_container() const; + const RouteTrie& route_container() const; -private: +protected: uint16_t _admin_distance; // 0 .. 255 - ProtocolType _protocol_type; // IGP or EGP + // EventLoop& _eventloop; - RouteContainer* _ip_route_table; + RouteTrie* _ip_route_table; uint32_t _gen; + + virtual int generic_delete_route(const IPRouteEntry*) = 0; + virtual int generic_add_route(const IPRouteEntry&) = 0; + virtual void allocate_deletion_table(RouteTrie* ip_route_trie) = 0; }; +template +class TypedOriginTable { }; + +template +class TypedOriginTable : public OriginTable { +public: + TypedOriginTable(const string& tablename, uint16_t admin_distance, EventLoop& eventloop) : + OriginTable(tablename, admin_distance, eventloop), _protocol_type(IGP) {} + ~TypedOriginTable() {} + + int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_igp_route(route); } + int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_igp_route(route); } + + int protocol_type() const { return _protocol_type;} + +protected: + void allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie); + + ProtocolType _protocol_type; // IGP or EGP +}; + +template +class TypedOriginTable : public OriginTable { +public: + TypedOriginTable(const string& tablename, uint16_t admin_distance, EventLoop& eventloop) : + OriginTable(tablename, admin_distance, eventloop), _protocol_type(EGP) {} + ~TypedOriginTable() {} + + int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_egp_route(route); } + int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_egp_route(route); } + + int protocol_type() const { return _protocol_type;} +protected: + void allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie); + + ProtocolType _protocol_type; // IGP or EGP +}; template inline uint32_t @@ -201,7 +244,7 @@ OriginTable::route_count() const } template -inline const typename OriginTable::RouteContainer& +inline const typename OriginTable::RouteTrie& OriginTable::route_container() const { return *_ip_route_table; diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index 39ee5485d..7e432134b 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -58,8 +58,8 @@ PolicyConnectedTable::~PolicyConnectedTable () } template -int -PolicyConnectedTable::add_route(const IPRouteEntry& route) +void +PolicyConnectedTable::generic_add_route(const IPRouteEntry& route) { debug_msg("[RIB] PolicyConnectedTable ADD ROUTE: %s\n", route.str().c_str()); @@ -69,41 +69,68 @@ PolicyConnectedTable::add_route(const IPRouteEntry& route) _route_table.insert(original->net(), original); do_filtering(*original); +} - RouteTable* next = this->next_table(); - XLOG_ASSERT(next); +template +int +PolicyConnectedTable::add_igp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); + + XLOG_ASSERT(this->next_table()); // Send the possibly modified route down - return next->add_route(*original); + return this->next_table()->add_igp_route(route); } template int -PolicyConnectedTable::delete_route(const IPRouteEntry* route) +PolicyConnectedTable::add_egp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); + + XLOG_ASSERT(this->next_table()); + + // Send the possibly modified route down + return this->next_table()->add_egp_route(route); +} + +template +void +PolicyConnectedTable::generic_delete_route(const IPRouteEntry* route) { XLOG_ASSERT(route != NULL); debug_msg("[RIB] PolicyConnectedTable DELETE ROUTE: %s\n", route->str().c_str()); - // delete our copy - typename RouteContainer::iterator i; - i = _route_table.lookup_node(route->net()); - - XLOG_ASSERT(i != _route_table.end()); + XLOG_ASSERT(_route_table.lookup_node(route->net()) != _route_table.end()); - IPRouteEntry* re = *i; _route_table.erase(route->net()); - RouteTable* next = this->next_table(); - XLOG_ASSERT(next); + do_filtering(*(const_cast* >(route))); +} - do_filtering(*re); +template +int +PolicyConnectedTable::delete_igp_route(const IPRouteEntry* route) +{ + this->generic_delete_route(route); + XLOG_ASSERT(this->next_table()); // propagate the delete - int ret = next->delete_route(re); + return this->next_table()->delete_igp_route(route); +} - return ret; +template +int +PolicyConnectedTable::delete_egp_route(const IPRouteEntry* route) +{ + this->generic_delete_route(route); + + XLOG_ASSERT(this->next_table()); + // propagate the delete + return this->next_table()->delete_egp_route(route); } template diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index e9bcd18dc..5668cf7c7 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -52,8 +52,10 @@ public: PolicyConnectedTable(RouteTable* parent, PolicyFilters& pfs); ~PolicyConnectedTable(); - int add_route(const IPRouteEntry& route); - int delete_route(const IPRouteEntry* route); + int add_igp_route(const IPRouteEntry& route); + int delete_igp_route(const IPRouteEntry* route); + int add_egp_route(const IPRouteEntry& route); + int delete_egp_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; @@ -78,6 +80,9 @@ private: */ void do_filtering(IPRouteEntry& r); + void generic_add_route(const IPRouteEntry& route); + void generic_delete_route(const IPRouteEntry* route); + typedef Trie* > RouteContainer; diff --git a/xorp/rib/rt_tab_pol_redist.cc b/xorp/rib/rt_tab_pol_redist.cc index 31a6805e8..e6d721b4f 100644 --- a/xorp/rib/rt_tab_pol_redist.cc +++ b/xorp/rib/rt_tab_pol_redist.cc @@ -56,8 +56,8 @@ PolicyRedistTable::PolicyRedistTable(RouteTable* parent, XrlRouter& rtr, } template -int -PolicyRedistTable::add_route(const IPRouteEntry& route) +void +PolicyRedistTable::generic_add_route(const IPRouteEntry& route) { debug_msg("[RIB] PolicyRedistTable ADD ROUTE: %s\n", route.str().c_str()); @@ -69,16 +69,33 @@ PolicyRedistTable::add_route(const IPRouteEntry& route) // if there are any, then redistribute if (!protos.empty()) add_redist(route, protos); +} + +template +int +PolicyRedistTable::add_igp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); - RouteTable* next = this->next_table(); - XLOG_ASSERT(next != NULL); + XLOG_ASSERT(this->next_table() != NULL); - return next->add_route(route); + return this->next_table()->add_igp_route(route); } template int -PolicyRedistTable::delete_route(const IPRouteEntry* route) +PolicyRedistTable::add_egp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); + + XLOG_ASSERT(this->next_table() != NULL); + + return this->next_table()->add_egp_route(route); +} + +template +void +PolicyRedistTable::generic_delete_route(const IPRouteEntry* route) { XLOG_ASSERT(route != NULL); @@ -92,11 +109,28 @@ PolicyRedistTable::delete_route(const IPRouteEntry* route) // if there are any, stop redistributing if (!protos.empty()) del_redist(*route, protos); +} + +template +int +PolicyRedistTable::delete_igp_route(const IPRouteEntry* route) +{ + this->generic_delete_route(route); + + XLOG_ASSERT(this->next_table() != NULL); + + return this->next_table()->delete_igp_route(route); +} + +template +int +PolicyRedistTable::delete_egp_route(const IPRouteEntry* route) +{ + this->generic_delete_route(route); - RouteTable* next = this->next_table(); - XLOG_ASSERT(next != NULL); + XLOG_ASSERT(this->next_table() != NULL); - return next->delete_route(route); + return this->next_table()->delete_egp_route(route); } template diff --git a/xorp/rib/rt_tab_pol_redist.hh b/xorp/rib/rt_tab_pol_redist.hh index eaf27802c..4216b176f 100644 --- a/xorp/rib/rt_tab_pol_redist.hh +++ b/xorp/rib/rt_tab_pol_redist.hh @@ -128,8 +128,11 @@ public: PolicyRedistTable(RouteTable* parent, XrlRouter& rtr, PolicyRedistMap&, bool multicast); - int add_route(const IPRouteEntry& router); - int delete_route(const IPRouteEntry* route); + int add_igp_route(const IPRouteEntry& router); + int add_egp_route(const IPRouteEntry& router); + int delete_igp_route(const IPRouteEntry* route); + int delete_egp_route(const IPRouteEntry* route); + const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; RouteRange* lookup_route_range(const A& addr) const; @@ -190,6 +193,9 @@ private: */ void del_redist(const IPRouteEntry& route, const string& proto); + void generic_add_route(const IPRouteEntry& router); + void generic_delete_route(const IPRouteEntry* route); + RouteTable* _parent; diff --git a/xorp/rib/rt_tab_redist.cc b/xorp/rib/rt_tab_redist.cc index 1cec7915b..acf92c857 100644 --- a/xorp/rib/rt_tab_redist.cc +++ b/xorp/rib/rt_tab_redist.cc @@ -398,8 +398,8 @@ RedistTable::redistributor(const string& name) } template -int -RedistTable::add_route(const IPRouteEntry& route) +void +RedistTable::generic_add_route(const IPRouteEntry& route) { typename RouteIndex::iterator rci = _rt_index.find(route.net()); XLOG_ASSERT(rci == _rt_index.end()); @@ -412,15 +412,33 @@ RedistTable::add_route(const IPRouteEntry& route) i++; // XXX for safety increment iterator before prodding output r->redist_event().did_add(route); } +} + +template +int +RedistTable::add_igp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); if (this->next_table()) - return this->next_table()->add_route(route); + return this->next_table()->add_igp_route(route); return XORP_OK; } template int -RedistTable::delete_route(const IPRouteEntry* r) +RedistTable::add_egp_route(const IPRouteEntry& route) +{ + this->generic_add_route(route); + + if (this->next_table()) + return this->next_table()->add_egp_route(route); + return XORP_OK; +} + +template +void +RedistTable::generic_delete_route(const IPRouteEntry* r) { const IPRouteEntry& route = *r; @@ -448,9 +466,28 @@ RedistTable::delete_route(const IPRouteEntry* r) i++; // XXX for safety increment iterator before prodding output r->redist_event().did_delete(route); } +} + +template +int +RedistTable::delete_igp_route(const IPRouteEntry* r) +{ + this->generic_delete_route(r); + + if (this->next_table()) + return this->next_table()->delete_igp_route(r); + + return XORP_OK; +} + +template +int +RedistTable::delete_egp_route(const IPRouteEntry* r) +{ + this->generic_delete_route(r); if (this->next_table()) - return this->next_table()->delete_route(r); + return this->next_table()->delete_egp_route(r); return XORP_OK; } diff --git a/xorp/rib/rt_tab_redist.hh b/xorp/rib/rt_tab_redist.hh index 2371cd042..353bb303b 100644 --- a/xorp/rib/rt_tab_redist.hh +++ b/xorp/rib/rt_tab_redist.hh @@ -110,8 +110,11 @@ public: // // Standard RouteTable methods // - int add_route(const IPRouteEntry& route); - int delete_route(const IPRouteEntry* route); + int add_igp_route(const IPRouteEntry& route); + int add_egp_route(const IPRouteEntry& route); + int delete_igp_route(const IPRouteEntry* route); + int delete_egp_route(const IPRouteEntry* route); + const IPRouteEntry* lookup_route(const IPNet& net) const { return _parent->lookup_route(net); } const IPRouteEntry* lookup_route(const A& addr) const { return _parent->lookup_route(addr); } RouteRange* lookup_route_range(const A& addr) const { return _parent->lookup_route_range(addr); } @@ -134,6 +137,9 @@ protected: // table has been plumbed in. RouteIndex _rt_index; list*> _outputs; + + void generic_add_route(const IPRouteEntry& route); + void generic_delete_route(const IPRouteEntry* route); }; diff --git a/xorp/rib/rt_tab_register.cc b/xorp/rib/rt_tab_register.cc index 3369c5f50..77c138960 100644 --- a/xorp/rib/rt_tab_register.cc +++ b/xorp/rib/rt_tab_register.cc @@ -248,40 +248,63 @@ RegisterTable::notify_relevant_modules(bool add, return XORP_ERROR; } +template +void +RegisterTable::generic_add_route(const IPRouteEntry& route) +{ + notify_relevant_modules(true /* it's an add */, route); +} + template int -RegisterTable::add_route(const IPRouteEntry& route) +RegisterTable::add_igp_route(const IPRouteEntry& route) { debug_msg("RegisterTable::add_route %s\n", route.str().c_str()); - debug_msg("Before:\n"); - print(); + XLOG_ASSERT(this->next_table() != NULL); + this->next_table()->add_igp_route(route); - if (this->next_table() != NULL) - this->next_table()->add_route(route); + this->generic_add_route(route); + return XORP_OK; +} - notify_relevant_modules(true /* it's an add */, route); +template +int +RegisterTable::add_egp_route(const IPRouteEntry& route) +{ + debug_msg("RegisterTable::add_route %s\n", route.str().c_str()); + XLOG_ASSERT(this->next_table() != NULL); + this->next_table()->add_egp_route(route); - debug_msg("Add route called on register table %s\n", - this->tablename().c_str()); + this->generic_add_route(route); return XORP_OK; } +template +void +RegisterTable::generic_delete_route(const IPRouteEntry* route) +{ + notify_relevant_modules(false /* it's a delete */, *route); +} + template int -RegisterTable::delete_route(const IPRouteEntry* route) +RegisterTable::delete_igp_route(const IPRouteEntry* route) { - debug_msg("[REGT]: delete_route: %p\n%s\n", route, route->str().c_str()); - debug_msg("Before:\n"); - print(); + XLOG_ASSERT(this->next_table() != NULL); + this->next_table()->delete_igp_route(route); - if (this->next_table() != NULL) - this->next_table()->delete_route(route); + this->generic_delete_route(route); + return XORP_OK; +} - notify_relevant_modules(false /* it's a delete */, *route); - debug_msg("Delete route called on register table\n"); - debug_msg("After:\n"); - print(); +template +int +RegisterTable::delete_egp_route(const IPRouteEntry* route) +{ + XLOG_ASSERT(this->next_table() != NULL); + this->next_table()->delete_egp_route(route); + this->generic_delete_route(route); return XORP_OK; } @@ -307,7 +330,9 @@ RegisterTable::add_registration(const IPNet& net, RouteRegister* rr; if (iter == _ipregistry.end()) { // No existing registry for this subnet +#ifdef DEBUG_LOGGING print(); +#endif if (route != NULL) { debug_msg("[REGT] Add registration for net %s " "route %s module %s\n", @@ -343,7 +368,9 @@ RegisterTable::add_registration(const IPNet& net, rr = new RouteRegister(net, route, module); _ipregistry.insert(net, rr); +#ifdef DEBUG_LOGGING print(); +#endif } else { rr = *iter; rr->add_registrant(module); @@ -462,19 +489,19 @@ RegisterTable::str() const return oss.str(); } +#ifdef DEBUG_LOGGING template inline void RegisterTable::print() { -#ifdef DEBUG_LOGGING debug_msg("%s\n", str().c_str()); typename Trie* >::iterator iter; for (iter = _ipregistry.begin(); iter != _ipregistry.end(); ++iter) { debug_msg("----\n"); debug_msg("%s\n", (*iter)->str().c_str()); } -#endif } +#endif template void diff --git a/xorp/rib/rt_tab_register.hh b/xorp/rib/rt_tab_register.hh index 5680ad38e..ea9330c4a 100644 --- a/xorp/rib/rt_tab_register.hh +++ b/xorp/rib/rt_tab_register.hh @@ -288,29 +288,11 @@ public: */ ~RegisterTable(); - /** - * Add a new route to the RIB. This will be propagated downstream - * to the next table, but may also cause the RegisterTable to - * invalidate a RouteRegister because the new route overlaps an - * existing registration. - * - * @param route the new route. - * @param caller this must be this table's parent table. - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int add_route(const IPRouteEntry& route); + int add_igp_route(const IPRouteEntry& route); + int add_egp_route(const IPRouteEntry& route); - /** - * Delete a route from the RIB. This will be propagated - * downstream to the next table, but may also cause the - * RegisterTable to invalidate a RouteRegister referencing this - * route. - * - * @param route the route being deleted. - * @param caller this must be this table's parent table. - * @return XORP_OK on success, otherwise XORP_ERROR. - */ - int delete_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route); + int delete_egp_route(const IPRouteEntry* route); /** * Lookup a route in the RIB. This request will be propagated to @@ -352,7 +334,9 @@ public: * Print the contents of this RegisterTable as a string for * debugging purposes. */ +#ifdef DEBUG_LOGGING void print(); +#endif // Stuff specific to a Register Table @@ -410,6 +394,24 @@ private: void notify_route_changed(typename Trie* >::iterator trie_iter, const IPRouteEntry& changed_route); + /** + * Invalidate a RouteRegister referencing this + * route. + * + * @param route the new route. + * @return XORP_OK on success, otherwise XORP_ERROR. + */ + void generic_add_route(const IPRouteEntry& route); + + /** + * Invalidate a RouteRegister referencing this + * route. + * + * @param route the route being deleted. + * @return XORP_OK on success, otherwise XORP_ERROR. + */ + void generic_delete_route(const IPRouteEntry* route); + map _module_names; Trie* > _ipregistry; RouteTable* _parent; diff --git a/xorp/rib/tests/rt_tab_expect.hh b/xorp/rib/tests/rt_tab_expect.hh index 4da385d28..93ec936f1 100644 --- a/xorp/rib/tests/rt_tab_expect.hh +++ b/xorp/rib/tests/rt_tab_expect.hh @@ -51,7 +51,11 @@ public: void expect_add(const IPRouteEntry& route); void expect_delete(const IPRouteEntry& route); + int add_igp_route(const IPRouteEntry& route) { return this->add_route(route); } + int add_egp_route(const IPRouteEntry& route) { return this->add_route(route); } int add_route(const IPRouteEntry& route); + int delete_igp_route(const IPRouteEntry* route) { return this->delete_route(route); } + int delete_egp_route(const IPRouteEntry* route) { return this->delete_route(route); } int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; diff --git a/xorp/rib/tests/test_deletion.cc b/xorp/rib/tests/test_deletion.cc index eaf39d374..febbf444c 100644 --- a/xorp/rib/tests/test_deletion.cc +++ b/xorp/rib/tests/test_deletion.cc @@ -44,7 +44,7 @@ main(int /* argc */, char* argv[]) xlog_add_default_output(); xlog_start(); EventLoop eventloop; - OriginTable ot("origin", 1, IGP, eventloop); + TypedOriginTable ot("origin", 1, eventloop); ExpectTable dt("expect", &ot); Vif tmp_vif1("vif1"); diff --git a/xorp/rib/tests/test_redist.cc b/xorp/rib/tests/test_redist.cc index dfd1fb824..9c076c3cb 100644 --- a/xorp/rib/tests/test_redist.cc +++ b/xorp/rib/tests/test_redist.cc @@ -273,7 +273,8 @@ test_deterministic() EventLoop e; // Create an OriginTable - OriginTable origin("static", 1, IGP, e); + TypedOriginTable typed_origin("static", 1, e); + OriginTable& origin = typed_origin; IPPeerNextHop nh("22.0.0.1"); Protocol protocol("static", IGP, 1); Vif tmp_vif("vif0"); From 82a4d14f6cb2158bdcaa8db57a9debe034e4e692 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 18:00:53 +0200 Subject: [PATCH 27/38] xorp: libxorp: Add MemoryPool class More efficient memory handling. --- xorp/libxorp/memory_pool.hh | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 xorp/libxorp/memory_pool.hh diff --git a/xorp/libxorp/memory_pool.hh b/xorp/libxorp/memory_pool.hh new file mode 100644 index 000000000..a84e4c7c1 --- /dev/null +++ b/xorp/libxorp/memory_pool.hh @@ -0,0 +1,100 @@ +// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- +// vim:set sts=4 ts=8: + +// Copyright (c) 2012 XORP, Inc and Others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License, Version 2, June +// 1991 as published by the Free Software Foundation. Redistribution +// and/or modification of this program under the terms of any other +// version of the GNU General Public License is not permitted. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, +// see the GNU General Public License, Version 2, a copy of which can be +// found in the XORP LICENSE.gpl file. +// +// XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; +// http://xorp.net + +#ifndef _LIBXORP_MEMORY_POOL_HH_ +#define _LIBXORP_MEMORY_POOL_HH_ + +#include "xorp.h" + +template +class MemoryPool : public NONCOPYABLE { +public: + MemoryPool(); + ~MemoryPool(); + + //Allocate element of type T from free list + void* alloc(); + + // Return element to the free list + void free(void* doomed); +private: + // next element on the free list + MemoryPool* _next; + + // Add free elements to the list + void expand_free_list(); + + size_t _size; +}; + +template +MemoryPool::MemoryPool() : + _size((sizeof(T) > sizeof(MemoryPool)) ? sizeof(T) :sizeof(MemoryPool)) +{ + expand_free_list(); +} + +template +MemoryPool::~MemoryPool() +{ + for (MemoryPool *nextPtr = _next; nextPtr != NULL; nextPtr = _next) { + _next = _next->_next; + delete [] reinterpret_cast(nextPtr); + } +} + +template +inline void* +MemoryPool::alloc() +{ + if (!_next) + expand_free_list(); + + MemoryPool* head = _next; + _next = head->_next; + return head; +} + +template +inline void +MemoryPool::free(void* doomed) +{ + MemoryPool* head = reinterpret_cast* >(doomed); + + head->_next = _next; + _next = head; +} + +template +inline void +MemoryPool::expand_free_list() +{ + // We must allocate object large enough to contain the next pointer + MemoryPool* runner = reinterpret_cast* >(new char[_size]); + + _next = runner; + for (size_t i = 0; i < EXPANSION_SIZE; ++i) { + runner->_next = reinterpret_cast* >(new char[_size]); + runner = runner->_next; + } + runner->_next = NULL; +} + +#endif /* MEMORY_POOL_HH_ */ From 21be5fef8dcfdbfc2cdfa51eb11d33e104901e7d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 18:01:37 +0200 Subject: [PATCH 28/38] xorp: Use MemoryPool for NextHops and IPRouteEntrys --- xorp/libxorp/nexthop.cc | 46 +++++++++++++++++++++++++ xorp/libxorp/nexthop.hh | 11 ++++-- xorp/rib/route.cc | 75 +++++++++++++++++++++++++++++++++++++++++ xorp/rib/route.hh | 13 +++++++ 4 files changed, 143 insertions(+), 2 deletions(-) diff --git a/xorp/libxorp/nexthop.cc b/xorp/libxorp/nexthop.cc index 1825789c1..15c56f177 100644 --- a/xorp/libxorp/nexthop.cc +++ b/xorp/libxorp/nexthop.cc @@ -69,6 +69,29 @@ IPPeerNextHop::IPPeerNextHop(const A& from_ipaddr) { } +template +void* +IPPeerNextHop::operator new(size_t/* size*/) +{ + return memory_pool().alloc(); +} + +template +void +IPPeerNextHop::operator delete(void* ptr) +{ + memory_pool().free(ptr); +} + +template +inline +MemoryPool >& +IPPeerNextHop::memory_pool() +{ + static MemoryPool > mp; + return mp; +} + template IPEncapsNextHop::IPEncapsNextHop(const A& from_ipaddr) : IPNextHop(from_ipaddr) @@ -81,6 +104,29 @@ IPExternalNextHop::IPExternalNextHop(const A& from_ipaddr) { } +template +void* +IPExternalNextHop::operator new(size_t/* size*/) +{ + return memory_pool().alloc(); +} + +template +void +IPExternalNextHop::operator delete(void* ptr) +{ + memory_pool().free(ptr); +} + +template +inline +MemoryPool >& +IPExternalNextHop::memory_pool() +{ + static MemoryPool > mp; + return mp; +} + template DiscardNextHop::DiscardNextHop() : IPNextHop(A::ZERO()) diff --git a/xorp/libxorp/nexthop.hh b/xorp/libxorp/nexthop.hh index 87470beb0..bffec8255 100644 --- a/xorp/libxorp/nexthop.hh +++ b/xorp/libxorp/nexthop.hh @@ -28,6 +28,7 @@ #include "ipv4.hh" #include "ipv6.hh" #include "ipvx.hh" +#include "memory_pool.hh" // NextHop is a generic next hop object. // PeerNextHop is for next hops that are local peers. @@ -182,8 +183,11 @@ public: IPPeerNextHop* get_copy() { return new IPPeerNextHop(*this); } -private: + void* operator new(size_t size); + void operator delete(void* ptr); +private: + static MemoryPool >& memory_pool(); }; typedef IPPeerNextHop IPv4PeerNextHop; @@ -263,8 +267,11 @@ public: IPExternalNextHop* get_copy() { return new IPExternalNextHop(*this); } -private: + void* operator new(size_t size); + void operator delete(void* ptr); +private: + static MemoryPool >& memory_pool(); }; typedef IPExternalNextHop IPv4ExternalNextHop; diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index 249781e6c..30df58df6 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -107,6 +107,75 @@ IPRouteEntry::str() const string(" PolicyTags: ") + RouteEntry::_policytags.str(); } +template +void* +IPRouteEntry::operator new(size_t/* size*/) +{ + return memory_pool().alloc(); +} + +template +void +IPRouteEntry::operator delete(void* ptr) +{ + memory_pool().free(ptr); +} + +template +inline +MemoryPool >& +IPRouteEntry::memory_pool() +{ + static MemoryPool > mp; + return mp; +} + +template +void* +ResolvedIPRouteEntry::operator new(size_t/* size*/) +{ + return memory_pool().alloc(); +} + +template +void +ResolvedIPRouteEntry::operator delete(void* ptr) +{ + memory_pool().free(ptr); +} + +template +inline +MemoryPool >& +ResolvedIPRouteEntry::memory_pool() +{ + static MemoryPool > mp; + return mp; +} + +template +void* +UnresolvedIPRouteEntry::operator new(size_t/* size*/) +{ + return memory_pool().alloc(); +} + +template +void +UnresolvedIPRouteEntry::operator delete(void* ptr) +{ + memory_pool().free(ptr); +} + +template +inline +MemoryPool >& +UnresolvedIPRouteEntry::memory_pool() +{ + static MemoryPool > mp; + return mp; +} + template IPRouteEntry& IPRouteEntry::operator=(const IPRouteEntry& r) { if (this == &r) @@ -139,3 +208,9 @@ ResolvedIPRouteEntry& ResolvedIPRouteEntry::operator=(const ResolvedIPRout template class IPRouteEntry; template class IPRouteEntry; +template class ResolvedIPRouteEntry; +template class ResolvedIPRouteEntry; + +template class UnresolvedIPRouteEntry; +template class UnresolvedIPRouteEntry; + diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index 5ce968634..460a4f447 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -233,8 +233,12 @@ public: * @return a human readable representation of the route entry. */ string str() const; + void* operator new(size_t size); + void operator delete(void* ptr); protected: IPNextHop* _nexthop; +private: + static MemoryPool >& memory_pool(); }; typedef IPRouteEntry IPv4RouteEntry; @@ -322,7 +326,12 @@ public: */ typename RouteBackLink::iterator backlink() const { return _backlink; } + void* operator new(size_t size); + void operator delete(void* ptr); + private: + static MemoryPool >& memory_pool(); + const IPRouteEntry* _resolving_parent; const IPRouteEntry* _egp_parent; @@ -389,7 +398,11 @@ public: */ typename RouteBackLink::iterator backlink() const { return _backlink; } + void* operator new(size_t size); + void operator delete(void* ptr); + private: + static MemoryPool >& memory_pool(); // // _backlink is used for removing the corresponding entry from the // RouteTable's map that is indexed by the unresolved nexthop. From 7bf3039090a6f77d67ac9eb532dba97da6472788 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 18:05:51 +0200 Subject: [PATCH 29/38] xorp: rib: Make use of ResolvedIPRouteEntry by augmenting constructor arguments that it takes --- xorp/rib/route.hh | 7 +++---- xorp/rib/rt_tab_extint.cc | 10 +--------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index 460a4f447..b59073fad 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -278,11 +278,10 @@ public: * nexthop in the egp_parent into a local nexthop. * @param egp_parent the orginal route entry with a non-local nexthop. */ - ResolvedIPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, - Protocol* protocol, uint32_t metric, - const IPRouteEntry* resolving_parent, + ResolvedIPRouteEntry(const IPRouteEntry* resolving_parent, const IPRouteEntry* egp_parent) - : IPRouteEntry(net, vif, nexthop, protocol, metric, PolicyTags()), + : IPRouteEntry(egp_parent->net(), resolving_parent->vif(), + resolving_parent->nexthop()->get_copy(), egp_parent->protocol(), egp_parent->metric(), PolicyTags()), _resolving_parent(resolving_parent), _egp_parent(egp_parent) { } diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 049aaaca1..2085cc656 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -309,15 +309,7 @@ ExtIntTable::resolve_and_store_route(const IPRouteEntry& route, const IPRouteEntry* nexthop_route) { ResolvedIPRouteEntry* resolved_route; - resolved_route = new ResolvedIPRouteEntry(route.net(), - nexthop_route->vif(), - // IPRouteEntry will free memory for the nexthop. - // That's why we pass copy of NextHop pointer - // instead of pointer! - nexthop_route->nexthop()->get_copy(), - route.protocol(), - route.metric(), - nexthop_route, + resolved_route = new ResolvedIPRouteEntry(nexthop_route, &route); resolved_route->set_admin_distance(route.admin_distance()); _ip_resolved_table.insert(resolved_route->net(), resolved_route); From 8a8f85473e0721d6e0751915ec2b0891a7dad8d9 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 18:07:51 +0200 Subject: [PATCH 30/38] xorp: rib: Delete unnecessary functions --- xorp/rib/rib.cc | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index a36a5dabe..9a0bbd1f2 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -31,30 +31,6 @@ #include "rib.hh" -// ---------------------------------------------------------------------------- -// Inline table utility methods - -template -struct table_has_name { - table_has_name(const string& name) : _n(name) {} - bool operator() (const RouteTable* rt) const { - return rt->tablename() == _n; - } -private: - const string& _n; -}; - -template -struct table_has_name_and_type { - table_has_name_and_type(const string& name) : _n(name) {} - bool operator() (const RouteTable* rt) const { - const T* t = dynamic_cast(rt); - return (t != 0) && (rt->tablename() == _n); - } -private: - const string& _n; -}; - template inline OriginTable* RIB::find_origin_table(const string& tablename) From e17c2971e8356a2554a988e6346074784965a622 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Mon, 9 Jul 2012 18:31:15 +0200 Subject: [PATCH 31/38] xorp: Enable user to disable assertions --- xorp/SConstruct | 16 ++++++++++++++++ xorp/libxorp/xlog.h | 6 +++++- xorp/site_scons/config/allconfig.py | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/xorp/SConstruct b/xorp/SConstruct index 96ee5f6ca..5cc2972e0 100644 --- a/xorp/SConstruct +++ b/xorp/SConstruct @@ -83,6 +83,7 @@ vars.AddVariables( BoolVariable('disable_otherlogs', 'Force disable other logs', False), BoolVariable('disable_profile', 'Disable Xorp Profiler feature', False), BoolVariable('disable_werror', 'Disable -Werror compiler flag', False), + BoolVariable('disable_assert', 'Force disabling assertions - use with caution', False), BoolVariable('enable_lex_hack', 'Works around lex/yacc issues on FreeBSD', False), BoolVariable('enable_builddirrun', 'Enable Xorp to run from BUILD_DIR', False), BoolVariable('enable_boost', 'Use BOOST', False), @@ -298,6 +299,7 @@ print 'Disable fatal logs : ', env['disable_fatallogs'] print 'Disable info logs : ', env['disable_infologs'] print 'Disable assert logs : ', env['disable_assertlogs'] print 'Disable other logs : ', env['disable_otherlogs'] +print 'Disable assert: ', env['disable_assert'] env['CONFIGURELOG'] = str(builddir) + os.sep + 'config.log' @@ -604,6 +606,20 @@ if tst and not ((tst == "no") or (tst == "false")): else: env['disable_otherlogs'] = False +tst = ARGUMENTS.get('disable_assert', False) +if tst and not ((tst == "no") or (tst == "false")): + env['disable_assert'] = True + env['disable_werror'] = True + env['disable_otherlogs'] = True + env['disable_assertlogs'] = True + env['disable_infologs'] = True + env['disable_fatallogs'] = True + env['disable_tracelogs'] = True + env['disable_errorlogs'] = True + env['disable_warninglogs'] = True +else: + env['disable_assert'] = False + ########## start configure magic if env.has_key('LIBS'): diff --git a/xorp/libxorp/xlog.h b/xorp/libxorp/xlog.h index 525b57952..352a84c2c 100644 --- a/xorp/libxorp/xlog.h +++ b/xorp/libxorp/xlog.h @@ -345,6 +345,9 @@ void _xlog_with_level(int log_level, #define XLOG_RTRMGR_ONLY_NO_PREAMBLE(fmt...) do{}while(0) #endif +#ifdef NO_ASSERT +#define XLOG_ASSERT(assertion) do {} while(0) +#else #ifdef L_ASSERT /** * XORP replacement for assert(3). @@ -362,7 +365,8 @@ void _xlog_with_level(int log_level, } while (0) #else # define XLOG_ASSERT(assertion) assert(assertion) -#endif +#endif /* L_ASSERT */ +#endif /* NO_ASSERT */ /** * A marker that can be used to indicate code that should never be executed. diff --git a/xorp/site_scons/config/allconfig.py b/xorp/site_scons/config/allconfig.py index 125ffda63..0624b472d 100644 --- a/xorp/site_scons/config/allconfig.py +++ b/xorp/site_scons/config/allconfig.py @@ -498,6 +498,8 @@ def DoAllConfig(env, conf, host_os): conf.Define('L_OTHER') if not (env.has_key('disable_fatallogs') and env['disable_fatallogs']): conf.Define('L_FATAL') + if (env.has_key('disable_assert') and env['disable_assert']): + conf.Define('NO_ASSERT') ########## # v6 stack From 005da8adb8dfc9b76ff0fa997de73be4be843b8b Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 10 Jul 2012 17:11:13 +0200 Subject: [PATCH 32/38] xorp: rib: Add admin_distance parameter to RouteEntry constructor --- xorp/rib/route.cc | 8 ++++---- xorp/rib/route.hh | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index 30df58df6..c6e2de2b5 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -32,9 +32,9 @@ template RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, const PolicyTags& policytags, const IPNet& net) + uint32_t metric, const PolicyTags& policytags, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), - _admin_distance(UNKNOWN_ADMIN_DISTANCE), _metric(metric), + _admin_distance(admin_distance), _metric(metric), _policytags(policytags), _net(net) { if (_vif != NULL) @@ -43,9 +43,9 @@ RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, template RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, const IPNet& net) + uint32_t metric, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), - _admin_distance(UNKNOWN_ADMIN_DISTANCE), _metric(metric), _net(net) + _admin_distance(admin_distance), _metric(metric), _net(net) { if (_vif != NULL) _vif->incr_usage_counter(); diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index b59073fad..6685e056e 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -56,10 +56,12 @@ public: * @param metric the routing protocol metric for this route. */ RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, const PolicyTags& policytags, const IPNet& net); + uint32_t metric, const PolicyTags& policytags, + const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, const IPNet& net); + uint32_t metric, const IPNet& net, + uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); RouteEntry(const RouteEntry& r); From ce316a6036bf3f7e9646a2031ebc0483b5ab072a Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 10 Jul 2012 17:11:52 +0200 Subject: [PATCH 33/38] xorp: rib: Check if nexthop == NULL only in IPRouteEntry constructor --- xorp/rib/route.hh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index 6685e056e..936bbaeed 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -181,7 +181,7 @@ public: */ IPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, Protocol* protocol, uint32_t metric) - : RouteEntry(vif, protocol, metric, net), _nexthop(nexthop) {} + : RouteEntry(vif, protocol, metric, net), _nexthop(nexthop) { XLOG_ASSERT(nexthop); } /** * Constructor for IPRouteEntry. @@ -198,7 +198,7 @@ public: IPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, Protocol* protocol, uint32_t metric, const PolicyTags& policytags) - : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) { } + : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) { XLOG_ASSERT(nexthop); } IPRouteEntry(const IPRouteEntry& r); IPRouteEntry& operator=(const IPRouteEntry& rhs); @@ -222,12 +222,7 @@ public: * @return the route entry's next-hop router address. If there is no * next-hop router, then the return value is IPv4#ZERO() or IPv6#ZERO(). */ - const A& nexthop_addr() const { - if (_nexthop != NULL) - return _nexthop->addr(); - else - return A::ZERO(); - } + const A& nexthop_addr() const { return _nexthop->addr(); } /** * Get the route entry as a string for debugging purposes. From 518bb4773d9c71795efbb4d8088627e90464005d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Tue, 10 Jul 2012 17:39:15 +0200 Subject: [PATCH 34/38] xorp: Make nexthop and policytags be shared_pointers in RouteEntries That way, all copies of RouteEntries share the same nexthop and policytag version. --- xorp/libxorp/nexthop.hh | 4 ---- xorp/rib/route.cc | 27 +++++++++++++++++--------- xorp/rib/route.hh | 43 +++++++++++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/xorp/libxorp/nexthop.hh b/xorp/libxorp/nexthop.hh index bffec8255..a27478c95 100644 --- a/xorp/libxorp/nexthop.hh +++ b/xorp/libxorp/nexthop.hh @@ -142,7 +142,6 @@ public: * * Callers ARE RESPONSIBLE for freeing the memory */ - virtual IPNextHop* get_copy() = 0; protected: const A _addr; @@ -219,7 +218,6 @@ public: */ int type() const { return ENCAPS_NEXTHOP; } - IPEncapsNextHop* get_copy() { return new IPEncapsNextHop(*this); } private: //_cached_peer is the cached copy of the local peer we send the @@ -299,7 +297,6 @@ public: */ int type() const { return DISCARD_NEXTHOP; } - DiscardNextHop* get_copy() { return new DiscardNextHop(*this); } private: @@ -326,7 +323,6 @@ public: */ int type() const { return UNREACHABLE_NEXTHOP; } - UnreachableNextHop* get_copy() { return new UnreachableNextHop(*this); } private: diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index c6e2de2b5..9ec00c4cb 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -35,7 +35,7 @@ RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, uint32_t metric, const PolicyTags& policytags, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), _admin_distance(admin_distance), _metric(metric), - _policytags(policytags), _net(net) + _policytags(new PolicyTags(policytags)), _net(net) { if (_vif != NULL) _vif->incr_usage_counter(); @@ -45,7 +45,20 @@ template RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, uint32_t metric, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), - _admin_distance(admin_distance), _metric(metric), _net(net) + _admin_distance(admin_distance), _metric(metric), + _policytags(new PolicyTags()), _net(net) +{ + if (_vif != NULL) + _vif->incr_usage_counter(); +} + +template +RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, + uint32_t metric, smart_ptr& policytags, + const IPNet& net, uint16_t admin_distance) + : _vif(vif), _protocol(protocol), + _admin_distance(admin_distance), _metric(metric), + _policytags(policytags), _net(net) { if (_vif != NULL) _vif->incr_usage_counter(); @@ -90,10 +103,6 @@ RouteEntry::~RouteEntry() template class RouteEntry; template class RouteEntry; -template -IPRouteEntry::IPRouteEntry(const IPRouteEntry& ipr) - : RouteEntry(ipr), _nexthop(ipr.nexthop()->get_copy()) { } - template string IPRouteEntry::str() const @@ -101,10 +110,10 @@ IPRouteEntry::str() const string dst = (RouteEntry::_net.is_valid()) ? RouteEntry::_net.str() : string("NULL"); string vif = (RouteEntry::_vif) ? string(RouteEntry::_vif->name()) : string("NULL"); return string("Dst: ") + dst + string(" Vif: ") + vif + - string(" NextHop: ") + (_nexthop ? _nexthop->str() : "no next hop") + + string(" NextHop: ") + _nexthop->str() + string(" Metric: ") + c_format("%d", RouteEntry::_metric) + string(" Protocol: ") + RouteEntry::_protocol->name() + - string(" PolicyTags: ") + RouteEntry::_policytags.str(); + string(" PolicyTags: ") + RouteEntry::_policytags->str(); } template @@ -181,7 +190,7 @@ IPRouteEntry& IPRouteEntry::operator=(const IPRouteEntry& r) { if (this == &r) return *this; RouteEntry::operator=(r); - _nexthop = r._nexthop->get_copy(); + _nexthop = r._nexthop; return *this; } diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index 936bbaeed..c95399e19 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -33,6 +33,18 @@ #include "protocol.hh" +#ifdef USE_BOOST + +#include +#define smart_ptr boost::shared_ptr + +#else + +#include "libxorp/ref_ptr.hh" +#define smart_ptr ref_ptr + +#endif + template class RibVif; @@ -63,6 +75,10 @@ public: uint32_t metric, const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); + RouteEntry(RibVif* vif, Protocol* protocol, + uint32_t metric, smart_ptr& policytags, + const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); + RouteEntry(const RouteEntry& r); RouteEntry& operator=(const RouteEntry& r); @@ -144,8 +160,10 @@ public: * * @return the policy-tags for this route. */ - PolicyTags& policytags() { return _policytags; } - const PolicyTags& policytags() const { return _policytags; } + PolicyTags& policytags() { return *_policytags; } + const PolicyTags& policytags() const { return *_policytags; } + + smart_ptr& policytags_shared() { return _policytags; } protected: RibVif* _vif; @@ -154,7 +172,7 @@ protected: uint16_t _admin_distance; // Lower is better uint32_t _metric; // Lower is better - PolicyTags _policytags; // Tags used for policy route redistribution + smart_ptr _policytags; // Tags used for policy route redistribution IPNet _net; // The route entry's subnet address }; @@ -200,13 +218,17 @@ public: const PolicyTags& policytags) : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) { XLOG_ASSERT(nexthop); } - IPRouteEntry(const IPRouteEntry& r); + IPRouteEntry(const IPNet& net, RibVif* vif, + smart_ptr >& nexthop, Protocol* protocol, uint32_t metric, + smart_ptr& policytags, uint16_t admin_distance) + : RouteEntry(vif, protocol, metric, policytags, net, admin_distance), _nexthop(nexthop) { } + IPRouteEntry& operator=(const IPRouteEntry& rhs); /** * Destructor for Routing Table Entry */ - virtual ~IPRouteEntry() { delete _nexthop; } + virtual ~IPRouteEntry() { } /** * Get the NextHop router. @@ -214,7 +236,9 @@ public: * @return the NextHop router to which packets matching this * entry should be forwarded. */ - IPNextHop* nexthop() const { return _nexthop; } + IPNextHop* nexthop() const { return _nexthop.get(); } + + smart_ptr >& nexthop_shared() { return _nexthop; } /** * Get the route entry's next-hop router address. @@ -233,7 +257,7 @@ public: void* operator new(size_t size); void operator delete(void* ptr); protected: - IPNextHop* _nexthop; + smart_ptr > _nexthop; private: static MemoryPool >& memory_pool(); }; @@ -278,7 +302,10 @@ public: ResolvedIPRouteEntry(const IPRouteEntry* resolving_parent, const IPRouteEntry* egp_parent) : IPRouteEntry(egp_parent->net(), resolving_parent->vif(), - resolving_parent->nexthop()->get_copy(), egp_parent->protocol(), egp_parent->metric(), PolicyTags()), + const_cast*>(resolving_parent)->nexthop_shared(), + egp_parent->protocol(), egp_parent->metric(), + const_cast*>(egp_parent)->policytags_shared(), + egp_parent->admin_distance()), _resolving_parent(resolving_parent), _egp_parent(egp_parent) { } From 337f04ee9d53739520e31c070eeb2984b30deff1 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Wed, 11 Jul 2012 11:29:14 +0200 Subject: [PATCH 35/38] xorp: rib: Removed lookup_route and parent functions from base RouteTable Those functions are implemented only in Tables where they are acctualy needed. They are implemented only in ExtIntTable, OriginTable and RedistTable. All lookups are performed on ExtInt table. ExtINt table performs lookups on Origin tables to find masked routes. lookup_route functions in Redist table are needed for proper route redistribution. All tables are now unidirectional connected. Only tables that need to know about their parents are Deletion and Register table. Deletion table needs to know about it's parent, so it could be appropriately unplumbed. Register table needs to know about its ExtInt table so it could lookup route range. Passed all rib tests --- xorp/rib/rib.cc | 12 ++-- xorp/rib/rt_tab_base.cc | 6 +- xorp/rib/rt_tab_base.hh | 11 +--- xorp/rib/rt_tab_deletion.cc | 98 --------------------------------- xorp/rib/rt_tab_deletion.hh | 34 ------------ xorp/rib/rt_tab_extint.cc | 2 +- xorp/rib/rt_tab_extint.hh | 4 +- xorp/rib/rt_tab_origin.cc | 38 ++----------- xorp/rib/rt_tab_origin.hh | 20 +------ xorp/rib/rt_tab_pol_conn.cc | 65 ++-------------------- xorp/rib/rt_tab_pol_conn.hh | 10 +--- xorp/rib/rt_tab_pol_redist.cc | 52 ++--------------- xorp/rib/rt_tab_pol_redist.hh | 11 +--- xorp/rib/rt_tab_redist.cc | 41 +++++++------- xorp/rib/rt_tab_redist.hh | 17 +++--- xorp/rib/rt_tab_register.cc | 2 +- xorp/rib/rt_tab_register.hh | 32 ++--------- xorp/rib/tests/rt_tab_expect.cc | 16 ++---- xorp/rib/tests/rt_tab_expect.hh | 7 ++- xorp/rib/tests/test_deletion.cc | 18 +++--- 20 files changed, 82 insertions(+), 414 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index 9a0bbd1f2..dd82542ff 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -437,8 +437,8 @@ RIB::initialize_register(RegisterServer& register_server) XLOG_ASSERT(_final_table == _ext_int_table); - _register_table->set_parent(_final_table); - _final_table->set_next_table(_register_table); + _register_table->set_parent(_ext_int_table); + _ext_int_table->set_next_table(_register_table); _final_table = _register_table; return XORP_OK; @@ -831,7 +831,7 @@ RIB::add_route(const string& tablename, // // Search for a route to a directly-connected destination // - const IPRouteEntry* re = _connected_origin_table->lookup_route(nexthop_addr); + const IPRouteEntry* re = _connected_origin_table->lookup_ip_route(nexthop_addr); if (re != NULL) // We found a route for the nexthop vif = re->vif(); @@ -924,7 +924,7 @@ RIB::verify_route(const A& lookup_addr, // 1. Check for an expected route miss. // 2. Check table entry validity and existence. - re = _final_table->lookup_route(lookup_addr); + re = _ext_int_table->lookup_route(lookup_addr); if (re == NULL || re->vif() == NULL) { if (matchtype == RibVerifyType(MISS)) { debug_msg("****ROUTE MISS SUCCESSFULLY VERIFIED****\n"); @@ -1009,7 +1009,7 @@ RIB::lookup_route(const A& lookupaddr) { debug_msg("looking up %s\n", lookupaddr.str().c_str()); - const IPRouteEntry* re = _final_table->lookup_route(lookupaddr); + const IPRouteEntry* re = _ext_int_table->lookup_route(lookupaddr); // Case 1: Route miss. Return the null IP address. // Vif cannot be NULL for a valid route. if (re == NULL || re->vif() == NULL) @@ -1046,7 +1046,7 @@ template RouteRange* RIB::route_range_lookup(const A& lookupaddr) { - return _final_table->lookup_route_range(lookupaddr); + return _ext_int_table->lookup_route_range(lookupaddr); } template diff --git a/xorp/rib/rt_tab_base.cc b/xorp/rib/rt_tab_base.cc index 996426598..fb2f041f2 100644 --- a/xorp/rib/rt_tab_base.cc +++ b/xorp/rib/rt_tab_base.cc @@ -43,12 +43,10 @@ RouteTable::set_next_table(RouteTable* next_table) template void RouteTable::replace_policytags(const IPRouteEntry& route, - const PolicyTags& prevtags, - RouteTable* caller) + const PolicyTags& prevtags) { XLOG_ASSERT(_next_table); - UNUSED(caller); - _next_table->replace_policytags(route, prevtags, this); + _next_table->replace_policytags(route, prevtags); } diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index d769986f3..a0b1965d7 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -171,28 +171,19 @@ public: virtual int delete_igp_route(const IPRouteEntry* route) = 0; virtual int delete_egp_route(const IPRouteEntry* route) = 0; - virtual const IPRouteEntry* lookup_route(const IPNet& net) const = 0; - - virtual const IPRouteEntry* lookup_route(const A& addr) const = 0; - - virtual RouteRange* lookup_route_range(const A& addr) const = 0; - virtual void set_next_table(RouteTable* next_table); virtual TableType type() const = 0; virtual string str() const = 0; virtual void flush() {} - virtual void set_parent(RouteTable*) {} - const string& tablename() const { return _tablename; } RouteTable* next_table() { return _next_table; } const RouteTable* next_table() const { return _next_table; } // this call should be received and dealt with by the PolicyRedistTable. virtual void replace_policytags(const IPRouteEntry& route, - const PolicyTags& prevtags, - RouteTable* caller); + const PolicyTags& prevtags); protected: void set_tablename(const string& s) { _tablename = s; } diff --git a/xorp/rib/rt_tab_deletion.cc b/xorp/rib/rt_tab_deletion.cc index b58994214..3cdadbf5d 100644 --- a/xorp/rib/rt_tab_deletion.cc +++ b/xorp/rib/rt_tab_deletion.cc @@ -44,7 +44,6 @@ DeletionTable::DeletionTable(const string& tablename, { XLOG_ASSERT(_parent != NULL); this->set_next_table(_parent->next_table()); - this->next_table()->set_parent(this); parent->set_next_table(this); } @@ -133,102 +132,6 @@ DeletionTable::delete_all_routes() _ip_route_table->delete_all_nodes(); } -template -const IPRouteEntry* -DeletionTable::lookup_route(const IPNet& net) const -{ - const IPRouteEntry* parent_route = _parent->lookup_route(net); - - typename RouteTrie::iterator iter; - iter = _ip_route_table->lookup_node(net); - - if (parent_route != NULL) { - // - // If we succeeded in looking up the route in the parent table, - // then the route MUST NOT be in our deletion table. - // - XLOG_ASSERT(iter == _ip_route_table->end()); - return parent_route; - } else { - // - // While we hold routes to be deleted, we haven't told anyone - // downstream they've gone yet. We have to pretend they're - // still there (for consistency reasons) until we've got round - // to telling downstream that they've actually gone. - // - return (iter == _ip_route_table->end()) ? NULL : *iter; - } -} - -template -const IPRouteEntry* -DeletionTable::lookup_route(const A& addr) const -{ - const IPRouteEntry* parent_route = _parent->lookup_route(addr); - - typename RouteTrie::iterator iter; - iter = _ip_route_table->find(addr); - - if (parent_route != NULL) { - if (iter == _ip_route_table->end()) { - return parent_route; - } else { - // - // Both our parent and ourselves have a route. We need to - // return the more specific route. If the two are the same - // this is a fatal error. - // - const IPRouteEntry* our_route = *iter; - XLOG_ASSERT(our_route->prefix_len() != parent_route->prefix_len()); - - if (our_route->prefix_len() > parent_route->prefix_len()) { - return our_route; - } else { - return parent_route; - } - } - XLOG_UNREACHABLE(); - } - - // - // While we hold routes to be deleted, we haven't told anyone - // downstream they've gone yet. We have to pretend they're - // still there (for consistency reasons) until we've got round - // to telling downstream that they've actually gone. - // - return (iter == _ip_route_table->end()) ? NULL : *iter; -} - -template -RouteRange* -DeletionTable::lookup_route_range(const A& addr) const -{ - const IPRouteEntry* route; - typename RouteTrie::iterator iter; - iter = _ip_route_table->find(addr); - - if (iter == _ip_route_table->end()) - route = NULL; - else - route = *iter; - - A bottom_addr, top_addr; - _ip_route_table->find_bounds(addr, bottom_addr, top_addr); - RouteRange* rr = new RouteRange(addr, route, top_addr, bottom_addr); - debug_msg("Deletion Table: %s returning lower bound for %s of %s\n", - this->tablename().c_str(), addr.str().c_str(), - bottom_addr.str().c_str()); - debug_msg("Deletion Table: %s returning upper bound for %s of %s\n", - this->tablename().c_str(), addr.str().c_str(), - top_addr.str().c_str()); - - // Merge our own route range with that of our parent. - RouteRange* parent_rr = _parent->lookup_route_range(addr); - rr->merge(parent_rr); - delete parent_rr; - return rr; -} - template void DeletionTable::background_deletion_pass() @@ -253,7 +156,6 @@ void DeletionTable::unplumb_self() { _parent->set_next_table(this->next_table()); - this->next_table()->set_parent(_parent); delete this; } diff --git a/xorp/rib/rt_tab_deletion.hh b/xorp/rib/rt_tab_deletion.hh index 527345059..7f2716ecd 100644 --- a/xorp/rib/rt_tab_deletion.hh +++ b/xorp/rib/rt_tab_deletion.hh @@ -85,40 +85,6 @@ public: */ void delete_all_routes(); - /** - * Lookup a specific subnet to see if it is in this DeletionTable - * or the upstream tables. - * - * @param net the subnet to look up. - * @return a pointer to the route entry if it exists, NULL otherwise. - */ - const IPRouteEntry* lookup_route(const IPNet& net) const; - - /** - * Lookup an IP address to get the most specific (longest prefix - * length) route in the DeletionTable or the upstream tables that - * matches this address. - * - * @param addr the IP address to look up. - * @return a pointer to the most specific route entry if any entry - * matches, NULL otherwise. - */ - const IPRouteEntry* lookup_route(const A& addr) const; - - /** - * Lookup an IP addressto get the most specific (longest prefix - * length) route in the union of the DeletionTable and the - * upstream tables that matches this address, along with the - * RouteRange information for this address and route. - * - * @see RouteRange - * @param addr the IP address to look up. - * @return a pointer to a RouteRange class instance containing the - * relevant answer. It is up to the recipient of this pointer to - * free the associated memory. - */ - RouteRange* lookup_route_range(const A& addr) const; - /** * Delete a route, and reschedule background_deletion_pass again * on a zero-second timer until all the routes have been deleted diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 2085cc656..02deccac3 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -367,7 +367,7 @@ ExtIntTable::masked_route(const IPRouteEntry* route) const IPRouteEntry* found = NULL; XLOG_ASSERT(border != _all_tables.end()); for (typename RouteTableMap::iterator iter = ++border; iter != _all_tables.end(); ++iter) { - found = iter->second->lookup_route(route->net()); + found = iter->second->lookup_ip_route(route->net()); if (found) return found; } diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index de2461abb..2c4aa283f 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -22,7 +22,7 @@ #ifndef __RIB_RT_TAB_EXTINT_HH__ #define __RIB_RT_TAB_EXTINT_HH__ -#include "rt_tab_base.hh" +#include "rt_tab_origin.hh" /** @@ -177,7 +177,7 @@ private: typedef multimap, ResolvedIPRouteEntry* > ResolvingParentMultiMap; typedef map, UnresolvedIPRouteEntry* > IpUnresolvedTableMap; typedef Trie* > RouteTrie; - typedef map* > RouteTableMap; + typedef map* > RouteTableMap; typedef set AdminDistanceSet; bool delete_ext_route(const IPRouteEntry* route, bool winning_route = true); diff --git a/xorp/rib/rt_tab_origin.cc b/xorp/rib/rt_tab_origin.cc index f0c296016..4f89ae6d7 100644 --- a/xorp/rib/rt_tab_origin.cc +++ b/xorp/rib/rt_tab_origin.cc @@ -63,7 +63,7 @@ OriginTable::add_route(IPRouteEntry* route) debug_msg("OT[%s]: Adding route %s\n", this->tablename().c_str(), route->str().c_str()); - if (lookup_route(route->net()) != NULL) { + if (lookup_ip_route(route->net()) != NULL) { delete (route); return XORP_ERROR; } @@ -143,53 +143,27 @@ OriginTable::routing_protocol_shutdown() template const IPRouteEntry* -OriginTable::lookup_route(const IPNet& net) const +OriginTable::lookup_ip_route(const IPNet& net) const { debug_msg("------------------\nlookup_route in table %s\n", this->tablename().c_str()); debug_msg("OriginTable: Looking up route %s\n", net.str().c_str()); - typename RouteTrie::iterator iter; - iter = _ip_route_table->lookup_node(net); + typename RouteTrie::iterator iter = _ip_route_table->lookup_node(net); return (iter == _ip_route_table->end()) ? NULL : *iter; } template const IPRouteEntry* -OriginTable::lookup_route(const A& addr) const +OriginTable::lookup_ip_route(const A& addr) const { debug_msg("------------------\nlookup_route in table %s\n", this->tablename().c_str()); debug_msg("OriginTable (%u): Looking up route for addr %s\n", XORP_UINT_CAST(_admin_distance), addr.str().c_str()); - typename RouteTrie::iterator iter; - iter = _ip_route_table->find(addr); - if (iter == _ip_route_table->end()) { - debug_msg("No match found\n"); - } - return (iter == _ip_route_table->end()) ? NULL : *iter; -} + typename RouteTrie::iterator iter = _ip_route_table->find(addr); -template -RouteRange* -OriginTable::lookup_route_range(const A& addr) const -{ - const IPRouteEntry* route; - typename RouteTrie::iterator iter; - iter = _ip_route_table->find(addr); - - route = (iter == _ip_route_table->end()) ? NULL : *iter; - - A bottom_addr, top_addr; - _ip_route_table->find_bounds(addr, bottom_addr, top_addr); - RouteRange* rr = new RouteRange(addr, route, top_addr, bottom_addr); - debug_msg("Origin Table: %s returning lower bound for %s of %s\n", - this->tablename().c_str(), addr.str().c_str(), - bottom_addr.str().c_str()); - debug_msg("Origin Table: %s returning upper bound for %s of %s\n", - this->tablename().c_str(), addr.str().c_str(), - top_addr.str().c_str()); - return rr; + return (iter == _ip_route_table->end()) ? NULL : *iter; } template diff --git a/xorp/rib/rt_tab_origin.hh b/xorp/rib/rt_tab_origin.hh index f150b7bc6..11166f05b 100644 --- a/xorp/rib/rt_tab_origin.hh +++ b/xorp/rib/rt_tab_origin.hh @@ -112,7 +112,7 @@ public: * @param net the subnet to look up. * @return a pointer to the route entry if it exists, NULL otherwise. */ - const IPRouteEntry* lookup_route(const IPNet& net) const; + const IPRouteEntry* lookup_ip_route(const IPNet& net) const; /** * Lookup an IP address to get the most specific (longest prefix @@ -122,21 +122,7 @@ public: * @return a pointer to the most specific route entry if any entry * matches, NULL otherwise. */ - const IPRouteEntry* lookup_route(const A& addr) const; - - /** - * Lookup an IP addressto get the most specific (longest prefix - * length) route in the OriginTable that matches this address, - * along with the RouteRange information for this address and - * route. - * - * @see RouteRange - * @param addr the IP address to look up. - * @return a pointer to a RouteRange class instance containing the - * relevant answer. It is up to the recipient of this pointer to - * free the associated memory. - */ - RouteRange* lookup_route_range(const A& addr) const; + const IPRouteEntry* lookup_ip_route(const A& addr) const; /** * Changes the admin distance @@ -183,7 +169,7 @@ protected: uint16_t _admin_distance; // 0 .. 255 // EventLoop& _eventloop; - RouteTrie* _ip_route_table; + RouteTrie* _ip_route_table; uint32_t _gen; virtual int generic_delete_route(const IPRouteEntry*) = 0; diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index 7e432134b..4d363809b 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -42,13 +42,12 @@ const string PolicyConnectedTable::table_name = "policy-connected-table"; template PolicyConnectedTable::PolicyConnectedTable (RouteTable* parent, PolicyFilters& pfs) - : RouteTable(table_name), _parent(parent), _policy_filters(pfs) + : RouteTable(table_name), _policy_filters(pfs) { - if (_parent->next_table()) { - this->set_next_table(_parent->next_table()); - this->next_table()->set_parent(this); + if (parent->next_table()) { + this->set_next_table(parent->next_table()); } - _parent->set_next_table(this); + parent->set_next_table(this); } template @@ -133,59 +132,6 @@ PolicyConnectedTable::delete_egp_route(const IPRouteEntry* route) return this->next_table()->delete_egp_route(route); } -template -const IPRouteEntry* -PolicyConnectedTable::lookup_route(const IPNet& net) const -{ - XLOG_ASSERT(_parent); - - typename RouteContainer::iterator i; - i = _route_table.lookup_node(net); - - // check if we have route [we should have same routes as origin table]. - if (i == _route_table.end()) - return NULL; - - return *i; -} - - -template -const IPRouteEntry* -PolicyConnectedTable::lookup_route(const A& addr) const -{ - XLOG_ASSERT(_parent); - - typename RouteContainer::iterator i; - i = _route_table.find(addr); - - // same as above - if (i == _route_table.end()) - return NULL; - - return *i; -} - - -template -RouteRange* -PolicyConnectedTable::lookup_route_range(const A& addr) const -{ - XLOG_ASSERT(_parent); - - // XXX: no policy tags in ranges for now - return _parent->lookup_route_range(addr); -} - - -template -void -PolicyConnectedTable::set_parent(RouteTable* new_parent) -{ - _parent = new_parent; -} - - template string PolicyConnectedTable::str() const @@ -193,7 +139,6 @@ PolicyConnectedTable::str() const ostringstream oss; oss << "------" << endl; oss << "PolicyConnectedTable" << endl; - oss << "parent: " << const_cast< PolicyConnectedTable* >(this)->parent()->tablename() << endl; if (this->next_table()) oss << "next table: " << this->next_table()->tablename() << endl; else @@ -220,7 +165,7 @@ PolicyConnectedTable::push_routes() do_filtering(*prev); // only policytags may change - next->replace_policytags(*prev, prev->policytags(), this); + next->replace_policytags(*prev, prev->policytags()); } } diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index 5668cf7c7..614f5472e 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -56,13 +56,9 @@ public: int delete_igp_route(const IPRouteEntry* route); int add_egp_route(const IPRouteEntry& route); int delete_egp_route(const IPRouteEntry* route); - const IPRouteEntry* lookup_route(const IPNet& net) const; - const IPRouteEntry* lookup_route(const A& addr) const; - RouteRange* lookup_route_range(const A& addr) const; + TableType type() const { return POLICY_CONNECTED_TABLE; } - const RouteTable* parent() const { return _parent; } - RouteTable* parent() { return _parent; } - void set_parent(RouteTable* new_parent); + string str() const; /** @@ -87,8 +83,6 @@ private: typedef Trie* > RouteContainer; - RouteTable* _parent; - RouteContainer _route_table; // Copy of routes // we have this so we may push routes. diff --git a/xorp/rib/rt_tab_pol_redist.cc b/xorp/rib/rt_tab_pol_redist.cc index e6d721b4f..829f047ff 100644 --- a/xorp/rib/rt_tab_pol_redist.cc +++ b/xorp/rib/rt_tab_pol_redist.cc @@ -41,18 +41,16 @@ PolicyRedistTable::PolicyRedistTable(RouteTable* parent, XrlRouter& rtr, PolicyRedistMap& rmap, bool multicast) : RouteTable(table_name), - _parent(parent), _xrl_router(rtr), _eventloop(_xrl_router.eventloop()), _redist_map(rmap), _redist_client(&_xrl_router), _multicast(multicast) { - if (_parent->next_table() != NULL) { - this->set_next_table(_parent->next_table()); - this->next_table()->set_parent(this); + if (parent->next_table() != NULL) { + this->set_next_table(parent->next_table()); } - _parent->set_next_table(this); + parent->set_next_table(this); } template @@ -133,44 +131,6 @@ PolicyRedistTable::delete_egp_route(const IPRouteEntry* route) return this->next_table()->delete_egp_route(route); } -template -const IPRouteEntry* -PolicyRedistTable::lookup_route(const IPNet& net) const -{ - XLOG_ASSERT(_parent != NULL); - - return _parent->lookup_route(net); -} - - -template -const IPRouteEntry* -PolicyRedistTable::lookup_route(const A& addr) const -{ - XLOG_ASSERT(_parent != NULL); - - return _parent->lookup_route(addr); -} - - -template -RouteRange* -PolicyRedistTable::lookup_route_range(const A& addr) const -{ - XLOG_ASSERT(_parent != NULL); - - return _parent->lookup_route_range(addr); -} - - -template -void -PolicyRedistTable::set_parent(RouteTable* new_parent) -{ - _parent = new_parent; -} - - template string PolicyRedistTable::str() const @@ -178,7 +138,6 @@ PolicyRedistTable::str() const ostringstream oss; oss << "------" << endl; oss << "PolicyRedistTable" << endl; - oss << "parent: " << const_cast* >(this)->parent()->tablename() << endl; if (this->next_table()) oss << "next table: " << this->next_table()->tablename() << endl; else @@ -255,11 +214,8 @@ PolicyRedistTable::del_redist(const IPRouteEntry& route, template void PolicyRedistTable::replace_policytags(const IPRouteEntry& route, - const PolicyTags& prevtags, - RouteTable* caller) + const PolicyTags& prevtags) { - XLOG_ASSERT(caller == _parent); - set del_protos; set add_protos; diff --git a/xorp/rib/rt_tab_pol_redist.hh b/xorp/rib/rt_tab_pol_redist.hh index 4216b176f..5fa256017 100644 --- a/xorp/rib/rt_tab_pol_redist.hh +++ b/xorp/rib/rt_tab_pol_redist.hh @@ -133,13 +133,7 @@ public: int delete_igp_route(const IPRouteEntry* route); int delete_egp_route(const IPRouteEntry* route); - const IPRouteEntry* lookup_route(const IPNet& net) const; - const IPRouteEntry* lookup_route(const A& addr) const; - RouteRange* lookup_route_range(const A& addr) const; TableType type() const { return POLICY_REDIST_TABLE; } - const RouteTable* parent() const { return _parent; } - RouteTable* parent() { return _parent; } - void set_parent(RouteTable* new_parent); string str() const; void xrl_cb(const XrlError&, string); @@ -154,8 +148,7 @@ public: * @param caller the table which invoked this method. */ void replace_policytags(const IPRouteEntry& route, - const PolicyTags& prevtags, - RouteTable* caller); + const PolicyTags& prevtags); private: @@ -197,8 +190,6 @@ private: void generic_delete_route(const IPRouteEntry* route); - RouteTable* _parent; - XrlRouter& _xrl_router; EventLoop& _eventloop; diff --git a/xorp/rib/rt_tab_redist.cc b/xorp/rib/rt_tab_redist.cc index acf92c857..5de5cc6f4 100644 --- a/xorp/rib/rt_tab_redist.cc +++ b/xorp/rib/rt_tab_redist.cc @@ -194,7 +194,7 @@ Redistributor::dump_a_route() } // Lookup route and announce it via output - const IPRouteEntry* ipr = _table->lookup_route(*ci); + const IPRouteEntry* ipr = _table->lookup_ip_route(*ci); XLOG_ASSERT(ipr != 0); if (policy_accepts(*ipr)) _output->add_route(*ipr); @@ -345,13 +345,12 @@ Redistributor::OutputEventInterface::fatal_error() template RedistTable::RedistTable(const string& tablename, RouteTable* parent) - : RouteTable(tablename), _parent(parent) + : RouteTable(tablename) { - if (_parent->next_table()) { - this->set_next_table(_parent->next_table()); - this->next_table()->set_parent(this); + if (parent->next_table()) { + this->set_next_table(parent->next_table()); } - _parent->set_next_table(this); + parent->set_next_table(this); } template @@ -383,6 +382,14 @@ RedistTable::remove_redistributor(Redistributor* r) } } +template +const IPRouteEntry* +RedistTable::lookup_ip_route(const IPNet& net) const +{ + typename IPRouteTrie::iterator iter = _ip_route_table.lookup_node(net); + return (iter == _ip_route_table.end()) ? NULL : *iter; +} + template Redistributor* RedistTable::redistributor(const string& name) @@ -401,10 +408,10 @@ template void RedistTable::generic_add_route(const IPRouteEntry& route) { - typename RouteIndex::iterator rci = _rt_index.find(route.net()); - XLOG_ASSERT(rci == _rt_index.end()); + XLOG_ASSERT(_rt_index.find(route.net()) == _rt_index.end()); _rt_index.insert(route.net()); + _ip_route_table.insert(route.net(), &route); typename list*>::iterator i = _outputs.begin(); while (i != _outputs.end()) { @@ -438,13 +445,11 @@ RedistTable::add_egp_route(const IPRouteEntry& route) template void -RedistTable::generic_delete_route(const IPRouteEntry* r) +RedistTable::generic_delete_route(const IPRouteEntry* route) { - const IPRouteEntry& route = *r; - - debug_msg("delete_route for %s\n", route.net().str().c_str()); + debug_msg("delete_route for %s\n", route->net().str().c_str()); - typename RouteIndex::iterator rci = _rt_index.find(route.net()); + typename RouteIndex::iterator rci = _rt_index.find(route->net()); XLOG_ASSERT(rci != _rt_index.end()); typename list*>::iterator i; @@ -454,17 +459,18 @@ RedistTable::generic_delete_route(const IPRouteEntry* r) while (i != _outputs.end()) { Redistributor* r = *i; i++; // XXX for safety increment iterator before prodding output - r->redist_event().will_delete(route); + r->redist_event().will_delete(*route); } _rt_index.erase(rci); + _ip_route_table.erase(route->net()); // Announce delete as fait accompli i = _outputs.begin(); while (i != _outputs.end()) { Redistributor* r = *i; i++; // XXX for safety increment iterator before prodding output - r->redist_event().did_delete(route); + r->redist_event().did_delete(*route); } } @@ -513,11 +519,6 @@ RedistTable::str() const } } - if (this->parent()) - s += "parent = " + this->parent()->tablename() + "\n"; - else - s += "no parent table\n"; - if (this->next_table() == NULL) { s += "no next table\n"; } else { diff --git a/xorp/rib/rt_tab_redist.hh b/xorp/rib/rt_tab_redist.hh index 353bb303b..1b70f4541 100644 --- a/xorp/rib/rt_tab_redist.hh +++ b/xorp/rib/rt_tab_redist.hh @@ -115,13 +115,10 @@ public: int delete_igp_route(const IPRouteEntry* route); int delete_egp_route(const IPRouteEntry* route); - const IPRouteEntry* lookup_route(const IPNet& net) const { return _parent->lookup_route(net); } - const IPRouteEntry* lookup_route(const A& addr) const { return _parent->lookup_route(addr); } - RouteRange* lookup_route_range(const A& addr) const { return _parent->lookup_route_range(addr); } + const IPRouteEntry* lookup_ip_route(const IPNet& net) const; + TableType type() const { return REDIST_TABLE; } - const RouteTable* parent() const { return _parent; } - RouteTable* parent() { return _parent; } - void set_parent(RouteTable* new_parent) { _parent = new_parent; } + string str() const; /** @@ -131,12 +128,11 @@ public: const RouteIndex& route_index() const { return _rt_index; } protected: - RouteTable* _parent; // Immediately upstream table. May - // differ from _from_table if a - // Deletion table or another redist - // table has been plumbed in. + typedef Trie* > IPRouteTrie; + RouteIndex _rt_index; list*> _outputs; + IPRouteTrie _ip_route_table; void generic_add_route(const IPRouteEntry& route); void generic_delete_route(const IPRouteEntry* route); @@ -271,6 +267,7 @@ private: friend class OutputEventInterface; private: + EventLoop& _e; string _name; RedistTable* _table; diff --git a/xorp/rib/rt_tab_register.cc b/xorp/rib/rt_tab_register.cc index 77c138960..88e0976a5 100644 --- a/xorp/rib/rt_tab_register.cc +++ b/xorp/rib/rt_tab_register.cc @@ -94,7 +94,7 @@ RegisterTable::~RegisterTable() template void -RegisterTable::set_parent(RouteTable* new_parent) +RegisterTable::set_parent(ExtIntTable* new_parent) { _parent = new_parent; } diff --git a/xorp/rib/rt_tab_register.hh b/xorp/rib/rt_tab_register.hh index ea9330c4a..9b0d4ca55 100644 --- a/xorp/rib/rt_tab_register.hh +++ b/xorp/rib/rt_tab_register.hh @@ -27,7 +27,7 @@ #include "libxorp/debug.h" -#include "rt_tab_base.hh" +#include "rt_tab_extint.hh" class RegisterServer; @@ -294,36 +294,12 @@ public: int delete_igp_route(const IPRouteEntry* route); int delete_egp_route(const IPRouteEntry* route); - /** - * Lookup a route in the RIB. This request will be propagated to - * the parent table unchanged. - */ - const IPRouteEntry* lookup_route(const IPNet& net) const { - return _parent->lookup_route(net); - } - - /** - * Lookup a route in the RIB. This request will be propagated to - * the parent table unchanged. - */ - const IPRouteEntry* lookup_route(const A& addr) const { - return _parent->lookup_route(addr); - } - /** * Lookup a route_range in the RIB. This request will be * propagated to the parent table unchanged. It is not expected * this will be called, but not prohibited. */ - RouteRange* lookup_route_range(const A& addr) const { - return _parent->lookup_route_range(addr); - } - - /** - * @return the parent @ref RouteTable of this RegisterTable. - */ - const RouteTable* parent() const { return _parent; } - RouteTable* parent() { return _parent; } + RouteRange* lookup_route_range(const A& addr) const { return _parent->lookup_route_range(addr); } /** * @return this RegisterTable as a string for debugging purposes. @@ -373,7 +349,7 @@ public: */ TableType type() const { return REGISTER_TABLE; } - void set_parent(RouteTable* new_parent); + void set_parent(ExtIntTable* new_parent); /** * Cause the register server to push out queued changes to the @@ -414,7 +390,7 @@ private: map _module_names; Trie* > _ipregistry; - RouteTable* _parent; + ExtIntTable* _parent; RegisterServer& _register_server; bool _multicast; // true if a multicast rib }; diff --git a/xorp/rib/tests/rt_tab_expect.cc b/xorp/rib/tests/rt_tab_expect.cc index ff1352ca9..f4b29dcef 100644 --- a/xorp/rib/tests/rt_tab_expect.cc +++ b/xorp/rib/tests/rt_tab_expect.cc @@ -92,7 +92,7 @@ ExpectedRouteChange::str() const template ExpectTable::ExpectTable(const string& tablename, - RouteTable* parent) + OriginTable* parent) : RouteTable(tablename) { _parent = parent; @@ -168,28 +168,22 @@ template const IPRouteEntry* ExpectTable::lookup_route(const IPNet& net) const { - return _parent->lookup_route(net); + return _parent->lookup_ip_route(net); } template const IPRouteEntry* ExpectTable::lookup_route(const A& addr) const { - return _parent->lookup_route(addr); + return _parent->lookup_ip_route(addr); } template void ExpectTable::set_parent(RouteTable* new_parent) { - _parent = new_parent; -} - -template -RouteRange* -ExpectTable::lookup_route_range(const A& addr) const -{ - return _parent->lookup_route_range(addr); + _parent = dynamic_cast* >(new_parent); + XLOG_ASSERT(_parent); } template string diff --git a/xorp/rib/tests/rt_tab_expect.hh b/xorp/rib/tests/rt_tab_expect.hh index 93ec936f1..a12aee735 100644 --- a/xorp/rib/tests/rt_tab_expect.hh +++ b/xorp/rib/tests/rt_tab_expect.hh @@ -23,6 +23,7 @@ #define __RIB_RT_TAB_EXPECT_HH__ #include "rt_tab_base.hh" +#include "rt_tab_origin.hh" template class ExpectedRouteChange; @@ -42,7 +43,7 @@ template class ExpectedRouteChange; template class ExpectTable : public RouteTable { public: - ExpectTable(const string& tablename, RouteTable* parent); + ExpectTable(const string& tablename, OriginTable* parent); ~ExpectTable(); const list >& expected_route_changes() const { @@ -59,7 +60,7 @@ public: int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const; - RouteRange* lookup_route_range(const A& addr) const; + TableType type() const { return EXPECT_TABLE; } RouteTable* parent() { return _parent; } const RouteTable* parent() const { return _parent; } @@ -67,7 +68,7 @@ public: string str() const; private: - RouteTable* _parent; + OriginTable* _parent; list > _expected_route_changes; }; diff --git a/xorp/rib/tests/test_deletion.cc b/xorp/rib/tests/test_deletion.cc index febbf444c..6e80e999c 100644 --- a/xorp/rib/tests/test_deletion.cc +++ b/xorp/rib/tests/test_deletion.cc @@ -85,13 +85,12 @@ main(int /* argc */, char* argv[]) dt.expect_delete(route1); dt.expect_delete(route2); - XLOG_ASSERT(dt.parent()->type() == ORIGIN_TABLE); ot.routing_protocol_shutdown(); // Validate that a deletion table got added - XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); - while (dt.parent()->type() != ORIGIN_TABLE) { - XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); + XLOG_ASSERT(dt.parent()->next_table()->type() == DELETION_TABLE); + while (dt.parent()->next_table()->type() != EXPECT_TABLE) { + XLOG_ASSERT(dt.parent()->next_table()->type() == DELETION_TABLE); eventloop.run(); } XLOG_ASSERT(dt.expected_route_changes().empty()); @@ -109,10 +108,9 @@ main(int /* argc */, char* argv[]) ot.add_route(new IPRouteEntry(route1)); ot.add_route(new IPRouteEntry(route2)); - XLOG_ASSERT(dt.parent()->type() == ORIGIN_TABLE); ot.routing_protocol_shutdown(); - XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); + XLOG_ASSERT(dt.parent()->next_table()->type() == DELETION_TABLE); IPRouteEntry route3(net1, &vif2, nh2.get_copy(), &protocol, 101); dt.expect_delete(route1); @@ -122,15 +120,13 @@ main(int /* argc */, char* argv[]) dt.expect_delete(route2); - XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); - while (dt.parent()->type() != ORIGIN_TABLE) { - XLOG_ASSERT(dt.parent()->type() == DELETION_TABLE); + XLOG_ASSERT(dt.parent()->next_table()->type() == DELETION_TABLE); + while (dt.parent()->next_table()->type() != EXPECT_TABLE) { + XLOG_ASSERT(dt.parent()->next_table()->type() == DELETION_TABLE); eventloop.run(); } XLOG_ASSERT(dt.expected_route_changes().empty()); - XLOG_ASSERT(dt.parent()->type() == ORIGIN_TABLE); - dt.expect_delete(route3); ot.delete_route(net1); From d0d9df102564c5f0ba03e0db4be68699f7050f3d Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 12 Jul 2012 09:40:05 +0200 Subject: [PATCH 36/38] xorp: rib: Templetize functions for adding new origin tables --- xorp/rib/parser_direct_cmds.hh | 2 +- xorp/rib/rib.cc | 68 ++++++++++++++-------------------- xorp/rib/rib.hh | 11 ++++-- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/xorp/rib/parser_direct_cmds.hh b/xorp/rib/parser_direct_cmds.hh index 5885c713c..e848faf71 100644 --- a/xorp/rib/parser_direct_cmds.hh +++ b/xorp/rib/parser_direct_cmds.hh @@ -36,7 +36,7 @@ public: // On the context of this test code, we don't care whether it's an // IGP or an EGP, because we do the plumbing explicitly. So it's // safe to just say it's an IGP, even if its not. - return _rib.new_origin_table(_tablename, "", "", _admin_distance, IGP); + return _rib.new_origin_table(_tablename, "", "", _admin_distance); } private: RIB& _rib; diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index dd82542ff..fb306ffd3 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -50,6 +50,20 @@ RIB::find_origin_table(const string& tablename) return NULL; } +template +template +inline OriginTable* +RIB::find_origin_table_smart(const string& tablename) +{ + switch (protocol_type) { + case IGP: + return find_igp_origin_table(tablename); + case EGP: + return find_egp_origin_table(tablename); + } + return NULL; +} + template inline OriginTable* RIB::find_igp_origin_table(const string& tablename) @@ -445,25 +459,17 @@ RIB::initialize_register(RegisterServer& register_server) } template +template int RIB::new_origin_table(const string& tablename, const string& target_class, const string& target_instance, - uint16_t admin_distance, - ProtocolType protocol_type) + uint16_t admin_distance) { OriginTable* ot = NULL; - switch (protocol_type) { - case IGP: - ot = new TypedOriginTable(tablename, admin_distance, _eventloop); - break; - case EGP: - ot = new TypedOriginTable(tablename, admin_distance, _eventloop); - break; - default: - XLOG_UNREACHABLE(); - break; - } + + ot = new TypedOriginTable(tablename, admin_distance, _eventloop); + if (ot == NULL || add_table(ot) != XORP_OK) { XLOG_WARNING("Could not add origin table %s", tablename.c_str()); delete ot; @@ -1079,7 +1085,7 @@ RIB::add_igp_table(const string& tablename, const string& target_instance) { debug_msg("add_igp_table %s\n", tablename.c_str()); - int r = add_origin_table(tablename, target_class, target_instance, IGP); + int r = add_origin_table(tablename, target_class, target_instance); if (r != XORP_OK) return r; @@ -1116,7 +1122,7 @@ RIB::add_egp_table(const string& tablename, const string& target_instance) { debug_msg("add_egp_table %s\n", tablename.c_str()); - int r = add_origin_table(tablename, target_class, target_instance, EGP); + int r = add_origin_table(tablename, target_class, target_instance); if (r != XORP_OK) { return r; } @@ -1181,11 +1187,11 @@ RIB::plumb_origin_table(OriginTable*& ot) // template +template int RIB::add_origin_table(const string& tablename, const string& target_class, - const string& target_instance, - ProtocolType protocol_type) + const string& target_instance) { debug_msg("add_origin_table %s type: %d\n", tablename.c_str(), protocol_type); @@ -1200,17 +1206,7 @@ RIB::add_origin_table(const string& tablename, // Check if table exists and check type if so OriginTable* ot = NULL; - switch (protocol_type) { - case IGP: - ot = find_igp_origin_table(tablename); - break; - case EGP: - ot = find_egp_origin_table(tablename); - break; - default: - XLOG_UNREACHABLE(); - break; - } + ot = find_origin_table_smart(tablename); if (ot != NULL) { // @@ -1229,23 +1225,13 @@ RIB::add_origin_table(const string& tablename, return XORP_OK; } - if (new_origin_table(tablename, target_class, target_instance, - get_protocol_admin_distance(tablename), protocol_type) != XORP_OK) { + if (new_origin_table(tablename, target_class, target_instance, + get_protocol_admin_distance(tablename)) != XORP_OK) { debug_msg("new_origin_table failed\n"); return XORP_ERROR; } - switch (protocol_type) { - case IGP: - ot = find_igp_origin_table(tablename); - break; - case EGP: - ot = find_egp_origin_table(tablename); - break; - default: - XLOG_UNREACHABLE(); - break; - } + ot = find_origin_table_smart(tablename); return plumb_origin_table(ot); } diff --git a/xorp/rib/rib.hh b/xorp/rib/rib.hh index a4643bc2b..ed35046a2 100644 --- a/xorp/rib/rib.hh +++ b/xorp/rib/rib.hh @@ -172,11 +172,11 @@ public: * @param protocol_type the routing protocol type (@ref ProtocolType). * @return XORP_OK on success, otherwise XORP_ERROR. */ + template int new_origin_table(const string& tablename, const string& target_class, const string& target_instance, - uint16_t admin_distance, - ProtocolType protocol_type); + uint16_t admin_distance); /** * Inform the RIB about the existence of a Virtual Interface. @@ -562,10 +562,10 @@ private: * @param protocol_type the routing protocol type (@ref ProtocolType). * @return XORP_OK on success, otherwise XORP_ERROR. */ + template int add_origin_table(const string& tablename, const string& target_class, - const string& target_instance, - ProtocolType protocol_type); + const string& target_instance); /** * Used to implement @ref delete_igp_table and @ref delete_egp_table. @@ -608,6 +608,9 @@ private: */ OriginTable* find_origin_table(const string& tablename); + template + OriginTable* find_origin_table_smart(const string& tablename); + /** * Find a IGP origin routing table, given its table name * From 4f51f3166d32be862170356e64d4df3dcf5fee41 Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Thu, 12 Jul 2012 12:59:35 +0200 Subject: [PATCH 37/38] xorp: rib: Save protocols in the appropriate RIBs --- xorp/rib/protocol.cc | 5 ++- xorp/rib/protocol.hh | 2 +- xorp/rib/rib.cc | 58 +++++++++------------------------ xorp/rib/rib.hh | 2 -- xorp/rib/route.cc | 18 +++++----- xorp/rib/route.hh | 16 ++++----- xorp/rib/rt_tab_origin.cc | 2 ++ xorp/rib/rt_tab_origin.hh | 18 ++++++---- xorp/rib/tests/test_deletion.cc | 2 +- xorp/rib/tests/test_redist.cc | 4 ++- 10 files changed, 53 insertions(+), 74 deletions(-) diff --git a/xorp/rib/protocol.cc b/xorp/rib/protocol.cc index f46c566fa..ec7f1d5ff 100644 --- a/xorp/rib/protocol.cc +++ b/xorp/rib/protocol.cc @@ -28,11 +28,10 @@ #include "protocol.hh" -Protocol::Protocol(const string& name, ProtocolType protocol_type, - uint32_t genid) +Protocol::Protocol(const string& name, ProtocolType protocol_type) : _name(name), _protocol_type(protocol_type), - _genid(genid) + _genid(0) { } diff --git a/xorp/rib/protocol.hh b/xorp/rib/protocol.hh index 56e48396b..c9a421a7a 100644 --- a/xorp/rib/protocol.hh +++ b/xorp/rib/protocol.hh @@ -53,7 +53,7 @@ public: * protocol goes down and comes up, the genid should be * incremented). */ - Protocol(const string& name, ProtocolType protocol_type, uint32_t genid); + Protocol(const string& name, ProtocolType protocol_type); /** * @return the protocol type. diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index fb306ffd3..ed0a8a26f 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -127,12 +127,12 @@ template Protocol* RIB::find_protocol(const string& protocol) { - typename map::iterator mi = _protocols.find(protocol); + OriginTable* ot = find_origin_table(protocol); - if (mi == _protocols.end()) { - return NULL; - } - return mi->second; + if (ot) + return &(ot->protocol()); + + return NULL; } template @@ -322,11 +322,6 @@ RIB::~RIB() delete _policy_redist_table; _policy_redist_table = NULL; - while (! _protocols.empty()) { - delete _protocols.begin()->second; - _protocols.erase(_protocols.begin()); - } - while (_vifs.empty() == false) { delete _vifs.begin()->second; _vifs.erase(_vifs.begin()); @@ -343,11 +338,13 @@ list RIB::registered_protocol_names() const { list names; - map::const_iterator iter; + typename OriginTableMap::const_iterator iter; - for (iter = _protocols.begin(); iter != _protocols.end(); ++iter) { + for (iter = _igp_origin_tables.begin(); iter != _igp_origin_tables.end(); ++iter) + names.push_back(iter->first); + + for (iter = _egp_origin_tables.begin(); iter != _egp_origin_tables.end(); ++iter) names.push_back(iter->first); - } return (names); } @@ -784,19 +781,6 @@ RIB::add_route(const string& tablename, // Sanity check - we should have initialized RIB XLOG_ASSERT(_connected_origin_table); - Protocol* protocol = find_protocol(tablename); - if (protocol == NULL) { - if (_errors_are_fatal) { - XLOG_FATAL("Attempting to add route with unknown protocol \"%s\".", - tablename.c_str()); - } else { - XLOG_ERROR("Attempting to add route with unknown protocol \"%s\".", - tablename.c_str()); - - return XORP_ERROR; - } - } - OriginTable* ot = find_origin_table(tablename); if (ot == NULL) { if (_errors_are_fatal) { @@ -808,6 +792,7 @@ RIB::add_route(const string& tablename, return XORP_ERROR; } } + const Protocol& protocol = ot->protocol(); RibVif* vif = NULL; IPNextHop* nexthop = NULL; @@ -828,8 +813,7 @@ RIB::add_route(const string& tablename, } IPNextHop* nexthop = create_peer_nexthop(nexthop_addr); - ot->add_route(new IPRouteEntry(net, vif, nexthop, protocol, - metric, policytags)); + ot->add_route(new IPRouteEntry(net, vif, nexthop, &protocol, metric, policytags)); flush(); return XORP_OK; } @@ -844,7 +828,7 @@ RIB::add_route(const string& tablename, if (vif != NULL) nexthop = create_peer_nexthop(nexthop_addr); - else if (vif == NULL && protocol->protocol_type() == IGP) { + else if (vif == NULL && ot->protocol_type() == IGP) { debug_msg("**not directly connected route found for nexthop\n"); // // XXX: If the route came from an IGP, then we must have @@ -861,7 +845,7 @@ RIB::add_route(const string& tablename, // // Add the route // - ot->add_route(new IPRouteEntry(net, vif, nexthop, protocol, metric, policytags)); + ot->add_route(new IPRouteEntry(net, vif, nexthop, &protocol, metric, policytags)); flush(); return XORP_OK; @@ -1196,19 +1180,12 @@ RIB::add_origin_table(const string& tablename, debug_msg("add_origin_table %s type: %d\n", tablename.c_str(), protocol_type); - Protocol* protocol = find_protocol(tablename); - if (protocol == NULL) { - protocol = new Protocol(tablename, protocol_type, 0); - _protocols[tablename] = protocol; - } else { - protocol->increment_genid(); - } - // Check if table exists and check type if so OriginTable* ot = NULL; ot = find_origin_table_smart(tablename); if (ot != NULL) { + ot->protocol().increment_genid(); // // Table already exists, hence use it. // @@ -1354,11 +1331,6 @@ RIB::print_rib() const cout << "==============================================================" << endl; - cout << "Protocols: " << endl; - for_each(_protocols.begin(), _protocols.end(), - print_from_pair(",")); - cout << endl; - cout << "**************************************************************" << endl; #endif // DEBUG_LOGGING } diff --git a/xorp/rib/rib.hh b/xorp/rib/rib.hh index ed35046a2..309d4452f 100644 --- a/xorp/rib/rib.hh +++ b/xorp/rib/rib.hh @@ -712,7 +712,6 @@ private: protected: typedef map* > OriginTableMap; typedef map* > RedistTableMap; - typedef map ProtocolMap; RibManager& _rib_manager; EventLoop& _eventloop; @@ -737,7 +736,6 @@ protected: ExtIntTable* _ext_int_table; - ProtocolMap _protocols; OriginTableMap _routing_protocol_instances; map*> _vifs; map*> _deleted_vifs; diff --git a/xorp/rib/route.cc b/xorp/rib/route.cc index 9ec00c4cb..48f9061a2 100644 --- a/xorp/rib/route.cc +++ b/xorp/rib/route.cc @@ -31,7 +31,7 @@ #include "route.hh" template -RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, +RouteEntry::RouteEntry(RibVif* vif, const Protocol* protocol, uint32_t metric, const PolicyTags& policytags, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), _admin_distance(admin_distance), _metric(metric), @@ -42,8 +42,8 @@ RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, } template -RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, const IPNet& net, uint16_t admin_distance) +RouteEntry::RouteEntry(RibVif* vif, const Protocol* protocol, + uint32_t metric, const IPNet& net, uint16_t admin_distance) : _vif(vif), _protocol(protocol), _admin_distance(admin_distance), _metric(metric), _policytags(new PolicyTags()), _net(net) @@ -53,12 +53,12 @@ RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, } template -RouteEntry::RouteEntry(RibVif* vif, Protocol* protocol, - uint32_t metric, smart_ptr& policytags, - const IPNet& net, uint16_t admin_distance) - : _vif(vif), _protocol(protocol), - _admin_distance(admin_distance), _metric(metric), - _policytags(policytags), _net(net) +RouteEntry::RouteEntry(RibVif* vif, const Protocol* protocol, + uint32_t metric, smart_ptr& policytags, + const IPNet& net, uint16_t admin_distance) + : _vif(vif), _protocol(protocol), + _admin_distance(admin_distance), _metric(metric), + _policytags(policytags), _net(net) { if (_vif != NULL) _vif->incr_usage_counter(); diff --git a/xorp/rib/route.hh b/xorp/rib/route.hh index c95399e19..79a433f63 100644 --- a/xorp/rib/route.hh +++ b/xorp/rib/route.hh @@ -67,15 +67,15 @@ public: * @param protocol the routing protocol that originated this route. * @param metric the routing protocol metric for this route. */ - RouteEntry(RibVif* vif, Protocol* protocol, + RouteEntry(RibVif* vif, const Protocol* protocol, uint32_t metric, const PolicyTags& policytags, const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); - RouteEntry(RibVif* vif, Protocol* protocol, + RouteEntry(RibVif* vif, const Protocol* protocol, uint32_t metric, const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); - RouteEntry(RibVif* vif, Protocol* protocol, + RouteEntry(RibVif* vif, const Protocol* protocol, uint32_t metric, smart_ptr& policytags, const IPNet& net, uint16_t admin_distance = UNKNOWN_ADMIN_DISTANCE); @@ -128,7 +128,7 @@ public: * @return the routing protocol that originated this route. * @see Protocol. */ - Protocol* protocol() const { return _protocol; } + const Protocol* protocol() const { return _protocol; } /** * Display the route for debugging purposes. @@ -168,7 +168,7 @@ public: protected: RibVif* _vif; - Protocol* _protocol; // The routing protocol that instantiated this route + const Protocol* _protocol; // The routing protocol that instantiated this route uint16_t _admin_distance; // Lower is better uint32_t _metric; // Lower is better @@ -198,7 +198,7 @@ public: * @param metric the routing protocol metric for this route. */ IPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, - Protocol* protocol, uint32_t metric) + const Protocol* protocol, uint32_t metric) : RouteEntry(vif, protocol, metric, net), _nexthop(nexthop) { XLOG_ASSERT(nexthop); } /** @@ -214,12 +214,12 @@ public: * @param policytags the policy-tags for this route. */ IPRouteEntry(const IPNet& net, RibVif* vif, IPNextHop* nexthop, - Protocol* protocol, uint32_t metric, + const Protocol* protocol, uint32_t metric, const PolicyTags& policytags) : RouteEntry(vif, protocol, metric, policytags, net), _nexthop(nexthop) { XLOG_ASSERT(nexthop); } IPRouteEntry(const IPNet& net, RibVif* vif, - smart_ptr >& nexthop, Protocol* protocol, uint32_t metric, + smart_ptr >& nexthop, const Protocol* protocol, uint32_t metric, smart_ptr& policytags, uint16_t admin_distance) : RouteEntry(vif, protocol, metric, policytags, net, admin_distance), _nexthop(nexthop) { } diff --git a/xorp/rib/rt_tab_origin.cc b/xorp/rib/rt_tab_origin.cc index 4f89ae6d7..71a57ee9c 100644 --- a/xorp/rib/rt_tab_origin.cc +++ b/xorp/rib/rt_tab_origin.cc @@ -25,6 +25,8 @@ #include "libxorp/xlog.h" #include "libxorp/debug.h" +#include "protocol.hh" + #include "rt_tab_origin.hh" #include "rt_tab_deletion.hh" diff --git a/xorp/rib/rt_tab_origin.hh b/xorp/rib/rt_tab_origin.hh index 11166f05b..ce6559d75 100644 --- a/xorp/rib/rt_tab_origin.hh +++ b/xorp/rib/rt_tab_origin.hh @@ -138,6 +138,8 @@ public: * @return the routing protocol type (@ref ProtocolType). */ virtual int protocol_type() const = 0; + virtual const Protocol& protocol() const = 0; + virtual Protocol& protocol() = 0; /** * @return the table type (@ref TableType). @@ -184,35 +186,39 @@ template class TypedOriginTable : public OriginTable { public: TypedOriginTable(const string& tablename, uint16_t admin_distance, EventLoop& eventloop) : - OriginTable(tablename, admin_distance, eventloop), _protocol_type(IGP) {} + OriginTable(tablename, admin_distance, eventloop), _protocol(tablename, IGP) {} ~TypedOriginTable() {} int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_igp_route(route); } int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_igp_route(route); } - int protocol_type() const { return _protocol_type;} + int protocol_type() const { return _protocol.protocol_type();} + const Protocol& protocol() const { return _protocol;} + Protocol& protocol() { return _protocol;} protected: void allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie); - ProtocolType _protocol_type; // IGP or EGP + Protocol _protocol; // IGP or EGP }; template class TypedOriginTable : public OriginTable { public: TypedOriginTable(const string& tablename, uint16_t admin_distance, EventLoop& eventloop) : - OriginTable(tablename, admin_distance, eventloop), _protocol_type(EGP) {} + OriginTable(tablename, admin_distance, eventloop), _protocol(tablename, EGP) {} ~TypedOriginTable() {} int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_egp_route(route); } int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_egp_route(route); } - int protocol_type() const { return _protocol_type;} + int protocol_type() const { return _protocol.protocol_type();} + const Protocol& protocol() const { return _protocol;} + Protocol& protocol() { return _protocol;} protected: void allocate_deletion_table(typename OriginTable::RouteTrie* ip_route_trie); - ProtocolType _protocol_type; // IGP or EGP + Protocol _protocol; // IGP or EGP }; template diff --git a/xorp/rib/tests/test_deletion.cc b/xorp/rib/tests/test_deletion.cc index 6e80e999c..877ec9dc7 100644 --- a/xorp/rib/tests/test_deletion.cc +++ b/xorp/rib/tests/test_deletion.cc @@ -53,7 +53,7 @@ main(int /* argc */, char* argv[]) RibVif vif2(NULL, tmp_vif2); IPPeerNextHop nh1(IPv4("1.0.0.1")); IPPeerNextHop nh2(IPv4("1.0.0.2")); - Protocol protocol("test", IGP, 0); + Protocol protocol("test", IGP); IPv4Net net1("10.0.1.0/24"); IPv4Net net2("10.0.2.0/24"); diff --git a/xorp/rib/tests/test_redist.cc b/xorp/rib/tests/test_redist.cc index 9c076c3cb..6a2f98c89 100644 --- a/xorp/rib/tests/test_redist.cc +++ b/xorp/rib/tests/test_redist.cc @@ -276,7 +276,9 @@ test_deterministic() TypedOriginTable typed_origin("static", 1, e); OriginTable& origin = typed_origin; IPPeerNextHop nh("22.0.0.1"); - Protocol protocol("static", IGP, 1); + Protocol& protocol = typed_origin.protocol(); + protocol.increment_genid(); + Vif tmp_vif("vif0"); RibVif vif(NULL, tmp_vif); From 8ce730880efc997f062767679a83f8b6207d6b2b Mon Sep 17 00:00:00 2001 From: Igor Maravic Date: Fri, 15 Mar 2013 12:07:20 +0100 Subject: [PATCH 38/38] xorp: rib: Further RIB optimizations We don't cache wining EGP routes any more, since they're already cached in resolved and unresolved routes. Added a flag which stops the EGP route resolving after the IGP route delete, if the better IGP route is coming imiditaly after that delete. Passed all RIB tests. --- xorp/rib/rib.cc | 13 ++- xorp/rib/rt_tab_base.hh | 4 +- xorp/rib/rt_tab_deletion.cc | 12 +-- xorp/rib/rt_tab_deletion.hh | 6 +- xorp/rib/rt_tab_extint.cc | 186 +++++++++++++------------------- xorp/rib/rt_tab_extint.hh | 18 ++-- xorp/rib/rt_tab_origin.cc | 4 +- xorp/rib/rt_tab_origin.hh | 18 ++-- xorp/rib/rt_tab_pol_conn.cc | 8 +- xorp/rib/rt_tab_pol_conn.hh | 4 +- xorp/rib/rt_tab_pol_redist.cc | 8 +- xorp/rib/rt_tab_pol_redist.hh | 4 +- xorp/rib/rt_tab_redist.cc | 8 +- xorp/rib/rt_tab_redist.hh | 4 +- xorp/rib/rt_tab_register.cc | 8 +- xorp/rib/rt_tab_register.hh | 4 +- xorp/rib/tests/rt_tab_expect.hh | 4 +- 17 files changed, 139 insertions(+), 174 deletions(-) diff --git a/xorp/rib/rib.cc b/xorp/rib/rib.cc index ed0a8a26f..4a26a635b 100644 --- a/xorp/rib/rib.cc +++ b/xorp/rib/rib.cc @@ -867,7 +867,7 @@ RIB::replace_route(const string& tablename, if (NULL == ot) return XORP_ERROR; // Table is not an origin table - int response = ot->delete_route(net); + int response = ot->delete_route(net, true); if (response != XORP_OK) return response; @@ -911,6 +911,7 @@ RIB::verify_route(const A& lookup_addr, RibVerifyType matchtype) { const IPRouteEntry* re; + int return_value = (matchtype == RibVerifyType(MISS) ? XORP_OK : XORP_ERROR); // 1. Check for an expected route miss. // 2. Check table entry validity and existence. @@ -965,7 +966,7 @@ RIB::verify_route(const A& lookup_addr, debug_msg("NextHop: Exp: %s != Got: %s\n", nexthop_addr.str().c_str(), route_nexthop->addr().str().c_str()); - return XORP_ERROR; + return return_value; } else { debug_msg("NextHop: Exp: %s != Got: %s\n", nexthop_addr.str().c_str(), @@ -974,7 +975,7 @@ RIB::verify_route(const A& lookup_addr, if (ifname != re->vif()->name()) { XLOG_ERROR("Interface \"%s\" does not match expected \"%s\".", re->vif()->str().c_str(), ifname.c_str()); - return XORP_ERROR; + return return_value; } else { debug_msg("Ifname: Exp: %s == Got: %s\n", ifname.c_str(), @@ -983,12 +984,16 @@ RIB::verify_route(const A& lookup_addr, if (metric != re->metric()) { XLOG_ERROR("Metric \"%u\" does not match expected \"%u\".", XORP_UINT_CAST(re->metric()), XORP_UINT_CAST(metric)); - return XORP_ERROR; + return return_value; } else { debug_msg("Metric: Exp: %u == Got: %u\n", XORP_UINT_CAST(metric), XORP_UINT_CAST(re->metric())); } + if (matchtype == RibVerifyType(MISS)) { + XLOG_ERROR("****We got valid IP route, but we expected MISS****\n"); + return XORP_ERROR; + } debug_msg("****IP ROUTE SUCCESSFULLY VERIFIED****\n"); return XORP_OK; } diff --git a/xorp/rib/rt_tab_base.hh b/xorp/rib/rt_tab_base.hh index a0b1965d7..58a9915b8 100644 --- a/xorp/rib/rt_tab_base.hh +++ b/xorp/rib/rt_tab_base.hh @@ -168,8 +168,8 @@ public: virtual int add_igp_route(const IPRouteEntry& route) = 0; virtual int add_egp_route(const IPRouteEntry& route) = 0; - virtual int delete_igp_route(const IPRouteEntry* route) = 0; - virtual int delete_egp_route(const IPRouteEntry* route) = 0; + virtual int delete_igp_route(const IPRouteEntry* route, bool b = false) = 0; + virtual int delete_egp_route(const IPRouteEntry* route, bool b = false) = 0; virtual void set_next_table(RouteTable* next_table); diff --git a/xorp/rib/rt_tab_deletion.cc b/xorp/rib/rt_tab_deletion.cc index 3cdadbf5d..c8ddc4fcf 100644 --- a/xorp/rib/rt_tab_deletion.cc +++ b/xorp/rib/rt_tab_deletion.cc @@ -70,7 +70,7 @@ DeletionTable::add_igp_route(const IPRouteEntry& route) // const IPRouteEntry* our_route = *iter; _ip_route_table->erase(route.net()); - this->next_table()->delete_igp_route(our_route); + this->next_table()->delete_igp_route(our_route, true); delete our_route; } @@ -92,7 +92,7 @@ DeletionTable::add_egp_route(const IPRouteEntry& route) // const IPRouteEntry* our_route = *iter; _ip_route_table->erase(route.net()); - this->next_table()->delete_egp_route(our_route); + this->next_table()->delete_egp_route(our_route, true); delete our_route; } @@ -101,22 +101,22 @@ DeletionTable::add_egp_route(const IPRouteEntry& route) template int -DeletionTable::delete_igp_route(const IPRouteEntry* route) +DeletionTable::delete_igp_route(const IPRouteEntry* route, bool b) { // The route MUST NOT be in our trie. XLOG_ASSERT(_ip_route_table->lookup_node(route->net()) == _ip_route_table->end()); - return this->next_table()->delete_igp_route(route); + return this->next_table()->delete_igp_route(route, b); } template int -DeletionTable::delete_egp_route(const IPRouteEntry* route) +DeletionTable::delete_egp_route(const IPRouteEntry* route, bool b) { // The route MUST NOT be in our trie. XLOG_ASSERT(_ip_route_table->lookup_node(route->net()) == _ip_route_table->end()); - return this->next_table()->delete_egp_route(route); + return this->next_table()->delete_egp_route(route, b); } template diff --git a/xorp/rib/rt_tab_deletion.hh b/xorp/rib/rt_tab_deletion.hh index 7f2716ecd..43ed71b51 100644 --- a/xorp/rib/rt_tab_deletion.hh +++ b/xorp/rib/rt_tab_deletion.hh @@ -72,11 +72,11 @@ public: * Delete a route. This route MUST NOT be in the DeletionTable trie. * * @param route the route entry to be deleted. - * @param caller the caller route table. + * @param b determines if the better route is coming right after deleting route * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_igp_route(const IPRouteEntry* route); - int delete_egp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool b = false); + int delete_egp_route(const IPRouteEntry* route, bool b = false); /** * Delete all the routes that are in this DeletionTable. The diff --git a/xorp/rib/rt_tab_extint.cc b/xorp/rib/rt_tab_extint.cc index 02deccac3..0752ac4d7 100644 --- a/xorp/rib/rt_tab_extint.cc +++ b/xorp/rib/rt_tab_extint.cc @@ -126,7 +126,7 @@ ExtIntTable::best_igp_route(const IPRouteEntry& route) _wining_igp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() > route.admin_distance()) { - this->delete_igp_route(*iter); + this->delete_igp_route(*iter, true); _wining_igp_routes.insert(route.net(), &route); return true; } else if ((*iter)->admin_distance() == route.admin_distance()) { @@ -136,25 +136,6 @@ ExtIntTable::best_igp_route(const IPRouteEntry& route) return false; } -template -bool -ExtIntTable::best_egp_route(const IPRouteEntry& route) -{ - typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(route.net()); - if (iter == _wining_egp_routes.end()) { - _wining_egp_routes.insert(route.net(), &route); - return true; - } else if ((*iter)->admin_distance() > route.admin_distance()) { - this->delete_egp_route(*iter); - _wining_egp_routes.insert(route.net(), &route); - return true; - } else if ((*iter)->admin_distance() == route.admin_distance()) { - // It's best EGP Route, but it wasn't overall best route when we added it first time - return true; - } - return false; -} - template int ExtIntTable::add_igp_route(const IPRouteEntry& route) @@ -233,6 +214,20 @@ ExtIntTable::add_direct_egp_route(const IPRouteEntry& route) return XORP_OK; } +template +void +ExtIntTable::create_unresolved_route(const IPRouteEntry& route) +{ + UnresolvedIPRouteEntry* unresolved_route = + new UnresolvedIPRouteEntry(&route); + + _ip_unresolved_table.insert(make_pair(route.net(), unresolved_route)); + typename UnresolvedRouteBackLink::iterator backlink = + _ip_unresolved_nexthops.insert(make_pair(route.nexthop_addr(), unresolved_route)); + + unresolved_route->set_backlink(backlink); +} + template int ExtIntTable::add_indirect_egp_route(const IPRouteEntry& route) @@ -244,14 +239,7 @@ ExtIntTable::add_indirect_egp_route(const IPRouteEntry& route) if (nexthop_route == NULL) { // Store the fact that this was unresolved for later debug_msg("nexthop %s was unresolved\n", rt_nexthop->addr().str().c_str()); - UnresolvedIPRouteEntry* unresolved_route = - new UnresolvedIPRouteEntry(&route); - - _ip_unresolved_table.insert(make_pair(route.net(), unresolved_route)); - typename UnresolvedRouteBackLink::iterator backlink = - _ip_unresolved_nexthops.insert(make_pair(rt_nexthop->addr(), unresolved_route)); - - unresolved_route->set_backlink(backlink); + create_unresolved_route(route); return XORP_ERROR; } else { const IPRouteEntry* found = lookup_route(route.net()); @@ -293,10 +281,6 @@ ExtIntTable::add_egp_route(const IPRouteEntry& route) // The new route comes from the EGP table debug_msg("route comes from EGP %s\n", route.str().c_str()); - // Is it the best EGP route? - if (!best_egp_route(route)) - return XORP_ERROR; - if (route.nexthop()->type() == PEER_NEXTHOP) return add_direct_egp_route(route); else @@ -343,22 +327,6 @@ ExtIntTable::deleting_best_igp_route(const IPRouteEntry* route) return false; } -template -bool -ExtIntTable::deleting_best_egp_route(const IPRouteEntry* route) -{ - typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(route->net()); - if (iter != _wining_egp_routes.end()) { - if ((*iter)->admin_distance() != route->admin_distance()) - return false; - else { - _wining_egp_routes.erase(route->net()); - return true; - } - } - return false; -} - template const IPRouteEntry* ExtIntTable::masked_route(const IPRouteEntry* route) @@ -376,7 +344,7 @@ ExtIntTable::masked_route(const IPRouteEntry* route) template void -ExtIntTable::delete_resolved_routes(const IPRouteEntry* route) +ExtIntTable::delete_resolved_routes(const IPRouteEntry* route, bool b) { const ResolvedIPRouteEntry* found_resolved = lookup_by_igp_parent(route->net()); @@ -405,63 +373,75 @@ ExtIntTable::delete_resolved_routes(const IPRouteEntry* route) // old pointer with the existing pointer. // That way we don't have any memory leaking. - add_egp_route(*egp_parent); + if (!b) + add_egp_route(*egp_parent); + else + create_unresolved_route(*egp_parent); + found_resolved = lookup_by_igp_parent(route->net()); } } template int -ExtIntTable::delete_igp_route(const IPRouteEntry* route) +ExtIntTable::delete_best_igp_route(const IPRouteEntry* route, bool b) { XLOG_ASSERT(_igp_ad_set.find(route->admin_distance()) != _igp_ad_set.end()); debug_msg(" called from _int_table\n"); debug_msg("route comes from IGP %s\n", route->str().c_str()); // If it came here, than we're certainly deleting wining IGP route - if (!deleting_best_igp_route(route)) - return XORP_ERROR; + const IPRouteEntry* found_route = lookup_route(route->net()); - const IPRouteEntry* found_route = NULL; + if (found_route) { + if (found_route->admin_distance() < route->admin_distance()) + // This route wasn't the best route overall + return XORP_ERROR; - if (!_egp_ad_set.empty()) { - found_route = lookup_route(route->net()); - - if (found_route != NULL) { - if (found_route->admin_distance() == route->admin_distance()) - // This route was the best route overall - found_route = NULL; - else { - // Our route wasn't the best route overall - XLOG_ASSERT(found_route->admin_distance() < route->admin_distance()); - return XORP_ERROR; + // Our route was the best route overall + XLOG_ASSERT(found_route->admin_distance() == route->admin_distance()); + + // Propagate the original delete + _wining_routes.erase(route->net()); + this->next_table()->delete_igp_route(route); + + if (!_egp_ad_set.empty()) + delete_resolved_routes(route, b); + + if (!b) { + const IPRouteEntry* found_route = masked_route(route); + + if (found_route) { + if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) + add_igp_route(*found_route); + else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) + add_egp_route(*found_route); + else + XLOG_UNREACHABLE(); } } - - delete_resolved_routes(route); } - // Propagate the original delete - _wining_routes.erase(route->net()); + return XORP_OK; +} - this->next_table()->delete_igp_route(route); +template +int +ExtIntTable::delete_igp_route(const IPRouteEntry* route, bool b) +{ + debug_msg(" called from _int_table\n"); + debug_msg("route comes from IGP %s\n", route->str().c_str()); + // If it came here, than we're certainly deleting wining IGP route - found_route = masked_route(route); + if (!deleting_best_igp_route(route)) + return XORP_ERROR; - if (found_route) { - if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) - add_igp_route(*found_route); - else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) - add_egp_route(*found_route); - else - XLOG_UNREACHABLE(); - } - return XORP_OK; + return delete_best_igp_route(route, b); } template int -ExtIntTable::delete_egp_route(const IPRouteEntry* route) +ExtIntTable::delete_egp_route(const IPRouteEntry* route, bool b) { XLOG_ASSERT(_egp_ad_set.find(route->admin_distance()) != _egp_ad_set.end()); debug_msg("ExtIntTable::delete_route %s\n", route->str().c_str()); @@ -469,30 +449,24 @@ ExtIntTable::delete_egp_route(const IPRouteEntry* route) debug_msg("route comes from EGP %s\n", route->str().c_str()); - if (!deleting_best_egp_route(route)) - return XORP_ERROR; - const IPRouteEntry* found_route = lookup_route(route->net()); - if (found_route != NULL) { - if (found_route->admin_distance() == route->admin_distance()) - found_route = NULL; - else if (found_route->admin_distance() < route->admin_distance()) { + if (found_route && (found_route->admin_distance() < route->admin_distance())) { //Our route wasn't the best overall - delete_ext_route(found_route, false); return XORP_OK; - } } - found_route = masked_route(route); + if (!b) { + found_route = masked_route(route); - if (this->delete_ext_route(route) && found_route) { - if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) - add_igp_route(*found_route); - else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) - add_egp_route(*found_route); - else - XLOG_UNREACHABLE(); + if (this->delete_ext_route(route) && found_route) { + if (_igp_ad_set.find(found_route->admin_distance()) != _igp_ad_set.end()) + add_igp_route(*found_route); + else if (_egp_ad_set.find(found_route->admin_distance()) != _egp_ad_set.end()) + add_egp_route(*found_route); + else + XLOG_UNREACHABLE(); + } } return XORP_OK; @@ -772,22 +746,6 @@ ExtIntTable::lookup_winning_igp_route(const A& addr) const return ((iter == _wining_igp_routes.end()) ? NULL : *iter); } -template -inline const IPRouteEntry* -ExtIntTable::lookup_winning_egp_route(const IPNet& ipnet) const -{ - typename RouteTrie::iterator iter = _wining_egp_routes.lookup_node(ipnet); - return ((iter == _wining_egp_routes.end()) ? NULL : *iter); -} - -template -inline const IPRouteEntry* -ExtIntTable::lookup_winning_egp_route(const A& addr) const -{ - typename RouteTrie::iterator iter = _wining_egp_routes.find(addr); - return ((iter == _wining_egp_routes.end()) ? NULL : *iter); -} - template RouteRange* ExtIntTable::lookup_route_range(const A& addr) const diff --git a/xorp/rib/rt_tab_extint.hh b/xorp/rib/rt_tab_extint.hh index 2c4aa283f..47cfe0728 100644 --- a/xorp/rib/rt_tab_extint.hh +++ b/xorp/rib/rt_tab_extint.hh @@ -97,9 +97,11 @@ public: * @param caller the parent table sending the delete_route. * @return XORP_OK on success, otherwise XORP_ERROR. */ - int delete_igp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool b); - int delete_egp_route(const IPRouteEntry* route); + int delete_best_igp_route(const IPRouteEntry* route, bool b); + + int delete_egp_route(const IPRouteEntry* route, bool b); /** * Lookup a specific subnet. The lookup will first look in the @@ -206,19 +208,15 @@ private: const IPNet& subnet) const; const IPRouteEntry* lookup_winning_igp_route(const A& addr) const; - const IPRouteEntry* lookup_winning_egp_route( - const IPNet& subnet) const; - const IPRouteEntry* lookup_winning_egp_route(const A& addr) const; - bool best_igp_route(const IPRouteEntry& route); - bool best_egp_route(const IPRouteEntry& route); bool deleting_best_igp_route(const IPRouteEntry* route); - bool deleting_best_egp_route(const IPRouteEntry* route); const IPRouteEntry* masked_route(const IPRouteEntry* route); - void delete_resolved_routes(const IPRouteEntry* route); + void delete_resolved_routes(const IPRouteEntry* route, bool b); + + void create_unresolved_route(const IPRouteEntry& route); int add_direct_egp_route(const IPRouteEntry& route); int add_indirect_egp_route(const IPRouteEntry& route); @@ -241,8 +239,6 @@ private: // Tries where we cache wining IGP, EGP and overall routes RouteTrie _wining_igp_routes; - RouteTrie _wining_egp_routes; // Here, all wining EGP routes will be stored - //(resolved, unresolved and connected) RouteTrie _wining_routes; // Overall wining routes! static const string& ext_int_name(); diff --git a/xorp/rib/rt_tab_origin.cc b/xorp/rib/rt_tab_origin.cc index 71a57ee9c..5adb4d519 100644 --- a/xorp/rib/rt_tab_origin.cc +++ b/xorp/rib/rt_tab_origin.cc @@ -83,7 +83,7 @@ OriginTable::add_route(IPRouteEntry* route) template int -OriginTable::delete_route(const IPNet& net) +OriginTable::delete_route(const IPNet& net, bool b) { debug_msg("OT[%s]: Deleting route %s\n", this->tablename().c_str(), net.str().c_str()); @@ -98,7 +98,7 @@ OriginTable::delete_route(const IPNet& net) _ip_route_table->erase(net); // Propagate to next table XLOG_ASSERT(this->next_table() != NULL); - this->generic_delete_route(found); + this->generic_delete_route(found, b); // Finally we're done, and can cleanup delete found; diff --git a/xorp/rib/rt_tab_origin.hh b/xorp/rib/rt_tab_origin.hh index ce6559d75..201801fcd 100644 --- a/xorp/rib/rt_tab_origin.hh +++ b/xorp/rib/rt_tab_origin.hh @@ -88,10 +88,10 @@ public: * @param net the subnet of the route entry to be deleted. * @return XORP_OK on success, otherwise XORP_ERROR. */ - virtual int delete_route(const IPNet& net); + virtual int delete_route(const IPNet& net, bool b = false); - int delete_igp_route(const IPRouteEntry*) { return XORP_ERROR; }; - int delete_egp_route(const IPRouteEntry*) { return XORP_ERROR; }; + int delete_igp_route(const IPRouteEntry*, bool) { return XORP_ERROR; }; + int delete_egp_route(const IPRouteEntry*, bool) { return XORP_ERROR; }; /** * Delete all the routes that are in this OriginTable. The @@ -174,7 +174,7 @@ protected: RouteTrie* _ip_route_table; uint32_t _gen; - virtual int generic_delete_route(const IPRouteEntry*) = 0; + virtual int generic_delete_route(const IPRouteEntry*, bool) = 0; virtual int generic_add_route(const IPRouteEntry&) = 0; virtual void allocate_deletion_table(RouteTrie* ip_route_trie) = 0; }; @@ -190,7 +190,10 @@ public: ~TypedOriginTable() {} int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_igp_route(route); } - int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_igp_route(route); } + int generic_delete_route(const IPRouteEntry* route, bool b) + { + return this->next_table()->delete_igp_route(route, b); + } int protocol_type() const { return _protocol.protocol_type();} const Protocol& protocol() const { return _protocol;} @@ -210,7 +213,10 @@ public: ~TypedOriginTable() {} int generic_add_route(const IPRouteEntry& route) { return this->next_table()->add_egp_route(route); } - int generic_delete_route(const IPRouteEntry* route) { return this->next_table()->delete_egp_route(route); } + int generic_delete_route(const IPRouteEntry* route, bool b) + { + return this->next_table()->delete_egp_route(route, b); + } int protocol_type() const { return _protocol.protocol_type();} const Protocol& protocol() const { return _protocol;} diff --git a/xorp/rib/rt_tab_pol_conn.cc b/xorp/rib/rt_tab_pol_conn.cc index 4d363809b..1de97e833 100644 --- a/xorp/rib/rt_tab_pol_conn.cc +++ b/xorp/rib/rt_tab_pol_conn.cc @@ -112,24 +112,24 @@ PolicyConnectedTable::generic_delete_route(const IPRouteEntry* route) template int -PolicyConnectedTable::delete_igp_route(const IPRouteEntry* route) +PolicyConnectedTable::delete_igp_route(const IPRouteEntry* route, bool b) { this->generic_delete_route(route); XLOG_ASSERT(this->next_table()); // propagate the delete - return this->next_table()->delete_igp_route(route); + return this->next_table()->delete_igp_route(route, b); } template int -PolicyConnectedTable::delete_egp_route(const IPRouteEntry* route) +PolicyConnectedTable::delete_egp_route(const IPRouteEntry* route, bool b) { this->generic_delete_route(route); XLOG_ASSERT(this->next_table()); // propagate the delete - return this->next_table()->delete_egp_route(route); + return this->next_table()->delete_egp_route(route, b); } template diff --git a/xorp/rib/rt_tab_pol_conn.hh b/xorp/rib/rt_tab_pol_conn.hh index 614f5472e..e7d019936 100644 --- a/xorp/rib/rt_tab_pol_conn.hh +++ b/xorp/rib/rt_tab_pol_conn.hh @@ -53,9 +53,9 @@ public: ~PolicyConnectedTable(); int add_igp_route(const IPRouteEntry& route); - int delete_igp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool b); int add_egp_route(const IPRouteEntry& route); - int delete_egp_route(const IPRouteEntry* route); + int delete_egp_route(const IPRouteEntry* route, bool b); TableType type() const { return POLICY_CONNECTED_TABLE; } diff --git a/xorp/rib/rt_tab_pol_redist.cc b/xorp/rib/rt_tab_pol_redist.cc index 829f047ff..34377ee37 100644 --- a/xorp/rib/rt_tab_pol_redist.cc +++ b/xorp/rib/rt_tab_pol_redist.cc @@ -111,24 +111,24 @@ PolicyRedistTable::generic_delete_route(const IPRouteEntry* route) template int -PolicyRedistTable::delete_igp_route(const IPRouteEntry* route) +PolicyRedistTable::delete_igp_route(const IPRouteEntry* route, bool b) { this->generic_delete_route(route); XLOG_ASSERT(this->next_table() != NULL); - return this->next_table()->delete_igp_route(route); + return this->next_table()->delete_igp_route(route, b); } template int -PolicyRedistTable::delete_egp_route(const IPRouteEntry* route) +PolicyRedistTable::delete_egp_route(const IPRouteEntry* route, bool b) { this->generic_delete_route(route); XLOG_ASSERT(this->next_table() != NULL); - return this->next_table()->delete_egp_route(route); + return this->next_table()->delete_egp_route(route, b); } template diff --git a/xorp/rib/rt_tab_pol_redist.hh b/xorp/rib/rt_tab_pol_redist.hh index 5fa256017..fe0e46fe6 100644 --- a/xorp/rib/rt_tab_pol_redist.hh +++ b/xorp/rib/rt_tab_pol_redist.hh @@ -130,8 +130,8 @@ public: int add_igp_route(const IPRouteEntry& router); int add_egp_route(const IPRouteEntry& router); - int delete_igp_route(const IPRouteEntry* route); - int delete_egp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool); + int delete_egp_route(const IPRouteEntry* route, bool); TableType type() const { return POLICY_REDIST_TABLE; } string str() const; diff --git a/xorp/rib/rt_tab_redist.cc b/xorp/rib/rt_tab_redist.cc index 5de5cc6f4..354ae2e06 100644 --- a/xorp/rib/rt_tab_redist.cc +++ b/xorp/rib/rt_tab_redist.cc @@ -476,24 +476,24 @@ RedistTable::generic_delete_route(const IPRouteEntry* route) template int -RedistTable::delete_igp_route(const IPRouteEntry* r) +RedistTable::delete_igp_route(const IPRouteEntry* r, bool b) { this->generic_delete_route(r); if (this->next_table()) - return this->next_table()->delete_igp_route(r); + return this->next_table()->delete_igp_route(r, b); return XORP_OK; } template int -RedistTable::delete_egp_route(const IPRouteEntry* r) +RedistTable::delete_egp_route(const IPRouteEntry* r, bool b) { this->generic_delete_route(r); if (this->next_table()) - return this->next_table()->delete_egp_route(r); + return this->next_table()->delete_egp_route(r, b); return XORP_OK; } diff --git a/xorp/rib/rt_tab_redist.hh b/xorp/rib/rt_tab_redist.hh index 1b70f4541..d92d2a283 100644 --- a/xorp/rib/rt_tab_redist.hh +++ b/xorp/rib/rt_tab_redist.hh @@ -112,8 +112,8 @@ public: // int add_igp_route(const IPRouteEntry& route); int add_egp_route(const IPRouteEntry& route); - int delete_igp_route(const IPRouteEntry* route); - int delete_egp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool b); + int delete_egp_route(const IPRouteEntry* route, bool b); const IPRouteEntry* lookup_ip_route(const IPNet& net) const; diff --git a/xorp/rib/rt_tab_register.cc b/xorp/rib/rt_tab_register.cc index 88e0976a5..3b66065b3 100644 --- a/xorp/rib/rt_tab_register.cc +++ b/xorp/rib/rt_tab_register.cc @@ -288,10 +288,10 @@ RegisterTable::generic_delete_route(const IPRouteEntry* route) template int -RegisterTable::delete_igp_route(const IPRouteEntry* route) +RegisterTable::delete_igp_route(const IPRouteEntry* route, bool b) { XLOG_ASSERT(this->next_table() != NULL); - this->next_table()->delete_igp_route(route); + this->next_table()->delete_igp_route(route, b); this->generic_delete_route(route); return XORP_OK; @@ -299,10 +299,10 @@ RegisterTable::delete_igp_route(const IPRouteEntry* route) template int -RegisterTable::delete_egp_route(const IPRouteEntry* route) +RegisterTable::delete_egp_route(const IPRouteEntry* route, bool b) { XLOG_ASSERT(this->next_table() != NULL); - this->next_table()->delete_egp_route(route); + this->next_table()->delete_egp_route(route, b); this->generic_delete_route(route); return XORP_OK; diff --git a/xorp/rib/rt_tab_register.hh b/xorp/rib/rt_tab_register.hh index 9b0d4ca55..4c9f0c755 100644 --- a/xorp/rib/rt_tab_register.hh +++ b/xorp/rib/rt_tab_register.hh @@ -291,8 +291,8 @@ public: int add_igp_route(const IPRouteEntry& route); int add_egp_route(const IPRouteEntry& route); - int delete_igp_route(const IPRouteEntry* route); - int delete_egp_route(const IPRouteEntry* route); + int delete_igp_route(const IPRouteEntry* route, bool); + int delete_egp_route(const IPRouteEntry* route, bool); /** * Lookup a route_range in the RIB. This request will be diff --git a/xorp/rib/tests/rt_tab_expect.hh b/xorp/rib/tests/rt_tab_expect.hh index a12aee735..1384811a0 100644 --- a/xorp/rib/tests/rt_tab_expect.hh +++ b/xorp/rib/tests/rt_tab_expect.hh @@ -55,8 +55,8 @@ public: int add_igp_route(const IPRouteEntry& route) { return this->add_route(route); } int add_egp_route(const IPRouteEntry& route) { return this->add_route(route); } int add_route(const IPRouteEntry& route); - int delete_igp_route(const IPRouteEntry* route) { return this->delete_route(route); } - int delete_egp_route(const IPRouteEntry* route) { return this->delete_route(route); } + int delete_igp_route(const IPRouteEntry* route, bool) { return this->delete_route(route); } + int delete_egp_route(const IPRouteEntry* route, bool) { return this->delete_route(route); } int delete_route(const IPRouteEntry* route); const IPRouteEntry* lookup_route(const IPNet& net) const; const IPRouteEntry* lookup_route(const A& addr) const;