12 #include <arpa/inet.h> 14 #define MAKE_ENTRY6(r, e) std::make_pair(BgpRib6EntryKey(r), e) 28 const uint8_t nexthop_linklocal[16],
const std::vector<std::shared_ptr<BgpPathAttrib>> attribs)
31 memcpy(this->nexthop_global, nexthop_global, 16);
32 if (nexthop_linklocal != NULL) memcpy(this->nexthop_linklocal, nexthop_linklocal, 16);
33 else memset(this->nexthop_linklocal, 0, 16);
44 this->logger = logger;
48 rib6_t::iterator BgpRib6::find_entry(
const Prefix6 &prefix, uint32_t
src) {
49 std::pair<rib6_t::iterator, rib6_t::iterator> its =
52 if (its.first == rib.end())
return rib.end();
54 for (rib6_t::iterator it = its.first; it != its.second; it++) {
55 if (it->second.route == prefix && it->second.src_router_id == src) {
63 rib6_t::iterator BgpRib6::find_best (
const Prefix6 &prefix) {
64 std::pair<rib6_t::iterator, rib6_t::iterator> its =
67 rib6_t::iterator best = rib.end();
68 if (its.first == rib.end())
return rib.end();
70 for (rib6_t::iterator it = its.first; it != its.second; it++) {
71 if (it->second.route == prefix) {
72 if (best == rib.end()) best = it;
74 const BgpRib6Entry *best_ptr = selectEntry(&(best->second), &(it->second));
75 best = best_ptr == &(best->second) ? best : it;
83 std::pair<const BgpRib6Entry*, bool> BgpRib6::insertPriv(uint32_t
src_router_id,
86 const std::vector<std::shared_ptr<BgpPathAttrib>> &
attribs,
87 int32_t
weight, uint32_t ibgp_asn) {
88 std::lock_guard<std::recursive_mutex> lock(mutex);
92 new_entry.
src = ibgp_asn > 0 ? SRC_IBGP : SRC_EBGP;
95 const char *op =
"new_entry";
96 const char *act =
"new_best";
98 std::pair<rib6_t::iterator, rib6_t::iterator> entries = rib.equal_range(
BgpRib6EntryKey(route));
100 bool newly_inserted_is_best =
false;
101 bool best_changed =
false;
102 bool old_exist = entries.first != rib.end();
108 rib6_t::const_iterator to_replace = rib.end();
110 for (rib6_t::iterator it = entries.first; it != entries.second; it++) {
111 if (it->second.route != route)
continue;
112 if (it->second.src_router_id == src_router_id) {
116 old_best = selectEntry(old_best, &(it->second));
120 const BgpRib6Entry *candidate = selectEntry(&new_entry, old_best);
121 if (candidate == old_best) {
122 new_entry.
status = RS_STANDBY;
123 act =
"not_new_best";
125 if (old_best != NULL) old_best->
status = RS_STANDBY;
129 if (to_replace != rib.end()) {
130 const BgpRib6Entry *candidate = selectEntry(&(to_replace->second), old_best);
131 if (candidate == &(to_replace->second)) {
138 rib.erase(to_replace);
141 rib6_t::iterator inserted = rib.insert(MAKE_ENTRY6(route, new_entry));
144 newly_inserted_is_best = candidate == &new_entry;
145 new_best = newly_inserted_is_best ? &(inserted->second) : old_best;
149 best_changed = newly_inserted_is_best =
true;
150 rib6_t::iterator inserted = rib.insert(MAKE_ENTRY6(route, new_entry));
151 new_best = &(inserted->second);
154 if (new_best != NULL) new_best->
status = RS_ACTIVE;
156 LIBBGP_LOG(logger, INFO) {
157 uint8_t prefix_arr[16];
159 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET6_ADDRSTRLEN];
160 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
161 inet_ntop(AF_INET6, prefix_arr, prefix_str, INET6_ADDRSTRLEN);
162 logger->log(INFO,
"BgpRib6::insertPriv: (%s/%s) group %d, scope %s, route %s/%d\n", op, act, new_entry.
update_id, src_router_id_str, prefix_str, route.
getLength());
165 return std::make_pair(new_best, newly_inserted_is_best);
192 const uint8_t nexthop_global[16],
const uint8_t nexthop_linklocal[16], int32_t weight) {
193 std::vector<std::shared_ptr<BgpPathAttrib>>
attribs;
196 origin->origin = IGP;
198 attribs.push_back(std::shared_ptr<BgpPathAttrib>(origin));
199 attribs.push_back(std::shared_ptr<BgpPathAttrib>(as_path));
201 BgpRib6Entry new_entry(route, 0, nexthop_global, nexthop_linklocal, attribs);
205 for (
const auto &entry : rib) {
206 if (entry.second.src_router_id == 0 && entry.second.route == route) {
207 this->logger->
log(ERROR,
"BgpRib6::insert: route exists.\n");
212 if (entry.second.src_router_id == 0) {
213 if (memcmp(new_entry.
nexthop_global, entry.second.nexthop_global, 16) == 0 &&
215 use_update_id = entry.second.update_id;
220 std::lock_guard<std::recursive_mutex> lock(mutex);
223 rib6_t::const_iterator it = rib.insert(MAKE_ENTRY6(route, new_entry));
225 return &(it->second);
243 const std::vector<Prefix6> &routes,
const uint8_t nexthop_global[16],
244 const uint8_t nexthop_linklocal[16], int32_t weight) {
245 std::vector<BgpRib6Entry> inserted;
246 std::vector<std::shared_ptr<BgpPathAttrib>>
attribs;
249 origin->origin = IGP;
251 attribs.push_back(std::shared_ptr<BgpPathAttrib>(origin));
252 attribs.push_back(std::shared_ptr<BgpPathAttrib>(as_path));
254 for (
const Prefix6 &route : routes) {
255 rib6_t::const_iterator it = find_entry(route, 0);
257 if (it != rib.end())
continue;
259 BgpRib6Entry new_entry (route, 0, nexthop_global, nexthop_linklocal, attribs);
262 rib6_t::const_iterator isrt_it = rib.insert(MAKE_ENTRY6(route, new_entry));
263 inserted.push_back(isrt_it->second);
292 const uint8_t nexthop_global[16],
const uint8_t nexthop_linklocal[16],
293 const std::vector<std::shared_ptr<BgpPathAttrib>> &
attribs, int32_t weight,
297 return insertPriv(src_router_id, route, nexthop_global, nexthop_linklocal,
attribs, weight, ibgp_asn);
313 uint32_t src_router_id,
const std::vector<Prefix6> &routes,
314 const uint8_t nexthop_global[16],
const uint8_t nexthop_linklocal[16],
315 const std::vector<std::shared_ptr<BgpPathAttrib>> &
attribs, int32_t weight, uint32_t ibgp_asn) {
317 std::vector<BgpRib6Entry> updated;
318 std::vector<Prefix6> unchanged;
319 for (
const Prefix6 &route : routes) {
320 std::pair<const BgpRib6Entry*, bool> rslt = insertPriv(src_router_id, route, nexthop_global, nexthop_linklocal,
attribs, weight, ibgp_asn);
321 if (rslt.first != NULL) {
322 if (!rslt.second) updated.push_back(*(rslt.first));
323 else unchanged.push_back(route);
326 return std::make_pair(updated, unchanged);
342 std::lock_guard<std::recursive_mutex> lock(mutex);
344 std::pair<rib6_t::iterator, rib6_t::iterator> old_entries =
347 if (old_entries.first == rib.end())
348 return std::make_pair<bool, const BgpRib6Entry*>(
false, NULL);
350 const char *op =
"dropped/no_change";
354 rib6_t::const_iterator to_remove = rib.end();
356 for (rib6_t::iterator it = old_entries.first; it != old_entries.second; it++) {
357 if (it->second.route == route) {
358 if (it->second.src_router_id == src_router_id) {
362 replacement = selectEntry(replacement, &(it->second));
366 bool reachabled =
true;
368 if (to_remove == rib.end())
369 return std::make_pair<bool, const BgpRib6Entry*>(
false, NULL);
371 if (replacement != NULL) {
372 if (to_remove->second.status == RS_ACTIVE) {
373 op =
"dropped/best_changed";
374 }
else replacement = NULL;
377 op =
"dropped/unreachabled";
380 rib.erase(to_remove);
381 if (replacement != NULL) replacement->
status = RS_ACTIVE;
383 LIBBGP_LOG(logger, INFO) {
384 uint8_t prefix_arr[16];
386 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET6_ADDRSTRLEN];
387 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
388 inet_ntop(AF_INET6, prefix_arr, prefix_str, INET6_ADDRSTRLEN);
389 logger->log(INFO,
"BgpRib6::withdraw: (%s) scope %s, route %s/%d\n", op, src_router_id_str, prefix_str, route.
getLength());
392 return std::pair<bool, const BgpRib6Entry*>(reachabled, replacement);
403 std::pair<std::vector<Prefix6>, std::vector<BgpRib6Entry>>
BgpRib6::discard(uint32_t src_router_id) {
404 std::lock_guard<std::recursive_mutex> lock(mutex);
422 std::vector<Prefix6> reevaluate_routes;
423 std::vector<Prefix6> dropped_routes;
425 for (rib6_t::const_iterator it = rib.begin(); it != rib.end();) {
426 const char *op =
"dropped/silent";
427 if (it->second.src_router_id != src_router_id) {
431 if (it->second.status == RS_ACTIVE) {
432 reevaluate_routes.push_back(it->second.route);
433 op =
"dropped/pending-reevaluate";
435 LIBBGP_LOG(logger, INFO) {
436 uint8_t prefix_arr[16];
437 it->second.route.getPrefix(prefix_arr);
438 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET6_ADDRSTRLEN];
439 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
440 inet_ntop(AF_INET6, prefix_arr, prefix_str, INET6_ADDRSTRLEN);
441 logger->log(INFO,
"BgpRib6::discard: (%s) scope %s, route %s/%d\n", op, src_router_id_str, prefix_str, it->second.route.getLength());
446 std::vector<BgpRib6Entry> replacements;
448 for (std::vector<Prefix6>::const_iterator it = reevaluate_routes.begin(); it != reevaluate_routes.end(); it++) {
449 const char *op =
"replacement found";
451 rib6_t::iterator replacement = find_best(prefix);
452 if (replacement == rib.end()) {
453 dropped_routes.push_back(prefix);
454 op =
"no available replacement";
456 replacement->second.status = RS_ACTIVE;
457 replacements.push_back(replacement->second);
460 LIBBGP_LOG(logger, INFO) {
461 uint8_t prefix_arr[16];
463 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET6_ADDRSTRLEN];
464 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
465 inet_ntop(AF_INET6, prefix_arr, prefix_str, INET6_ADDRSTRLEN);
466 logger->log(INFO,
"BgpRib6::discard: (%s) scope %s, route %s/%d\n", op, src_router_id_str, prefix_str, prefix.
getLength());
470 return std::make_pair(dropped_routes, replacements);
492 for (
const auto &entry : rib) {
493 if (entry.second.status != RS_ACTIVE)
continue;
494 if (entry.second.route.includes(dest))
return &entry.second;
524 for (
const auto &entry : rib) {
525 if (entry.second.status != RS_ACTIVE)
continue;
526 if (entry.second.src_router_id != src_router_id)
continue;
527 if (entry.second.route.includes(dest))
return &entry.second;
IPv6 Route/Prefix related utilities.
std::vector< std::shared_ptr< BgpPathAttrib > > attribs
Path attributes for this entry.
Key for the Rib6 entry map.
BgpRib6Entry(Prefix6 r, uint32_t src, const uint8_t nexthop_global[16], const uint8_t nexthop_linklocal[16], const std::vector< std::shared_ptr< BgpPathAttrib >> attribs)
Construct a new BgpRib6Entry.
uint8_t getLength() const
Get netmask.
void log(LogLevel level, const char *format_str,...)
Log a message. Consider using LIBBGP_LOG if logging the message needs a lot of computing power...
uint8_t nexthop_global[16]
Global IPv6 address of the next hop in network btyes order.
BgpRouteSource src
Source of this entry.
uint32_t ibgp_peer_asn
ASN of the IBGP peer. (Valid iff src == SRC_IBGP)
int32_t weight
Weight of this entry.
uint32_t src_router_id
The originating BGP speaker's ID of this entry. (network bytes order)
std::pair< bool, const BgpRib6Entry * > withdraw(uint32_t src_router_id, const Prefix6 &route)
Withdraw a route from RIB.
std::pair< std::vector< Prefix6 >, std::vector< BgpRib6Entry > > discard(uint32_t src_router_id)
Drop all routes from RIB that originated from a BGP speaker.
void getPrefix(uint8_t prefix[16]) const
Get prefix.
const BgpRib6Entry * insert(BgpLogHandler *logger, const Prefix6 &route, const uint8_t nexthop_global[16], const uint8_t nexthop_linklocal[16], int32_t weight=0)
Insert a local route into RIB.
Prefix6 route
The prefix of this entry.
BgpRouteStatus status
Status of this entry.
uint64_t update_id
The update ID.
const BgpRib6Entry * lookup(const uint8_t dest[16]) const
Lookup a destination in RIB.
uint8_t nexthop_linklocal[16]
Link local IPv6 address of the next hop in network btyes order. (all 0 if not avaliable) ...
const rib6_t & get() const
Get the RIB.
The BGP Routing Information Base for IPv6.
BgpRib6(BgpLogHandler *logger)
Construct a new BgpRib6 object with logging.