Commit dbb9cad67e for frr

commit dbb9cad67e49ff6aadaedb81bc3a99455ef07b20
Author: Donatas Abraitis <donatas@opensourcerouting.org>
Date:   Fri Sep 18 15:04:29 2026 +0300

    bgpd: Process withdrawals first in NLRIs handling

    RFC 4271 clearly says:

    An UPDATE message SHOULD NOT include the same address prefix in the
       WITHDRAWN ROUTES and Network Layer Reachability Information fields.
       However, a BGP speaker MUST be able to process UPDATE messages in
       this form.  A BGP speaker SHOULD treat an UPDATE message of this form
       as though the WITHDRAWN ROUTES do not contain the address prefix.

    Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>

diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 0591c0b745..3c9c9b349d 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -2401,10 +2401,10 @@ static int bgp_update_receive(struct peer_connection *connection, bgp_size_t siz
 	bgp_size_t update_len;
 	bgp_size_t withdraw_len;
 	enum NLRI_TYPES {
-		NLRI_UPDATE,
 		NLRI_WITHDRAW,
-		NLRI_MP_UPDATE,
 		NLRI_MP_WITHDRAW,
+		NLRI_UPDATE,
+		NLRI_MP_UPDATE,
 		NLRI_TYPE_MAX
 	};
 	struct bgp_nlri nlris[NLRI_TYPE_MAX];
@@ -2559,7 +2559,7 @@ static int bgp_update_receive(struct peer_connection *connection, bgp_size_t siz
 			   withdraw_len, attribute_len, update_len);

 	/* Parse any given NLRIs */
-	for (int i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++) {
+	for (int i = NLRI_WITHDRAW; i < NLRI_TYPE_MAX; i++) {
 		if (!nlris[i].nlri)
 			continue;

@@ -2596,9 +2596,8 @@ static int bgp_update_receive(struct peer_connection *connection, bgp_size_t siz
 			flog_err(EC_BGP_UPDATE_RCV,
 				 "%s [Error] Error parsing NLRI", peer->host);
 			if (peer_established(connection))
-				bgp_notify_send(connection,
-						BGP_NOTIFY_UPDATE_ERR,
-						i <= NLRI_WITHDRAW
+				bgp_notify_send(connection, BGP_NOTIFY_UPDATE_ERR,
+						(i == NLRI_WITHDRAW || i == NLRI_UPDATE)
 							? BGP_NOTIFY_UPDATE_INVAL_NETWORK
 							: BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
 			bgp_attr_unintern_sub(&attr);