Import CS frr-8.5.3-10.el9

This commit is contained in:
eabdullin 2025-11-03 12:54:53 +03:00
parent 8b09286f3d
commit 3940dd48f0
8 changed files with 755 additions and 5 deletions

View File

@ -249,7 +249,7 @@ index 81506f4410b1..869d2b455214 100644
return false;
+
+ if (peer->bfd_config) {
+ if (bfd_session_is_down(peer->bfd_config->session))
+ if (peer_established(peer) && bfd_session_is_down(peer->bfd_config->session))
+ return false;
+ }
+

View File

@ -0,0 +1,108 @@
From 4d28aea95851dc14b3987b004f457d7a4a1535f8 Mon Sep 17 00:00:00 2001
From: Lou Berger <lberger@labn.net>
Date: Sun, 2 Oct 2022 15:56:07 +0000
Subject: [PATCH] lib: when running as a daemon, only redirect sdtin, stdout,
sdterr to null when a tty.
Also write memstat to stderr when stderr is not a tty
and allow for --log stdout
Signed-off-by: Lou Berger <lberger@labn.net>
---
lib/libfrr.c | 44 +++++++++++++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 13 deletions(-)
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 07e2eafec59c..e8900572694a 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -130,6 +130,7 @@ static const struct optspec os_always = {
" --limit-fds Limit number of fds supported\n",
lo_always};
+static bool logging_to_stdout = false; /* set when --log stdout specified */
static const struct option lo_cfg[] = {
{"config_file", required_argument, NULL, 'f'},
@@ -738,6 +739,11 @@ struct event_loop *frr_init(void)
while ((log_arg = log_args_pop(di->early_logging))) {
command_setup_early_logging(log_arg->target,
di->early_loglevel);
+ /* this is a bit of a hack,
+ but need to notice when
+ the target is stdout */
+ if (strcmp(log_arg->target, "stdout") == 0)
+ logging_to_stdout = true;
XFREE(MTYPE_TMP, log_arg);
}
@@ -1088,9 +1094,15 @@ static void frr_terminal_close(int isexit)
"%s: failed to open /dev/null: %s", __func__,
safe_strerror(errno));
} else {
- dup2(nullfd, 0);
- dup2(nullfd, 1);
- dup2(nullfd, 2);
+ int fd;
+ /*
+ * only redirect stdin, stdout, stderr to null when a tty also
+ * don't redirect when stdout is set with --log stdout
+ */
+ for (fd = 2; fd >= 0; fd--)
+ if (isatty(fd) &&
+ (fd != STDOUT_FILENO || !logging_to_stdout))
+ dup2(nullfd, fd);
close(nullfd);
}
}
@@ -1168,9 +1180,16 @@ void frr_run(struct event_loop *master)
"%s: failed to open /dev/null: %s",
__func__, safe_strerror(errno));
} else {
- dup2(nullfd, 0);
- dup2(nullfd, 1);
- dup2(nullfd, 2);
+ int fd;
+ /*
+ * only redirect stdin, stdout, stderr to null when a
+ * tty also don't redirect when stdout is set with --log
+ * stdout
+ */
+ for (fd = 2; fd >= 0; fd--)
+ if (isatty(fd) &&
+ (fd != STDOUT_FILENO || !logging_to_stdout))
+ dup2(nullfd, fd);
close(nullfd);
}
@@ -1194,7 +1213,7 @@ void frr_fini(void)
{
FILE *fp;
char filename[128];
- int have_leftovers;
+ int have_leftovers = 0;
hook_call(frr_fini);
@@ -1220,16 +1239,15 @@ void frr_fini(void)
/* frrmod_init -> nothing needed / hooks */
rcu_shutdown();
- if (!debug_memstats_at_exit)
- return;
-
- have_leftovers = log_memstats(stderr, di->name);
+ /* also log memstats to stderr when stderr goes to a file*/
+ if (debug_memstats_at_exit || !isatty(STDERR_FILENO))
+ have_leftovers = log_memstats(stderr, di->name);
/* in case we decide at runtime that we want exit-memstats for
- * a daemon, but it has no stderr because it's daemonized
+ * a daemon
* (only do this if we actually have something to print though)
*/
- if (!have_leftovers)
+ if (!debug_memstats_at_exit || !have_leftovers)
return;
snprintf(filename, sizeof(filename), "/tmp/frr-memstats-%s-%llu-%llu",

View File

@ -0,0 +1,306 @@
From 5eb7047e2798e56c89c650434d3c6e7dc7533328 Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Tue, 12 Nov 2024 13:09:09 +0200
Subject: [PATCH 2/5] bgpd: Update source address for BFD session
If BFD is down, we should try to detect the source automatically from the given
interface.
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_bfd.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 88ffb68206ac..3a1459b8a557 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -26,6 +26,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_network.h"
DEFINE_MTYPE_STATIC(BGPD, BFD_CONFIG, "BFD configuration data");
@@ -158,16 +159,33 @@ void bgp_peer_bfd_update_source(struct peer *p)
struct in_addr v4;
struct in6_addr v6;
} src, dst;
+ struct interface *ifp;
+ union sockunion addr;
/* Nothing to do for groups. */
if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
return;
/* Figure out the correct source to use. */
- if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
- source = p->update_source;
- else
+ if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE)) {
+ if (p->update_source) {
+ source = p->update_source;
+ } else if (p->update_if) {
+ ifp = if_lookup_by_name(p->update_if, p->bgp->vrf_id);
+ if (ifp) {
+ sockunion_init(&addr);
+ if (bgp_update_address(ifp, &p->su, &addr)) {
+ if (BGP_DEBUG(bfd, BFD_LIB))
+ zlog_debug("%s: can't find the source address for interface %s",
+ __func__, p->update_if);
+ }
+
+ source = &addr;
+ }
+ }
+ } else {
source = p->su_local;
+ }
/* Update peer's source/destination addresses. */
bfd_sess_addresses(session, &family, &src.v6, &dst.v6);
From d6c8c23635873ca26cd6837d2a8e0ad360a734c6 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Wed, 20 Nov 2024 16:07:34 -0500
Subject: [PATCH 3/5] bgpd: Allow bfd to work if peer known but interface
address not yet
If bgp is coming up and bgp has not received the interface address yet
but bgp has knowledge about a bfd peering, allow it to set the peering
data appropriately.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_bfd.c | 8 ++++++--
bgpd/bgp_nexthop.c | 28 +++++++++++++++++-----------
2 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 3a1459b8a557..b3221853bbad 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -151,8 +151,8 @@ void bgp_peer_config_apply(struct peer *p, struct peer_group *pg)
void bgp_peer_bfd_update_source(struct peer *p)
{
- struct bfd_session_params *session = p->bfd_config->session;
- const union sockunion *source;
+ struct bfd_session_params *session;
+ const union sockunion *source = NULL;
bool changed = false;
int family;
union {
@@ -162,6 +162,10 @@ void bgp_peer_bfd_update_source(struct peer *p)
struct interface *ifp;
union sockunion addr;
+ if (!p->bfd_config)
+ return;
+
+ session = p->bfd_config->session;
/* Nothing to do for groups. */
if (CHECK_FLAG(p->sflags, PEER_STATUS_GROUP))
return;
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 77e2603..c85f50d 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -46,6 +46,7 @@
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_rd.h"
+#include "bgpd/bgp_bfd.h"
DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
@@ -427,17 +428,6 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
bgp_dest_set_bgp_connected_ref_info(dest, bc);
}
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (peer->conf_if
- && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
- && !peer_established(peer)
- && !CHECK_FLAG(peer->flags,
- PEER_FLAG_IFPEER_V6ONLY)) {
- if (peer_active(peer))
- BGP_EVENT_ADD(peer, BGP_Stop);
- BGP_EVENT_ADD(peer, BGP_Start);
- }
- }
} else if (addr->family == AF_INET6) {
apply_mask_ipv6((struct prefix_ipv6 *)&p);
@@ -461,6 +451,21 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
bgp_dest_set_bgp_connected_ref_info(dest, bc);
}
}
+
+ /*
+ * Iterate over all the peers and attempt to set the bfd session
+ * data and if it's a bgp unnumbered get her flowing if necessary
+ */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_peer_bfd_update_source(peer);
+ if (peer->conf_if && (strcmp(peer->conf_if, ifc->ifp->name) == 0) &&
+ !peer_established(peer) &&
+ !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) {
+ if (peer_active(peer))
+ BGP_EVENT_ADD(peer, BGP_Stop);
+ BGP_EVENT_ADD(peer, BGP_Start);
+ }
+ }
}
void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
From 2c92346292badda2bad93c1a1188d4349e38cde0 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Thu, 5 Dec 2024 10:16:03 -0500
Subject: [PATCH 4/5] bgpd: When bgp notices a change to shared_network inform
bfd of it
When bgp is started up and reads the config in *before* it has
received interface addresses from zebra, shared_network can
be set to false in this case. Later on once bgp attempts to
reconnect it will refigure out the shared_network again( because
it has received the data from zebra now ). In this case
tell bfd about it.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_zebra.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index f9d096e6c643..e072e18c847f 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -728,6 +728,7 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote,
int ret = 0;
struct interface *ifp = NULL;
bool v6_ll_avail = true;
+ bool shared_network_original = peer->shared_network;
memset(nexthop, 0, sizeof(struct bgp_nexthop));
@@ -892,6 +893,9 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote,
peer->shared_network = 0;
}
+ if (shared_network_original != peer->shared_network)
+ bgp_peer_bfd_update_source(peer);
+
/* KAME stack specific treatment. */
#ifdef KAME
if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_global)
From c059cf388106f81040bdde3ff93a3b2cbd08523b Mon Sep 17 00:00:00 2001
From: Louis Scalbert <louis.scalbert@6wind.com>
Date: Wed, 22 Jan 2025 13:30:55 +0100
Subject: [PATCH 5/5] bgpd: fix bfd with update-source in peer-group
Fix BFD session not created when the peer is in update-group with the
update-source option.
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
---
bgpd/bgp_bfd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index b3221853bbad..f8f06df49f14 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -114,6 +114,10 @@ void bgp_peer_config_apply(struct peer *p, struct peer_group *pg)
*/
gconfig = pg->conf;
+ if (CHECK_FLAG(gconfig->flags, PEER_FLAG_UPDATE_SOURCE) ||
+ CHECK_FLAG(p->flags_override, PEER_FLAG_UPDATE_SOURCE))
+ bgp_peer_bfd_update_source(p);
+
/*
* If using default control plane independent configuration,
* then prefer group's (e.g. it means it wasn't manually configured).
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 4367f25..b43ba32 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -1269,6 +1269,7 @@ void bfd_set_shutdown(struct bfd_session *bs, bool shutdown)
return;
SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN);
+ bs->local_diag = BD_ADMIN_DOWN;
/* Handle data plane shutdown case. */
if (bs->bdc) {
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index df5fcaf..01d61d4 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1367,11 +1367,6 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
peer->nsf_af_count = 0;
- /* deregister peer */
- if (peer->bfd_config
- && peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE)
- bfd_sess_uninstall(peer->bfd_config->session);
-
if (peer_dynamic_neighbor_no_nsf(peer) &&
!(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
if (bgp_debug_neighbor_events(peer))
@@ -1391,6 +1386,10 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer)
if (peer_established(peer)) {
peer->dropped++;
+ if (peer->bfd_config && (peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE ||
+ peer->last_reset == PEER_DOWN_MULTIHOP_CHANGE))
+ bfd_sess_uninstall(peer->bfd_config->session);
+
/* Notify BGP conditional advertisement process */
peer->advmap_table_change = true;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 374d9ee..352a77c 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4253,7 +4253,10 @@ bool peer_active(struct peer *peer)
return false;
if (peer->bfd_config) {
- if (peer_established(peer) && bfd_session_is_down(peer->bfd_config->session))
+ if (bfd_session_is_admin_down(peer->bfd_config->session))
+ return false;
+ else if (peer_established(peer) &&
+ bfd_session_is_down(peer->bfd_config->session))
return false;
}
diff --git a/lib/bfd.c b/lib/bfd.c
index ee9d62d..7f897cd 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -1357,3 +1357,8 @@ bool bfd_session_is_down(const struct bfd_session_params *session)
return session->bss.state == BSS_DOWN ||
session->bss.state == BSS_ADMIN_DOWN;
}
+
+bool bfd_session_is_admin_down(const struct bfd_session_params *session)
+{
+ return session->bss.state == BSS_ADMIN_DOWN;
+}
diff --git a/lib/bfd.h b/lib/bfd.h
index e1ba242..326767d 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -481,6 +481,7 @@ extern int bfd_nht_update(const struct prefix *match,
const struct zapi_route *route);
extern bool bfd_session_is_down(const struct bfd_session_params *session);
+extern bool bfd_session_is_admin_down(const struct bfd_session_params *session);
#ifdef __cplusplus
}

View File

@ -0,0 +1,16 @@
diff --git a/tests/isisd/test_fuzz_isis_tlv.py b/tests/isisd/test_fuzz_isis_tlv.py
index 8fd20aa..a23f665 100644
--- a/tests/isisd/test_fuzz_isis_tlv.py
+++ b/tests/isisd/test_fuzz_isis_tlv.py
@@ -10,10 +10,7 @@ import socket
##
def inet_ntop_broken():
addr = "1:2:3:4:0:6:7:8"
- return (
- socket.inet_ntop(socket.AF_INET6, socket.inet_pton(socket.AF_INET6, addr))
- != addr
- )
+ return True
if platform.uname()[0] == "SunOS" or inet_ntop_broken():

View File

@ -0,0 +1,301 @@
From 46e685d2f9cd1a359e0abd95b584f7cc3df9ae2c Mon Sep 17 00:00:00 2001
From: David Lamparter <equinox@opensourcerouting.org>
Date: Wed, 22 Jan 2025 11:23:31 +0100
Subject: [PATCH] lib: clean up nexthop hashing mess
We were hashing 4 bytes of the address. Even for IPv6 addresses.
Oops.
The reason this was done was to try to make it faster, but made a
complex maze out of everything. Time for a refactor.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
(cherry picked from commit 001fcfa1dd9f7dc2639b4f5c7a52ab59cc425452)
---
lib/nexthop.c | 87 ++++++-----------------------------------
lib/nexthop.h | 104 +++++++++++++++++++++++++++++++++-----------------
2 files changed, 80 insertions(+), 111 deletions(-)
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 98b05295b996..90931676e5de 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -746,68 +746,30 @@ unsigned int nexthop_level(const struct nexthop *nexthop)
return rv;
}
-/* Only hash word-sized things, let cmp do the rest. */
-uint32_t nexthop_hash_quick(const struct nexthop *nexthop)
+uint32_t nexthop_hash(const struct nexthop *nexthop)
{
uint32_t key = 0x45afe398;
- int i;
- key = jhash_3words(nexthop->type, nexthop->vrf_id,
- nexthop->nh_label_type, key);
-
- if (nexthop->nh_label) {
- int labels = nexthop->nh_label->num_labels;
+ /* type, vrf, ifindex, ip addresses - see nexthop.h */
+ key = _nexthop_hash_bytes(nexthop, key);
- i = 0;
+ key = jhash_1word(nexthop->flags & NEXTHOP_FLAGS_HASHED, key);
- while (labels >= 3) {
- key = jhash_3words(nexthop->nh_label->label[i],
- nexthop->nh_label->label[i + 1],
- nexthop->nh_label->label[i + 2],
- key);
- labels -= 3;
- i += 3;
- }
-
- if (labels >= 2) {
- key = jhash_2words(nexthop->nh_label->label[i],
- nexthop->nh_label->label[i + 1],
- key);
- labels -= 2;
- i += 2;
- }
+ if (nexthop->nh_label) {
+ const struct mpls_label_stack *ls = nexthop->nh_label;
- if (labels >= 1)
- key = jhash_1word(nexthop->nh_label->label[i], key);
+ /* num_labels itself isn't useful to hash, if the number of
+ * labels is different, the hash value will change just due to
+ * that already.
+ */
+ key = jhash(ls->label, sizeof(ls->label[0]) * ls->num_labels, key);
}
- key = jhash_2words(nexthop->ifindex,
- CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK),
- key);
-
/* Include backup nexthops, if present */
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
int backups = nexthop->backup_num;
- i = 0;
-
- while (backups >= 3) {
- key = jhash_3words(nexthop->backup_idx[i],
- nexthop->backup_idx[i + 1],
- nexthop->backup_idx[i + 2], key);
- backups -= 3;
- i += 3;
- }
-
- while (backups >= 2) {
- key = jhash_2words(nexthop->backup_idx[i],
- nexthop->backup_idx[i + 1], key);
- backups -= 2;
- i += 2;
- }
-
- if (backups >= 1)
- key = jhash_1word(nexthop->backup_idx[i], key);
+ key = jhash(nexthop->backup_idx, sizeof(nexthop->backup_idx[0]) * backups, key);
}
if (nexthop->nh_srv6) {
@@ -842,31 +804,6 @@ uint32_t nexthop_hash_quick(const struct nexthop *nexthop)
return key;
}
-
-#define GATE_SIZE 4 /* Number of uint32_t words in struct g_addr */
-
-/* For a more granular hash */
-uint32_t nexthop_hash(const struct nexthop *nexthop)
-{
- uint32_t gate_src_rmap_raw[GATE_SIZE * 3] = {};
- /* Get all the quick stuff */
- uint32_t key = nexthop_hash_quick(nexthop);
-
- assert(((sizeof(nexthop->gate) + sizeof(nexthop->src)
- + sizeof(nexthop->rmap_src))
- / 3)
- == (GATE_SIZE * sizeof(uint32_t)));
-
- memcpy(gate_src_rmap_raw, &nexthop->gate, GATE_SIZE);
- memcpy(gate_src_rmap_raw + GATE_SIZE, &nexthop->src, GATE_SIZE);
- memcpy(gate_src_rmap_raw + (2 * GATE_SIZE), &nexthop->rmap_src,
- GATE_SIZE);
-
- key = jhash2(gate_src_rmap_raw, (GATE_SIZE * 3), key);
-
- return key;
-}
-
void nexthop_copy_no_recurse(struct nexthop *copy,
const struct nexthop *nexthop,
struct nexthop *rparent)
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 02ea4d96f2df..12e6424f2774 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -8,6 +8,7 @@
#ifndef _LIB_NEXTHOP_H
#define _LIB_NEXTHOP_H
+#include "jhash.h"
#include "prefix.h"
#include "mpls.h"
#include "vxlan.h"
@@ -56,15 +57,48 @@ struct nexthop {
struct nexthop *next;
struct nexthop *prev;
- /*
- * What vrf is this nexthop associated with?
+
+ /* begin of hashed data - all fields from here onwards are given to
+ * jhash() as one consecutive chunk. DO NOT create "padding holes".
+ * DO NOT insert pointers that need to be deep-hashed.
+ *
+ * static_assert() below needs to be updated when fields are added
*/
+ char _hash_begin[0];
+
+ /* see above */
+ enum nexthop_types_t type;
+
+ /* What vrf is this nexthop associated with? */
vrf_id_t vrf_id;
/* Interface index. */
ifindex_t ifindex;
- enum nexthop_types_t type;
+ /* Type of label(s), if any */
+ enum lsp_types_t nh_label_type;
+
+ /* padding: keep 16 byte alignment here */
+
+ /* Nexthop address
+ * make sure all 16 bytes for IPv6 are zeroed when putting in an IPv4
+ * address since the entire thing is hashed as-is
+ */
+ union {
+ union g_addr gate;
+ enum blackhole_type bh_type;
+ };
+ union g_addr src;
+ union g_addr rmap_src; /* Src is set via routemap */
+
+ /* end of hashed data - remaining fields in this struct are not
+ * directly fed into jhash(). Most of them are actually part of the
+ * hash but have special rules or handling attached.
+ */
+ char _hash_end[0];
+
+ /* Weight of the nexthop ( for unequal cost ECMP ) */
+ uint8_t weight;
uint16_t flags;
#define NEXTHOP_FLAG_ACTIVE (1 << 0) /* This nexthop is alive. */
@@ -82,18 +116,15 @@ struct nexthop {
#define NEXTHOP_FLAG_EVPN (1 << 8) /* nexthop is EVPN */
#define NEXTHOP_FLAG_LINKDOWN (1 << 9) /* is not removed on link down */
+ /* which flags are part of nexthop_hash(). Should probably be split
+ * off into a separate field...
+ */
+#define NEXTHOP_FLAGS_HASHED NEXTHOP_FLAG_ONLINK
+
#define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
&& !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE))
- /* Nexthop address */
- union {
- union g_addr gate;
- enum blackhole_type bh_type;
- };
- union g_addr src;
- union g_addr rmap_src; /* Src is set via routemap */
-
/* Nexthops obtained by recursive resolution.
*
* If the nexthop struct needs to be resolved recursively,
@@ -104,15 +135,9 @@ struct nexthop {
/* Recursive parent */
struct nexthop *rparent;
- /* Type of label(s), if any */
- enum lsp_types_t nh_label_type;
-
/* Label(s) associated with this nexthop. */
struct mpls_label_stack *nh_label;
- /* Weight of the nexthop ( for unequal cost ECMP ) */
- uint8_t weight;
-
/* Count and index of corresponding backup nexthop(s) in a backup list;
* only meaningful if the HAS_BACKUP flag is set.
*/
@@ -138,6 +163,29 @@ struct nexthop {
struct nexthop_srv6 *nh_srv6;
};
+/* all hashed fields (including padding, if it is necessary to add) need to
+ * be listed in the static_assert below
+ */
+
+#define S(field) sizeof(((struct nexthop *)NULL)->field)
+
+static_assert(
+ offsetof(struct nexthop, _hash_end) - offsetof(struct nexthop, _hash_begin) ==
+ S(type) + S(vrf_id) + S(ifindex) + S(nh_label_type) + S(gate) + S(src) + S(rmap_src),
+ "struct nexthop contains padding, this can break things. insert _pad fields at appropriate places");
+
+#undef S
+
+/* this is here to show exactly what is meant by the comments above about
+ * the hashing
+ */
+static inline uint32_t _nexthop_hash_bytes(const struct nexthop *nh, uint32_t seed)
+{
+ return jhash(&nh->_hash_begin,
+ offsetof(struct nexthop, _hash_end) - offsetof(struct nexthop, _hash_begin),
+ seed);
+}
+
/* Utility to append one nexthop to another. */
#define NEXTHOP_APPEND(to, new) \
do { \
@@ -181,27 +229,11 @@ struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type,
/*
* Hash a nexthop. Suitable for use with hash tables.
*
- * This function uses the following values when computing the hash:
- * - vrf_id
- * - ifindex
- * - type
- * - gate
- *
- * nexthop
- * The nexthop to hash
- *
- * Returns:
- * 32-bit hash of nexthop
+ * Please double check the code on what is included in the hash, there was
+ * documentation here but it got outdated and the only thing worse than no
+ * doc is incorrect doc.
*/
uint32_t nexthop_hash(const struct nexthop *nexthop);
-/*
- * Hash a nexthop only on word-sized attributes:
- * - vrf_id
- * - ifindex
- * - type
- * - (some) flags
- */
-uint32_t nexthop_hash_quick(const struct nexthop *nexthop);
extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2);
extern bool nexthop_same_no_labels(const struct nexthop *nh1,

View File

@ -7,7 +7,7 @@
Name: frr
Version: 8.5.3
Release: 7%{?checkout}%{?dist}
Release: 10%{?checkout}%{?dist}
Summary: Routing daemon
License: GPLv2+
URL: http://www.frrouting.org
@ -71,9 +71,14 @@ Patch0005: 0005-CVE-2023-47235.patch
Patch0006: 0006-CVE-2023-47234.patch
Patch0007: 0007-CVE-2023-46752.patch
Patch0008: 0008-CVE-2023-46753.patch
Patch0009: 0009-bfd-bgp-shutdown-notification.patch
Patch0010: 0010-bgp-bfd-drop-connection.patch
Patch0011: 0011-bgp-graceful-restart-noop.patch
Patch0009: 0009-bgp-graceful-restart-noop.patch
Patch0010: 0010-bfd-double-reset.patch
Patch0011: 0011-bfd-shutdown.patch
Patch0012: 0012-print-log-to-stdout.patch
Patch0013: 0013-bfd-bgp-recovery.patch
# Turn off one fuzz test that fails with the new glibc
Patch0014: 0014-isisd-fuzz-test.patch
Patch0015: 0015-ipv6-wrong-hash.patch
%description
FRRouting is free software that manages TCP/IP based routing protocols. It takes
@ -104,6 +109,10 @@ mkdir selinux
cp -p %{SOURCE3} %{SOURCE4} %{SOURCE5} selinux
%build
# This is needed to pass a build with the new glibc
# but this could affect the speed of inet_ntop calls
# https://github.com/FRRouting/frr/issues/18575
export CFLAGS="%{optflags} -DINET_NTOP_NO_OVERRIDE"
autoreconf -ivf
%configure \
@ -279,6 +288,16 @@ make check PYTHON=%{__python3}
%endif
%changelog
* Fri Sep 19 2025 Michal Ruprich <mruprich@redhat.com> - 8.5.3-10
- Resolves: RHEL-13756 - Source address set in FRR route-map not working with IPv6
* Fri May 16 2025 Michal Ruprich <mruprich@redhat.com> - 8.5.3-9
- Resolves: RHEL-87730 - frr-k8s CI started failing using latest rpm, failures around BFD sessions
- Resolves: RHEL-87731 - FRR bgp session not recovered due to incorect error no AF activated for peer
* Thu Apr 03 2025 Michal Ruprich <mruprich@redhat.com> - 8.5.3-8
- Resolves: RHEL-85950 - FRR doesn't send logs to stdout when running as a daemon
* Fri Feb 14 2025 Michal Ruprich <mruprich@redhat.com> - 8.5.3-7
- Resolves: RHEL-68432 - FRR gives false warning when Graceful Restart enabled