mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge e37a5b4666
into 3dd4d417be
This commit is contained in:
commit
c650d0b3e6
|
@ -65,7 +65,7 @@ def setup_module(module):
|
|||
router.load_config(
|
||||
TopoRouter.RD_FPM_LISTENER,
|
||||
os.path.join(CWD, "{}/fpm_stub.conf".format(rname)),
|
||||
"-r",
|
||||
"-r -z /tmp/fpm_test.data",
|
||||
)
|
||||
|
||||
tgen.start_router()
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
XREF_SETUP();
|
||||
|
||||
PREDECL_RBTREE_UNIQ(fpm_route);
|
||||
PREDECL_HASH(fpm_nhg);
|
||||
|
||||
/* Route structure to store in RB tree */
|
||||
struct fpm_route {
|
||||
|
@ -72,6 +73,39 @@ static int fpm_route_cmp(const struct fpm_route *a, const struct fpm_route *b)
|
|||
/* RB tree for storing routes */
|
||||
DECLARE_RBTREE_UNIQ(fpm_route, struct fpm_route, rb_item, fpm_route_cmp);
|
||||
|
||||
/* Nexthop group structure to store in Hash table */
|
||||
struct fpm_nhg {
|
||||
uint32_t id; /* Nexthop group ID */
|
||||
uint8_t family; /* Address family */
|
||||
uint8_t protocol; /* Routing protocol that installed nhg */
|
||||
uint8_t scope; /* Scope */
|
||||
bool is_blackhole; /* Is this a blackhole nexthop? */
|
||||
uint8_t num_nexthops; /* Number of nexthops in the group */
|
||||
|
||||
/* Individual nexthops in the group */
|
||||
struct {
|
||||
uint32_t id; /* Nexthop ID */
|
||||
uint8_t weight; /* Weight of this nexthop */
|
||||
} nexthops[MULTIPATH_NUM]; /* Support up to MULTIPATH_NUM nexthops in a group */
|
||||
|
||||
struct fpm_nhg_item hash_item;
|
||||
};
|
||||
|
||||
/* Comparison function for nexthop groups */
|
||||
static int fpm_nhg_cmp(const struct fpm_nhg *a, const struct fpm_nhg *b)
|
||||
{
|
||||
return a->id - b->id;
|
||||
}
|
||||
|
||||
/* Hash function for nexthop groups */
|
||||
static uint32_t fpm_nhg_hash(const struct fpm_nhg *a)
|
||||
{
|
||||
return jhash_1word(a->id, 0x55aa5a5a);
|
||||
}
|
||||
|
||||
/* Hash table for storing nexthop groups */
|
||||
DECLARE_HASH(fpm_nhg, struct fpm_nhg, hash_item, fpm_nhg_cmp, fpm_nhg_hash);
|
||||
|
||||
struct glob {
|
||||
int server_sock;
|
||||
int sock;
|
||||
|
@ -81,6 +115,7 @@ struct glob {
|
|||
FILE *output_file;
|
||||
const char *dump_file;
|
||||
struct fpm_route_head route_tree;
|
||||
struct fpm_nhg_head nhg_hash;
|
||||
};
|
||||
|
||||
struct glob glob_space;
|
||||
|
@ -343,8 +378,6 @@ netlink_prot_to_s(unsigned char prot)
|
|||
}
|
||||
}
|
||||
|
||||
#define MAX_NHS 16
|
||||
|
||||
struct netlink_nh {
|
||||
struct rtattr *gateway;
|
||||
int if_index;
|
||||
|
@ -364,7 +397,7 @@ struct netlink_msg_ctx {
|
|||
/*
|
||||
* Nexthops.
|
||||
*/
|
||||
struct netlink_nh nhs[MAX_NHS];
|
||||
struct netlink_nh nhs[MULTIPATH_NUM];
|
||||
unsigned long num_nhs;
|
||||
|
||||
struct rtattr *dest;
|
||||
|
@ -606,6 +639,10 @@ static int parse_route_msg(struct netlink_msg_ctx *ctx)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Forward declaration for handle_nexthop_update */
|
||||
static void handle_nexthop_update(struct nlmsghdr *hdr, struct nhmsg *nhmsg, struct rtattr *tb[],
|
||||
bool is_add);
|
||||
|
||||
/*
|
||||
* parse_nexthop_msg
|
||||
*/
|
||||
|
@ -618,6 +655,8 @@ static int parse_nexthop_msg(struct nlmsghdr *hdr)
|
|||
uint8_t nhg_count = 0;
|
||||
const char *err_msg = NULL;
|
||||
char protocol_str[32] = "Unknown";
|
||||
char nexthop_buf[16192] = "";
|
||||
size_t buf_pos = 0;
|
||||
|
||||
nhmsg = NLMSG_DATA(hdr);
|
||||
len = hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*nhmsg));
|
||||
|
@ -639,16 +678,41 @@ static int parse_nexthop_msg(struct nlmsghdr *hdr)
|
|||
if (tb[NHA_ID])
|
||||
nhgid = *(uint32_t *)RTA_DATA(tb[NHA_ID]);
|
||||
|
||||
/* Count nexthops in the group */
|
||||
/* Count nexthops in the group and collect NH IDs */
|
||||
if (tb[NHA_GROUP]) {
|
||||
struct nexthop_grp *nhg = (struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
|
||||
size_t count = (RTA_PAYLOAD(tb[NHA_GROUP]) / sizeof(*nhg));
|
||||
|
||||
if (count > 0 && (count * sizeof(*nhg)) == RTA_PAYLOAD(tb[NHA_GROUP]))
|
||||
nhg_count = count;
|
||||
if (count > 0 && (count * sizeof(*nhg)) == RTA_PAYLOAD(tb[NHA_GROUP])) {
|
||||
nhg_count = count > MULTIPATH_NUM ? MULTIPATH_NUM
|
||||
: count; /* Limit to our array size */
|
||||
|
||||
/* Build a string with all nexthop IDs and their weights */
|
||||
buf_pos = 0;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
int len_written;
|
||||
if (i > 0)
|
||||
nexthop_buf[buf_pos++] = ',';
|
||||
|
||||
if (nhg[i].weight > 1)
|
||||
len_written = snprintf(nexthop_buf + buf_pos,
|
||||
sizeof(nexthop_buf) - buf_pos,
|
||||
" %u(w:%u)", nhg[i].id,
|
||||
nhg[i].weight);
|
||||
else
|
||||
len_written = snprintf(nexthop_buf + buf_pos,
|
||||
sizeof(nexthop_buf) - buf_pos, " %u",
|
||||
nhg[i].id);
|
||||
|
||||
if (len_written > 0)
|
||||
buf_pos += len_written;
|
||||
}
|
||||
nexthop_buf[buf_pos] = '\0';
|
||||
}
|
||||
} else if (tb[NHA_OIF] || tb[NHA_GATEWAY]) {
|
||||
/* Single nexthop case */
|
||||
nhg_count = 1;
|
||||
snprintf(nexthop_buf, sizeof(nexthop_buf), " Singleton");
|
||||
}
|
||||
|
||||
/* Print blackhole status if applicable */
|
||||
|
@ -659,11 +723,15 @@ static int parse_nexthop_msg(struct nlmsghdr *hdr)
|
|||
protocol_str, nhmsg->nh_family);
|
||||
} else {
|
||||
fprintf(glob->output_file,
|
||||
"[%s] %s Nexthop Group ID: %u, Protocol: %s, Contains %u nexthops, Family: %u, Scope: %u\n",
|
||||
"[%s] %s Nexthop Group ID: %u, Protocol: %s, Contains %u nexthops, Family: %u, Scope: %u\n"
|
||||
" Nexthops:%s\n",
|
||||
get_timestamp(), hdr->nlmsg_type == RTM_NEWNEXTHOP ? "New" : "Del", nhgid,
|
||||
protocol_str, nhg_count, nhmsg->nh_family, nhmsg->nh_scope);
|
||||
protocol_str, nhg_count, nhmsg->nh_family, nhmsg->nh_scope, nexthop_buf);
|
||||
}
|
||||
|
||||
/* Update the nexthop hash table */
|
||||
handle_nexthop_update(hdr, nhmsg, tb, hdr->nlmsg_type == RTM_NEWNEXTHOP);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -847,6 +915,104 @@ static void handle_route_update(struct netlink_msg_ctx *ctx, bool is_add)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handle_nexthop_update
|
||||
* Handles adding or removing a nexthop group from the nexthop hash
|
||||
*/
|
||||
static void handle_nexthop_update(struct nlmsghdr *hdr, struct nhmsg *nhmsg, struct rtattr *tb[],
|
||||
bool is_add)
|
||||
{
|
||||
struct fpm_nhg *nhg;
|
||||
struct fpm_nhg *existing;
|
||||
struct fpm_nhg lookup = { 0 };
|
||||
uint32_t nhgid = 0;
|
||||
uint8_t nhg_count = 0;
|
||||
|
||||
/* Get Nexthop Group ID */
|
||||
if (tb[NHA_ID])
|
||||
nhgid = *(uint32_t *)RTA_DATA(tb[NHA_ID]);
|
||||
else
|
||||
return; /* Can't process without an ID */
|
||||
|
||||
/* Count nexthops in the group */
|
||||
if (tb[NHA_GROUP]) {
|
||||
struct nexthop_grp *nhgrp = (struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
|
||||
size_t count = (RTA_PAYLOAD(tb[NHA_GROUP]) / sizeof(*nhgrp));
|
||||
|
||||
if (count > 0 && (count * sizeof(*nhgrp)) == RTA_PAYLOAD(tb[NHA_GROUP]))
|
||||
nhg_count = count > MULTIPATH_NUM ? MULTIPATH_NUM
|
||||
: count; /* Limit to our array size */
|
||||
} else if (tb[NHA_OIF] || tb[NHA_GATEWAY]) {
|
||||
/* Single nexthop case */
|
||||
nhg_count = 1;
|
||||
}
|
||||
|
||||
/* Set up lookup key */
|
||||
lookup.id = nhgid;
|
||||
|
||||
/* Look up existing nexthop group */
|
||||
existing = fpm_nhg_find(&glob->nhg_hash, &lookup);
|
||||
|
||||
if (is_add) {
|
||||
if (existing) {
|
||||
/* Nexthop group exists, update it */
|
||||
existing->family = nhmsg->nh_family;
|
||||
existing->protocol = nhmsg->nh_protocol;
|
||||
existing->scope = nhmsg->nh_scope;
|
||||
existing->is_blackhole = tb[NHA_BLACKHOLE] ? true : false;
|
||||
existing->num_nexthops = nhg_count;
|
||||
|
||||
/* Update individual nexthop IDs and weights */
|
||||
if (tb[NHA_GROUP]) {
|
||||
struct nexthop_grp *nhgrp =
|
||||
(struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
|
||||
for (size_t i = 0; i < nhg_count; i++) {
|
||||
existing->nexthops[i].id = nhgrp[i].id;
|
||||
existing->nexthops[i].weight = nhgrp[i].weight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Create new nexthop group */
|
||||
nhg = calloc(1, sizeof(struct fpm_nhg));
|
||||
if (!nhg) {
|
||||
fprintf(stderr, "Failed to allocate nexthop group structure\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy nexthop group information */
|
||||
nhg->id = nhgid;
|
||||
nhg->family = nhmsg->nh_family;
|
||||
nhg->protocol = nhmsg->nh_protocol;
|
||||
nhg->scope = nhmsg->nh_scope;
|
||||
nhg->is_blackhole = tb[NHA_BLACKHOLE] ? true : false;
|
||||
nhg->num_nexthops = nhg_count;
|
||||
|
||||
/* Store individual nexthop IDs and weights */
|
||||
if (tb[NHA_GROUP]) {
|
||||
struct nexthop_grp *nhgrp =
|
||||
(struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
|
||||
for (size_t i = 0; i < nhg_count; i++) {
|
||||
nhg->nexthops[i].id = nhgrp[i].id;
|
||||
nhg->nexthops[i].weight = nhgrp[i].weight;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add nexthop group to hash */
|
||||
if (fpm_nhg_add(&glob->nhg_hash, nhg)) {
|
||||
fprintf(stderr, "Failed to add nexthop group to hash\n");
|
||||
free(nhg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Remove nexthop group from hash */
|
||||
if (existing) {
|
||||
existing = fpm_nhg_del(&glob->nhg_hash, existing);
|
||||
if (existing)
|
||||
free(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_netlink_msg
|
||||
*/
|
||||
|
@ -949,6 +1115,7 @@ static void fpm_serve(void)
|
|||
static void sigusr1_handler(int signum)
|
||||
{
|
||||
struct fpm_route *route;
|
||||
struct fpm_nhg *nhg;
|
||||
char buf[PREFIX_STRLEN];
|
||||
FILE *out = glob->output_file;
|
||||
FILE *dump_fp = NULL;
|
||||
|
@ -962,6 +1129,41 @@ static void sigusr1_handler(int signum)
|
|||
out = glob->output_file;
|
||||
}
|
||||
|
||||
fprintf(out, "\n=== Nexthop Group Hash Dump ===\n");
|
||||
fprintf(out, "Timestamp: %s\n", get_timestamp());
|
||||
fprintf(out, "Total nexthop groups: %zu\n", fpm_nhg_count(&glob->nhg_hash));
|
||||
fprintf(out, "Nexthop Groups:\n");
|
||||
|
||||
frr_each (fpm_nhg, &glob->nhg_hash, nhg) {
|
||||
fprintf(out, " ID: %u, Protocol: %s(%u), Family: %u, Nexthops: %u %s", nhg->id,
|
||||
netlink_prot_to_s(nhg->protocol), nhg->protocol, nhg->family,
|
||||
nhg->num_nexthops ? nhg->num_nexthops : 1,
|
||||
nhg->is_blackhole ? "BLACKHOLE" : "");
|
||||
|
||||
/* Display individual nexthops if any */
|
||||
if (nhg->num_nexthops > 0 && !nhg->is_blackhole) {
|
||||
if (nhg->nexthops[0].id == 0) {
|
||||
fprintf(out, "\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(out, " Nexthops: ");
|
||||
for (uint8_t i = 0; i < nhg->num_nexthops; i++) {
|
||||
if (i > 0)
|
||||
fprintf(out, ", ");
|
||||
|
||||
|
||||
if (nhg->nexthops[i].weight > 1)
|
||||
fprintf(out, "%u(w:%u)", nhg->nexthops[i].id,
|
||||
nhg->nexthops[i].weight);
|
||||
else
|
||||
fprintf(out, "%u", nhg->nexthops[i].id);
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
fprintf(out, "=====================\n\n");
|
||||
|
||||
fprintf(out, "\n=== Route Tree Dump ===\n");
|
||||
fprintf(out, "Timestamp: %s\n", get_timestamp());
|
||||
fprintf(out, "Total routes: %zu\n", fpm_route_count(&glob->route_tree));
|
||||
|
@ -972,6 +1174,8 @@ static void sigusr1_handler(int signum)
|
|||
fprintf(out, " Table %u, NHG %u: %s\n", route->table_id, route->nhg_id, buf);
|
||||
}
|
||||
fprintf(out, "=====================\n\n");
|
||||
|
||||
|
||||
fflush(out);
|
||||
|
||||
if (dump_fp)
|
||||
|
@ -989,6 +1193,7 @@ int main(int argc, char **argv)
|
|||
memset(glob, 0, sizeof(*glob));
|
||||
glob->output_file = stdout;
|
||||
fpm_route_init(&glob->route_tree);
|
||||
fpm_nhg_init(&glob->nhg_hash);
|
||||
|
||||
/* Set up signal handler for SIGUSR1 */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
|
Loading…
Reference in a new issue