aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2022-01-24 03:44:21 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2022-01-24 03:44:21 +0100
commit9dbb7eb6ebda016cd14ce8fef403c2b3f7bdd504 (patch)
tree62121fe6ef0706322353bb26525fc1199a74afe2
parenta9646efd40569f3a1d749bc1bd13219876b33a00 (diff)
downloadbird-9dbb7eb6ebda016cd14ce8fef403c2b3f7bdd504.tar.gz
BGP: Log route updates that were changed to withdraws
Typical BGP error handling is treat-as-withdraw, where an invalid route is replaced with a withdraw. Log route network when it happens.
-rw-r--r--proto/bgp/attrs.c4
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/packets.c8
3 files changed, 12 insertions, 1 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 24ba00ba..0688c7cd 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1845,6 +1845,10 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
{
struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2);
+ /* Error during attribute processing */
+ if (!attrs)
+ log(L_ERR "%s: Invalid route %N withdrawn", p->p.name, n->n.addr);
+
/* If attributes are invalid, we fail back to withdraw */
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
path = new->attrs->src->global_id;
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 5e025ccd..db05b693 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -423,6 +423,7 @@ struct bgp_parse_state {
int as4_session;
int add_path;
int mpls;
+ int reach_nlri_step;
u32 attrs_seen[256/32];
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 99b5d5b4..9843a9e0 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -1335,7 +1335,7 @@ bgp_update_next_hop_none(struct bgp_export_state *s, eattr *a, ea_list **to)
*/
static void
-bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0)
+bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a0)
{
if (path_id != s->last_id)
{
@@ -1348,6 +1348,10 @@ bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0)
if (!a0)
{
+ /* Route update was changed to withdraw */
+ if (s->err_withdraw && s->reach_nlri_step)
+ REPORT("Invalid route %N withdrawn", n);
+
/* Route withdraw */
rte_update3(&s->channel->c, n, NULL, s->last_src);
return;
@@ -2543,6 +2547,8 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
if (s.mp_unreach_len)
bgp_decode_nlri(&s, s.mp_unreach_af, s.mp_unreach_nlri, s.mp_unreach_len, NULL, NULL, 0);
+ s.reach_nlri_step = 1;
+
if (s.ip_reach_len)
bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_reach_nlri, s.ip_reach_len,
ea, s.ip_next_hop_data, s.ip_next_hop_len);