Line data Source code
1 : /* 2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "bgp/inet6vpn/inet6vpn_table.h" 6 : 7 : #include "bgp/ipeer.h" 8 : #include "bgp/bgp_server.h" 9 : #include "bgp/bgp_peer.h" 10 : #include "bgp/bgp_update.h" 11 : #include "bgp/inet6/inet6_table.h" 12 : #include "bgp/routing-instance/routing_instance.h" 13 : #include "net/rd.h" 14 : 15 8227 : Inet6VpnTable::Inet6VpnTable(DB *db, const std::string &name) 16 8227 : : BgpTable(db, name) { 17 8227 : } 18 : 19 : std::unique_ptr<DBEntry> 20 100218 : Inet6VpnTable::AllocEntry(const DBRequestKey *key) const { 21 100218 : const RequestKey *pfxkey = static_cast<const RequestKey *>(key); 22 100218 : return std::unique_ptr<DBEntry>(new Inet6VpnRoute(pfxkey->prefix)); 23 : } 24 : 25 : std::unique_ptr<DBEntry> 26 12 : Inet6VpnTable::AllocEntryStr(const std::string &key_str) const { 27 12 : Inet6VpnPrefix vpn_prefix = Inet6VpnPrefix::FromString(key_str); 28 24 : return std::unique_ptr<DBEntry> (new Inet6VpnRoute(vpn_prefix)); 29 : } 30 : 31 1236806 : size_t Inet6VpnTable::Hash(const DBEntry *entry) const { 32 1236806 : const Inet6VpnRoute *vpn_route = static_cast<const Inet6VpnRoute *>(entry); 33 1236806 : const Inet6VpnPrefix &vpn_prefix = vpn_route->GetPrefix(); 34 1237090 : Inet6Prefix prefix(vpn_prefix.addr(), vpn_prefix.prefixlen()); 35 1236772 : size_t value = Inet6Table::HashFunction(prefix); 36 1236267 : return value % DB::PartitionCount(); 37 : } 38 : 39 64816 : size_t Inet6VpnTable::Hash(const DBRequestKey *key) const { 40 64816 : const RequestKey *rkey = static_cast<const RequestKey *>(key); 41 64816 : Inet6Prefix prefix(rkey->prefix.addr(), rkey->prefix.prefixlen()); 42 64816 : size_t value = Inet6Table::HashFunction(prefix); 43 64816 : return value % DB::PartitionCount(); 44 : } 45 : 46 63048 : BgpRoute *Inet6VpnTable::TableFind(DBTablePartition *rtp, 47 : const DBRequestKey *prefix) { 48 63048 : const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix); 49 63048 : Inet6VpnRoute vpn_route(pfxkey->prefix); 50 126089 : return static_cast<BgpRoute *>(rtp->Find(&vpn_route)); 51 63072 : } 52 : 53 8227 : DBTableBase *Inet6VpnTable::CreateTable(DB *db, const std::string &name) { 54 8227 : Inet6VpnTable *table = new Inet6VpnTable(db, name); 55 8227 : table->Init(); 56 8227 : return table; 57 : } 58 : 59 20336 : static RouteDistinguisher GenerateDistinguisher( 60 : const BgpTable *src_table, const BgpPath *src_path) { 61 20336 : const RouteDistinguisher &source_rd = src_path->GetAttr()->source_rd(); 62 20336 : if (!src_path->GetPeer() || !(src_path->GetPeer()->IsRouterTypeBGPaaS())){ 63 19106 : if (!source_rd.IsZero()) 64 11439 : return source_rd; 65 : 66 7667 : assert(!src_path->GetPeer() || !src_path->GetPeer()->IsXmppPeer()); 67 7667 : const RoutingInstance *src_instance = src_table->routing_instance(); 68 7667 : return *src_instance->GetRD(); 69 : } 70 1230 : uint16_t peer_port_id = 0; 71 1230 : as_t asn_num = src_path->GetAttr()->neighbor_as(); 72 : 73 1230 : std::string ri_name = src_table->routing_instance()->name(); 74 2460 : for (const BgpPeer *peer = src_path->GetPeer()->server()->FindNextPeer(); peer != NULL; 75 1230 : peer = src_path->GetPeer()->server()->FindNextPeer(peer->peer_name())) { 76 3690 : if ((peer->peer_name().find(ri_name)!= std::string::npos)&& 77 3690 : (peer->peer_address_string().find(src_path->GetPeer()->ToString())!= std::string::npos)){ 78 1230 : peer_port_id = peer->peer_port(); 79 1230 : asn_num = peer->peer_as(); 80 1230 : break; 81 : } 82 : } 83 1230 : RouteDistinguisher new_source_rd = RouteDistinguisher(true, asn_num, peer_port_id); 84 1230 : return new_source_rd; 85 1230 : } 86 : 87 20336 : BgpRoute *Inet6VpnTable::RouteReplicate(BgpServer *server, BgpTable *src_table, 88 : BgpRoute *source_rt, const BgpPath *src_path, 89 : ExtCommunityPtr community) { 90 20336 : assert(src_table->family() == Address::INET6); 91 : 92 20336 : Inet6Route *src_rt = dynamic_cast<Inet6Route *>(source_rt); 93 20336 : assert(src_rt); 94 : 95 20336 : const RouteDistinguisher &rd = GenerateDistinguisher(src_table, src_path); 96 20336 : Inet6VpnPrefix vpn_prefix(rd, src_rt->GetPrefix().ip6_addr(), 97 40672 : src_rt->GetPrefix().prefixlen()); 98 : 99 20336 : Inet6VpnRoute vpn_route(vpn_prefix); 100 : DBTablePartition *partition = 101 20335 : static_cast<DBTablePartition *>(GetTablePartition(&vpn_route)); 102 20333 : BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&vpn_route)); 103 20335 : if (dest_route == NULL) { 104 12188 : dest_route = new Inet6VpnRoute(vpn_prefix); 105 12187 : partition->Add(dest_route); 106 : } else { 107 8147 : dest_route->ClearDelete(); 108 : } 109 : 110 20334 : BgpAttrDB *attr_db = server->attr_db(); 111 : 112 : BgpAttrPtr new_attr = 113 : server->attr_db()->ReplaceExtCommunityAndLocate(src_path->GetAttr(), 114 20333 : community); 115 20336 : new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd); 116 : 117 : // Check whether there's already a path with the given peer and path id. 118 : BgpPath *dest_path = 119 20336 : dest_route->FindSecondaryPath(source_rt, src_path->GetSource(), 120 : src_path->GetPeer(), 121 : src_path->GetPathId()); 122 20336 : if (dest_path != NULL) { 123 14170 : if ((new_attr != dest_path->GetOriginalAttr()) || 124 14170 : (src_path->GetFlags() != dest_path->GetFlags()) || 125 3805 : (src_path->GetLabel() != dest_path->GetLabel())) { 126 : // Update Attributes and notify (if needed) 127 4058 : assert(dest_route->RemoveSecondaryPath(source_rt, 128 : src_path->GetSource(), src_path->GetPeer(), 129 : src_path->GetPathId())); 130 : } else { 131 3746 : return dest_route; 132 : } 133 : } 134 : 135 : // Create replicated path and insert it on the route 136 : BgpSecondaryPath *replicated_path = 137 16590 : new BgpSecondaryPath(src_path->GetPeer(), src_path->GetPathId(), 138 16590 : src_path->GetSource(), new_attr, 139 16590 : src_path->GetFlags(), src_path->GetLabel()); 140 16590 : replicated_path->SetReplicateInfo(src_table, source_rt); 141 16590 : dest_route->InsertPath(replicated_path); 142 : 143 : // Always trigger notification. 144 16590 : partition->Notify(dest_route); 145 : 146 16590 : return dest_route; 147 20336 : } 148 : 149 119470 : bool Inet6VpnTable::Export(RibOut *ribout, Route *route, 150 : const RibPeerSet &peerset, UpdateInfoSList &uinfo_slist) { 151 119470 : BgpRoute *bgp_route = static_cast<BgpRoute *> (route); 152 119470 : UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset); 153 119464 : if (!uinfo) { 154 53544 : return false; 155 : } 156 65920 : uinfo_slist->push_front(*uinfo); 157 : 158 65971 : return true; 159 : } 160 : 161 159 : static void RegisterFactory() { 162 159 : DB::RegisterFactory("bgp.l3vpn-inet6.0", &Inet6VpnTable::CreateTable); 163 159 : } 164 : MODULE_INITIALIZER(RegisterFactory);