summaryrefslogtreecommitdiff
path: root/lib/zclient.c
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@opensourcerouting.org>2024-01-11 17:23:28 -0300
committerRafael Zalamena <rzalamena@opensourcerouting.org>2025-01-23 14:37:09 -0300
commit28a9ca3405a6f7923b5a51b0e2db6844928676db (patch)
tree5eac66f25964ae92201875ae803ba4d1b839eb13 /lib/zclient.c
parentdfdc12e1647341bd2402986c5753102ee2bbe4ab (diff)
lib,zebra: VRF table-direct support
Implement the necessary data structures and code changes to support sending table-direct routes to protocols running in different VRFs. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'lib/zclient.c')
-rw-r--r--lib/zclient.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 6aebe4377e..8fc9addf2f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -31,6 +31,7 @@
DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient");
DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs");
+DEFINE_MTYPE_STATIC(LIB, REDIST_TABLE_DIRECT, "Redistribution table direct");
/* Zebra client events. */
enum zclient_event { ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT };
@@ -157,6 +158,87 @@ void redist_del_instance(struct redist_proto *red, unsigned short instance)
}
}
+static void redist_free_table_direct(void *data)
+{
+ XFREE(MTYPE_REDIST_TABLE_DIRECT, data);
+}
+
+struct redist_table_direct *redist_lookup_table_direct(const struct redist_proto *red,
+ const struct redist_table_direct *table)
+{
+ struct redist_table_direct *ntable;
+ struct listnode *node;
+
+ if (red->instances == NULL)
+ return NULL;
+
+ for (ALL_LIST_ELEMENTS_RO(red->instances, node, ntable)) {
+ if (table->vrf_id != ntable->vrf_id)
+ continue;
+ if (table->table_id != ntable->table_id)
+ continue;
+
+ return ntable;
+ }
+
+ return NULL;
+}
+
+bool redist_table_direct_has_id(const struct redist_proto *red, int table_id)
+{
+ struct redist_table_direct *table;
+ struct listnode *node;
+
+ if (red->instances == NULL)
+ return false;
+
+ for (ALL_LIST_ELEMENTS_RO(red->instances, node, table)) {
+ if (table->table_id != table_id)
+ continue;
+
+ return true;
+ }
+
+ return false;
+}
+
+void redist_add_table_direct(struct redist_proto *red, const struct redist_table_direct *table)
+{
+ struct redist_table_direct *ntable;
+
+ ntable = redist_lookup_table_direct(red, table);
+ if (ntable != NULL)
+ return;
+
+ if (red->instances == NULL) {
+ red->instances = list_new();
+ red->instances->del = redist_free_table_direct;
+ }
+
+ red->enabled = 1;
+
+ ntable = XCALLOC(MTYPE_REDIST_TABLE_DIRECT, sizeof(*ntable));
+ ntable->vrf_id = table->vrf_id;
+ ntable->table_id = table->table_id;
+ listnode_add(red->instances, ntable);
+}
+
+void redist_del_table_direct(struct redist_proto *red, const struct redist_table_direct *table)
+{
+ struct redist_table_direct *ntable;
+
+ ntable = redist_lookup_table_direct(red, table);
+ if (ntable == NULL)
+ return;
+
+ listnode_delete(red->instances, ntable);
+ red->instances->del(ntable);
+ if (red->instances->count == 0) {
+ red->enabled = 0;
+ list_delete(&red->instances);
+ }
+}
+
void redist_del_all_instances(struct redist_proto *red)
{
if (!red->instances)
@@ -483,6 +565,17 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
+static void zclient_send_table_direct(struct zclient *zclient, afi_t afi, int type)
+{
+ struct redist_table_direct *table;
+ struct redist_proto *red = &zclient->mi_redist[afi][ZEBRA_ROUTE_TABLE_DIRECT];
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(red->instances, node, table))
+ zebra_redistribute_send(type, zclient, afi, ZEBRA_ROUTE_TABLE_DIRECT,
+ table->table_id, table->vrf_id);
+}
+
/* Send register requests to zebra daemon for the information in a VRF. */
void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
{
@@ -516,6 +609,12 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
if (!zclient->mi_redist[afi][i].enabled)
continue;
+ if (i == ZEBRA_ROUTE_TABLE_DIRECT) {
+ zclient_send_table_direct(zclient, afi,
+ ZEBRA_REDISTRIBUTE_ADD);
+ continue;
+ }
+
struct listnode *node;
unsigned short *id;
@@ -583,6 +682,12 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
if (!zclient->mi_redist[afi][i].enabled)
continue;
+ if (i == ZEBRA_ROUTE_TABLE_DIRECT) {
+ zclient_send_table_direct(zclient, afi,
+ ZEBRA_REDISTRIBUTE_DELETE);
+ continue;
+ }
+
struct listnode *node;
unsigned short *id;
@@ -4637,9 +4742,42 @@ static void zclient_read(struct event *thread)
zclient_event(ZCLIENT_READ, zclient);
}
+static void zclient_redistribute_table_direct(struct zclient *zclient, vrf_id_t vrf_id, afi_t afi,
+ int instance, int command)
+{
+ struct redist_proto *red = &zclient->mi_redist[afi][ZEBRA_ROUTE_TABLE_DIRECT];
+ bool has_table;
+ struct redist_table_direct table = {
+ .vrf_id = vrf_id,
+ .table_id = instance,
+ };
+
+ has_table = redist_lookup_table_direct(red, &table);
+
+ if (command == ZEBRA_REDISTRIBUTE_ADD) {
+ if (has_table)
+ return;
+
+ redist_add_table_direct(red, &table);
+ } else {
+ if (!has_table)
+ return;
+
+ redist_del_table_direct(red, &table);
+ }
+
+ if (zclient->sock > 0)
+ zebra_redistribute_send(command, zclient, afi, ZEBRA_ROUTE_TABLE_DIRECT, instance,
+ vrf_id);
+}
+
void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
int type, unsigned short instance, vrf_id_t vrf_id)
{
+ if (type == ZEBRA_ROUTE_TABLE_DIRECT) {
+ zclient_redistribute_table_direct(zclient, vrf_id, afi, instance, command);
+ return;
+ }
if (instance) {
if (command == ZEBRA_REDISTRIBUTE_ADD) {