mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 10:37:29 +00:00
Merge pull request #4789 from sworleys/Nexthop-Sort-Optimization
lib: Nexthop Sorting Optimizations
This commit is contained in:
commit
8ce4c74607
@ -65,9 +65,8 @@ static int _nexthop_labels_cmp(const struct nexthop *nh1,
|
|||||||
return memcmp(nhl1->label, nhl2->label, nhl1->num_labels);
|
return memcmp(nhl1->label, nhl2->label, nhl1->num_labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nexthop_g_addr_cmp(enum nexthop_types_t type,
|
int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1,
|
||||||
const union g_addr *addr1,
|
const union g_addr *addr2)
|
||||||
const union g_addr *addr2)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -92,13 +91,13 @@ static int _nexthop_g_addr_cmp(enum nexthop_types_t type,
|
|||||||
static int _nexthop_gateway_cmp(const struct nexthop *nh1,
|
static int _nexthop_gateway_cmp(const struct nexthop *nh1,
|
||||||
const struct nexthop *nh2)
|
const struct nexthop *nh2)
|
||||||
{
|
{
|
||||||
return _nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
|
return nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nexthop_source_cmp(const struct nexthop *nh1,
|
static int _nexthop_source_cmp(const struct nexthop *nh1,
|
||||||
const struct nexthop *nh2)
|
const struct nexthop *nh2)
|
||||||
{
|
{
|
||||||
return _nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
|
return nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _nexthop_cmp_no_labels(const struct nexthop *next1,
|
static int _nexthop_cmp_no_labels(const struct nexthop *next1,
|
||||||
|
@ -142,6 +142,9 @@ extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2);
|
|||||||
extern bool nexthop_same_no_labels(const struct nexthop *nh1,
|
extern bool nexthop_same_no_labels(const struct nexthop *nh1,
|
||||||
const struct nexthop *nh2);
|
const struct nexthop *nh2);
|
||||||
extern int nexthop_cmp(const struct nexthop *nh1, const struct nexthop *nh2);
|
extern int nexthop_cmp(const struct nexthop *nh1, const struct nexthop *nh2);
|
||||||
|
extern int nexthop_g_addr_cmp(enum nexthop_types_t type,
|
||||||
|
const union g_addr *addr1,
|
||||||
|
const union g_addr *addr2);
|
||||||
|
|
||||||
extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
|
extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
|
||||||
extern bool nexthop_labels_match(const struct nexthop *nh1,
|
extern bool nexthop_labels_match(const struct nexthop *nh1,
|
||||||
|
@ -60,6 +60,16 @@ nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
|
|||||||
return strcmp(nhgc1->name, nhgc2->name);
|
return strcmp(nhgc1->name, nhgc2->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct nexthop *nexthop_group_tail(const struct nexthop_group *nhg)
|
||||||
|
{
|
||||||
|
struct nexthop *nexthop = nhg->nexthop;
|
||||||
|
|
||||||
|
while (nexthop && nexthop->next)
|
||||||
|
nexthop = nexthop->next;
|
||||||
|
|
||||||
|
return nexthop;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg)
|
uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg)
|
||||||
{
|
{
|
||||||
struct nexthop *nhop;
|
struct nexthop *nhop;
|
||||||
@ -129,7 +139,20 @@ void _nexthop_add(struct nexthop **target, struct nexthop *nexthop)
|
|||||||
void _nexthop_group_add_sorted(struct nexthop_group *nhg,
|
void _nexthop_group_add_sorted(struct nexthop_group *nhg,
|
||||||
struct nexthop *nexthop)
|
struct nexthop *nexthop)
|
||||||
{
|
{
|
||||||
struct nexthop *position, *prev;
|
struct nexthop *position, *prev, *tail;
|
||||||
|
|
||||||
|
/* Try to just append to the end first
|
||||||
|
* This trust it is already sorted
|
||||||
|
*/
|
||||||
|
|
||||||
|
tail = nexthop_group_tail(nhg);
|
||||||
|
|
||||||
|
if (tail && (nexthop_cmp(tail, nexthop) < 0)) {
|
||||||
|
tail->next = nexthop;
|
||||||
|
nexthop->prev = tail;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (position = nhg->nexthop, prev = NULL; position;
|
for (position = nhg->nexthop, prev = NULL; position;
|
||||||
prev = position, position = position->next) {
|
prev = position, position = position->next) {
|
||||||
|
@ -766,6 +766,92 @@ int zclient_route_send(uint8_t cmd, struct zclient *zclient,
|
|||||||
return zclient_send_message(zclient);
|
return zclient_send_message(zclient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1,
|
||||||
|
const struct zapi_nexthop *next2)
|
||||||
|
{
|
||||||
|
if (next1->label_num > next2->label_num)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (next1->label_num < next2->label_num)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return memcmp(next1->labels, next2->labels, next1->label_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
|
||||||
|
const struct zapi_nexthop *next2)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (next1->vrf_id < next2->vrf_id)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (next1->vrf_id > next2->vrf_id)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (next1->type < next2->type)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (next1->type > next2->type)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
switch (next1->type) {
|
||||||
|
case NEXTHOP_TYPE_IPV4:
|
||||||
|
case NEXTHOP_TYPE_IPV6:
|
||||||
|
ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
|
||||||
|
&next2->gate);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||||
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||||
|
ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
|
||||||
|
&next2->gate);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
/* Intentional Fall-Through */
|
||||||
|
case NEXTHOP_TYPE_IFINDEX:
|
||||||
|
if (next1->ifindex < next2->ifindex)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (next1->ifindex > next2->ifindex)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
|
if (next1->bh_type < next2->bh_type)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (next1->bh_type > next2->bh_type)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zapi_nexthop_cmp(const void *item1, const void *item2)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
const struct zapi_nexthop *next1 = item1;
|
||||||
|
const struct zapi_nexthop *next2 = item2;
|
||||||
|
|
||||||
|
ret = zapi_nexthop_cmp_no_labels(next1, next2);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = zapi_nexthop_labels_cmp(next1, next2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
|
||||||
|
uint16_t nexthop_num)
|
||||||
|
{
|
||||||
|
qsort(nh_grp, nexthop_num, sizeof(struct zapi_nexthop),
|
||||||
|
&zapi_nexthop_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
|
int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
|
||||||
{
|
{
|
||||||
struct zapi_nexthop *api_nh;
|
struct zapi_nexthop *api_nh;
|
||||||
@ -821,6 +907,8 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
|
||||||
|
|
||||||
stream_putw(s, api->nexthop_num);
|
stream_putw(s, api->nexthop_num);
|
||||||
|
|
||||||
for (i = 0; i < api->nexthop_num; i++) {
|
for (i = 0; i < api->nexthop_num; i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user