12 #include <arpa/inet.h> 13 #define MAKE_ENTRY4(r, e) std::make_pair(BgpRib4EntryKey(r), e) 17 BgpRib4Entry::BgpRib4Entry() {
28 BgpRib4Entry::BgpRib4Entry(
Prefix4 r, uint32_t
src,
const std::vector<std::shared_ptr<BgpPathAttrib>> as) :
route(r) {
40 for (
const std::shared_ptr<BgpPathAttrib> &attr :
attribs) {
41 if (attr->type_code == NEXT_HOP) {
56 this->logger = logger;
60 rib4_t::iterator BgpRib4::find_best (
const Prefix4 &prefix) {
61 std::pair<rib4_t::iterator, rib4_t::iterator> its =
64 rib4_t::iterator best = rib.end();
65 if (its.first == rib.end())
return rib.end();
67 for (rib4_t::iterator it = its.first; it != its.second; it++) {
68 if (it->second.route == prefix) {
69 if (best == rib.end()) best = it;
71 const BgpRib4Entry *best_ptr = selectEntry(&(best->second), &(it->second));
72 best = best_ptr == &(best->second) ? best : it;
80 rib4_t::iterator BgpRib4::find_entry (
const Prefix4 &prefix, uint32_t
src) {
81 std::pair<rib4_t::iterator, rib4_t::iterator> its =
84 if (its.first == rib.end())
return rib.end();
86 for (rib4_t::iterator it = its.first; it != its.second; it++) {
87 if (it->second.route == prefix && it->second.src_router_id == src) {
113 std::pair<const BgpRib4Entry*, bool> BgpRib4::insertPriv(uint32_t
src_router_id,
const Prefix4 &
route,
const std::vector<std::shared_ptr<BgpPathAttrib>> &attrib, int32_t
weight, uint32_t ibgp_asn) {
114 std::lock_guard<std::recursive_mutex> lock(mutex);
120 new_entry.
src = ibgp_asn > 0 ? SRC_IBGP : SRC_EBGP;
124 const char *op =
"new_entry";
125 const char *act =
"new_best";
127 std::pair<rib4_t::iterator, rib4_t::iterator> entries =
130 bool newly_inserted_is_best =
false;
131 bool best_changed =
false;
132 bool old_exist = entries.first != rib.end();
138 rib4_t::const_iterator to_replace = rib.end();
140 for (rib4_t::iterator it = entries.first; it != entries.second; it++) {
141 if (it->second.route != route)
continue;
142 if (it->second.src_router_id == src_router_id) {
146 old_best = selectEntry(old_best, &(it->second));
150 const BgpRib4Entry *candidate = selectEntry(&new_entry, old_best);
151 if (candidate == old_best) {
152 new_entry.
status = RS_STANDBY;
153 act =
"not_new_best";
155 if (old_best != NULL) old_best->
status = RS_STANDBY;
159 if (to_replace != rib.end()) {
160 const BgpRib4Entry *candidate = selectEntry(&(to_replace->second), old_best);
161 if (candidate == &(to_replace->second)) {
168 rib.erase(to_replace);
171 rib4_t::iterator inserted = rib.insert(MAKE_ENTRY4(route, new_entry));
174 newly_inserted_is_best = candidate == &new_entry;
175 new_best = newly_inserted_is_best ? &(inserted->second) : old_best;
179 best_changed = newly_inserted_is_best =
true;
180 rib4_t::iterator inserted = rib.insert(MAKE_ENTRY4(route, new_entry));
181 new_best = &(inserted->second);
184 if (new_best != NULL) new_best->
status = RS_ACTIVE;
186 LIBBGP_LOG(logger, DEBUG) {
188 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET_ADDRSTRLEN];
189 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
190 inet_ntop(AF_INET, &prefix, prefix_str, INET_ADDRSTRLEN);
191 logger->log(DEBUG,
"BgpRib4::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());
194 return std::make_pair(new_best, newly_inserted_is_best);
219 std::vector<std::shared_ptr<BgpPathAttrib>>
attribs;
224 origin->origin = IGP;
226 attribs.push_back(std::shared_ptr<BgpPathAttrib>(origin));
227 attribs.push_back(std::shared_ptr<BgpPathAttrib>(nexhop_attr));
228 attribs.push_back(std::shared_ptr<BgpPathAttrib>(as_path));
232 for (
const auto &entry : rib) {
233 if (entry.second.src_router_id == 0 && entry.second.route == route) {
234 this->logger->
log(ERROR,
"BgpRib4::insert: route exists.\n");
239 if (entry.second.src_router_id == 0) {
240 for (
const std::shared_ptr<BgpPathAttrib> &attr : entry.second.attribs) {
241 if (attr->type_code == NEXT_HOP) {
243 if (nh.
next_hop == nexthop) use_update_id = entry.second.update_id;
250 std::lock_guard<std::recursive_mutex> lock(mutex);
254 rib4_t::const_iterator it = rib.insert(MAKE_ENTRY4(route, new_entry));
256 return &(it->second);
273 std::vector<BgpRib4Entry> inserted;
274 std::vector<std::shared_ptr<BgpPathAttrib>>
attribs;
279 origin->origin = IGP;
281 attribs.push_back(std::shared_ptr<BgpPathAttrib>(origin));
282 attribs.push_back(std::shared_ptr<BgpPathAttrib>(nexhop_attr));
283 attribs.push_back(std::shared_ptr<BgpPathAttrib>(as_path));
285 for (
const Prefix4 &route : routes) {
286 rib4_t::const_iterator it = find_entry(route, 0);
288 if (it != rib.end())
continue;
293 rib4_t::const_iterator isrt_it = rib.insert(MAKE_ENTRY4(route, new_entry));
294 inserted.push_back(isrt_it->second);
311 std::pair<const BgpRib4Entry*, bool>
BgpRib4::insert(uint32_t src_router_id,
const Prefix4 &route,
const std::vector<std::shared_ptr<BgpPathAttrib>> &attrib, int32_t weight, uint32_t ibgp_asn) {
313 return insertPriv(src_router_id, route, attrib, weight, ibgp_asn);
327 std::pair<std::vector<BgpRib4Entry>, std::vector<Prefix4>>
BgpRib4::insert(uint32_t src_router_id,
const std::vector<Prefix4> &routes,
const std::vector<std::shared_ptr<BgpPathAttrib>> &attrib, int32_t weight, uint32_t ibgp_asn) {
329 std::vector<BgpRib4Entry> updated;
330 std::vector<Prefix4> unchanged;
331 for (
const Prefix4 &route : routes) {
332 std::pair<const BgpRib4Entry*, bool> rslt = insertPriv(src_router_id, route, attrib, weight, ibgp_asn);
333 if (rslt.first != NULL) {
334 if (!rslt.second) updated.push_back(*(rslt.first));
335 else unchanged.push_back(route);
338 return std::make_pair(updated, unchanged);
354 std::lock_guard<std::recursive_mutex> lock(mutex);
355 std::pair<rib4_t::iterator, rib4_t::iterator> old_entries =
358 if (old_entries.first == rib.end())
359 return std::make_pair<bool, const BgpRib4Entry*>(
false, NULL);
361 const char *op =
"dropped/no_change";
364 rib4_t::const_iterator to_remove = rib.end();
366 for (rib4_t::iterator it = old_entries.first; it != old_entries.second; it++) {
367 if (it->second.route == route) {
368 if (it->second.src_router_id == src_router_id) {
372 replacement = selectEntry(replacement, &(it->second));
376 bool reachabled =
true;
378 if (to_remove == rib.end())
379 return std::make_pair<bool, const BgpRib4Entry*>(
false, NULL);
381 if (replacement != NULL) {
383 if (to_remove->second.status == RS_ACTIVE) {
384 op =
"dropped/best_changed";
385 }
else replacement = NULL;
388 op =
"dropped/unreachabled";
391 rib.erase(to_remove);
392 if (replacement != NULL) replacement->
status = RS_ACTIVE;
394 LIBBGP_LOG(logger, DEBUG) {
396 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET_ADDRSTRLEN];
397 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
398 inet_ntop(AF_INET, &prefix, prefix_str, INET_ADDRSTRLEN);
399 logger->log(DEBUG,
"BgpRib4::withdraw: (%s) scope %s, route %s/%d\n", op, src_router_id_str, prefix_str, route.
getLength());
402 return std::pair<bool, const BgpRib4Entry*>(reachabled, replacement);
414 std::pair<std::vector<Prefix4>, std::vector<BgpRib4Entry>>
BgpRib4::discard(uint32_t src_router_id) {
415 std::lock_guard<std::recursive_mutex> lock(mutex);
416 std::vector<Prefix4> reevaluate_routes;
417 std::vector<Prefix4> dropped_routes;
419 for (rib4_t::const_iterator it = rib.begin(); it != rib.end();) {
420 const char *op =
"dropped/silent";
421 if (it->second.src_router_id != src_router_id) {
425 if (it->second.status == RS_ACTIVE) {
426 reevaluate_routes.push_back(it->second.route);
427 op =
"dropped/pending-reevaluate";
429 LIBBGP_LOG(logger, DEBUG) {
430 uint32_t prefix = it->second.route.
getPrefix();
431 char src_router_id_str[INET_ADDRSTRLEN], prefix_str[INET_ADDRSTRLEN];
432 inet_ntop(AF_INET, &src_router_id, src_router_id_str, INET_ADDRSTRLEN);
433 inet_ntop(AF_INET, &prefix, prefix_str, INET_ADDRSTRLEN);
434 logger->log(DEBUG,
"BgpRib4::discard: (%s) scope %s, route %s/%d\n", op, src_router_id_str, prefix_str, it->second.route.getLength());
439 std::vector<BgpRib4Entry> replacements;
441 for (std::vector<Prefix4>::const_iterator it = reevaluate_routes.begin(); it != reevaluate_routes.end(); it++) {
442 const char *op =
"replacement found";
444 rib4_t::iterator replacement = find_best(prefix);
445 if (replacement == rib.end()) {
446 dropped_routes.push_back(prefix);
447 op =
"no available replacement";
449 replacement->second.status = RS_ACTIVE;
450 replacements.push_back(replacement->second);
453 LIBBGP_LOG(logger, DEBUG) {
455 char prefix_str[INET_ADDRSTRLEN];
456 inet_ntop(AF_INET, &pfx, prefix_str, INET_ADDRSTRLEN);
457 logger->log(DEBUG,
"BgpRib4::discard: %s for route %s/%d\n", op, prefix_str, prefix.
getLength());
461 return std::make_pair(dropped_routes, replacements);
481 for (
const auto &entry : rib) {
482 if (entry.second.status != RS_ACTIVE)
continue;
483 if (entry.second.route.includes(dest))
return &entry.second;
513 for (
const auto &entry : rib) {
514 if (entry.second.status != RS_ACTIVE)
continue;
515 if (entry.second.src_router_id != src_router_id)
continue;
516 if (entry.second.route.includes(dest))
return &entry.second;
uint32_t getPrefix() const
Get prefix.
std::vector< std::shared_ptr< BgpPathAttrib > > attribs
Path attributes for this entry.
Prefix4 route
The prefix of this entry.
Key for the Rib4 entry map.
std::pair< bool, const BgpRib4Entry * > withdraw(uint32_t src_router_id, const Prefix4 &route)
Withdraw a route from RIB.
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 getLength() const
Get netmask.
BgpRouteSource src
Source of this entry.
uint32_t ibgp_peer_asn
ASN of the IBGP peer. (Valid iff src == SRC_IBGP)
IPv4 Route/Prefix related utilities.
int32_t weight
Weight of this entry.
BgpRib4(BgpLogHandler *logger)
Construct a new BgpRib4 object with logging.
uint32_t src_router_id
The originating BGP speaker's ID of this entry. (network bytes order)
The IPv4 BGP Routing Information Base.
const BgpRib4Entry * insert(BgpLogHandler *logger, const Prefix4 &route, uint32_t nexthop, int32_t weight=0)
Insert a local route into RIB.
BgpRouteStatus status
Status of this entry.
uint64_t update_id
The update ID.
uint32_t getNexthop() const
Get nexthop for this entry.
uint32_t next_hop
The nexthop in network byte order.
std::pair< std::vector< Prefix4 >, std::vector< BgpRib4Entry > > discard(uint32_t src_router_id)
Drop all routes from RIB that originated from a BGP speaker.
const rib4_t & get() const
Get the RIB.
const BgpRib4Entry * lookup(uint32_t dest) const
Lookup a destination in RIB.