33#define _COMPONENT_ "db"
40#define INIT_TABLE_CAPACITY 256
41#define INIT_ADJ_TRIBS_CAPACITY 32
43static trib_t g_trib = { 0 };
45const char *entry_type_strs[] = {
61 if (ATTR_IS_USED_ADVERTPATH(entry->
attrs.
use)) {
63 * entry->
attrs.advertpath_size);
65 * entry->
attrs.advertpath_size);
67 if (ATTR_IS_USED_ROUTEDPATH(entry->
attrs.
use)) {
69 * entry->
attrs.routedpath_size);
71 * entry->
attrs.routedpath_size);
73 if (ATTR_IS_USED_COMMUNITIES(entry->
attrs.
use)) {
75 * entry->
attrs.communities_size);
77 sizeof(community_t) * entry->
attrs.communities_size);
87 if (ATTR_IS_USED_ADVERTPATH(entry->
attrs.
use))
89 if (ATTR_IS_USED_ROUTEDPATH(entry->
attrs.
use))
91 if (ATTR_IS_USED_COMMUNITIES(entry->
attrs.
use))
99 t->capacity = INIT_TABLE_CAPACITY;
101 t->table = malloc(t->capacity *
sizeof(
entry_t*));
108 for (
size_t i = 0; i < src->size; i++)
115 for (
size_t i = 0; i < t->size; i++)
123 if (g_trib.local_routes.table)
130 table_init(&t->local_routes);
131 table_init(&t->ext_trib);
132 table_init(&t->loc_trib);
133 table_init(&t->optimized_loc_trib);
135 t->adj_tribs_capacity = INIT_ADJ_TRIBS_CAPACITY;
136 t->adj_tribs_size = 0;
137 t->adj_tribs_in = malloc(t->adj_tribs_capacity *
sizeof(
table_t));
146 if (trib->adj_tribs_capacity < trib->adj_tribs_size + 1) {
147 trib->adj_tribs_capacity *= 2;
148 trib->adj_tribs_in = realloc(trib->adj_tribs_in,
149 trib->adj_tribs_capacity *
sizeof(
table_t));
151 trib->adj_tribs_capacity *
sizeof(
table_t));
154 trib->adj_tribs_in[trib->adj_tribs_size] = in;
156 trib->adj_tribs_size++;
165 for (
size_t i = 0; i < trib->adj_tribs_size; i++) {
166 if (trib->adj_tribs_in[i] == in && trib->
adj_tribs_out[i] == out) {
169 memmove(&trib->adj_tribs_in[i], &trib->adj_tribs_in[i+1],
170 sizeof(
table_t*) * (trib->adj_tribs_size - i));
172 sizeof(
table_t*) * (trib->adj_tribs_size - i));
173 trib->adj_tribs_size--;
186 free(trib->adj_tribs_in);
194 for (
size_t i = 0; i < t->size; i++)
195 if (t->table[i]->
af ==
af && strcmp(t->table[i]->
prefix, prefix) == 0)
206 for (
size_t i = 0; i < table->size; i++) {
207 if (
af && table->table[i]->
af !=
af)
211 int len = strlen(table->table[i]->
prefix);
212 if (strncmp(table->table[i]->
prefix, address, len) == 0)
214 if (len <= specificity)
226 if (table->capacity < table->size + 1) {
227 table->capacity *= 2;
228 table->table = realloc(table->table,
229 table->capacity *
sizeof(
entry_t*));
232 table->table[table->size++] = entry;
252trib_table_insert_or_replace_if_new(
table_t *table,
entry_t *route)
264 ((*match)->app_proto == route->
app_proto) &&
266 ((*match)->attrs.routedpath_size == route->
attrs.routedpath_size) &&
267 ((*match)->attrs.advertpath_size == route->
attrs.advertpath_size) &&
268 ((*match)->attrs.communities_size == route->
attrs.communities_size) &&
273 (strcmp((*match)->attrs.nexthop, route->
attrs.
nexthop) == 0) &&
275 sizeof(uint32_t) * route->
attrs.advertpath_size) == 0) &&
277 sizeof(uint32_t) * route->
attrs.routedpath_size) == 0) &&
279 sizeof(uint32_t) * route->
attrs.communities_size) == 0) &&
281 ((*match)->attrs.use == route->
attrs.
use)
287 if ((*match)->seq < route->
seq)
288 (*match)->seq = route->
seq;
298 for (
size_t i = 0; i < table->size; i++)
323 if (e1->
attrs.routedpath_size != e2->
attrs.routedpath_size)
324 return e1->
attrs.routedpath_size < e2->
attrs.routedpath_size;
333 INFO(
"identical route preference for %s", e1->
prefix);
349 for (
size_t i = 0; i < t2->size; i++) {
358 if (entry_compare(*match, t2->table[i], itad)) {
364 DEBUG(
"route %s left out of selection algo", t2->table[i]->
prefix);
372 for (
size_t i = 0; i < src->size; i++) {
380apply_policy(
table_t *dst,
const table_t *src, uint32_t local_itad,
383 for (
size_t i = 0; i < src->size; i++) {
393 for (
size_t j = 0; j < s->actions_size; j++) {
394 switch (s->actions[j].attribute) {
404 e->
attrs.routedpath_size = s->actions[j].value
405 + e->
attrs.routedpath_size;
407 e->
attrs.routedpath_size *
sizeof(uint32_t));
408 for (
size_t k = 0; k < s->actions[j].value; k++)
422 for (
size_t i = 0; i < trib->local_routes.size; i++) {
432select_eligible_routes_out(
table_t *loc, uint32_t itad, uint32_t
id)
437 for (
size_t i = 0; i < loc->size; i++) {
443 for (
int j = 0; j < loc->table[i]->
attrs.advertpath_size; j++)
446 for (
int j = 0; j < loc->table[i]->
attrs.routedpath_size; j++)
461 table_t *eligible = select_eligible_routes_out(&trib->optimized_loc_trib,
462 adj_trib_out->peer_itad, adj_trib_out->
peer_id);
465 table_init(&policied);
469 apply_policy(&policied, eligible, trib->
local_itad,
472 table_copy(&policied, eligible);
474 for (
size_t i = 0; i < policied.size; i++)
475 trib_table_insert_or_replace_if_new(adj_trib_out,
492 table_init(&scratch);
494 struct timespec start, end;
495 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);
497 table_select_into(&trib->ext_trib, &trib->local_routes, trib->
local_itad);
498 for (
size_t i = 0; i < trib->adj_tribs_size; i++) {
499 if (trib->adj_tribs_in[i]->peer_itad != trib->
local_itad) {
501 if (trib->adj_tribs_in[i]->
routemap) {
503 apply_policy(&scratch, trib->adj_tribs_in[i], trib->
local_itad,
505 table_select_into(&trib->ext_trib, &scratch, trib->
local_itad);
507 table_select_into(&trib->ext_trib, trib->adj_tribs_in[i],
513 table_select_into(&trib->loc_trib, &trib->ext_trib, trib->
local_itad);
514 for (
size_t i = 0; i < trib->adj_tribs_size; i++)
515 if (trib->adj_tribs_in[i]->peer_itad == trib->
local_itad)
516 table_select_into(&trib->loc_trib, trib->adj_tribs_in[i],
521 optimize_table(&trib->optimized_loc_trib, &trib->loc_trib);
523 for (
size_t i = 0; i < trib->adj_tribs_size; i++) {
527 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
529 DEBUG(
"TRIB updated in %fus", (1000000.0 * (
double)(end.tv_sec - start.tv_sec))
530 + (0.001 * (
double)(end.tv_nsec - start.tv_nsec)));
539 size_t new_ents_size = 0, new_ents_capacity = INIT_TABLE_CAPACITY;
540 entry_t **new_ents = malloc(
sizeof(
entry_t*) * new_ents_capacity);
542 for (
size_t i = 0; i < table->size; i++) {
543 if (table->table[i]->
sent)
546 if (new_ents_size + 1 > new_ents_capacity) {
547 new_ents_capacity *= 2;
548 new_ents = realloc(new_ents,
sizeof(
entry_t*) * new_ents_capacity);
551 new_ents[new_ents_size++] = table->table[i];
554 *new_ents_out = new_ents;
555 return new_ents_size;
568 if (!ATTR_IS_USED_NEXTHOP(a1->
use) || !ATTR_IS_USED_NEXTHOP(a2->
use)) {
569 ERROR(
"reachable route compared without nexthop");
575 ((!ATTR_IS_USED_ADVERTPATH(a1->
use) || !ATTR_IS_USED_ADVERTPATH(a2->
use)) ||
576 (a1->advertpath_size == a2->advertpath_size &&
578 sizeof(uint32_t) * a1->advertpath_size))) &&
579 ((!ATTR_IS_USED_ROUTEDPATH(a1->
use) || !ATTR_IS_USED_ROUTEDPATH(a2->
use)) ||
580 (a1->routedpath_size == a2->routedpath_size &&
582 sizeof(uint32_t) * a1->routedpath_size))) &&
583 ((!ATTR_IS_USED_LOCALPREF(a1->
use) || !ATTR_IS_USED_LOCALPREF(a2->
use)) ||
585 ((!ATTR_IS_USED_METRIC(a1->
use) || !ATTR_IS_USED_METRIC(a2->
use)) ||
587 ((!ATTR_IS_USED_COMMUNITIES(a1->
use) || !ATTR_IS_USED_COMMUNITIES(a2->
use)) ||
588 (a1->communities_size == a2->communities_size &&
590 sizeof(uint32_t) * a1->communities_size)));
597 for (
size_t i = 0; i < groups_size; i++)
598 if (attrs_equals(&e->
attrs, &groups[i].attrs))
606 g->capacity = INIT_TABLE_CAPACITY;
615 if (g->size + 1 > g->capacity) {
618 sizeof(
entry_t*) * g->capacity);
629 size_t groups_size = 0, groups_capacity = entry_size;
632 for (
size_t i = 0; i < entry_size; i++) {
633 entry_group_t *ingroup = is_entry_in_group(entries[i], groups,
637 if (groups_size + 1 > groups_capacity) {
638 groups_capacity *= 2;
639 groups = realloc(groups,
sizeof(
entry_group_t) * groups_capacity);
642 ingroup = &groups[groups_size++];
643 group_init(ingroup, &entries[i]->attrs);
646 group_insert(ingroup, entries[i]);
650 *groups_out = groups;
#define DEBUG(format,...)
log for debugging purposes
Definition logging.h:65
#define ERROR(format,...)
log an error
Definition logging.h:56
#define INFO(format,...)
log informational event
Definition logging.h:62
const routemap_statement_t * routemap_match(const routemap_t *routemap, const char *route)
Match route against route map matchers.
Definition pib.c:367
@ ROUTEMAP_SET_METRIC
Definition pib.h:49
@ ROUTEMAP_SET_ITADPATH_PREPEND
Definition pib.h:51
@ ROUTEMAP_SET_NEXTHOP
Definition pib.h:50
@ ROUTEMAP_SET_LOCALPREF
Definition pib.h:48
Protocol definition header.
af
Address families.
Definition protocol.h:211
app_proto
Application protocols.
Definition protocol.h:225
Groupable attributes that are related to a route.
Definition trib.h:52
char * nexthop
Definition trib.h:56
uint32_t local_pref
Definition trib.h:62
int atomicaggregate
Definition trib.h:61
uint32_t nextitad
Definition trib.h:55
community_t * communities
Definition trib.h:64
uint32_t use
Definition trib.h:53
int convertedroute
Definition trib.h:66
uint32_t * advertpath
Definition trib.h:57
int withdrawn
Definition trib.h:54
uint32_t metric
Definition trib.h:63
uint32_t * routedpath
Definition trib.h:59
entry_t ** entries
Definition trib.h:113
entry_attrs_t attrs
Definition trib.h:112
Route Entry.
Definition trib.h:78
int sent
Definition trib.h:99
uint16_t af
Definition trib.h:80
entry_type_t type
Definition trib.h:84
uint32_t learn_lsid
Definition trib.h:91
int32_t seq
Definition trib.h:94
uint32_t learn_itad
Definition trib.h:89
entry_attrs_t attrs
Definition trib.h:97
time_t time
Definition trib.h:95
uint16_t app_proto
Definition trib.h:81
char * prefix
Definition trib.h:82
Route map statement.
Definition pib.h:69
Route map.
Definition pib.h:79
Route Table.
Definition trib.h:103
uint32_t peer_id
Definition trib.h:104
routemap_t * routemap
Definition trib.h:107
Telephony Routing Information Base.
Definition trib.h:140
uint32_t local_itad
Definition trib.h:141
table_t ** adj_tribs_out
Definition trib.h:145
void trib_update_local(trib_t *trib)
Update local routes when ITAD is defined.
Definition trib.c:420
size_t get_new_entries(const table_t *table, entry_t ***new_ents_out)
Return array of new entry references to new.
Definition trib.c:537
size_t group_entries_by_attrs(entry_t **entries, size_t entry_size, entry_group_t **groups_out)
Group array of entry references by attributes.
Definition trib.c:625
entry_t ** trib_table_find(table_t *t, uint16_t af, const char *prefix)
Find exact route in table.
Definition trib.c:192
void trib_destroy(trib_t *trib)
Deinit TRIB structure.
Definition trib.c:180
void trib_adj_pair_add(trib_t *trib, table_t *in, table_t *out)
Add and init pair of tables owned by caller.
Definition trib.c:144
void trib_table_insert(table_t *table, entry_t *entry)
Add route to table.
Definition trib.c:224
void trib_table_deinit(table_t *t)
Deinitialize table.
Definition trib.c:113
void entry_destroy(entry_t *entry)
Destroy entry.
Definition trib.c:83
void trib_update_adj_out(trib_t *trib, table_t *adj_trib_out)
Update an Adj-TRIB-Out.
Definition trib.c:458
trib_t * trib_new(uint32_t local_itad)
Initialize TRIB structure.
Definition trib.c:121
void trib_update_full(trib_t *trib)
Execute route selection.
Definition trib.c:484
entry_t * entry_clone(const entry_t *entry)
Clone entry.
Definition trib.c:52
const entry_t * trib_table_lookup(const table_t *table, uint16_t af, uint16_t app_proto, const char *address)
Lookup address in table.
Definition trib.c:201
void trib_table_clear(table_t *table)
Destroy all entries and clear table.
Definition trib.c:296
Telephony Routing Information Base.