diff --git a/.gitmodules b/.gitmodules index 1b7aed9f145f..b76f589bdfa8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,7 +46,7 @@ [submodule "src/sonic-frr/frr"] path = src/sonic-frr/frr url = https://github.com/sonic-net/sonic-frr.git - branch = frr/8.5 + branch = frr-10.0.1 [submodule "platform/p4/p4-hlir/p4-hlir-v1.1"] path = platform/p4/p4-hlir/p4-hlir-v1.1 url = https://github.com/p4lang/p4-hlir.git diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index 445dbf08688a..0a26dd51c3fa 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -29,6 +29,17 @@ stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true +[program:mgmtd] +command=/usr/lib/frr/mgmtd -A 127.0.0.1 +priority=4 +autostart=false +autorestart=true +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + [program:zebra] command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M dplane_fpm_sonic -M snmp --asic-offload=notify_on_offload priority=4 diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 index 54b408b50bd2..e2fd50bfcfba 100644 --- a/platform/vs/docker-sonic-vs/Dockerfile.j2 +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -60,7 +60,9 @@ RUN apt-get install -y net-tools \ # For libkrb5-dev comerr-dev \ libgssrpc4 \ - libkdb5-10 + libkdb5-10 \ + libprotobuf-c-dev \ + protobuf-c-compiler # For sonic-config-engine Python 3 package # Install pyangbind here, outside sonic-config-engine dependencies, as pyangbind causes enum34 to be installed. diff --git a/platform/vs/docker-sonic-vs/supervisord.conf.j2 b/platform/vs/docker-sonic-vs/supervisord.conf.j2 index d8d9ce390cb8..d389f28311cf 100644 --- a/platform/vs/docker-sonic-vs/supervisord.conf.j2 +++ b/platform/vs/docker-sonic-vs/supervisord.conf.j2 @@ -163,6 +163,14 @@ stderr_logfile=syslog environment=ASAN_OPTIONS="log_path=/var/log/asan/teammgrd-asan.log{{ asan_extra_options }}" {% endif %} +[program:mgmtd] +command=/usr/lib/frr/mgmtd -A 127.0.0.1 +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + [program:zebra] command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M dplane_fpm_sonic --asic-offload=notify_on_offload priority=13 diff --git a/rules/frr.mk b/rules/frr.mk index da42179a0312..ff3c3ea4ab17 100644 --- a/rules/frr.mk +++ b/rules/frr.mk @@ -1,9 +1,9 @@ # FRRouting (frr) package -FRR_VERSION = 8.5.4 +FRR_VERSION = 10.0.1 FRR_SUBVERSION = 0 -FRR_BRANCH = frr/8.5 -FRR_TAG = frr-8.5.4 +FRR_BRANCH = frr-10.0.1 +FRR_TAG = frr-10.0.1 export FRR_VERSION FRR_SUBVERSION FRR_BRANCH FRR_TAG diff --git a/rules/libyang2.mk b/rules/libyang2.mk index ca6d611b52ee..e683ff05eb1f 100644 --- a/rules/libyang2.mk +++ b/rules/libyang2.mk @@ -1,8 +1,8 @@ # libyang2 -LIBYANG2_VERSION_BASE = 2.0 -LIBYANG2_VERSION = $(LIBYANG2_VERSION_BASE).112 -LIBYANG2_SUBVERSION = 6 +LIBYANG2_VERSION_BASE = 2.1 +LIBYANG2_VERSION = $(LIBYANG2_VERSION_BASE).148 +LIBYANG2_SUBVERSION = 0.2 LIBYANG2_FULLVERSION = $(LIBYANG2_VERSION)-$(LIBYANG2_SUBVERSION) export LIBYANG2_VERSION_BASE @@ -10,14 +10,14 @@ export LIBYANG2_VERSION export LIBYANG2_SUBVERSION export LIBYANG2_FULLVERSION -LIBYANG2 = libyang2_$(LIBYANG2_FULLVERSION)_$(CONFIGURED_ARCH).deb +LIBYANG2 = libyang2t64_$(LIBYANG2_FULLVERSION)_$(CONFIGURED_ARCH).deb $(LIBYANG2)_SRC_PATH = $(SRC_PATH)/libyang2 SONIC_MAKE_DEBS += $(LIBYANG2) LIBYANG2_DEV = libyang2-dev_$(LIBYANG2_FULLVERSION)_$(CONFIGURED_ARCH).deb $(eval $(call add_derived_package,$(LIBYANG2),$(LIBYANG2_DEV))) -LIBYANG2_DBG = libyang2-dbgsym_$(LIBYANG2_FULLVERSION)_$(CONFIGURED_ARCH).deb +LIBYANG2_DBG = libyang2t64-dbgsym_$(LIBYANG2_FULLVERSION)_$(CONFIGURED_ARCH).deb $(eval $(call add_derived_package,$(LIBYANG2),$(LIBYANG2_DBG))) diff --git a/sonic-slave-bookworm/Dockerfile.j2 b/sonic-slave-bookworm/Dockerfile.j2 index 8416c3166fe0..ed995079552b 100644 --- a/sonic-slave-bookworm/Dockerfile.j2 +++ b/sonic-slave-bookworm/Dockerfile.j2 @@ -145,6 +145,8 @@ RUN apt-get update && apt-get install -y eatmydata && eatmydata apt-get install libjson-c-dev \ libsystemd-dev \ libcmocka-dev \ + libprotobuf-c-dev \ + protobuf-c-compiler \ #{%- if CROSS_BUILD_ENVIRON != "y" %} python3-all-dev \ python3-all-dbg \ diff --git a/sonic-slave-bullseye/Dockerfile.j2 b/sonic-slave-bullseye/Dockerfile.j2 index 1aca2a0ba5e3..b1a98863d3fc 100644 --- a/sonic-slave-bullseye/Dockerfile.j2 +++ b/sonic-slave-bullseye/Dockerfile.j2 @@ -148,6 +148,8 @@ RUN apt-get update && apt-get install -y eatmydata && eatmydata apt-get install libsystemd-dev \ python3-ipaddr \ libcmocka-dev \ + libprotobuf-c-dev \ + protobuf-c-compiler \ #{%- if CROSS_BUILD_ENVIRON != "y" %} python3-all-dev \ python3-all-dbg \ diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index dce6daa520a0..b65a1a08957c 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -144,6 +144,8 @@ RUN apt-get update && apt-get install -y eatmydata && eatmydata apt-get install libsystemd-dev \ python-ipaddr \ libcmocka-dev \ + libprotobuf-c-dev \ + protobuf-c-compiler \ {%- if CROSS_BUILD_ENVIRON != "y" %} python3-all-dev \ python3-all-dbg \ diff --git a/src/libyang2/Makefile b/src/libyang2/Makefile index fab24590a340..16d80587573e 100644 --- a/src/libyang2/Makefile +++ b/src/libyang2/Makefile @@ -5,7 +5,7 @@ SHELL = /bin/bash LIBYANG_URL = https://sonicstorage.blob.core.windows.net/debian/pool/main/liby/libyang DSC_FILE = libyang2_$(LIBYANG2_FULLVERSION).dsc -ORIG_FILE = libyang2_$(LIBYANG2_VERSION).orig.tar.gz +ORIG_FILE = libyang2_$(LIBYANG2_VERSION).orig.tar.xz DEBIAN_FILE = libyang2_$(LIBYANG2_FULLVERSION).debian.tar.xz DSC_FILE_URL = $(LIBYANG_URL)/$(DSC_FILE) @@ -26,6 +26,10 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : dpkg-source -x libyang2_$(LIBYANG2_FULLVERSION).dsc pushd libyang2-$(LIBYANG2_VERSION) + #The package libyang2.1.148 is taken from debian trixie, which only has dpkg-dev version 1.21.22 + #The bullseye package has dpkg-dev version 1.20.13 + #The VS package has dpkg-dev version 1.19.8 + sed -i 's/dpkg-dev (>= 1.22.5)/dpkg-dev (>= 1.19.8)/' debian/control #sed -i 's/set(LIBYANG_MAJOR_SOVERSION 1)/set(LIBYANG_MAJOR_SOVERSION 2)/' CMakeLists.txt #sed -i 's/libyang2/libyang2/' debian/libyang2.install # Enable large file support for 32-bit arch diff --git a/src/sonic-frr/Makefile b/src/sonic-frr/Makefile index 307089d91eae..6462af5ac6e4 100644 --- a/src/sonic-frr/Makefile +++ b/src/sonic-frr/Makefile @@ -36,6 +36,7 @@ endif ifeq ($(CROSS_BUILD_ENVIRON), y) git reset --hard endif + git branch -f master origin/$(FRR_BRANCH) git checkout master git branch -D $(FRR_BRANCH) popd diff --git a/src/sonic-frr/dplane_fpm_sonic/dplane_fpm_sonic.c b/src/sonic-frr/dplane_fpm_sonic/dplane_fpm_sonic.c index f01c647d4a67..6627e9331e87 100644 --- a/src/sonic-frr/dplane_fpm_sonic/dplane_fpm_sonic.c +++ b/src/sonic-frr/dplane_fpm_sonic/dplane_fpm_sonic.c @@ -32,6 +32,7 @@ #include #include "lib/zebra.h" +#include #include "lib/json.h" #include "lib/libfrr.h" #include "lib/frratomic.h" @@ -45,8 +46,6 @@ #include "zebra/zebra_dplane.h" #include "zebra/zebra_mpls.h" #include "zebra/zebra_router.h" -#include "zebra/zebra_evpn.h" -#include "zebra/zebra_evpn_mac.h" #include "zebra/zebra_vxlan_private.h" #include "zebra/kernel_netlink.h" #include "zebra/rt_netlink.h" @@ -165,22 +164,22 @@ struct fpm_nl_ctx { /* data plane events. */ struct zebra_dplane_provider *prov; struct frr_pthread *fthread; - struct thread *t_connect; - struct thread *t_read; - struct thread *t_write; - struct thread *t_event; - struct thread *t_nhg; - struct thread *t_dequeue; + struct event *t_connect; + struct event *t_read; + struct event *t_write; + struct event *t_event; + struct event *t_nhg; + struct event *t_dequeue; /* zebra events. */ - struct thread *t_lspreset; - struct thread *t_lspwalk; - struct thread *t_nhgreset; - struct thread *t_nhgwalk; - struct thread *t_ribreset; - struct thread *t_ribwalk; - struct thread *t_rmacreset; - struct thread *t_rmacwalk; + struct event *t_lspreset; + struct event *t_lspwalk; + struct event *t_nhgreset; + struct event *t_nhgwalk; + struct event *t_ribreset; + struct event *t_ribwalk; + struct event *t_rmacreset; + struct event *t_rmacwalk; /* Statistic counters. */ struct { @@ -238,26 +237,26 @@ enum fpm_nl_events { }; #define FPM_RECONNECT(fnc) \ - thread_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \ + event_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \ FNE_INTERNAL_RECONNECT, &(fnc)->t_event) #define WALK_FINISH(fnc, ev) \ - thread_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \ + event_add_event((fnc)->fthread->master, fpm_process_event, (fnc), \ (ev), NULL) /* * Prototypes. */ -static void fpm_process_event(struct thread *t); +static void fpm_process_event(struct event *t); static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx); -static void fpm_lsp_send(struct thread *t); -static void fpm_lsp_reset(struct thread *t); -static void fpm_nhg_send(struct thread *t); -static void fpm_nhg_reset(struct thread *t); -static void fpm_rib_send(struct thread *t); -static void fpm_rib_reset(struct thread *t); -static void fpm_rmac_send(struct thread *t); -static void fpm_rmac_reset(struct thread *t); +static void fpm_lsp_send(struct event *t); +static void fpm_lsp_reset(struct event *t); +static void fpm_nhg_send(struct event *t); +static void fpm_nhg_reset(struct event *t); +static void fpm_rib_send(struct event *t); +static void fpm_rib_reset(struct event *t); +static void fpm_rmac_send(struct event *t); +static void fpm_rmac_reset(struct event *t); /* * CLI. @@ -313,7 +312,7 @@ DEFUN(fpm_set_address, fpm_set_address_cmd, memcpy(&sin6->sin6_addr, naddr, sizeof(sin6->sin6_addr)); ask_reconnect: - thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc, + event_add_event(gfnc->fthread->master, fpm_process_event, gfnc, FNE_RECONNECT, &gfnc->t_event); return CMD_SUCCESS; } @@ -328,7 +327,7 @@ DEFUN(no_fpm_set_address, no_fpm_set_address_cmd, "FPM remote listening server port\n" "Remote FPM server port\n") { - thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc, + event_add_event(gfnc->fthread->master, fpm_process_event, gfnc, FNE_DISABLE, &gfnc->t_event); return CMD_SUCCESS; } @@ -342,7 +341,7 @@ DEFUN(fpm_use_nhg, fpm_use_nhg_cmd, if (gfnc->use_nhg) return CMD_SUCCESS; - thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc, + event_add_event(gfnc->fthread->master, fpm_process_event, gfnc, FNE_TOGGLE_NHG, &gfnc->t_nhg); return CMD_SUCCESS; @@ -358,7 +357,7 @@ DEFUN(no_fpm_use_nhg, no_fpm_use_nhg_cmd, if (!gfnc->use_nhg) return CMD_SUCCESS; - thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc, + event_add_event(gfnc->fthread->master, fpm_process_event, gfnc, FNE_TOGGLE_NHG, &gfnc->t_nhg); return CMD_SUCCESS; @@ -370,7 +369,7 @@ DEFUN(fpm_reset_counters, fpm_reset_counters_cmd, FPM_STR "FPM statistic counters\n") { - thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc, + event_add_event(gfnc->fthread->master, fpm_process_event, gfnc, FNE_RESET_COUNTERS, &gfnc->t_event); return CMD_SUCCESS; } @@ -491,19 +490,19 @@ static struct cmd_node fpm_node = { /* * FPM functions. */ -static void fpm_connect(struct thread *t); +static void fpm_connect(struct event *t); static void fpm_reconnect(struct fpm_nl_ctx *fnc) { /* Cancel all zebra threads first. */ - thread_cancel_async(zrouter.master, &fnc->t_lspreset, NULL); - thread_cancel_async(zrouter.master, &fnc->t_lspwalk, NULL); - thread_cancel_async(zrouter.master, &fnc->t_nhgreset, NULL); - thread_cancel_async(zrouter.master, &fnc->t_nhgwalk, NULL); - thread_cancel_async(zrouter.master, &fnc->t_ribreset, NULL); - thread_cancel_async(zrouter.master, &fnc->t_ribwalk, NULL); - thread_cancel_async(zrouter.master, &fnc->t_rmacreset, NULL); - thread_cancel_async(zrouter.master, &fnc->t_rmacwalk, NULL); + event_cancel_async(zrouter.master, &fnc->t_lspreset, NULL); + event_cancel_async(zrouter.master, &fnc->t_lspwalk, NULL); + event_cancel_async(zrouter.master, &fnc->t_nhgreset, NULL); + event_cancel_async(zrouter.master, &fnc->t_nhgwalk, NULL); + event_cancel_async(zrouter.master, &fnc->t_ribreset, NULL); + event_cancel_async(zrouter.master, &fnc->t_ribwalk, NULL); + event_cancel_async(zrouter.master, &fnc->t_rmacreset, NULL); + event_cancel_async(zrouter.master, &fnc->t_rmacwalk, NULL); /* * Grab the lock to empty the streams (data plane might try to @@ -519,20 +518,20 @@ static void fpm_reconnect(struct fpm_nl_ctx *fnc) stream_reset(fnc->ibuf); stream_reset(fnc->obuf); - THREAD_OFF(fnc->t_read); - THREAD_OFF(fnc->t_write); + EVENT_OFF(fnc->t_read); + EVENT_OFF(fnc->t_write); /* FPM is disabled, don't attempt to connect. */ if (fnc->disabled) return; - thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, + event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, &fnc->t_connect); } -static void fpm_read(struct thread *t) +static void fpm_read(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); fpm_msg_hdr_t fpm; ssize_t rv; char buf[65535]; @@ -564,7 +563,7 @@ static void fpm_read(struct thread *t) } /* Schedule the next read */ - thread_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket, + event_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket, &fnc->t_read); /* We've got an interruption. */ @@ -693,9 +692,9 @@ static void fpm_read(struct thread *t) stream_reset(fnc->ibuf); } -static void fpm_write(struct thread *t) +static void fpm_write(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); socklen_t statuslen; ssize_t bwritten; int rv, status; @@ -729,11 +728,11 @@ static void fpm_write(struct thread *t) * Starting with LSPs walk all FPM objects, marking them * as unsent and then replaying them. */ - thread_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0, + event_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0, &fnc->t_lspreset); /* Permit receiving messages now. */ - thread_add_read(fnc->fthread->master, fpm_read, fnc, + event_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket, &fnc->t_read); } @@ -791,15 +790,15 @@ static void fpm_write(struct thread *t) /* Stream is not empty yet, we must schedule more writes. */ if (STREAM_READABLE(fnc->obuf)) { stream_pulldown(fnc->obuf); - thread_add_write(fnc->fthread->master, fpm_write, fnc, + event_add_write(fnc->fthread->master, fpm_write, fnc, fnc->socket, &fnc->t_write); return; } } -static void fpm_connect(struct thread *t) +static void fpm_connect(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); struct sockaddr_in *sin = (struct sockaddr_in *)&fnc->addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&fnc->addr; socklen_t slen; @@ -810,7 +809,7 @@ static void fpm_connect(struct thread *t) if (sock == -1) { zlog_err("%s: fpm socket failed: %s", __func__, strerror(errno)); - thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, + event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, &fnc->t_connect); return; } @@ -836,7 +835,7 @@ static void fpm_connect(struct thread *t) close(sock); zlog_warn("%s: fpm connection failed: %s", __func__, strerror(errno)); - thread_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, + event_add_timer(fnc->fthread->master, fpm_connect, fnc, 3, &fnc->t_connect); return; } @@ -844,9 +843,9 @@ static void fpm_connect(struct thread *t) fnc->connecting = (errno == EINPROGRESS); fnc->socket = sock; if (!fnc->connecting) - thread_add_read(fnc->fthread->master, fpm_read, fnc, sock, + event_add_read(fnc->fthread->master, fpm_read, fnc, sock, &fnc->t_read); - thread_add_write(fnc->fthread->master, fpm_write, fnc, sock, + event_add_write(fnc->fthread->master, fpm_write, fnc, sock, &fnc->t_write); /* @@ -856,7 +855,7 @@ static void fpm_connect(struct thread *t) * If we are not connected, then delay the objects reset/send. */ if (!fnc->connecting) - thread_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0, + event_add_timer(zrouter.master, fpm_lsp_reset, fnc, 0, &fnc->t_lspreset); } @@ -886,9 +885,9 @@ static struct zebra_vrf *vrf_lookup_by_table_id(uint32_t table_id) /** * Resets the SRv6 routes FPM flags so we send all SRv6 routes again. */ -static void fpm_srv6_route_reset(struct thread *t) +static void fpm_srv6_route_reset(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); rib_dest_t *dest; struct route_node *rn; struct route_entry *re; @@ -910,14 +909,14 @@ static void fpm_srv6_route_reset(struct thread *t) nexthop = re->nhe->nhg.nexthop; if (nexthop && nexthop->nh_srv6 && - !sid_zero(&nexthop->nh_srv6->seg6_segs)) + !sid_zero((const struct seg6_seg_stack *)nexthop->nh_srv6->seg6_segs)) /* Unset FPM installation flag so it gets installed again. */ UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); } } /* Schedule next step: send RIB routes. */ - thread_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk); + event_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk); } /* @@ -975,7 +974,7 @@ static ssize_t netlink_srv6_localsid_msg_encode(int cmd, req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; if ((cmd == RTM_NEWSRV6LOCALSID) && - (v6_rr_semantics)) + (zrouter.v6_rr_semantics)) req->n.nlmsg_flags |= NLM_F_REPLACE; req->n.nlmsg_type = cmd; @@ -1202,8 +1201,9 @@ static ssize_t netlink_srv6_vpn_route_msg_encode(int cmd, uint32_t table_id; struct interface *ifp; struct in6_addr encap_src_addr = {}; - struct listnode *node; struct connected *connected; + struct vrf *vrf; + struct prefix *cp; struct { struct nlmsghdr n; @@ -1212,7 +1212,7 @@ static ssize_t netlink_srv6_vpn_route_msg_encode(int cmd, } *req = (void *)data; nexthop = dplane_ctx_get_ng(ctx)->nexthop; - if (!nexthop || !nexthop->nh_srv6 || sid_zero(&nexthop->nh_srv6->seg6_segs)) + if (!nexthop || !nexthop->nh_srv6 || sid_zero((const struct seg6_seg_stack *)nexthop->nh_srv6->seg6_segs)) return -1; p = dplane_ctx_get_dest(ctx); @@ -1230,7 +1230,7 @@ static ssize_t netlink_srv6_vpn_route_msg_encode(int cmd, req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; if ((cmd == RTM_NEWROUTE) && - ((p->family == AF_INET) || v6_rr_semantics)) + ((p->family == AF_INET) || zrouter.v6_rr_semantics)) req->n.nlmsg_flags |= NLM_F_REPLACE; req->n.nlmsg_type = cmd; @@ -1291,13 +1291,19 @@ static ssize_t netlink_srv6_vpn_route_msg_encode(int cmd, * if it is valid */ ifp = if_lookup_by_name("lo", VRF_DEFAULT); + vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME); + if (!vrf) + return false; if (ifp) { - FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) { - if (connected->address->family == AF_INET6 && - !IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6) && - !IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6)) { - encap_src_addr = connected->address->u.prefix6; - break; + FOR_ALL_INTERFACES (vrf, ifp) { + frr_each (if_connected, ifp->connected, connected) { + cp = connected->address; + if (cp->family == AF_INET6 && + !IN6_IS_ADDR_LOOPBACK(&cp->u.prefix6) && + !IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { + encap_src_addr = cp->u.prefix6; + break; + } } } } @@ -1348,7 +1354,7 @@ static ssize_t netlink_srv6_msg_encode(int cmd, if (!netlink_srv6_localsid_msg_encode( cmd, ctx, data, datalen, fpm, force_nhg)) return 0; - } else if (!sid_zero(&nexthop->nh_srv6->seg6_segs)) { + } else if (!sid_zero(nexthop->nh_srv6->seg6_segs)) { if (!netlink_srv6_vpn_route_msg_encode( cmd, ctx, data, datalen, fpm, force_nhg)) return 0; @@ -1417,7 +1423,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) } else { rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx, nl_buf, sizeof(nl_buf), - true, fnc->use_nhg); + true, fnc->use_nhg, false); if (rv <= 0) { zlog_err( "%s: netlink_route_multipath_msg_encode failed", @@ -1448,7 +1454,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) } else { rv = netlink_route_multipath_msg_encode( RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len], - sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg); + sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg, false); if (rv <= 0) { zlog_err( "%s: netlink_route_multipath_msg_encode failed", @@ -1513,7 +1519,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) case DPLANE_OP_ADDR_INSTALL: case DPLANE_OP_ADDR_UNINSTALL: if (strmatch(dplane_ctx_get_ifname(ctx), "lo")) - thread_add_timer(fnc->fthread->master, fpm_srv6_route_reset, + event_add_timer(fnc->fthread->master, fpm_srv6_route_reset, fnc, 0, &fnc->t_ribreset); break; @@ -1610,7 +1616,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) memory_order_relaxed); /* Tell the thread to start writing. */ - thread_add_write(fnc->fthread->master, fpm_write, fnc, fnc->socket, + event_add_write(fnc->fthread->master, fpm_write, fnc, fnc->socket, &fnc->t_write); return 0; @@ -1647,9 +1653,9 @@ static int fpm_lsp_send_cb(struct hash_bucket *bucket, void *arg) return HASHWALK_CONTINUE; } -static void fpm_lsp_send(struct thread *t) +static void fpm_lsp_send(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); struct fpm_lsp_arg fla; @@ -1665,11 +1671,11 @@ static void fpm_lsp_send(struct thread *t) WALK_FINISH(fnc, FNE_LSP_FINISHED); /* Now move onto routes */ - thread_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0, + event_add_timer(zrouter.master, fpm_nhg_reset, fnc, 0, &fnc->t_nhgreset); } else { /* Didn't finish - reschedule LSP walk */ - thread_add_timer(zrouter.master, fpm_lsp_send, fnc, 0, + event_add_timer(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk); } } @@ -1707,9 +1713,9 @@ static int fpm_nhg_send_cb(struct hash_bucket *bucket, void *arg) return HASHWALK_CONTINUE; } -static void fpm_nhg_send(struct thread *t) +static void fpm_nhg_send(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); struct fpm_nhg_arg fna; fna.fnc = fnc; @@ -1726,19 +1732,19 @@ static void fpm_nhg_send(struct thread *t) /* We are done sending next hops, lets install the routes now. */ if (fna.complete) { WALK_FINISH(fnc, FNE_NHG_FINISHED); - thread_add_timer(zrouter.master, fpm_rib_reset, fnc, 0, + event_add_timer(zrouter.master, fpm_rib_reset, fnc, 0, &fnc->t_ribreset); } else /* Otherwise reschedule next hop group again. */ - thread_add_timer(zrouter.master, fpm_nhg_send, fnc, 0, + event_add_timer(zrouter.master, fpm_nhg_send, fnc, 0, &fnc->t_nhgwalk); } /** * Send all RIB installed routes to the connected data plane. */ -static void fpm_rib_send(struct thread *t) +static void fpm_rib_send(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); rib_dest_t *dest; struct route_node *rn; struct route_table *rt; @@ -1768,7 +1774,7 @@ static void fpm_rib_send(struct thread *t) /* Free the temporary allocated context. */ dplane_ctx_fini(&ctx); - thread_add_timer(zrouter.master, fpm_rib_send, + event_add_timer(zrouter.master, fpm_rib_send, fnc, 1, &fnc->t_ribwalk); return; } @@ -1785,7 +1791,7 @@ static void fpm_rib_send(struct thread *t) WALK_FINISH(fnc, FNE_RIB_FINISHED); /* Schedule next event: RMAC reset. */ - thread_add_event(zrouter.master, fpm_rmac_reset, fnc, 0, + event_add_event(zrouter.master, fpm_rmac_reset, fnc, 0, &fnc->t_rmacreset); } @@ -1805,6 +1811,7 @@ static void fpm_enqueue_rmac_table(struct hash_bucket *bucket, void *arg) struct zebra_mac *zrmac = bucket->data; struct zebra_if *zif = fra->zl3vni->vxlan_if->info; const struct zebra_l2info_vxlan *vxl = &zif->l2info.vxl; + struct zebra_vxlan_vni *vni; struct zebra_if *br_zif; vlanid_t vid; bool sticky; @@ -1816,16 +1823,17 @@ static void fpm_enqueue_rmac_table(struct hash_bucket *bucket, void *arg) sticky = !!CHECK_FLAG(zrmac->flags, (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)); br_zif = (struct zebra_if *)(zif->brslave_info.br_if->info); - vid = IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) ? vxl->access_vlan : 0; + vni = zebra_vxlan_if_vni_find(zif, fra->zl3vni->vni); + vid = IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) ? vxl->vni_info.vni.access_vlan : 0; dplane_ctx_reset(fra->ctx); dplane_ctx_set_op(fra->ctx, DPLANE_OP_MAC_INSTALL); dplane_mac_init(fra->ctx, fra->zl3vni->vxlan_if, zif->brslave_info.br_if, vid, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, sticky, + &zrmac->macaddr, vni->vni, zrmac->fwd_info.r_vtep_ip, sticky, 0 /*nhg*/, 0 /*update_flags*/); if (fpm_nl_enqueue(fra->fnc, fra->ctx) == -1) { - thread_add_timer(zrouter.master, fpm_rmac_send, + event_add_timer(zrouter.master, fpm_rmac_send, fra->fnc, 1, &fra->fnc->t_rmacwalk); fra->complete = false; } @@ -1840,11 +1848,11 @@ static void fpm_enqueue_l3vni_table(struct hash_bucket *bucket, void *arg) hash_iterate(zl3vni->rmac_table, fpm_enqueue_rmac_table, zl3vni); } -static void fpm_rmac_send(struct thread *t) +static void fpm_rmac_send(struct event *t) { struct fpm_rmac_arg fra; - fra.fnc = THREAD_ARG(t); + fra.fnc = EVENT_ARG(t); fra.ctx = dplane_ctx_alloc(); fra.complete = true; hash_iterate(zrouter.l3vni_table, fpm_enqueue_l3vni_table, &fra); @@ -1866,14 +1874,14 @@ static void fpm_nhg_reset_cb(struct hash_bucket *bucket, void *arg) UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_FPM); } -static void fpm_nhg_reset(struct thread *t) +static void fpm_nhg_reset(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); hash_iterate(zrouter.nhgs_id, fpm_nhg_reset_cb, NULL); /* Schedule next step: send next hop groups. */ - thread_add_event(zrouter.master, fpm_nhg_send, fnc, 0, &fnc->t_nhgwalk); + event_add_event(zrouter.master, fpm_nhg_send, fnc, 0, &fnc->t_nhgwalk); } /* @@ -1886,23 +1894,23 @@ static void fpm_lsp_reset_cb(struct hash_bucket *bucket, void *arg) UNSET_FLAG(lsp->flags, LSP_FLAG_FPM); } -static void fpm_lsp_reset(struct thread *t) +static void fpm_lsp_reset(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); hash_iterate(zvrf->lsp_table, fpm_lsp_reset_cb, NULL); /* Schedule next step: send LSPs */ - thread_add_event(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk); + event_add_event(zrouter.master, fpm_lsp_send, fnc, 0, &fnc->t_lspwalk); } /** * Resets the RIB FPM flags so we send all routes again. */ -static void fpm_rib_reset(struct thread *t) +static void fpm_rib_reset(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); rib_dest_t *dest; struct route_node *rn; struct route_table *rt; @@ -1921,7 +1929,7 @@ static void fpm_rib_reset(struct thread *t) } /* Schedule next step: send RIB routes. */ - thread_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk); + event_add_event(zrouter.master, fpm_rib_send, fnc, 0, &fnc->t_ribwalk); } /* @@ -1941,20 +1949,20 @@ static void fpm_unset_l3vni_table(struct hash_bucket *bucket, void *arg) hash_iterate(zl3vni->rmac_table, fpm_unset_rmac_table, zl3vni); } -static void fpm_rmac_reset(struct thread *t) +static void fpm_rmac_reset(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); hash_iterate(zrouter.l3vni_table, fpm_unset_l3vni_table, NULL); /* Schedule next event: send RMAC entries. */ - thread_add_event(zrouter.master, fpm_rmac_send, fnc, 0, + event_add_event(zrouter.master, fpm_rmac_send, fnc, 0, &fnc->t_rmacwalk); } -static void fpm_process_queue(struct thread *t) +static void fpm_process_queue(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); struct zebra_dplane_ctx *ctx; bool no_bufs = false; uint64_t processed_contexts = 0; @@ -1997,7 +2005,7 @@ static void fpm_process_queue(struct thread *t) /* Re-schedule if we ran out of buffer space */ if (no_bufs) - thread_add_timer(fnc->fthread->master, fpm_process_queue, + event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0, &fnc->t_dequeue); /* @@ -2013,10 +2021,10 @@ static void fpm_process_queue(struct thread *t) /** * Handles external (e.g. CLI, data plane or others) events. */ -static void fpm_process_event(struct thread *t) +static void fpm_process_event(struct event *t) { - struct fpm_nl_ctx *fnc = THREAD_ARG(t); - enum fpm_nl_events event = THREAD_VAL(t); + struct fpm_nl_ctx *fnc = EVENT_ARG(t); + enum fpm_nl_events event = EVENT_VAL(t); switch (event) { case FNE_DISABLE: @@ -2100,19 +2108,19 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov) static int fpm_nl_finish_early(struct fpm_nl_ctx *fnc) { /* Disable all events and close socket. */ - THREAD_OFF(fnc->t_lspreset); - THREAD_OFF(fnc->t_lspwalk); - THREAD_OFF(fnc->t_nhgreset); - THREAD_OFF(fnc->t_nhgwalk); - THREAD_OFF(fnc->t_ribreset); - THREAD_OFF(fnc->t_ribwalk); - THREAD_OFF(fnc->t_rmacreset); - THREAD_OFF(fnc->t_rmacwalk); - THREAD_OFF(fnc->t_event); - THREAD_OFF(fnc->t_nhg); - thread_cancel_async(fnc->fthread->master, &fnc->t_read, NULL); - thread_cancel_async(fnc->fthread->master, &fnc->t_write, NULL); - thread_cancel_async(fnc->fthread->master, &fnc->t_connect, NULL); + EVENT_OFF(fnc->t_lspreset); + EVENT_OFF(fnc->t_lspwalk); + EVENT_OFF(fnc->t_nhgreset); + EVENT_OFF(fnc->t_nhgwalk); + EVENT_OFF(fnc->t_ribreset); + EVENT_OFF(fnc->t_ribwalk); + EVENT_OFF(fnc->t_rmacreset); + EVENT_OFF(fnc->t_rmacwalk); + EVENT_OFF(fnc->t_event); + EVENT_OFF(fnc->t_nhg); + event_cancel_async(fnc->fthread->master, &fnc->t_read, NULL); + event_cancel_async(fnc->fthread->master, &fnc->t_write, NULL); + event_cancel_async(fnc->fthread->master, &fnc->t_connect, NULL); if (fnc->socket != -1) { close(fnc->socket); @@ -2201,7 +2209,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) if (atomic_load_explicit(&fnc->counters.ctxqueue_len, memory_order_relaxed) > 0) - thread_add_timer(fnc->fthread->master, fpm_process_queue, + event_add_timer(fnc->fthread->master, fpm_process_queue, fnc, 0, &fnc->t_dequeue); /* Ensure dataplane thread is rescheduled if we hit the work limit */ @@ -2211,7 +2219,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) return 0; } -static int fpm_nl_new(struct thread_master *tm) +static int fpm_nl_new(struct event_loop *tm) { struct zebra_dplane_provider *prov = NULL; int rv; diff --git a/src/sonic-frr/frr b/src/sonic-frr/frr index de0e358b877a..3fbd709d888a 160000 --- a/src/sonic-frr/frr +++ b/src/sonic-frr/frr @@ -1 +1 @@ -Subproject commit de0e358b877ac9b595e7fb387a302c960a4c02d1 +Subproject commit 3fbd709d888ab94db178e44a5b9d67c3653e0b17 diff --git a/src/sonic-frr/patch/0008-Use-vrf_id-for-vrf-not-tabled_id.patch b/src/sonic-frr/patch/0008-Use-vrf_id-for-vrf-not-tabled_id.patch index ae8b05f06bd0..bf5dce51c9a3 100644 --- a/src/sonic-frr/patch/0008-Use-vrf_id-for-vrf-not-tabled_id.patch +++ b/src/sonic-frr/patch/0008-Use-vrf_id-for-vrf-not-tabled_id.patch @@ -5,15 +5,14 @@ Subject: [PATCH] From 349e3f758860be0077b69919c39764d3486ec44a Mon Sep 17 00:00:00 2001 Subject: [PATCH] use vrf id instead of table id Signed-off-by: Stepan Blyschak - diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c -index 325199eff..587045eac 100644 +index b8d097e58..b81a9db6d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c -@@ -406,6 +406,30 @@ vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) - return VRF_DEFAULT; +@@ -385,6 +385,31 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop) + return proto; } - + +static uint32_t table_lookup_by_vrf(vrf_id_t vrf_id, ns_id_t ns_id) +{ + struct vrf *vrf; @@ -37,14 +36,15 @@ index 325199eff..587045eac 100644 + + return RT_TABLE_UNSPEC; +} ++ + /** * @parse_encap_mpls() - Parses encapsulated mpls attributes * @tb: Pointer to rtattr to look for nested items in. -@@ -782,14 +806,26 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, +@@ -817,14 +842,26 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, if (rtm->rtm_family == AF_MPLS) return 0; - + - /* Table corresponding to route. */ - if (tb[RTA_TABLE]) - table = *(int *)RTA_DATA(tb[RTA_TABLE]); @@ -58,7 +58,7 @@ index 325199eff..587045eac 100644 + table = rtm->rtm_table; + + /* Map to VRF */ -+ vrf_id = vrf_lookup_by_table(table, ns_id); ++ vrf_id = zebra_vrf_lookup_by_table(table, ns_id); + } else { + /* With FPM, rtm_table contains vrf id, see netlink_route_multipath_msg_encode */ + if (tb[RTA_TABLE]) @@ -69,14 +69,14 @@ index 325199eff..587045eac 100644 + /* Map to table */ + table = table_lookup_by_vrf(vrf_id, ns_id); + } - + - /* Map to VRF */ -- vrf_id = vrf_lookup_by_table(table, ns_id); +- vrf_id = zebra_vrf_lookup_by_table(table, ns_id); if (vrf_id == VRF_DEFAULT) { if (!is_zebra_valid_kernel_table(table) && !is_zebra_main_routing_table(table)) -@@ -2102,12 +2138,24 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, - +@@ -2283,13 +2320,25 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx + /* Table corresponding to this route. */ table_id = dplane_ctx_get_table(ctx); - if (table_id < 256) @@ -85,6 +85,7 @@ index 325199eff..587045eac 100644 - req->r.rtm_table = RT_TABLE_UNSPEC; - if (!nl_attr_put32(&req->n, datalen, RTA_TABLE, table_id)) - return 0; +- } + if (!fpm) { + if (table_id < 256) + req->r.rtm_table = table_id; @@ -103,9 +104,7 @@ index 325199eff..587045eac 100644 + if (!nl_attr_put32(&req->n, datalen, RTA_TABLE, vrf)) + return 0; + } - } - - if (IS_ZEBRA_DEBUG_KERNEL) --- -2.17.1 ++ } + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( diff --git a/src/sonic-frr/patch/0009-bgpd-Ensure-suppress-fib-pending-works-with-network-.patch b/src/sonic-frr/patch/0009-bgpd-Ensure-suppress-fib-pending-works-with-network-.patch deleted file mode 100644 index a276f9ba5b49..000000000000 --- a/src/sonic-frr/patch/0009-bgpd-Ensure-suppress-fib-pending-works-with-network-.patch +++ /dev/null @@ -1,132 +0,0 @@ -From c4a198c977168a6bd420197d19c8a4c0f4eacc8a Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Wed, 22 Mar 2023 11:35:28 -0400 -Subject: [PATCH] From 5a1d3c9e24791ebdb7e375a02afe9c5f6146c488 Mon Sep 17 - 00:00:00 2001 Subject: [PATCH] bgpd: Ensure suppress-fib-pending works with - network statements - -The flag for telling BGP that a route is expected to be installed -first before notifying a peer was always being set upon receipt -of a path that could be accepted as bestpath. This is not correct: -imagine that you have a peer sending you a route and you have a -network statement that covers the same route. Irrelevant if the -network statement would win the flag on the dest was being set -in bgp_update. Thus you could get into a situation where -the network statement path wins but since the flag is set on -the node, it will never be announced to a peer. - -Let's just move the setting of the flag into bgp_zebra_announce -and _withdraw. In _announce set the flag to TRUE when suppress-fib -is enabled. In _withdraw just always unset the flag as that a withdrawal -does not need to wait for rib removal before announcing. This will -cover the case when a network statement is added after the route has -been learned from a peer. - -Signed-off-by: Donald Sharp - -diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index f00c54c40..a7a5c9849 100644 ---- a/bgpd/bgp_route.c -+++ b/bgpd/bgp_route.c -@@ -3203,11 +3203,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - if (bgp_fibupd_safi(safi) - && !bgp_option_check(BGP_OPT_NO_FIB)) { - -- if (BGP_SUPPRESS_FIB_ENABLED(bgp) -- && new_select->sub_type == BGP_ROUTE_NORMAL) -- SET_FLAG(dest->flags, -- BGP_NODE_FIB_INSTALL_PENDING); -- - if (new_select->type == ZEBRA_ROUTE_BGP - && (new_select->sub_type == BGP_ROUTE_NORMAL - || new_select->sub_type -@@ -3313,10 +3308,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - || new_select->sub_type == BGP_ROUTE_AGGREGATE - || new_select->sub_type == BGP_ROUTE_IMPORTED)) { - -- if (BGP_SUPPRESS_FIB_ENABLED(bgp)) -- SET_FLAG(dest->flags, -- BGP_NODE_FIB_INSTALL_PENDING); -- - /* if this is an evpn imported type-5 prefix, - * we need to withdraw the route first to clear - * the nh neigh and the RMAC entry. -@@ -4261,18 +4252,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, - bgp_attr_flush(&new_attr); - goto filtered; - } -- /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following -- * condition : -- * Suppress fib is enabled -- * BGP_OPT_NO_FIB is not enabled -- * Route type is BGP_ROUTE_NORMAL (peer learnt routes) -- * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set) -- */ -- if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp) -- && (sub_type == BGP_ROUTE_NORMAL) -- && (!bgp_option_check(BGP_OPT_NO_FIB)) -- && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED))) -- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); - - /* If neighbor soo is configured, tag all incoming routes with - * this SoO tag and then filter out advertisements in -diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index 95e80ba1b..efcf49785 100644 ---- a/bgpd/bgp_zebra.c -+++ b/bgpd/bgp_zebra.c -@@ -1322,6 +1322,14 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, - uint32_t bos = 0; - uint32_t exp = 0; - -+ /* -+ * BGP is installing this route and bgp has been configured -+ * to suppress announcements until the route has been installed -+ * let's set the fact that we expect this route to be installed -+ */ -+ if (BGP_SUPPRESS_FIB_ENABLED(bgp)) -+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); -+ - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ -@@ -1758,6 +1766,12 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, - struct zapi_route api; - struct peer *peer; - -+ /* -+ * If we are withdrawing the route, we don't need to have this -+ * flag set. So unset it. -+ */ -+ UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING); -+ - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ -diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py -index 6d2b65a61..7bcb28166 100644 ---- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py -+++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py -@@ -230,6 +230,20 @@ def test_bgp_allow_as_in(): - assertmsg = '"r2" 192.168.1.1/32 route should be gone' - assert result is None, assertmsg - -+def test_local_vs_non_local(): -+ tgen = get_topogen() -+ -+ if tgen.routers_have_failure(): -+ pytest.skip(tgen.errors) -+ -+ r2 = tgen.gears["r2"] -+ -+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 uni 60.0.0.0/24 json")) -+ paths = output["paths"] -+ for i in range(len(paths)): -+ if "fibPending" in paths[i]: -+ assert(False), "Route 60.0.0.0/24 should not have fibPending" -+ - - if __name__ == "__main__": - args = ["-s"] + sys.argv[1:] --- -2.17.1 - diff --git a/src/sonic-frr/patch/0010-bgpd-Change-log-level-for-graceful-restart-events.patch b/src/sonic-frr/patch/0010-bgpd-Change-log-level-for-graceful-restart-events.patch index 54fcc1575a75..be4bbb6a8602 100644 --- a/src/sonic-frr/patch/0010-bgpd-Change-log-level-for-graceful-restart-events.patch +++ b/src/sonic-frr/patch/0010-bgpd-Change-log-level-for-graceful-restart-events.patch @@ -3,49 +3,43 @@ From: stormliang Date: Mon, 19 Jun 2023 13:57:01 +0000 Subject: [PATCH] From c423bce4db804c1d07d65ce3d06a9e62c4eceb2b Mon Sep 17 00:00:00 2001 Subject: [PATCH] change log level for graceful restart events - - diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c -index 9624adfbe..74b4dfc4a 100644 +index 504343994..f58ab7c02 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c -@@ -778,10 +778,10 @@ static void bgp_graceful_restart_timer_expire(struct thread *thread) - - peer = THREAD_ARG(thread); - +@@ -739,9 +739,9 @@ static void bgp_graceful_restart_timer_expire(struct event *thread) + afi_t afi; + safi_t safi; + - if (bgp_debug_neighbor_events(peer)) { - zlog_debug("%pBP graceful restart timer expired", peer); - zlog_debug("%pBP graceful restart stalepath timer stopped", -- peer); + if (peer) { + zlog_info("%pBP graceful restart timer expired", peer); + zlog_info("%pBP graceful restart stalepath timer stopped", -+ peer); + peer); } - - FOREACH_AFI_SAFI (afi, safi) { -@@ -842,8 +842,8 @@ static void bgp_graceful_stale_timer_expire(struct thread *thread) - - peer = THREAD_ARG(thread); - + +@@ -801,8 +801,8 @@ static void bgp_graceful_stale_timer_expire(struct event *thread) + afi_t afi; + safi_t safi; + - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%pBP graceful restart stalepath timer expired", + if (peer) + zlog_info("%pBP graceful restart stalepath timer expired", peer); - + /* NSF delete stale route */ -@@ -1412,20 +1412,17 @@ enum bgp_fsm_state_progress bgp_stop(struct peer *peer) +@@ -1380,20 +1380,17 @@ enum bgp_fsm_state_progress bgp_stop(struct peer_connection *connection) /* graceful restart */ - if (peer->t_gr_stale) { - THREAD_OFF(peer->t_gr_stale); + if (connection->t_gr_stale) { + EVENT_OFF(connection->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug( -- "%pBP graceful restart stalepath timer stopped", -- peer); -+ zlog_info( -+ "%pBP graceful restart stalepath timer stopped", -+ peer); ++ zlog_info( + "%pBP graceful restart stalepath timer stopped", + peer); } if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) { - if (bgp_debug_neighbor_events(peer)) { @@ -62,55 +56,46 @@ index 9624adfbe..74b4dfc4a 100644 + zlog_info( + "%pBP graceful restart stalepath timer started for %d sec", + peer, peer->bgp->stalepath_time); - BGP_TIMER_ON(peer->t_gr_restart, + BGP_TIMER_ON(connection->t_gr_restart, bgp_graceful_restart_timer_expire, peer->v_gr_restart); -@@ -2225,17 +2222,15 @@ static enum bgp_fsm_state_progress bgp_establish(struct peer *peer) +@@ -2216,8 +2213,7 @@ bgp_establish(struct peer_connection *connection) UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); - if (peer->t_gr_stale) { - THREAD_OFF(peer->t_gr_stale); + if (connection->t_gr_stale) { + EVENT_OFF(connection->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug( -- "%pBP graceful restart stalepath timer stopped", -- peer); + zlog_info( -+ "%pBP graceful restart stalepath timer stopped", -+ peer); + "%pBP graceful restart stalepath timer stopped", + peer); } - } - - if (peer->t_gr_restart) { - THREAD_OFF(peer->t_gr_restart); +@@ -2225,8 +2221,7 @@ bgp_establish(struct peer_connection *connection) + + if (connection->t_gr_restart) { + EVENT_OFF(connection->t_gr_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%pBP graceful restart timer stopped", peer); + zlog_info("%pBP graceful restart timer stopped", peer); } - + /* Reset uptime, turn on keepalives, send current table. */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c -index 8b3a1e3dd..2f3b837a5 100644 +index d6d874be2..337879a2d 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c -@@ -2453,15 +2453,13 @@ void peer_nsf_stop(struct peer *peer) - - if (peer->t_gr_restart) { - THREAD_OFF(peer->t_gr_restart); +@@ -2629,13 +2629,11 @@ void peer_nsf_stop(struct peer *peer) + + if (peer->connection->t_gr_restart) { + EVENT_OFF(peer->connection->t_gr_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%pBP graceful restart timer stopped", peer); + zlog_info("%pBP graceful restart timer stopped", peer); } - if (peer->t_gr_stale) { - THREAD_OFF(peer->t_gr_stale); + if (peer->connection->t_gr_stale) { + EVENT_OFF(peer->connection->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug( -- "%pBP graceful restart stalepath timer stopped", -- peer); + zlog_info( -+ "%pBP graceful restart stalepath timer stopped", -+ peer); + "%pBP graceful restart stalepath timer stopped", + peer); } - bgp_clear_route_all(peer); - } --- -2.17.1 - diff --git a/src/sonic-frr/patch/0011-zebra-Static-routes-async-notification-do-not-need-t.patch b/src/sonic-frr/patch/0011-zebra-Static-routes-async-notification-do-not-need-t.patch deleted file mode 100644 index 6b633badf97b..000000000000 --- a/src/sonic-frr/patch/0011-zebra-Static-routes-async-notification-do-not-need-t.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 56d349ef47ba24bcf838488b1e40474755655259 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 29 Jun 2023 09:35:00 -0400 -Subject: [PATCH] zebra: Static routes async notification do not need this test - -When using asic_offload with an asynchronous notification the -rib_route_match_ctx function is testing for distance and tag -being correct against the re. - -Normal route notification for static routes is this(well really all routes): -a) zebra dplane generates a ctx to send to the dplane for route install -b) dplane installs it in the kernel -c) if the dplane_fpm_nl.c module is being used it installs it. -d) The context's success code is set to it worked and passes the context -back up to zebra for processing. -e) Zebra master receives this and checks the distance and tag are correct -for static routes and accepts the route and marks it installed. - -If the operator is using a wait for install mechansim where the dplane -is asynchronously sending the result back up at a future time *and* -it is using the dplane_fpm_nl.c code where it uses the rt_netlink.c -route parsing code, then there is no way to set distance as that we -do not pass distance to the kernel. - -As such static routes were never being properly handled since the re and -context would not match and the route would still be marked as queued. - -Modify the code such that the asynchronous path notification for static -routes ignores the distance and tag's as that there is no way to test -for this data from that path at this point in time. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index fd6df441c6..039c44cc09 100644 ---- a/zebra/zebra_rib.c -+++ b/zebra/zebra_rib.c -@@ -1465,7 +1465,7 @@ static void zebra_rib_evaluate_mpls(struct route_node *rn) - */ - static bool rib_route_match_ctx(const struct route_entry *re, - const struct zebra_dplane_ctx *ctx, -- bool is_update) -+ bool is_update, bool async) - { - bool result = false; - -@@ -1481,13 +1481,12 @@ static bool rib_route_match_ctx(const struct route_entry *re, - /* We use an extra test for statics, and another for - * kernel routes. - */ -- if (re->type == ZEBRA_ROUTE_STATIC && -+ if (re->type == ZEBRA_ROUTE_STATIC && !async && - (re->distance != dplane_ctx_get_old_distance(ctx) || - re->tag != dplane_ctx_get_old_tag(ctx))) { - result = false; - } else if (re->type == ZEBRA_ROUTE_KERNEL && -- re->metric != -- dplane_ctx_get_old_metric(ctx)) { -+ re->metric != dplane_ctx_get_old_metric(ctx)) { - result = false; - } - } -@@ -1509,7 +1508,7 @@ static bool rib_route_match_ctx(const struct route_entry *re, - /* We use an extra test for statics, and another for - * kernel routes. - */ -- if (re->type == ZEBRA_ROUTE_STATIC && -+ if (re->type == ZEBRA_ROUTE_STATIC && !async && - (re->distance != dplane_ctx_get_distance(ctx) || - re->tag != dplane_ctx_get_tag(ctx))) { - result = false; -@@ -1973,13 +1972,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) - RNODE_FOREACH_RE(rn, rib) { - - if (re == NULL) { -- if (rib_route_match_ctx(rib, ctx, false)) -+ if (rib_route_match_ctx(rib, ctx, false, false)) - re = rib; - } - - /* Check for old route match */ - if (is_update && (old_re == NULL)) { -- if (rib_route_match_ctx(rib, ctx, true /*is_update*/)) -+ if (rib_route_match_ctx(rib, ctx, true, false)) - old_re = rib; - } - -@@ -2247,7 +2246,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) - * info. - */ - RNODE_FOREACH_RE(rn, re) { -- if (rib_route_match_ctx(re, ctx, false /*!update*/)) -+ if (rib_route_match_ctx(re, ctx, false, true)) - break; - } - --- -2.17.1 - diff --git a/src/sonic-frr/patch/0012-zebra-Rename-vrf_lookup_by_tableid-to-zebra_vrf_look.patch b/src/sonic-frr/patch/0012-zebra-Rename-vrf_lookup_by_tableid-to-zebra_vrf_look.patch deleted file mode 100644 index ca6517fbf655..000000000000 --- a/src/sonic-frr/patch/0012-zebra-Rename-vrf_lookup_by_tableid-to-zebra_vrf_look.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 2b9c7592a9857ddccc77b9d3f178e0c5bd5f19ed Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Wed, 26 Apr 2023 23:25:27 -0400 -Subject: [PATCH] zebra: Rename vrf_lookup_by_tableid to zebra_vrf_lookup.. - -Rename the vrf_lookup_by_id function to zebra_vrf_lookup_by_id -and move to zebra_vrf.c where it nominally belongs, as that -we need zebra specific data to find this vrf_id and as such -it does not belong in vrf.c - -Signed-off-by: Donald Sharp - -diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c -index 81347b550a..4599121261 100644 ---- a/zebra/if_netlink.c -+++ b/zebra/if_netlink.c -@@ -342,7 +342,8 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, - if (!vrf_lookup_by_id((vrf_id_t)ifi->ifi_index)) { - vrf_id_t exist_id; - -- exist_id = vrf_lookup_by_table(nl_table_id, ns_id); -+ exist_id = -+ zebra_vrf_lookup_by_table(nl_table_id, ns_id); - if (exist_id != VRF_DEFAULT) { - vrf = vrf_lookup_by_id(exist_id); - -diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c -index 587045eac2..6b9b047858 100644 ---- a/zebra/rt_netlink.c -+++ b/zebra/rt_netlink.c -@@ -379,33 +379,6 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop) - return proto; - } - --/* --Pending: create an efficient table_id (in a tree/hash) based lookup) -- */ --vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) --{ -- struct vrf *vrf; -- struct zebra_vrf *zvrf; -- -- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { -- zvrf = vrf->info; -- if (zvrf == NULL) -- continue; -- /* case vrf with netns : match the netnsid */ -- if (vrf_is_backend_netns()) { -- if (ns_id == zvrf_id(zvrf)) -- return zvrf_id(zvrf); -- } else { -- /* VRF is VRF_BACKEND_VRF_LITE */ -- if (zvrf->table_id != table_id) -- continue; -- return zvrf_id(zvrf); -- } -- } -- -- return VRF_DEFAULT; --} -- - static uint32_t table_lookup_by_vrf(vrf_id_t vrf_id, ns_id_t ns_id) - { - struct vrf *vrf; -@@ -814,7 +787,7 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, - table = rtm->rtm_table; - - /* Map to VRF */ -- vrf_id = vrf_lookup_by_table(table, ns_id); -+ vrf_id = zebra_vrf_lookup_by_table(table, ns_id); - } else { - /* With FPM, rtm_table contains vrf id, see netlink_route_multipath_msg_encode */ - if (tb[RTA_TABLE]) -@@ -1114,7 +1087,7 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h, - else - table = rtm->rtm_table; - -- vrf = vrf_lookup_by_table(table, ns_id); -+ vrf = zebra_vrf_lookup_by_table(table, ns_id); - - if (tb[RTA_IIF]) - iif = *(int *)RTA_DATA(tb[RTA_IIF]); -diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h -index 8506367ae4..364aac0f6b 100644 ---- a/zebra/rt_netlink.h -+++ b/zebra/rt_netlink.h -@@ -102,7 +102,6 @@ extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, - uint16_t vid); - extern int netlink_neigh_read_specific_ip(const struct ipaddr *ip, - struct interface *vlan_if); --extern vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id); - - struct nl_batch; - extern enum netlink_msg_status -diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c -index be5e91495f..c59cb7c0a7 100644 ---- a/zebra/zebra_vrf.c -+++ b/zebra/zebra_vrf.c -@@ -389,6 +389,33 @@ struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf) - return zvrf; - } - -+/* -+Pending: create an efficient table_id (in a tree/hash) based lookup) -+ */ -+vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) -+{ -+ struct vrf *vrf; -+ struct zebra_vrf *zvrf; -+ -+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { -+ zvrf = vrf->info; -+ if (zvrf == NULL) -+ continue; -+ /* case vrf with netns : match the netnsid */ -+ if (vrf_is_backend_netns()) { -+ if (ns_id == zvrf_id(zvrf)) -+ return zvrf_id(zvrf); -+ } else { -+ /* VRF is VRF_BACKEND_VRF_LITE */ -+ if (zvrf->table_id != table_id) -+ continue; -+ return zvrf_id(zvrf); -+ } -+ } -+ -+ return VRF_DEFAULT; -+} -+ - /* Lookup VRF by identifier. */ - struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id) - { -diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h -index 02e3c197c9..937e7fb144 100644 ---- a/zebra/zebra_vrf.h -+++ b/zebra/zebra_vrf.h -@@ -252,6 +252,7 @@ extern struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, - extern void zebra_vrf_update_all(struct zserv *client); - extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id); - extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *); -+extern vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id); - extern struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf); - extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t); - --- -2.17.1 - diff --git a/src/sonic-frr/patch/0013-zebra-Move-protodown_r_bit-to-a-better-spot.patch b/src/sonic-frr/patch/0013-zebra-Move-protodown_r_bit-to-a-better-spot.patch deleted file mode 100644 index cd88419fcbd6..000000000000 --- a/src/sonic-frr/patch/0013-zebra-Move-protodown_r_bit-to-a-better-spot.patch +++ /dev/null @@ -1,181 +0,0 @@ -From c43808ca6daa59d533e14790ffc7f2e11b508924 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 27 Apr 2023 07:37:58 -0400 -Subject: [PATCH] zebra: Move protodown_r_bit to a better spot - -Since we are moving some code handling out of the dataplane -and into zebra proper, lets move the protodown r bit as well. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c -index 4599121261..95889e22fd 100644 ---- a/zebra/if_netlink.c -+++ b/zebra/if_netlink.c -@@ -78,7 +78,6 @@ - #include "zebra/zebra_trace.h" - - extern struct zebra_privs_t zserv_privs; --uint8_t frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT; - - /* Note: on netlink systems, there should be a 1-to-1 mapping between interface - names and ifindex values. */ -@@ -819,9 +818,7 @@ static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id, - - static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield) - { -- /* This shouldn't be possible */ -- assert(frr_protodown_r_bit < 32); -- return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit)); -+ return (rc_bitfield == (((uint32_t)1) << if_netlink_get_frr_protodown_r_bit())); - } - - /* -@@ -2247,9 +2244,10 @@ ssize_t netlink_intf_msg_encode(uint16_t cmd, - return -1; - - nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_MASK, -- (1 << frr_protodown_r_bit)); -+ (1 << if_netlink_get_frr_protodown_r_bit())); - nl_attr_put32(&req->n, buflen, IFLA_PROTO_DOWN_REASON_VALUE, -- ((int)pd_reason_val) << frr_protodown_r_bit); -+ ((int)pd_reason_val) -+ << if_netlink_get_frr_protodown_r_bit()); - - nl_attr_nest_end(&req->n, nest_protodown_reason); - -@@ -2274,37 +2272,6 @@ void interface_list(struct zebra_ns *zns) - interface_addr_lookup_netlink(zns); - } - --void if_netlink_set_frr_protodown_r_bit(uint8_t bit) --{ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Protodown reason bit index changed: bit-index %u -> bit-index %u", -- frr_protodown_r_bit, bit); -- -- frr_protodown_r_bit = bit; --} -- --void if_netlink_unset_frr_protodown_r_bit(void) --{ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Protodown reason bit index changed: bit-index %u -> bit-index %u", -- frr_protodown_r_bit, FRR_PROTODOWN_REASON_DEFAULT_BIT); -- -- frr_protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT; --} -- -- --bool if_netlink_frr_protodown_r_bit_is_set(void) --{ -- return (frr_protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT); --} -- --uint8_t if_netlink_get_frr_protodown_r_bit(void) --{ -- return frr_protodown_r_bit; --} -- - /** - * netlink_request_tunneldump() - Request all tunnels from the linux kernel - * -diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h -index 21ae1713be..f5a170a609 100644 ---- a/zebra/if_netlink.h -+++ b/zebra/if_netlink.h -@@ -54,17 +54,6 @@ extern int netlink_tunneldump_read(struct zebra_ns *zns); - extern enum netlink_msg_status - netlink_put_intf_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); - --#define FRR_PROTODOWN_REASON_DEFAULT_BIT 7 --/* Protodown bit setter/getter -- * -- * Allow users to change the bit if it conflicts with another -- * on their system. -- */ --extern void if_netlink_set_frr_protodown_r_bit(uint8_t bit); --extern void if_netlink_unset_frr_protodown_r_bit(void); --extern bool if_netlink_frr_protodown_r_bit_is_set(void); --extern uint8_t if_netlink_get_frr_protodown_r_bit(void); -- - #ifdef __cplusplus - } - #endif -diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c -index a9a7b66ce7..12689804ea 100644 ---- a/zebra/zebra_router.c -+++ b/zebra/zebra_router.c -@@ -280,6 +280,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack) - { - zrouter.sequence_num = 0; - -+ zrouter.protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT; -+ - zrouter.allow_delete = false; - - zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS; -diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h -index e0ef86f082..61bde4ac2a 100644 ---- a/zebra/zebra_router.h -+++ b/zebra/zebra_router.h -@@ -244,6 +244,8 @@ struct zebra_router { - - /* Should we allow non FRR processes to delete our routes */ - bool allow_delete; -+ -+ uint8_t protodown_r_bit; - }; - - #define GRACEFUL_RESTART_TIME 60 -@@ -302,6 +304,32 @@ static inline bool zebra_router_in_shutdown(void) - return atomic_load_explicit(&zrouter.in_shutdown, memory_order_relaxed); - } - -+#define FRR_PROTODOWN_REASON_DEFAULT_BIT 7 -+/* Protodown bit setter/getter -+ * -+ * Allow users to change the bit if it conflicts with another -+ * on their system. -+ */ -+static inline void if_netlink_set_frr_protodown_r_bit(uint8_t bit) -+{ -+ zrouter.protodown_r_bit = bit; -+} -+ -+static inline void if_netlink_unset_frr_protodown_r_bit(void) -+{ -+ zrouter.protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT; -+} -+ -+static inline bool if_netlink_frr_protodown_r_bit_is_set(void) -+{ -+ return (zrouter.protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT); -+} -+ -+static inline uint8_t if_netlink_get_frr_protodown_r_bit(void) -+{ -+ return zrouter.protodown_r_bit; -+} -+ - /* zebra_northbound.c */ - extern const struct frr_yang_module_info frr_zebra_info; - -diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c -index c59cb7c0a7..9c5b38b96b 100644 ---- a/zebra/zebra_vrf.c -+++ b/zebra/zebra_vrf.c -@@ -390,7 +390,7 @@ struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf) - } - - /* --Pending: create an efficient table_id (in a tree/hash) based lookup) -+ * Pending: create an efficient table_id (in a tree/hash) based lookup) - */ - vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) - { --- -2.17.1 - diff --git a/src/sonic-frr/patch/0014-zebra-Remove-unused-dplane_intf_delete.patch b/src/sonic-frr/patch/0014-zebra-Remove-unused-dplane_intf_delete.patch deleted file mode 100644 index 756e0cf97419..000000000000 --- a/src/sonic-frr/patch/0014-zebra-Remove-unused-dplane_intf_delete.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 88f7441f56bf61008a52adda97525ffb20f9543d Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Fri, 14 Apr 2023 07:43:19 -0400 -Subject: [PATCH] zebra: Remove unused dplane_intf_delete - -There is no need for this functionality and it is -not used. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c -index 4927af5625..a6c08f7371 100644 ---- a/zebra/zebra_dplane.c -+++ b/zebra/zebra_dplane.c -@@ -4648,18 +4648,6 @@ enum zebra_dplane_result dplane_intf_update(const struct interface *ifp) - return ret; - } - --/* -- * Enqueue a interface delete for the dataplane. -- */ --enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp) --{ -- enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; -- -- if (ifp) -- ret = dplane_intf_update_internal(ifp, DPLANE_OP_INTF_DELETE); -- return ret; --} -- - /* - * Enqueue vxlan/evpn mac add (or update). - */ -diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h -index ae13243a16..9ef0afd3a8 100644 ---- a/zebra/zebra_dplane.h -+++ b/zebra/zebra_dplane.h -@@ -758,7 +758,6 @@ enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp, - */ - enum zebra_dplane_result dplane_intf_add(const struct interface *ifp); - enum zebra_dplane_result dplane_intf_update(const struct interface *ifp); --enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp); - - /* - * Enqueue tc link changes for the dataplane. --- -2.17.1 - diff --git a/src/sonic-frr/patch/0015-zebra-Remove-unused-add-variable.patch b/src/sonic-frr/patch/0015-zebra-Remove-unused-add-variable.patch deleted file mode 100644 index dc263d3d94c0..000000000000 --- a/src/sonic-frr/patch/0015-zebra-Remove-unused-add-variable.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 4cc6c7af6f7c72ddf18ab562f4e2c2b25e32f1b5 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Sat, 15 Apr 2023 08:04:51 -0400 -Subject: [PATCH] zebra: Remove unused add variable - -Function was not using the add variable. Remove it. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c -index 95889e22fd..e54fb09022 100644 ---- a/zebra/if_netlink.c -+++ b/zebra/if_netlink.c -@@ -670,7 +670,7 @@ static void netlink_interface_update_l2info(struct interface *ifp, - struct zebra_l2info_bridge bridge_info; - - netlink_extract_bridge_info(link_data, &bridge_info); -- zebra_l2_bridge_add_update(ifp, &bridge_info, add); -+ zebra_l2_bridge_add_update(ifp, &bridge_info); - } else if (IS_ZEBRA_IF_VLAN(ifp)) { - struct zebra_l2info_vlan vlan_info; - -diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c -index 8a9f3dffe3..07bbc6e3bc 100644 ---- a/zebra/zebra_l2.c -+++ b/zebra/zebra_l2.c -@@ -258,8 +258,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add) - * map slaves (if any) to the bridge. - */ - void zebra_l2_bridge_add_update(struct interface *ifp, -- struct zebra_l2info_bridge *bridge_info, -- int add) -+ struct zebra_l2info_bridge *bridge_info) - { - struct zebra_if *zif; - -diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h -index 1c3e98158d..8fef008f52 100644 ---- a/zebra/zebra_l2.h -+++ b/zebra/zebra_l2.h -@@ -109,8 +109,7 @@ extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave, - extern void - zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave); - extern void zebra_l2_bridge_add_update(struct interface *ifp, -- struct zebra_l2info_bridge *bridge_info, -- int add); -+ struct zebra_l2info_bridge *bridge_info); - extern void zebra_l2_bridge_del(struct interface *ifp); - extern void zebra_l2_vlanif_update(struct interface *ifp, - struct zebra_l2info_vlan *vlan_info); --- -2.17.1 - diff --git a/src/sonic-frr/patch/0016-zebra-Remove-duplicate-function-for-netlink-interfac.patch b/src/sonic-frr/patch/0016-zebra-Remove-duplicate-function-for-netlink-interfac.patch deleted file mode 100644 index 8f13d20f0052..000000000000 --- a/src/sonic-frr/patch/0016-zebra-Remove-duplicate-function-for-netlink-interfac.patch +++ /dev/null @@ -1,301 +0,0 @@ -From e12ffa6871d33712b03fc2ca28de278913e95bce Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 13 Apr 2023 16:43:27 -0400 -Subject: [PATCH] zebra: Remove duplicate function for netlink interface - changes - -Turns out FRR has 2 functions one specifically for startup -and one for normal day to day operations. There were only -a couple of minor differences from what I could tell, and -where they were different the after startup functionality should -have been updated too. I cannot figure out why we have 2. - -Non-startup handling of bonds appears to be incorrect -so let's fix that. Additionally the speed was not -properly being set in non-startup situations. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c -index e54fb09022..ed5b3c4a66 100644 ---- a/zebra/if_netlink.c -+++ b/zebra/if_netlink.c -@@ -938,178 +938,6 @@ static void if_sweep_protodown(struct zebra_if *zif) - dplane_intf_update(zif->ifp); - } - --/* -- * Called from interface_lookup_netlink(). This function is only used -- * during bootstrap. -- */ --static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) --{ -- int len; -- struct ifinfomsg *ifi; -- struct rtattr *tb[IFLA_MAX + 1]; -- struct rtattr *linkinfo[IFLA_MAX + 1]; -- struct interface *ifp; -- char *name = NULL; -- char *kind = NULL; -- char *desc = NULL; -- char *slave_kind = NULL; -- struct zebra_ns *zns = NULL; -- vrf_id_t vrf_id = VRF_DEFAULT; -- enum zebra_iftype zif_type = ZEBRA_IF_OTHER; -- enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE; -- ifindex_t bridge_ifindex = IFINDEX_INTERNAL; -- ifindex_t link_ifindex = IFINDEX_INTERNAL; -- ifindex_t bond_ifindex = IFINDEX_INTERNAL; -- struct zebra_if *zif; -- ns_id_t link_nsid = ns_id; -- uint8_t bypass = 0; -- -- frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup); -- -- zns = zebra_ns_lookup(ns_id); -- ifi = NLMSG_DATA(h); -- -- if (h->nlmsg_type != RTM_NEWLINK) -- return 0; -- -- len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); -- if (len < 0) { -- zlog_err( -- "%s: Message received from netlink is of a broken size: %d %zu", -- __func__, h->nlmsg_len, -- (size_t)NLMSG_LENGTH(sizeof(struct ifinfomsg))); -- return -1; -- } -- -- /* We are interested in some AF_BRIDGE notifications. */ -- if (ifi->ifi_family == AF_BRIDGE) -- return netlink_bridge_interface(h, len, ns_id, startup); -- -- /* Looking up interface name. */ -- memset(linkinfo, 0, sizeof(linkinfo)); -- netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, -- NLA_F_NESTED); -- -- /* check for wireless messages to ignore */ -- if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("%s: ignoring IFLA_WIRELESS message", -- __func__); -- return 0; -- } -- -- if (tb[IFLA_IFNAME] == NULL) -- return -1; -- name = (char *)RTA_DATA(tb[IFLA_IFNAME]); -- -- if (tb[IFLA_IFALIAS]) -- desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]); -- -- if (tb[IFLA_LINKINFO]) { -- netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, -- tb[IFLA_LINKINFO]); -- -- if (linkinfo[IFLA_INFO_KIND]) -- kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); -- -- if (linkinfo[IFLA_INFO_SLAVE_KIND]) -- slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); -- -- if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0) -- netlink_determine_zebra_iftype("bond_slave", &zif_type); -- else -- netlink_determine_zebra_iftype(kind, &zif_type); -- } -- -- /* If VRF, create the VRF structure itself. */ -- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { -- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name); -- vrf_id = (vrf_id_t)ifi->ifi_index; -- } -- -- if (tb[IFLA_MASTER]) { -- if (slave_kind && (strcmp(slave_kind, "vrf") == 0) -- && !vrf_is_backend_netns()) { -- zif_slave_type = ZEBRA_IF_SLAVE_VRF; -- vrf_id = *(uint32_t *)RTA_DATA(tb[IFLA_MASTER]); -- } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) { -- zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; -- bridge_ifindex = -- *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); -- } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) { -- zif_slave_type = ZEBRA_IF_SLAVE_BOND; -- bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); -- bypass = netlink_parse_lacp_bypass(linkinfo); -- } else -- zif_slave_type = ZEBRA_IF_SLAVE_OTHER; -- } -- if (vrf_is_backend_netns()) -- vrf_id = (vrf_id_t)ns_id; -- -- /* If linking to another interface, note it. */ -- if (tb[IFLA_LINK]) -- link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); -- -- if (tb[IFLA_LINK_NETNSID]) { -- link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]); -- link_nsid = ns_id_get_absolute(ns_id, link_nsid); -- } -- -- ifp = if_get_by_name(name, vrf_id, NULL); -- set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */ -- -- ifp->flags = ifi->ifi_flags & 0x0000fffff; -- ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); -- ifp->metric = 0; -- ifp->speed = get_iflink_speed(ifp, NULL); -- ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; -- -- /* Set zebra interface type */ -- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); -- if (IS_ZEBRA_IF_VRF(ifp)) -- SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); -- -- /* -- * Just set the @link/lower-device ifindex. During nldump interfaces are -- * not ordered in any fashion so we may end up getting upper devices -- * before lower devices. We will setup the real linkage once the dump -- * is complete. -- */ -- zif = (struct zebra_if *)ifp->info; -- zif->link_ifindex = link_ifindex; -- -- if (desc) { -- XFREE(MTYPE_ZIF_DESC, zif->desc); -- zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc); -- } -- -- /* Hardware type and address. */ -- ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); -- -- netlink_interface_update_hw_addr(tb, ifp); -- -- if_add_update(ifp); -- -- /* Extract and save L2 interface information, take additional actions. -- */ -- netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], -- 1, link_nsid); -- if (IS_ZEBRA_IF_BOND(ifp)) -- zebra_l2if_update_bond(ifp, true); -- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) -- zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id, -- ZEBRA_BRIDGE_NO_ACTION); -- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) -- zebra_l2if_update_bond_slave(ifp, bond_ifindex, !!bypass); -- -- if (tb[IFLA_PROTO_DOWN]) { -- netlink_proc_dplane_if_protodown(zif, tb); -- if_sweep_protodown(zif); -- } -- -- return 0; --} -- - /* Request for specific interface or address information from the kernel */ - static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family, - int type, uint32_t filter_mask) -@@ -1165,7 +993,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) - ret = netlink_request_intf_addr(netlink_cmd, AF_PACKET, RTM_GETLINK, 0); - if (ret < 0) - return ret; -- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, -+ ret = netlink_parse_info(netlink_link_change, netlink_cmd, &dp_info, 0, - true); - if (ret < 0) - return ret; -@@ -1175,7 +1003,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) - RTEXT_FILTER_BRVLAN); - if (ret < 0) - return ret; -- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0, -+ ret = netlink_parse_info(netlink_link_change, netlink_cmd, &dp_info, 0, - true); - if (ret < 0) - return ret; -@@ -1816,6 +1644,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - ifindex_t master_infindex = IFINDEX_INTERNAL; - uint8_t bypass = 0; - -+ frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup); -+ - zns = zebra_ns_lookup(ns_id); - ifi = NLMSG_DATA(h); - -@@ -1884,7 +1714,10 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); - -- netlink_determine_zebra_iftype(kind, &zif_type); -+ if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0) -+ netlink_determine_zebra_iftype("bond_slave", &zif_type); -+ else -+ netlink_determine_zebra_iftype(kind, &zif_type); - } - - /* If linking to another interface, note it. */ -@@ -1961,6 +1794,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - } - ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); - ifp->metric = 0; -+ ifp->speed = get_iflink_speed(ifp, NULL); - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Set interface type */ -@@ -1972,6 +1806,16 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - /* Update link. */ - zebra_if_update_link(ifp, link_ifindex, link_nsid); - -+ /* -+ * Just set the @link/lower-device ifindex. During -+ * nldump interfaces are not ordered in any fashion so -+ * we may end up getting upper devices before lower -+ * devices. We will setup the real linkage once the dump -+ * is complete. -+ */ -+ zif = (struct zebra_if *)ifp->info; -+ zif->link_ifindex = link_ifindex; -+ - ifp->ll_type = - netlink_to_zebra_link_type(ifi->ifi_type); - netlink_interface_update_hw_addr(tb, ifp); -@@ -1984,6 +1828,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - netlink_interface_update_l2info( - ifp, linkinfo[IFLA_INFO_DATA], - 1, link_nsid); -+ if (IS_ZEBRA_IF_BOND(ifp)) -+ zebra_l2if_update_bond(ifp, true); - if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) - zebra_l2if_update_bridge_slave( - ifp, bridge_ifindex, ns_id, -@@ -1992,10 +1838,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - zebra_l2if_update_bond_slave(ifp, bond_ifindex, - !!bypass); - -- if (tb[IFLA_PROTO_DOWN]) -+ if (tb[IFLA_PROTO_DOWN]) { - netlink_proc_dplane_if_protodown(ifp->info, tb); -+ if (startup) -+ if_sweep_protodown(zif); -+ } - if (IS_ZEBRA_IF_BRIDGE(ifp)) { -- zif = ifp->info; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug( - "RTM_NEWLINK ADD for %s(%u), vlan-aware %d", -@@ -2329,7 +2177,7 @@ int netlink_tunneldump_read(struct zebra_ns *zns) - if (ret < 0) - return ret; - -- ret = netlink_parse_info(netlink_interface, netlink_cmd, -+ ret = netlink_parse_info(netlink_link_change, netlink_cmd, - &dp_info, 0, true); - - if (ret < 0) --- -2.17.1 - diff --git a/src/sonic-frr/patch/0017-zebra-Add-code-to-get-set-interface-to-pass-up-from-.patch b/src/sonic-frr/patch/0017-zebra-Add-code-to-get-set-interface-to-pass-up-from-.patch deleted file mode 100644 index c46c29737a0e..000000000000 --- a/src/sonic-frr/patch/0017-zebra-Add-code-to-get-set-interface-to-pass-up-from-.patch +++ /dev/null @@ -1,809 +0,0 @@ -From 1b576b080613cd545ecd742b6a16146ab781695f Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 20 Apr 2023 08:51:42 -0400 -Subject: [PATCH] zebra: Add code to get/set interface to pass up from dplane - -1) Add a bunch of get/set functions and associated data -structure in zebra_dplane to allow the setting and retrieval -of interface netlink data up into the master pthread. - -2) Add a bit of code to breakup startup into stages. This is -because FRR currently has a mix of dplane and non dplane interactions -and the code needs to be paused before continuing on. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c -index 804eb43a44..0d629fe0b9 100644 ---- a/zebra/dplane_fpm_nl.c -+++ b/zebra/dplane_fpm_nl.c -@@ -955,6 +955,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) - case DPLANE_OP_TC_FILTER_DELETE: - case DPLANE_OP_TC_FILTER_UPDATE: - case DPLANE_OP_NONE: -+ case DPLANE_OP_STARTUP_STAGE: - break; - - } -diff --git a/zebra/interface.c b/zebra/interface.c -index 84e52d4b43..a05b9690ef 100644 ---- a/zebra/interface.c -+++ b/zebra/interface.c -@@ -1590,6 +1590,7 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) - case DPLANE_OP_TC_FILTER_ADD: - case DPLANE_OP_TC_FILTER_DELETE: - case DPLANE_OP_TC_FILTER_UPDATE: -+ case DPLANE_OP_STARTUP_STAGE: - break; /* should never hit here */ - } - } -diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c -index 42afe61469..4cd84cada2 100644 ---- a/zebra/kernel_netlink.c -+++ b/zebra/kernel_netlink.c -@@ -1632,6 +1632,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth, - case DPLANE_OP_IPSET_DELETE: - case DPLANE_OP_IPSET_ENTRY_ADD: - case DPLANE_OP_IPSET_ENTRY_DELETE: -+ case DPLANE_OP_STARTUP_STAGE: - return FRR_NETLINK_ERROR; - - case DPLANE_OP_GRE_SET: -diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c -index 684ccc3ed5..f3462b9f22 100644 ---- a/zebra/kernel_socket.c -+++ b/zebra/kernel_socket.c -@@ -1631,6 +1631,7 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list) - case DPLANE_OP_GRE_SET: - case DPLANE_OP_INTF_ADDR_ADD: - case DPLANE_OP_INTF_ADDR_DEL: -+ case DPLANE_OP_STARTUP_STAGE: - zlog_err("Unhandled dplane data for %s", - dplane_op2str(dplane_ctx_get_op(ctx))); - res = ZEBRA_DPLANE_REQUEST_FAILURE; -diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c -index a6c08f7371..0b33a5189c 100644 ---- a/zebra/zebra_dplane.c -+++ b/zebra/zebra_dplane.c -@@ -193,10 +193,43 @@ struct dplane_br_port_info { - */ - struct dplane_intf_info { - -+ enum zebra_iftype zif_type; -+ ifindex_t bond_ifindex; -+ ifindex_t link_ifindex; -+ int32_t mtu; -+ vrf_id_t vrf_id; -+ enum zebra_slave_iftype zif_slave_type; -+ ifindex_t master_ifindex; -+ ifindex_t bridge_ifindex; -+ ns_id_t link_nsid; -+ enum zebra_slave_iftype zslave_type; -+ uint8_t bypass; -+ enum zebra_link_type zltype; -+ bool startup; -+ uint8_t family; -+ struct zebra_vxlan_vni_array *vniarray; -+ struct zebra_dplane_bridge_vlan_info bvinfo; -+ struct zebra_dplane_bridge_vlan_info_array *bvarray; -+ -+ char desc[128]; -+ -+ int32_t hw_addr_len; -+ uint8_t hw_addr[INTERFACE_HWADDR_MAX]; -+ -+ uint32_t table_id; -+ -+ struct zebra_l2info_bridge binfo; -+ struct zebra_l2info_vlan vinfo; -+ struct zebra_l2info_vxlan vxinfo; -+ struct zebra_l2info_gre grinfo; -+ -+ uint32_t rc_bitfield; -+ - uint32_t metric; - uint32_t flags; - - bool protodown; -+ bool protodown_set; - bool pd_reason_val; - - #define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */ -@@ -408,6 +441,7 @@ struct zebra_dplane_ctx { - struct dplane_neigh_table neightable; - struct dplane_gre_ctx gre; - struct dplane_netconf_info netconf; -+ enum zebra_dplane_startup_notifications spot; - } u; - - /* Namespace info, used especially for netlink kernel communication */ -@@ -820,8 +854,14 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) - case DPLANE_OP_NONE: - case DPLANE_OP_IPSET_ADD: - case DPLANE_OP_IPSET_DELETE: -+ break; - case DPLANE_OP_INTF_INSTALL: - case DPLANE_OP_INTF_UPDATE: -+ if (ctx->u.intf.vniarray) -+ XFREE(MTYPE_TMP, ctx->u.intf.vniarray); -+ if (ctx->u.intf.bvarray) -+ XFREE(MTYPE_TMP, ctx->u.intf.bvarray); -+ break; - case DPLANE_OP_INTF_DELETE: - case DPLANE_OP_TC_QDISC_INSTALL: - case DPLANE_OP_TC_QDISC_UNINSTALL: -@@ -845,6 +885,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx) - break; - case DPLANE_OP_GRE_SET: - case DPLANE_OP_INTF_NETCONFIG: -+ case DPLANE_OP_STARTUP_STAGE: - break; - } - } -@@ -1168,6 +1209,8 @@ const char *dplane_op2str(enum dplane_op_e op) - case DPLANE_OP_TC_FILTER_UPDATE: - ret = "TC__FILTER_UPDATE"; - break; -+ case DPLANE_OP_STARTUP_STAGE: -+ ret = "STARTUP_STAGE"; - } - - return ret; -@@ -1309,6 +1352,422 @@ const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx) - return ctx->zd_ifname; - } - -+void dplane_ctx_set_ifp_bridge_vlan_info_array( -+ struct zebra_dplane_ctx *ctx, -+ struct zebra_dplane_bridge_vlan_info_array *bvarray) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.bvarray = bvarray; -+} -+ -+const struct zebra_dplane_bridge_vlan_info_array * -+dplane_ctx_get_ifp_bridge_vlan_info_array(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.bvarray; -+} -+ -+void dplane_ctx_set_ifp_vxlan_vni_array(struct zebra_dplane_ctx *ctx, -+ struct zebra_vxlan_vni_array *vniarray) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.vniarray = vniarray; -+} -+ -+const struct zebra_vxlan_vni_array * -+dplane_ctx_get_ifp_vxlan_vni_array(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.vniarray; -+} -+ -+void dplane_ctx_set_ifp_bridge_vlan_info( -+ struct zebra_dplane_ctx *ctx, -+ struct zebra_dplane_bridge_vlan_info *bvinfo) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.bvinfo = *bvinfo; -+} -+ -+const struct zebra_dplane_bridge_vlan_info * -+dplane_ctx_get_ifp_bridge_vlan_info(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return &ctx->u.intf.bvinfo; -+} -+ -+void dplane_ctx_set_ifp_family(struct zebra_dplane_ctx *ctx, uint8_t family) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.family = family; -+} -+ -+uint8_t dplane_ctx_get_ifp_family(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.family; -+} -+ -+void dplane_ctx_set_ifp_zltype(struct zebra_dplane_ctx *ctx, -+ enum zebra_link_type zltype) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.zltype = zltype; -+} -+ -+enum zebra_link_type -+dplane_ctx_get_ifp_zltype(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.zltype; -+} -+ -+void dplane_ctx_set_ifp_link_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t link_ifindex) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.link_ifindex = link_ifindex; -+} -+ -+ifindex_t dplane_ctx_get_ifp_link_ifindex(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.link_ifindex; -+} -+ -+void dplane_ctx_set_ifp_desc(struct zebra_dplane_ctx *ctx, const char *desc) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ strlcpy(ctx->u.intf.desc, desc, sizeof(ctx->u.intf.desc)); -+} -+ -+char *dplane_ctx_get_ifp_desc(struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.desc; -+} -+ -+void dplane_ctx_set_ifp_flags(struct zebra_dplane_ctx *ctx, uint64_t flags) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.flags = flags; -+} -+ -+uint64_t dplane_ctx_get_ifp_flags(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.flags; -+} -+ -+void dplane_ctx_set_ifp_bypass(struct zebra_dplane_ctx *ctx, uint8_t bypass) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.bypass = bypass; -+} -+ -+uint8_t dplane_ctx_get_ifp_bypass(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.bypass; -+} -+ -+void dplane_ctx_set_ifp_bridge_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t bridge_ifindex) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.bridge_ifindex = bridge_ifindex; -+} -+ -+ifindex_t dplane_ctx_get_ifp_bridge_ifindex(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.bridge_ifindex; -+} -+ -+void dplane_ctx_set_ifp_zif_slave_type(struct zebra_dplane_ctx *ctx, -+ enum zebra_slave_iftype zslave_type) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.zslave_type = zslave_type; -+} -+ -+enum zebra_slave_iftype -+dplane_ctx_get_ifp_zif_slave_type(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.zslave_type; -+} -+ -+void dplane_ctx_set_ifp_master_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t master_ifindex) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.master_ifindex = master_ifindex; -+} -+ -+ifindex_t dplane_ctx_get_ifp_master_ifindex(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.master_ifindex; -+} -+ -+void dplane_ctx_set_ifp_mtu(struct zebra_dplane_ctx *ctx, uint32_t mtu) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.mtu = mtu; -+} -+ -+uint32_t dplane_ctx_get_ifp_mtu(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.mtu; -+} -+ -+void dplane_ctx_set_ifp_vrf_id(struct zebra_dplane_ctx *ctx, vrf_id_t vrf_id) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.vrf_id = vrf_id; -+} -+ -+vrf_id_t dplane_ctx_get_ifp_vrf_id(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.vrf_id; -+} -+ -+void dplane_ctx_set_ifp_link_nsid(struct zebra_dplane_ctx *ctx, -+ ns_id_t link_nsid) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.link_nsid = link_nsid; -+} -+ -+ns_id_t dplane_ctx_get_ifp_link_nsid(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.link_nsid; -+} -+ -+void dplane_ctx_set_ifp_startup(struct zebra_dplane_ctx *ctx, bool startup) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.startup = startup; -+} -+ -+bool dplane_ctx_get_ifp_startup(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.startup; -+} -+ -+void dplane_ctx_set_ifp_protodown_set(struct zebra_dplane_ctx *ctx, bool set) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.protodown_set = set; -+} -+ -+bool dplane_ctx_get_ifp_protodown_set(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.protodown_set; -+} -+ -+void dplane_ctx_set_ifp_protodown(struct zebra_dplane_ctx *ctx, bool protodown) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.protodown = protodown; -+} -+ -+bool dplane_ctx_get_ifp_protodown(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.protodown; -+} -+ -+ifindex_t dplane_ctx_get_ifp_bond_ifindex(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.bond_ifindex; -+} -+ -+void dplane_ctx_set_ifp_rc_bitfield(struct zebra_dplane_ctx *ctx, -+ uint32_t rc_bitfield) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.rc_bitfield = rc_bitfield; -+} -+ -+uint32_t dplane_ctx_get_ifp_rc_bitfield(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.rc_bitfield; -+} -+ -+void dplane_ctx_set_ifp_gre_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_gre *grinfo) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.grinfo = *grinfo; -+} -+ -+const struct zebra_l2info_gre * -+dplane_ctx_get_ifp_gre_info(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return &ctx->u.intf.grinfo; -+} -+ -+void dplane_ctx_set_ifp_vxlan_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_vxlan *vxinfo) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.vxinfo = *vxinfo; -+} -+ -+const struct zebra_l2info_vxlan * -+dplane_ctx_get_ifp_vxlan_info(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return &ctx->u.intf.vxinfo; -+} -+ -+void dplane_ctx_set_ifp_vlan_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_vlan *vinfo) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.vinfo = *vinfo; -+} -+ -+const struct zebra_l2info_vlan * -+dplane_ctx_get_ifp_vlan_info(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return &ctx->u.intf.vinfo; -+} -+ -+void dplane_ctx_set_ifp_bridge_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_bridge *binfo) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.binfo = *binfo; -+} -+ -+const struct zebra_l2info_bridge * -+dplane_ctx_get_ifp_bridge_info(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return &ctx->u.intf.binfo; -+} -+ -+void dplane_ctx_set_ifp_table_id(struct zebra_dplane_ctx *ctx, -+ uint32_t table_id) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.table_id = table_id; -+} -+ -+uint32_t dplane_ctx_get_ifp_table_id(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.table_id; -+} -+ -+void dplane_ctx_set_ifp_hw_addr(struct zebra_dplane_ctx *ctx, -+ int32_t hw_addr_len, uint8_t *hw_addr) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.hw_addr_len = hw_addr_len; -+ memcpy(ctx->u.intf.hw_addr, hw_addr, hw_addr_len); -+} -+ -+int32_t dplane_ctx_get_ifp_hw_addr_len(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.hw_addr_len; -+} -+ -+const uint8_t *dplane_ctx_get_ifp_hw_addr(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.hw_addr; -+} -+ -+void dplane_ctx_set_ifp_bond_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t bond_ifindex) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.bond_ifindex = bond_ifindex; -+} -+ -+enum zebra_iftype -+dplane_ctx_get_ifp_zif_type(const struct zebra_dplane_ctx *ctx) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ return ctx->u.intf.zif_type; -+} -+ -+void dplane_ctx_set_ifp_zif_type(struct zebra_dplane_ctx *ctx, -+ enum zebra_iftype zif_type) -+{ -+ DPLANE_CTX_VALID(ctx); -+ -+ ctx->u.intf.zif_type = zif_type; -+} -+ - void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname) - { - DPLANE_CTX_VALID(ctx); -@@ -6102,6 +6561,7 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx) - case DPLANE_OP_TC_FILTER_ADD: - case DPLANE_OP_TC_FILTER_DELETE: - case DPLANE_OP_TC_FILTER_UPDATE: -+ case DPLANE_OP_STARTUP_STAGE: - break; - } - } -@@ -6274,6 +6734,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx) - break; - - case DPLANE_OP_NONE: -+ case DPLANE_OP_STARTUP_STAGE: - if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) - atomic_fetch_add_explicit(&zdplane_info.dg_other_errors, - 1, memory_order_relaxed); -@@ -6966,6 +7427,25 @@ void zebra_dplane_start(void) - frr_pthread_run(zdplane_info.dg_pthread, NULL); - } - -+enum zebra_dplane_startup_notifications -+dplane_ctx_get_startup_spot(struct zebra_dplane_ctx *ctx) -+{ -+ return ctx->u.spot; -+} -+ -+void zebra_dplane_startup_stage(struct zebra_ns *zns, -+ enum zebra_dplane_startup_notifications spot) -+{ -+ struct zebra_dplane_ctx *ctx = dplane_ctx_alloc(); -+ -+ ctx->zd_op = DPLANE_OP_STARTUP_STAGE; -+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_QUEUED; -+ -+ ctx->u.spot = spot; -+ dplane_ctx_set_ns_id(ctx, zns->ns_id); -+ -+ dplane_provider_enqueue_to_zebra(ctx); -+} - /* - * Initialize the dataplane module at startup; called by zebra rib_init() - */ -diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h -index 9ef0afd3a8..c10482ed96 100644 ---- a/zebra/zebra_dplane.h -+++ b/zebra/zebra_dplane.h -@@ -100,6 +100,11 @@ enum zebra_dplane_result { - ZEBRA_DPLANE_REQUEST_FAILURE, - }; - -+enum zebra_dplane_startup_notifications { -+ ZEBRA_DPLANE_INTERFACES_READ, -+ ZEBRA_DPLANE_TUNNELS_READ, -+ ZEBRA_DPLANE_ADDRESSES_READ, -+}; - /* - * API between the zebra dataplane system and the main zebra processing - * context. -@@ -201,7 +206,10 @@ enum dplane_op_e { - DPLANE_OP_TC_CLASS_UPDATE, - DPLANE_OP_TC_FILTER_ADD, - DPLANE_OP_TC_FILTER_DELETE, -- DPLANE_OP_TC_FILTER_UPDATE -+ DPLANE_OP_TC_FILTER_UPDATE, -+ -+ /* Startup Control */ -+ DPLANE_OP_STARTUP_STAGE, - }; - - /* -@@ -336,6 +344,105 @@ const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx); - void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname); - ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx); - void dplane_ctx_set_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex); -+void dplane_ctx_set_ifp_bond_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t ifindex); -+ifindex_t dplane_ctx_get_ifp_bond_ifindex(const struct zebra_dplane_ctx *ctx); -+enum zebra_iftype -+dplane_ctx_get_ifp_zif_type(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_zif_type(struct zebra_dplane_ctx *ctx, -+ enum zebra_iftype zif_type); -+void dplane_ctx_set_ifp_table_id(struct zebra_dplane_ctx *ctx, -+ uint32_t table_id); -+uint32_t dplane_ctx_get_ifp_table_id(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_hw_addr(struct zebra_dplane_ctx *ctx, -+ int32_t hw_addr_len, uint8_t *hw_addr); -+int32_t dplane_ctx_get_ifp_hw_addr_len(const struct zebra_dplane_ctx *ctx); -+const uint8_t *dplane_ctx_get_ifp_hw_addr(const struct zebra_dplane_ctx *ctx); -+struct zebra_l2info_bridge; -+void dplane_ctx_set_ifp_bridge_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_bridge *binfo); -+const struct zebra_l2info_bridge * -+dplane_ctx_get_ifp_bridge_info(const struct zebra_dplane_ctx *ctx); -+struct zebra_l2info_vlan; -+void dplane_ctx_set_ifp_vlan_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_vlan *vinfo); -+const struct zebra_l2info_vlan * -+dplane_ctx_get_ifp_vlan_info(const struct zebra_dplane_ctx *ctx); -+struct zebra_l2info_vxlan; -+void dplane_ctx_set_ifp_vxlan_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_vxlan *vxinfo); -+const struct zebra_l2info_vxlan * -+dplane_ctx_get_ifp_vxlan_info(const struct zebra_dplane_ctx *ctx); -+struct zebra_l2info_gre; -+void dplane_ctx_set_ifp_gre_info(struct zebra_dplane_ctx *ctx, -+ struct zebra_l2info_gre *greinfo); -+const struct zebra_l2info_gre * -+dplane_ctx_get_ifp_gre_info(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_zltype(struct zebra_dplane_ctx *ctx, -+ enum zebra_link_type zlt); -+enum zebra_link_type -+dplane_ctx_get_ifp_zltype(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_link_nsid(struct zebra_dplane_ctx *ctx, ns_id_t ns_id); -+ns_id_t dplane_ctx_get_ifp_link_nsid(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_desc(struct zebra_dplane_ctx *ctx, const char *desc); -+char *dplane_ctx_get_ifp_desc(struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_mtu(struct zebra_dplane_ctx *ctx, uint32_t mtu); -+uint32_t dplane_ctx_get_ifp_mtu(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_vrf_id(struct zebra_dplane_ctx *ctx, vrf_id_t vrf_id); -+vrf_id_t dplane_ctx_get_ifp_vrf_id(const struct zebra_dplane_ctx *ctx); -+enum zebra_slave_iftype; -+void dplane_ctx_set_ifp_zif_slave_type(struct zebra_dplane_ctx *ctx, -+ enum zebra_slave_iftype zslave_type); -+enum zebra_slave_iftype -+dplane_ctx_get_ifp_zif_slave_type(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_master_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t master_ifindex); -+ifindex_t dplane_ctx_get_ifp_master_ifindex(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_bridge_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t bridge_ifindex); -+ifindex_t dplane_ctx_get_ifp_bridge_ifindex(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_bypass(struct zebra_dplane_ctx *ctx, uint8_t bypass); -+uint8_t dplane_ctx_get_ifp_bypass(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_flags(struct zebra_dplane_ctx *ctx, uint64_t flags); -+uint64_t dplane_ctx_get_ifp_flags(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_protodown(struct zebra_dplane_ctx *ctx, bool protodown); -+bool dplane_ctx_get_ifp_protodown(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_startup(struct zebra_dplane_ctx *ctx, bool startup); -+bool dplane_ctx_get_ifp_startup(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_protodown_set(struct zebra_dplane_ctx *ctx, bool set); -+bool dplane_ctx_get_ifp_protodown_set(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_rc_bitfield(struct zebra_dplane_ctx *ctx, -+ uint32_t rc_bitfield); -+uint32_t dplane_ctx_get_ifp_rc_bitfield(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_link_ifindex(struct zebra_dplane_ctx *ctx, -+ ifindex_t link_ifindex); -+ifindex_t dplane_ctx_get_ifp_link_ifindex(const struct zebra_dplane_ctx *ctx); -+void dplane_ctx_set_ifp_family(struct zebra_dplane_ctx *ctx, uint8_t family); -+uint8_t dplane_ctx_get_ifp_family(const struct zebra_dplane_ctx *ctx); -+struct zebra_vxlan_vni_array; -+void dplane_ctx_set_ifp_vxlan_vni_array(struct zebra_dplane_ctx *ctx, -+ struct zebra_vxlan_vni_array *vniarray); -+const struct zebra_vxlan_vni_array * -+dplane_ctx_get_ifp_vxlan_vni_array(const struct zebra_dplane_ctx *ctx); -+struct zebra_dplane_bridge_vlan_info { -+ uint16_t flags; -+ uint16_t vid; -+}; -+void dplane_ctx_set_ifp_bridge_vlan_info( -+ struct zebra_dplane_ctx *ctx, -+ struct zebra_dplane_bridge_vlan_info *bvinfo); -+const struct zebra_dplane_bridge_vlan_info * -+dplane_ctx_get_ifp_bridge_vlan_info(const struct zebra_dplane_ctx *ctx); -+ -+struct zebra_dplane_bridge_vlan_info_array { -+ int count; -+ struct zebra_dplane_bridge_vlan_info array[0]; -+}; -+void dplane_ctx_set_ifp_bridge_vlan_info_array( -+ struct zebra_dplane_ctx *ctx, -+ struct zebra_dplane_bridge_vlan_info_array *bvarray); -+const struct zebra_dplane_bridge_vlan_info_array * -+dplane_ctx_get_ifp_bridge_vlan_info_array(const struct zebra_dplane_ctx *ctx); - - /* Retrieve last/current provider id */ - uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx); -@@ -1083,6 +1190,9 @@ void zebra_dplane_pre_finish(void); - void zebra_dplane_finish(void); - void zebra_dplane_shutdown(void); - -+void zebra_dplane_startup_stage(struct zebra_ns *zns, -+ enum zebra_dplane_startup_notifications spot); -+ - /* - * decision point for sending a routing update through the old - * straight to zebra master pthread or through the dplane to -@@ -1093,6 +1203,9 @@ void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, - struct nexthop_group *ng, int startup, - struct zebra_dplane_ctx *ctx); - -+enum zebra_dplane_startup_notifications -+dplane_ctx_get_startup_spot(struct zebra_dplane_ctx *ctx); -+ - #ifdef __cplusplus - } - #endif -diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c -index 758fed7280..8f686eb5f8 100644 ---- a/zebra/zebra_nhg.c -+++ b/zebra/zebra_nhg.c -@@ -3177,6 +3177,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) - case DPLANE_OP_TC_FILTER_ADD: - case DPLANE_OP_TC_FILTER_DELETE: - case DPLANE_OP_TC_FILTER_UPDATE: -+ case DPLANE_OP_STARTUP_STAGE: - break; - } - } -diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index 5e50d720a6..201fc761ae 100644 ---- a/zebra/zebra_rib.c -+++ b/zebra/zebra_rib.c -@@ -4770,6 +4770,7 @@ static void rib_process_dplane_results(struct thread *thread) - case DPLANE_OP_NEIGH_TABLE_UPDATE: - case DPLANE_OP_GRE_SET: - case DPLANE_OP_NONE: -+ case DPLANE_OP_STARTUP_STAGE: - break; - - } /* Dispatch by op code */ -diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c -index 5c67ad4f16..22c1824b5a 100644 ---- a/zebra/zebra_script.c -+++ b/zebra/zebra_script.c -@@ -428,6 +428,7 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx) - /* Not currently handled */ - case DPLANE_OP_INTF_NETCONFIG: /*NYI*/ - case DPLANE_OP_NONE: -+ case DPLANE_OP_STARTUP_STAGE: - break; - } /* Dispatch by op code */ - } --- -2.17.1 - diff --git a/src/sonic-frr/patch/0018-zebra-Use-zebra-dplane-for-RTM-link-and-addr.patch b/src/sonic-frr/patch/0018-zebra-Use-zebra-dplane-for-RTM-link-and-addr.patch deleted file mode 100644 index 98f3b224a75e..000000000000 --- a/src/sonic-frr/patch/0018-zebra-Use-zebra-dplane-for-RTM-link-and-addr.patch +++ /dev/null @@ -1,2154 +0,0 @@ -From 2c33b9ab847a53d8006687e89c0cbd589fe7071f Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Wed, 26 Apr 2023 23:02:09 -0400 -Subject: [PATCH] zebra: Use zebra dplane for RTM link and addr - -a) Move the reads of link and address information -into the dplane -b) Move the startup read of data into the dplane -as well. -c) Break up startup reading of the linux kernel data -into multiple phases. As that we have implied ordering -of data that must be read first and if the dplane has -taken over some data reading then we must delay initial -read-in of other data. - -Fixes: #13288 -Signed-off-by: Donald Sharp - -diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c -index ed5b3c4a66..7613f5fcc4 100644 ---- a/zebra/if_netlink.c -+++ b/zebra/if_netlink.c -@@ -79,64 +79,21 @@ - - extern struct zebra_privs_t zserv_privs; - --/* Note: on netlink systems, there should be a 1-to-1 mapping between interface -- names and ifindex values. */ --static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, -- struct zebra_ns *zns) --{ -- struct interface *oifp; -- -- if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL) -- && (oifp != ifp)) { -- if (ifi_index == IFINDEX_INTERNAL) -- flog_err( -- EC_LIB_INTERFACE, -- "Netlink is setting interface %s ifindex to reserved internal value %u", -- ifp->name, ifi_index); -- else { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "interface index %d was renamed from %s to %s", -- ifi_index, oifp->name, ifp->name); -- if (if_is_up(oifp)) -- flog_err( -- EC_LIB_INTERFACE, -- "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!", -- ifi_index, oifp->name, ifp->name); -- if_delete_update(&oifp); -- } -- } -- if_set_index(ifp, ifi_index); --} -- - /* Utility function to parse hardware link-layer address and update ifp */ - static void netlink_interface_update_hw_addr(struct rtattr **tb, -- struct interface *ifp) -+ struct zebra_dplane_ctx *ctx) - { -- int i; -- - if (tb[IFLA_ADDRESS]) { - int hw_addr_len; - - hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); - - if (hw_addr_len > INTERFACE_HWADDR_MAX) -- zlog_debug("Hardware address is too large: %d", -- hw_addr_len); -- else { -- ifp->hw_addr_len = hw_addr_len; -- memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), -- hw_addr_len); -- -- for (i = 0; i < hw_addr_len; i++) -- if (ifp->hw_addr[i] != 0) -- break; -- -- if (i == hw_addr_len) -- ifp->hw_addr_len = 0; -- else -- ifp->hw_addr_len = hw_addr_len; -- } -+ zlog_warn("Hardware address is too large: %d", -+ hw_addr_len); -+ else -+ dplane_ctx_set_ifp_hw_addr(ctx, hw_addr_len, -+ RTA_DATA(tb[IFLA_ADDRESS])); - } - } - -@@ -251,26 +208,6 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt) - } - } - --static inline void zebra_if_set_ziftype(struct interface *ifp, -- enum zebra_iftype zif_type, -- enum zebra_slave_iftype zif_slave_type) --{ -- struct zebra_if *zif; -- -- zif = (struct zebra_if *)ifp->info; -- zif->zif_slave_type = zif_slave_type; -- -- if (zif->zif_type != zif_type) { -- zif->zif_type = zif_type; -- /* If the if_type has been set to bond initialize ES info -- * against it. XXX - note that we don't handle the case where -- * a zif changes from bond to non-bond; it is really -- * an unexpected/error condition. -- */ -- zebra_evpn_if_init(zif); -- } --} -- - static void netlink_determine_zebra_iftype(const char *kind, - enum zebra_iftype *zif_type) - { -@@ -300,16 +237,11 @@ static void netlink_determine_zebra_iftype(const char *kind, - } - - static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, -- uint32_t ns_id, const char *name) -+ uint32_t ns_id, const char *name, -+ struct zebra_dplane_ctx *ctx) - { -- struct ifinfomsg *ifi; - struct rtattr *linkinfo[IFLA_INFO_MAX + 1]; - struct rtattr *attr[IFLA_VRF_MAX + 1]; -- struct vrf *vrf = NULL; -- struct zebra_vrf *zvrf; -- uint32_t nl_table_id; -- -- ifi = NLMSG_DATA(h); - - netlink_parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); - -@@ -331,75 +263,8 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, - return; - } - -- nl_table_id = *(uint32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); -- -- if (h->nlmsg_type == RTM_NEWLINK) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name, -- ifi->ifi_index, nl_table_id); -- -- if (!vrf_lookup_by_id((vrf_id_t)ifi->ifi_index)) { -- vrf_id_t exist_id; -- -- exist_id = -- zebra_vrf_lookup_by_table(nl_table_id, ns_id); -- if (exist_id != VRF_DEFAULT) { -- vrf = vrf_lookup_by_id(exist_id); -- -- flog_err( -- EC_ZEBRA_VRF_MISCONFIGURED, -- "VRF %s id %u table id overlaps existing vrf %s, misconfiguration exiting", -- name, ifi->ifi_index, vrf->name); -- exit(-1); -- } -- } -- -- vrf = vrf_update((vrf_id_t)ifi->ifi_index, name); -- if (!vrf) { -- flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", -- name, ifi->ifi_index); -- return; -- } -- -- /* -- * This is the only place that we get the actual kernel table_id -- * being used. We need it to set the table_id of the routes -- * we are passing to the kernel.... And to throw some totally -- * awesome parties. that too. -- * -- * At this point we *must* have a zvrf because the vrf_create -- * callback creates one. We *must* set the table id -- * before the vrf_enable because of( at the very least ) -- * static routes being delayed for installation until -- * during the vrf_enable callbacks. -- */ -- zvrf = (struct zebra_vrf *)vrf->info; -- zvrf->table_id = nl_table_id; -- -- /* Enable the created VRF. */ -- if (!vrf_enable(vrf)) { -- flog_err(EC_LIB_INTERFACE, -- "Failed to enable VRF %s id %u", name, -- ifi->ifi_index); -- return; -- } -- -- } else // h->nlmsg_type == RTM_DELLINK -- { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("RTM_DELLINK for VRF %s(%u)", name, -- ifi->ifi_index); -- -- vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index); -- -- if (!vrf) { -- flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s: vrf not found", -- __func__); -- return; -- } -- -- vrf_delete(vrf); -- } -+ dplane_ctx_set_ifp_table_id( -+ ctx, *(uint32_t *)RTA_DATA(attr[IFLA_VRF_TABLE])); - } - - static uint32_t get_iflink_speed(struct interface *interface, int *error) -@@ -659,58 +524,120 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data, - * bridge interface is added or updated, take further actions to map - * its members. Likewise, for VxLAN interface. - */ --static void netlink_interface_update_l2info(struct interface *ifp, -+static void netlink_interface_update_l2info(struct zebra_dplane_ctx *ctx, -+ enum zebra_iftype zif_type, - struct rtattr *link_data, int add, - ns_id_t link_nsid) - { -+ struct zebra_l2info_bridge bridge_info; -+ struct zebra_l2info_vlan vlan_info; -+ struct zebra_l2info_vxlan vxlan_info; -+ struct zebra_l2info_gre gre_info; -+ - if (!link_data) - return; - -- if (IS_ZEBRA_IF_BRIDGE(ifp)) { -- struct zebra_l2info_bridge bridge_info; -- -+ switch (zif_type) { -+ case ZEBRA_IF_BRIDGE: - netlink_extract_bridge_info(link_data, &bridge_info); -- zebra_l2_bridge_add_update(ifp, &bridge_info); -- } else if (IS_ZEBRA_IF_VLAN(ifp)) { -- struct zebra_l2info_vlan vlan_info; -- -+ dplane_ctx_set_ifp_bridge_info(ctx, &bridge_info); -+ break; -+ case ZEBRA_IF_VLAN: - netlink_extract_vlan_info(link_data, &vlan_info); -- zebra_l2_vlanif_update(ifp, &vlan_info); -- zebra_evpn_acc_bd_svi_set(ifp->info, NULL, -- !!if_is_operative(ifp)); -- } else if (IS_ZEBRA_IF_VXLAN(ifp)) { -- struct zebra_l2info_vxlan vxlan_info; -- -+ dplane_ctx_set_ifp_vlan_info(ctx, &vlan_info); -+ break; -+ case ZEBRA_IF_VXLAN: - netlink_extract_vxlan_info(link_data, &vxlan_info); - vxlan_info.link_nsid = link_nsid; -- zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add); -- if (link_nsid != NS_UNKNOWN && -- vxlan_info.ifindex_link) -- zebra_if_update_link(ifp, vxlan_info.ifindex_link, -- link_nsid); -- } else if (IS_ZEBRA_IF_GRE(ifp)) { -- struct zebra_l2info_gre gre_info; -- -+ dplane_ctx_set_ifp_vxlan_info(ctx, &vxlan_info); -+ break; -+ case ZEBRA_IF_GRE: - netlink_extract_gre_info(link_data, &gre_info); - gre_info.link_nsid = link_nsid; -- zebra_l2_greif_add_update(ifp, &gre_info, add); -- if (link_nsid != NS_UNKNOWN && -- gre_info.ifindex_link) -- zebra_if_update_link(ifp, gre_info.ifindex_link, -- link_nsid); -+ dplane_ctx_set_ifp_gre_info(ctx, &gre_info); -+ break; -+ case ZEBRA_IF_OTHER: -+ case ZEBRA_IF_VRF: -+ case ZEBRA_IF_MACVLAN: -+ case ZEBRA_IF_VETH: -+ case ZEBRA_IF_BOND: -+ case ZEBRA_IF_BOND_SLAVE: -+ break; - } - } - --static int netlink_bridge_vxlan_update(struct interface *ifp, -- struct rtattr *af_spec) -+#if 0 -+static int -+netlink_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx, -+ struct rtattr *af_spec) -+{ -+ int rem; -+ uint16_t flags; -+ struct rtattr *i; -+ struct zebra_vxlan_vni_array *vniarray = NULL; -+ struct zebra_vxlan_vni vni_end; -+ struct zebra_vxlan_vni vni_start; -+ struct rtattr *aftb[IFLA_BRIDGE_VLAN_TUNNEL_MAX + 1]; -+ int32_t count = 0; -+ -+ memset(&vni_start, 0, sizeof(vni_start)); -+ memset(&vni_end, 0, sizeof(vni_end)); -+ -+ for (i = RTA_DATA(af_spec), rem = RTA_PAYLOAD(af_spec); RTA_OK(i, rem); -+ i = RTA_NEXT(i, rem)) { -+ -+ if (i->rta_type != IFLA_BRIDGE_VLAN_TUNNEL_INFO) -+ continue; -+ -+ memset(aftb, 0, sizeof(aftb)); -+ netlink_parse_rtattr_nested(aftb, IFLA_BRIDGE_VLAN_TUNNEL_MAX, -+ i); -+ if (!aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID] || -+ !aftb[IFLA_BRIDGE_VLAN_TUNNEL_VID]) -+ /* vlan-vni info missing */ -+ return 0; -+ -+ count++; -+ flags = 0; -+ vniarray = XREALLOC( -+ MTYPE_TMP, vniarray, -+ sizeof(struct zebra_vxlan_vni_array) + -+ count * sizeof(struct zebra_vxlan_vni)); -+ -+ memset(&vniarray->vnis[count - 1], 0, -+ sizeof(struct zebra_vxlan_vni)); -+ -+ vniarray->vnis[count - 1].vni = -+ *(vni_t *)RTA_DATA(aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID]); -+ vniarray->vnis[count - 1].access_vlan = *(vlanid_t *)RTA_DATA( -+ aftb[IFLA_BRIDGE_VLAN_TUNNEL_VID]); -+ -+ if (aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]) -+ flags = *(uint16_t *)RTA_DATA( -+ aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]); -+ -+ vniarray->vnis[count - 1].flags = flags; -+ } -+ -+ if (count) { -+ vniarray->count = count; -+ dplane_ctx_set_ifp_vxlan_vni_array(ctx, vniarray); -+ } -+ return 0; -+} -+#endif -+static int netlink_bridge_vxlan_update(struct zebra_dplane_ctx *ctx, -+ struct rtattr *af_spec) - { - struct rtattr *aftb[IFLA_BRIDGE_MAX + 1]; - struct bridge_vlan_info *vinfo; -- vlanid_t access_vlan; -+ struct zebra_dplane_bridge_vlan_info bvinfo; - - if (!af_spec) - return 0; - -+ //netlink_bridge_vxlan_vlan_vni_map_update(ctx, af_spec); -+ - /* There is a 1-to-1 mapping of VLAN to VxLAN - hence - * only 1 access VLAN is accepted. - */ -@@ -719,119 +646,73 @@ static int netlink_bridge_vxlan_update(struct interface *ifp, - return 0; - - vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]); -- if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID)) -- return 0; -+ bvinfo.flags = vinfo->flags; -+ bvinfo.vid = vinfo->vid; - -- access_vlan = (vlanid_t)vinfo->vid; -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan, -- ifp->name, ifp->ifindex); -- zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan); -+ dplane_ctx_set_ifp_bridge_vlan_info(ctx, &bvinfo); - return 0; - } - --static void netlink_bridge_vlan_update(struct interface *ifp, -- struct rtattr *af_spec) -+static void netlink_bridge_vlan_update(struct zebra_dplane_ctx *ctx, -+ struct rtattr *af_spec) - { - struct rtattr *i; - int rem; -- uint16_t vid_range_start = 0; -- struct zebra_if *zif; -- bitfield_t old_vlan_bitmap; - struct bridge_vlan_info *vinfo; -- -- zif = (struct zebra_if *)ifp->info; -- -- /* cache the old bitmap addrs */ -- old_vlan_bitmap = zif->vlan_bitmap; -- /* create a new bitmap space for re-eval */ -- bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX); -+ struct zebra_dplane_bridge_vlan_info_array *bvarray = NULL; -+ int32_t count = 0; - - if (af_spec) { - for (i = RTA_DATA(af_spec), rem = RTA_PAYLOAD(af_spec); - RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { -- - if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) - continue; - -- vinfo = RTA_DATA(i); -- -- if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { -- vid_range_start = vinfo->vid; -- continue; -- } -+ count++; -+ bvarray = XREALLOC( -+ MTYPE_TMP, bvarray, -+ sizeof(struct -+ zebra_dplane_bridge_vlan_info_array) + -+ count * sizeof(struct -+ zebra_dplane_bridge_vlan_info)); - -- if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)) -- vid_range_start = vinfo->vid; -- -- zebra_vlan_bitmap_compute(ifp, vid_range_start, -- vinfo->vid); -+ vinfo = RTA_DATA(i); -+ bvarray->array[count - 1].flags = vinfo->flags; -+ bvarray->array[count - 1].vid = vinfo->vid; - } - } - -- zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap); -- -- bf_free(old_vlan_bitmap); -+ if (count) { -+ bvarray->count = count; -+ dplane_ctx_set_ifp_bridge_vlan_info_array(ctx, bvarray); -+ } - } - --static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id, -- int startup) -+static int netlink_bridge_interface(struct zebra_dplane_ctx *ctx, -+ struct rtattr *af_spec, int startup) - { -- char *name = NULL; -- struct ifinfomsg *ifi; -- struct rtattr *tb[IFLA_MAX + 1]; -- struct interface *ifp; -- struct zebra_if *zif; -- struct rtattr *af_spec; - -- /* Fetch name and ifindex */ -- ifi = NLMSG_DATA(h); -- netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); -- -- if (tb[IFLA_IFNAME] == NULL) -- return -1; -- name = (char *)RTA_DATA(tb[IFLA_IFNAME]); -- -- /* The interface should already be known, if not discard. */ -- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index); -- if (!ifp) { -- zlog_debug("Cannot find bridge IF %s(%u)", name, -- ifi->ifi_index); -- return 0; -- } -- -- /* We are only interested in the access VLAN i.e., AF_SPEC */ -- af_spec = tb[IFLA_AF_SPEC]; -- -- if (IS_ZEBRA_IF_VXLAN(ifp)) -- return netlink_bridge_vxlan_update(ifp, af_spec); -+ netlink_bridge_vxlan_update(ctx, af_spec); - - /* build vlan bitmap associated with this interface if that - * device type is interested in the vlans - */ -- zif = (struct zebra_if *)ifp->info; -- if (bf_is_inited(zif->vlan_bitmap)) -- netlink_bridge_vlan_update(ifp, af_spec); -+ netlink_bridge_vlan_update(ctx, af_spec); - -+ dplane_provider_enqueue_to_zebra(ctx); - return 0; - } - --static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield) --{ -- return (rc_bitfield == (((uint32_t)1) << if_netlink_get_frr_protodown_r_bit())); --} -- - /* - * Process interface protodown dplane update. - * - * If the interface is an es bond member then it must follow EVPN's - * protodown setting. - */ --static void netlink_proc_dplane_if_protodown(struct zebra_if *zif, -+static void netlink_proc_dplane_if_protodown(struct zebra_dplane_ctx *ctx, - struct rtattr **tb) - { - bool protodown; -- bool old_protodown; - uint32_t rc_bitfield = 0; - struct rtattr *pd_reason_info[IFLA_MAX + 1]; - -@@ -846,59 +727,9 @@ static void netlink_proc_dplane_if_protodown(struct zebra_if *zif, - pd_reason_info[IFLA_PROTO_DOWN_REASON_VALUE]); - } - -- /* -- * Set our reason code to note it wasn't us. -- * If the reason we got from the kernel is ONLY frr though, don't -- * set it. -- */ -- COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL, -- protodown && rc_bitfield && -- !is_if_protodown_reason_only_frr(rc_bitfield)); -- -- -- old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); -- if (protodown == old_protodown) -- return; -- -- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("interface %s dplane change, protdown %s", -- zif->ifp->name, protodown ? "on" : "off"); -- -- /* Set protodown, respectively */ -- COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown); -- -- if (zebra_evpn_is_es_bond_member(zif->ifp)) { -- /* Check it's not already being sent to the dplane first */ -- if (protodown && -- CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) { -- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "bond mbr %s protodown on recv'd but already sent protodown on to the dplane", -- zif->ifp->name); -- return; -- } -- -- if (!protodown && -- CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) { -- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "bond mbr %s protodown off recv'd but already sent protodown off to the dplane", -- zif->ifp->name); -- return; -- } -- -- if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "bond mbr %s reinstate protodown %s in the dplane", -- zif->ifp->name, old_protodown ? "on" : "off"); -- -- if (old_protodown) -- SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN); -- else -- SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN); -- -- dplane_intf_update(zif->ifp); -- } -+ dplane_ctx_set_ifp_rc_bitfield(ctx, rc_bitfield); -+ dplane_ctx_set_ifp_protodown(ctx, protodown); -+ dplane_ctx_set_ifp_protodown_set(ctx, true); - } - - static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo) -@@ -915,29 +746,6 @@ static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo) - return bypass; - } - --/* -- * Only called at startup to cleanup leftover protodown reasons we may -- * have not cleaned up. We leave protodown set though. -- */ --static void if_sweep_protodown(struct zebra_if *zif) --{ -- bool protodown; -- -- protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); -- -- if (!protodown) -- return; -- -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("interface %s sweeping protodown %s reason 0x%x", -- zif->ifp->name, protodown ? "on" : "off", -- zif->protodown_rc); -- -- /* Only clear our reason codes, leave external if it was set */ -- UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL); -- dplane_intf_update(zif->ifp); --} -- - /* Request for specific interface or address information from the kernel */ - static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family, - int type, uint32_t filter_mask) -@@ -984,7 +792,7 @@ int interface_lookup_netlink(struct zebra_ns *zns) - { - int ret; - struct zebra_dplane_info dp_info; -- struct nlsock *netlink_cmd = &zns->netlink_cmd; -+ struct nlsock *netlink_cmd = &zns->netlink_dplane_out; - - /* Capture key info from ns struct */ - zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/); -@@ -1008,6 +816,13 @@ int interface_lookup_netlink(struct zebra_ns *zns) - if (ret < 0) - return ret; - -+ return ret; -+} -+ -+void interface_list_tunneldump(struct zebra_ns *zns) -+{ -+ int ret; -+ - /* - * So netlink_tunneldump_read will initiate a request - * per tunnel to get data. If we are on a kernel that -@@ -1020,13 +835,12 @@ int interface_lookup_netlink(struct zebra_ns *zns) - */ - ret = netlink_tunneldump_read(zns); - if (ret < 0) -- return ret; -+ return; - -- /* fixup linkages */ -- zebra_if_update_all_links(zns); -- return 0; -+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_TUNNELS_READ); - } - -+ - /** - * interface_addr_lookup_netlink() - Look up interface addresses - * -@@ -1046,8 +860,8 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) - ret = netlink_request_intf_addr(netlink_cmd, AF_INET, RTM_GETADDR, 0); - if (ret < 0) - return ret; -- ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, -- 0, true); -+ ret = netlink_parse_info(netlink_interface_addr_dplane, netlink_cmd, -+ &dp_info, 0, true); - if (ret < 0) - return ret; - -@@ -1055,8 +869,8 @@ static int interface_addr_lookup_netlink(struct zebra_ns *zns) - ret = netlink_request_intf_addr(netlink_cmd, AF_INET6, RTM_GETADDR, 0); - if (ret < 0) - return ret; -- ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info, -- 0, true); -+ ret = netlink_parse_info(netlink_interface_addr_dplane, netlink_cmd, -+ &dp_info, 0, true); - if (ret < 0) - return ret; - -@@ -1616,7 +1430,6 @@ int netlink_interface_addr_dplane(struct nlmsghdr *h, ns_id_t ns_id, - - /* Enqueue ctx for main pthread to process */ - dplane_provider_enqueue_to_zebra(ctx); -- - return 0; - } - -@@ -1626,27 +1439,21 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; -- struct interface *ifp; - char *name = NULL; - char *kind = NULL; -- char *desc = NULL; - char *slave_kind = NULL; -- struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - enum zebra_iftype zif_type = ZEBRA_IF_OTHER; - enum zebra_slave_iftype zif_slave_type = ZEBRA_IF_SLAVE_NONE; - ifindex_t bridge_ifindex = IFINDEX_INTERNAL; - ifindex_t bond_ifindex = IFINDEX_INTERNAL; - ifindex_t link_ifindex = IFINDEX_INTERNAL; -- uint8_t old_hw_addr[INTERFACE_HWADDR_MAX]; -- struct zebra_if *zif; - ns_id_t link_nsid = ns_id; - ifindex_t master_infindex = IFINDEX_INTERNAL; - uint8_t bypass = 0; - - frrtrace(3, frr_zebra, netlink_interface, h, ns_id, startup); - -- zns = zebra_ns_lookup(ns_id); - ifi = NLMSG_DATA(h); - - /* assume if not default zns, then new VRF */ -@@ -1675,10 +1482,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - return -1; - } - -- /* We are interested in some AF_BRIDGE notifications. */ -- if (ifi->ifi_family == AF_BRIDGE) -- return netlink_bridge_interface(h, len, ns_id, startup); -- - /* Looking up interface name. */ - memset(linkinfo, 0, sizeof(linkinfo)); - netlink_parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, -@@ -1728,18 +1531,47 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]); - link_nsid = ns_id_get_absolute(ns_id, link_nsid); - } -- if (tb[IFLA_IFALIAS]) { -- desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]); -- } - -- /* See if interface is present. */ -- ifp = if_lookup_by_name_per_ns(zns, name); -+ struct zebra_dplane_ctx *ctx = dplane_ctx_alloc(); -+ dplane_ctx_set_ns_id(ctx, ns_id); -+ dplane_ctx_set_ifp_link_nsid(ctx, link_nsid); -+ dplane_ctx_set_ifp_zif_type(ctx, zif_type); -+ dplane_ctx_set_ifindex(ctx, ifi->ifi_index); -+ dplane_ctx_set_ifname(ctx, name); -+ dplane_ctx_set_ifp_startup(ctx, startup); -+ dplane_ctx_set_ifp_family(ctx, ifi->ifi_family); -+ -+ /* We are interested in some AF_BRIDGE notifications. */ -+#ifndef AF_BRIDGE -+#define AF_BRIDGE 7 -+#endif -+ if (ifi->ifi_family == AF_BRIDGE) { -+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_INSTALL); -+ return netlink_bridge_interface(ctx, tb[IFLA_AF_SPEC], startup); -+ } - - if (h->nlmsg_type == RTM_NEWLINK) { -+ dplane_ctx_set_ifp_link_ifindex(ctx, link_ifindex); -+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_INSTALL); -+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_QUEUED); -+ if (tb[IFLA_IFALIAS]) { -+ dplane_ctx_set_ifp_desc(ctx, -+ RTA_DATA(tb[IFLA_IFALIAS])); -+ } -+ if (!tb[IFLA_MTU]) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK for interface %s(%u) without MTU set", -+ name, ifi->ifi_index); -+ return 0; -+ } -+ dplane_ctx_set_ifp_mtu(ctx, *(int *)RTA_DATA(tb[IFLA_MTU])); -+ - /* If VRF, create or update the VRF structure itself. */ - if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { -- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name); -- vrf_id = (vrf_id_t)ifi->ifi_index; -+ netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name, -+ ctx); -+ vrf_id = ifi->ifi_index; - } - - if (tb[IFLA_MASTER]) { -@@ -1762,279 +1594,45 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) - } else - zif_slave_type = ZEBRA_IF_SLAVE_OTHER; - } -+ dplane_ctx_set_ifp_zif_slave_type(ctx, zif_slave_type); -+ dplane_ctx_set_ifp_vrf_id(ctx, vrf_id); -+ dplane_ctx_set_ifp_master_ifindex(ctx, master_infindex); -+ dplane_ctx_set_ifp_bridge_ifindex(ctx, bridge_ifindex); -+ dplane_ctx_set_ifp_bond_ifindex(ctx, bond_ifindex); -+ dplane_ctx_set_ifp_bypass(ctx, bypass); -+ dplane_ctx_set_ifp_zltype( -+ ctx, netlink_to_zebra_link_type(ifi->ifi_type)); -+ - if (vrf_is_backend_netns()) -- vrf_id = (vrf_id_t)ns_id; -- if (ifp == NULL -- || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { -- /* Add interface notification from kernel */ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u flags 0x%x", -- name, ifi->ifi_index, vrf_id, zif_type, -- zif_slave_type, master_infindex, -- ifi->ifi_flags); -- -- if (ifp == NULL) { -- /* unknown interface */ -- ifp = if_get_by_name(name, vrf_id, NULL); -- } else { -- /* pre-configured interface, learnt now */ -- if (ifp->vrf->vrf_id != vrf_id) -- if_update_to_new_vrf(ifp, vrf_id); -- } -- -- /* Update interface information. */ -- set_ifindex(ifp, ifi->ifi_index, zns); -- ifp->flags = ifi->ifi_flags & 0x0000fffff; -- if (!tb[IFLA_MTU]) { -- zlog_debug( -- "RTM_NEWLINK for interface %s(%u) without MTU set", -- name, ifi->ifi_index); -- return 0; -- } -- ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); -- ifp->metric = 0; -- ifp->speed = get_iflink_speed(ifp, NULL); -- ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; -- -- /* Set interface type */ -- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); -- if (IS_ZEBRA_IF_VRF(ifp)) -- SET_FLAG(ifp->status, -- ZEBRA_INTERFACE_VRF_LOOPBACK); -- -- /* Update link. */ -- zebra_if_update_link(ifp, link_ifindex, link_nsid); -- -- /* -- * Just set the @link/lower-device ifindex. During -- * nldump interfaces are not ordered in any fashion so -- * we may end up getting upper devices before lower -- * devices. We will setup the real linkage once the dump -- * is complete. -- */ -- zif = (struct zebra_if *)ifp->info; -- zif->link_ifindex = link_ifindex; -- -- ifp->ll_type = -- netlink_to_zebra_link_type(ifi->ifi_type); -- netlink_interface_update_hw_addr(tb, ifp); -- -- /* Inform clients, install any configured addresses. */ -- if_add_update(ifp); -- -- /* Extract and save L2 interface information, take -- * additional actions. */ -- netlink_interface_update_l2info( -- ifp, linkinfo[IFLA_INFO_DATA], -- 1, link_nsid); -- if (IS_ZEBRA_IF_BOND(ifp)) -- zebra_l2if_update_bond(ifp, true); -- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) -- zebra_l2if_update_bridge_slave( -- ifp, bridge_ifindex, ns_id, -- ZEBRA_BRIDGE_NO_ACTION); -- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) -- zebra_l2if_update_bond_slave(ifp, bond_ifindex, -- !!bypass); -- -- if (tb[IFLA_PROTO_DOWN]) { -- netlink_proc_dplane_if_protodown(ifp->info, tb); -- if (startup) -- if_sweep_protodown(zif); -- } -- if (IS_ZEBRA_IF_BRIDGE(ifp)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_NEWLINK ADD for %s(%u), vlan-aware %d", -- name, ifp->ifindex, -- IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( -- zif)); -- } -- } else if (ifp->vrf->vrf_id != vrf_id) { -- /* VRF change for an interface. */ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u flags 0x%x", -- name, ifp->ifindex, ifp->vrf->vrf_id, -- vrf_id, ifi->ifi_flags); -+ dplane_ctx_set_ifp_vrf_id(ctx, ns_id); - -- if_handle_vrf_change(ifp, vrf_id); -- } else { -- bool was_bridge_slave, was_bond_slave; -- uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION; -- zif = ifp->info; -+ dplane_ctx_set_ifp_flags(ctx, ifi->ifi_flags & 0x0000fffff); - -- /* Interface update. */ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_NEWLINK update for %s(%u) sl_type %d master %u flags 0x%x", -- name, ifp->ifindex, zif_slave_type, -- master_infindex, ifi->ifi_flags); -+ if (tb[IFLA_PROTO_DOWN]) { -+ dplane_ctx_set_ifp_protodown_set(ctx, true); -+ netlink_proc_dplane_if_protodown(ctx, tb); -+ } else -+ dplane_ctx_set_ifp_protodown_set(ctx, false); - -- set_ifindex(ifp, ifi->ifi_index, zns); -- if (!tb[IFLA_MTU]) { -- zlog_debug( -- "RTM_NEWLINK for interface %s(%u) without MTU set", -- name, ifi->ifi_index); -- return 0; -- } -- ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); -- ifp->metric = 0; -- -- /* Update interface type - NOTE: Only slave_type can -- * change. */ -- was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); -- was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp); -- zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); -- -- memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX); -- -- /* Update link. */ -- zebra_if_update_link(ifp, link_ifindex, link_nsid); -- -- ifp->ll_type = -- netlink_to_zebra_link_type(ifi->ifi_type); -- netlink_interface_update_hw_addr(tb, ifp); -- -- if (tb[IFLA_PROTO_DOWN]) -- netlink_proc_dplane_if_protodown(ifp->info, tb); -- -- if (if_is_no_ptm_operative(ifp)) { -- bool is_up = if_is_operative(ifp); -- ifp->flags = ifi->ifi_flags & 0x0000fffff; -- if (!if_is_no_ptm_operative(ifp) || -- CHECK_FLAG(zif->flags, -- ZIF_FLAG_PROTODOWN)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Intf %s(%u) has gone DOWN", -- name, ifp->ifindex); -- if_down(ifp); -- rib_update(RIB_UPDATE_KERNEL); -- } else if (if_is_operative(ifp)) { -- bool mac_updated = false; -- -- /* Must notify client daemons of new -- * interface status. */ -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Intf %s(%u) PTM up, notifying clients", -- name, ifp->ifindex); -- if_up(ifp, !is_up); -- -- /* Update EVPN VNI when SVI MAC change -- */ -- if (memcmp(old_hw_addr, ifp->hw_addr, -- INTERFACE_HWADDR_MAX)) -- mac_updated = true; -- if (IS_ZEBRA_IF_VLAN(ifp) -- && mac_updated) { -- struct interface *link_if; -- -- link_if = -- if_lookup_by_index_per_ns( -- zebra_ns_lookup(NS_DEFAULT), -- link_ifindex); -- if (link_if) -- zebra_vxlan_svi_up(ifp, -- link_if); -- } else if (mac_updated -- && IS_ZEBRA_IF_BRIDGE(ifp)) { -- zlog_debug( -- "Intf %s(%u) bridge changed MAC address", -- name, ifp->ifindex); -- chgflags = -- ZEBRA_BRIDGE_MASTER_MAC_CHANGE; -- } -- } -- } else { -- ifp->flags = ifi->ifi_flags & 0x0000fffff; -- if (if_is_operative(ifp) && -- !CHECK_FLAG(zif->flags, -- ZIF_FLAG_PROTODOWN)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Intf %s(%u) has come UP", -- name, ifp->ifindex); -- if_up(ifp, true); -- if (IS_ZEBRA_IF_BRIDGE(ifp)) -- chgflags = -- ZEBRA_BRIDGE_MASTER_UP; -- } else { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "Intf %s(%u) has gone DOWN", -- name, ifp->ifindex); -- if_down(ifp); -- rib_update(RIB_UPDATE_KERNEL); -- } -- } -- -- /* Extract and save L2 interface information, take -- * additional actions. */ -- netlink_interface_update_l2info( -- ifp, linkinfo[IFLA_INFO_DATA], -- 0, link_nsid); -- if (IS_ZEBRA_IF_BRIDGE(ifp)) -- zebra_l2if_update_bridge(ifp, chgflags); -- if (IS_ZEBRA_IF_BOND(ifp)) -- zebra_l2if_update_bond(ifp, true); -- if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) -- zebra_l2if_update_bridge_slave( -- ifp, bridge_ifindex, ns_id, chgflags); -- else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave) -- zebra_l2if_update_bond_slave(ifp, bond_ifindex, -- !!bypass); -- if (IS_ZEBRA_IF_BRIDGE(ifp)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_NEWLINK update for %s(%u), vlan-aware %d", -- name, ifp->ifindex, -- IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( -- zif)); -- } -- } -+ netlink_interface_update_hw_addr(tb, ctx); - -- zif = ifp->info; -- if (zif) { -- XFREE(MTYPE_ZIF_DESC, zif->desc); -- if (desc) -- zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc); -- } -+ /* Extract and save L2 interface information, take -+ * additional actions. */ -+ netlink_interface_update_l2info( -+ ctx, zif_type, linkinfo[IFLA_INFO_DATA], 1, link_nsid); - } else { -- /* Delete interface notification from kernel */ -- if (ifp == NULL) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "RTM_DELLINK for unknown interface %s(%u)", -- name, ifi->ifi_index); -- return 0; -- } -- - if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug("RTM_DELLINK for %s(%u)", name, -- ifp->ifindex); -- -- UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); -- -- if (IS_ZEBRA_IF_BOND(ifp)) -- zebra_l2if_update_bond(ifp, false); -- if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) -- zebra_l2if_update_bond_slave(ifp, bond_ifindex, false); -- /* Special handling for bridge or VxLAN interfaces. */ -- if (IS_ZEBRA_IF_BRIDGE(ifp)) -- zebra_l2_bridge_del(ifp); -- else if (IS_ZEBRA_IF_VXLAN(ifp)) -- zebra_l2_vxlanif_del(ifp); -- -- if_delete_update(&ifp); -- -- /* If VRF, delete the VRF structure itself. */ -- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) -- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name); -+ zlog_debug("RTM_DELLINK for %s(%u), enqueuing to zebra", -+ name, ifi->ifi_index); -+ -+ dplane_ctx_set_op(ctx, DPLANE_OP_INTF_DELETE); -+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_QUEUED); -+ -+ dplane_ctx_set_ifp_bond_ifindex(ctx, bond_ifindex); - } - -+ dplane_provider_enqueue_to_zebra(ctx); -+ - return 0; - } - -@@ -2111,6 +1709,13 @@ ssize_t netlink_intf_msg_encode(uint16_t cmd, - void interface_list(struct zebra_ns *zns) - { - interface_lookup_netlink(zns); -+ -+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_INTERFACES_READ); -+} -+ -+void interface_list_second(struct zebra_ns *zns) -+{ -+ zebra_if_update_all_links(zns); - /* We add routes for interface address, - * so we need to get the nexthop info - * from the kernel before we can do that -@@ -2118,6 +1723,8 @@ void interface_list(struct zebra_ns *zns) - netlink_nexthop_read(zns); - - interface_addr_lookup_netlink(zns); -+ -+ zebra_dplane_startup_stage(zns, ZEBRA_DPLANE_ADDRESSES_READ); - } - - /** -diff --git a/zebra/interface.c b/zebra/interface.c -index a05b9690ef..bfe7a06896 100644 ---- a/zebra/interface.c -+++ b/zebra/interface.c -@@ -1298,6 +1298,9 @@ static void zebra_if_addr_update_ctx(struct zebra_dplane_ctx *ctx, - const struct prefix *addr, *dest = NULL; - enum dplane_op_e op; - -+ if (!ifp) -+ return; -+ - op = dplane_ctx_get_op(ctx); - addr = dplane_ctx_get_intf_addr(ctx); - -@@ -1416,6 +1419,13 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, - enum dplane_netconf_status_e mpls, mcast_on, linkdown; - bool *mcast_set, *linkdown_set; - -+ if (!ifp && ifindex != -1 && ifindex != -2) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug("%s: Can't find ifp(%u)", __func__, ifindex); -+ -+ return; -+ } -+ - afi = dplane_ctx_get_afi(ctx); - mpls = dplane_ctx_get_netconf_mpls(ctx); - linkdown = dplane_ctx_get_netconf_linkdown(ctx); -@@ -1485,6 +1495,686 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, - (*linkdown_set ? "ON" : "OFF")); - } - -+static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex, -+ const char *name, uint32_t tableid, -+ ns_id_t ns_id) -+{ -+ struct vrf *vrf; -+ struct zebra_vrf *zvrf = NULL; -+ -+ if (op == DPLANE_OP_INTF_DELETE) { -+ if (IS_ZEBRA_DEBUG_DPLANE) -+ zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, -+ ifindex); -+ -+ vrf = vrf_lookup_by_id((vrf_id_t)ifindex); -+ if (!vrf) { -+ flog_warn(EC_ZEBRA_VRF_NOT_FOUND, -+ "%s(%u): vrf not found", name, ifindex); -+ return; -+ } -+ -+ vrf_delete(vrf); -+ } else { -+ if (IS_ZEBRA_DEBUG_DPLANE) -+ zlog_debug( -+ "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", -+ name, ifindex, tableid); -+ -+ if (!vrf_lookup_by_id((vrf_id_t)ifindex)) { -+ vrf_id_t exist_id; -+ -+ exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); -+ if (exist_id != VRF_DEFAULT) { -+ vrf = vrf_lookup_by_id(exist_id); -+ -+ flog_err( -+ EC_ZEBRA_VRF_MISCONFIGURED, -+ "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", -+ name, ifindex, vrf->name, vrf->vrf_id); -+ exit(-1); -+ } -+ } -+ -+ vrf = vrf_update((vrf_id_t)ifindex, name); -+ if (!vrf) { -+ flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", -+ name, ifindex); -+ return; -+ } -+ -+ /* -+ * This is the only place that we get the actual kernel table_id -+ * being used. We need it to set the table_id of the routes -+ * we are passing to the kernel.... And to throw some totally -+ * awesome parties. that too. -+ * -+ * At this point we *must* have a zvrf because the vrf_create -+ * callback creates one. We *must* set the table id -+ * before the vrf_enable because of( at the very least ) -+ * static routes being delayed for installation until -+ * during the vrf_enable callbacks. -+ */ -+ zvrf = (struct zebra_vrf *)vrf->info; -+ zvrf->table_id = tableid; -+ -+ /* Enable the created VRF. */ -+ if (!vrf_enable(vrf)) { -+ flog_err(EC_LIB_INTERFACE, -+ "Failed to enable VRF %s id %u", name, -+ ifindex); -+ return; -+ } -+ } -+} -+ -+/* -+ * Note: on netlink systems, there should be a 1-to-1 mapping -+ * between interface names and ifindex values. -+ */ -+static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, -+ struct zebra_ns *zns) -+{ -+ struct interface *oifp; -+ -+ oifp = if_lookup_by_index_per_ns(zns, ifi_index); -+ if ((oifp != NULL) && (oifp != ifp)) { -+ if (ifi_index == IFINDEX_INTERNAL) -+ flog_err( -+ EC_LIB_INTERFACE, -+ "Netlink is setting interface %s ifindex to reserved internal value %u", -+ ifp->name, ifi_index); -+ else { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "interface index %d was renamed from %s to %s", -+ ifi_index, oifp->name, ifp->name); -+ if (if_is_up(oifp)) -+ flog_err( -+ EC_LIB_INTERFACE, -+ "interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!", -+ ifi_index, oifp->name, ifp->name); -+ if_delete_update(&oifp); -+ } -+ } -+ if_set_index(ifp, ifi_index); -+} -+ -+static inline void zebra_if_set_ziftype(struct interface *ifp, -+ enum zebra_iftype zif_type, -+ enum zebra_slave_iftype zif_slave_type) -+{ -+ struct zebra_if *zif; -+ -+ zif = (struct zebra_if *)ifp->info; -+ zif->zif_slave_type = zif_slave_type; -+ -+ if (zif->zif_type != zif_type) { -+ zif->zif_type = zif_type; -+ /* If the if_type has been set to bond initialize ES info -+ * against it. XXX - note that we don't handle the case where -+ * a zif changes from bond to non-bond; it is really -+ * an unexpected/error condition. -+ */ -+ zebra_evpn_if_init(zif); -+ } -+} -+ -+static void interface_update_hw_addr(struct zebra_dplane_ctx *ctx, -+ struct interface *ifp) -+{ -+ int i; -+ -+ ifp->hw_addr_len = dplane_ctx_get_ifp_hw_addr_len(ctx); -+ memcpy(ifp->hw_addr, dplane_ctx_get_ifp_hw_addr(ctx), ifp->hw_addr_len); -+ -+ for (i = 0; i < ifp->hw_addr_len; i++) -+ if (ifp->hw_addr[i] != 0) -+ break; -+ -+ if (i == ifp->hw_addr_len) -+ ifp->hw_addr_len = 0; -+} -+ -+static void interface_update_l2info(struct zebra_dplane_ctx *ctx, -+ struct interface *ifp, -+ enum zebra_iftype zif_type, int add, -+ ns_id_t link_nsid) -+{ -+ const struct zebra_l2info_vxlan *vxlan_info; -+ const struct zebra_l2info_gre *gre_info; -+ -+ switch (zif_type) { -+ case ZEBRA_IF_BRIDGE: -+ zebra_l2_bridge_add_update(ifp, -+ dplane_ctx_get_ifp_bridge_info(ctx)); -+ break; -+ case ZEBRA_IF_VLAN: -+ zebra_l2_vlanif_update(ifp, dplane_ctx_get_ifp_vlan_info(ctx)); -+ zebra_evpn_acc_bd_svi_set(ifp->info, NULL, -+ !!if_is_operative(ifp)); -+ break; -+ case ZEBRA_IF_VXLAN: -+ vxlan_info = dplane_ctx_get_ifp_vxlan_info(ctx); -+ zebra_l2_vxlanif_add_update(ifp, vxlan_info, add); -+ if (link_nsid != NS_UNKNOWN && vxlan_info->ifindex_link) -+ zebra_if_update_link(ifp, vxlan_info->ifindex_link, -+ link_nsid); -+ break; -+ case ZEBRA_IF_GRE: -+ gre_info = dplane_ctx_get_ifp_gre_info(ctx); -+ zebra_l2_greif_add_update(ifp, gre_info, add); -+ if (link_nsid != NS_UNKNOWN && gre_info->ifindex_link) -+ zebra_if_update_link(ifp, gre_info->ifindex_link, -+ link_nsid); -+ break; -+ case ZEBRA_IF_OTHER: -+ case ZEBRA_IF_VRF: -+ case ZEBRA_IF_MACVLAN: -+ case ZEBRA_IF_VETH: -+ case ZEBRA_IF_BOND: -+ case ZEBRA_IF_BOND_SLAVE: -+ break; -+ } -+} -+ -+static bool is_if_protodown_reason_only_frr(uint32_t rc_bitfield) -+{ -+ uint8_t frr_protodown_r_bit = if_netlink_get_frr_protodown_r_bit(); -+ -+ return (rc_bitfield == (((uint32_t)1) << frr_protodown_r_bit)); -+} -+ -+static void interface_if_protodown(struct interface *ifp, bool protodown, -+ uint32_t rc_bitfield) -+{ -+ struct zebra_if *zif = ifp->info; -+ bool old_protodown; -+ -+ /* -+ * Set our reason code to note it wasn't us. -+ * If the reason we got from the kernel is ONLY frr though, don't -+ * set it. -+ */ -+ COND_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_EXTERNAL, -+ protodown && rc_bitfield && -+ !is_if_protodown_reason_only_frr(rc_bitfield)); -+ -+ -+ old_protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); -+ if (protodown == old_protodown) -+ return; -+ -+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE) -+ zlog_debug("interface %s dplane change, protodown %s", -+ ifp->name, protodown ? "on" : "off"); -+ -+ /* Set protodown, respectively */ -+ COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown); -+ -+ if (zebra_evpn_is_es_bond_member(ifp)) { -+ /* Check it's not already being sent to the dplane first */ -+ if (protodown && -+ CHECK_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN)) { -+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "bond mbr %s protodown on recv'd but already sent protodown on to the dplane", -+ ifp->name); -+ return; -+ } -+ -+ if (!protodown && -+ CHECK_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN)) { -+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "bond mbr %s protodown off recv'd but already sent protodown off to the dplane", -+ ifp->name); -+ return; -+ } -+ -+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "bond mbr %s reinstate protodown %s in the dplane", -+ ifp->name, old_protodown ? "on" : "off"); -+ -+ if (old_protodown) -+ SET_FLAG(zif->flags, ZIF_FLAG_SET_PROTODOWN); -+ else -+ SET_FLAG(zif->flags, ZIF_FLAG_UNSET_PROTODOWN); -+ -+ dplane_intf_update(zif->ifp); -+ } -+} -+ -+static void if_sweep_protodown(struct zebra_if *zif) -+{ -+ bool protodown; -+ -+ protodown = !!ZEBRA_IF_IS_PROTODOWN(zif); -+ -+ if (!protodown) -+ return; -+ -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug("interface %s sweeping protodown %s reason 0x%x", -+ zif->ifp->name, protodown ? "on" : "off", -+ zif->protodown_rc); -+ -+ /* Only clear our reason codes, leave external if it was set */ -+ UNSET_FLAG(zif->protodown_rc, ZEBRA_PROTODOWN_ALL); -+ dplane_intf_update(zif->ifp); -+} -+ -+static void interface_bridge_vxlan_update(struct zebra_dplane_ctx *ctx, -+ struct interface *ifp) -+{ -+ const struct zebra_dplane_bridge_vlan_info *bvinfo; -+ -+ bvinfo = dplane_ctx_get_ifp_bridge_vlan_info(ctx); -+ -+ if (!(bvinfo->flags & DPLANE_BRIDGE_VLAN_INFO_PVID)) -+ return; -+ -+ if (IS_ZEBRA_DEBUG_DPLANE) -+ zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", bvinfo->vid, -+ ifp->name, ifp->ifindex); -+ -+ zebra_l2_vxlanif_update_access_vlan(ifp, bvinfo->vid); -+} -+ -+static void interface_bridge_vlan_update(struct zebra_dplane_ctx *ctx, -+ struct interface *ifp) -+{ -+ struct zebra_if *zif = ifp->info; -+ const struct zebra_dplane_bridge_vlan_info_array *bvarray; -+ struct zebra_dplane_bridge_vlan_info bvinfo; -+ bitfield_t old_vlan_bitmap; -+ uint16_t vid_range_start = 0; -+ int32_t i; -+ -+ /* cache the old bitmap addrs */ -+ old_vlan_bitmap = zif->vlan_bitmap; -+ /* create a new bitmap space for re-eval */ -+ bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX); -+ -+ /* Could we have multiple bridge vlan infos? */ -+ bvarray = dplane_ctx_get_ifp_bridge_vlan_info_array(ctx); -+ if (!bvarray) -+ return; -+ -+ for (i = 0; i < bvarray->count; i++) { -+ bvinfo = bvarray->array[i]; -+ -+ if (bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN) { -+ vid_range_start = bvinfo.vid; -+ continue; -+ } -+ -+ if (!(bvinfo.flags & DPLANE_BRIDGE_VLAN_INFO_RANGE_END)) -+ vid_range_start = bvinfo.vid; -+ -+ zebra_vlan_bitmap_compute(ifp, vid_range_start, bvinfo.vid); -+ } -+ -+ zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap); -+ bf_free(old_vlan_bitmap); -+} -+ -+static void interface_bridge_handling(struct zebra_dplane_ctx *ctx, -+ struct interface *ifp, -+ enum zebra_iftype zif_type) -+{ -+ struct zebra_if *zif; -+ -+ if (!ifp) { -+ zlog_warn("Cannot find bridge if %s(%u)", -+ dplane_ctx_get_ifname(ctx), -+ dplane_ctx_get_ifindex(ctx)); -+ return; -+ } -+ -+ if (IS_ZEBRA_IF_VXLAN(ifp)) -+ return interface_bridge_vxlan_update(ctx, ifp); -+ -+ /* -+ * build vlan bitmap associated with this interface if that -+ * device type is interested in the vlans -+ */ -+ zif = ifp->info; -+ if (bf_is_inited(zif->vlan_bitmap)) -+ interface_bridge_vlan_update(ctx, ifp); -+} -+ -+static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) -+{ -+ enum dplane_op_e op = dplane_ctx_get_op(ctx); -+ const char *name = dplane_ctx_get_ifname(ctx); -+ ns_id_t ns_id = dplane_ctx_get_ns_id(ctx); -+ ifindex_t ifindex = dplane_ctx_get_ifindex(ctx); -+ ifindex_t bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); -+ uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx); -+ enum zebra_iftype zif_type = dplane_ctx_get_ifp_zif_type(ctx); -+ struct interface *ifp; -+ struct zebra_ns *zns; -+ -+ zns = zebra_ns_lookup(ns_id); -+ if (!zns) { -+ zlog_err("Where is our namespace?"); -+ return; -+ } -+ -+ if (IS_ZEBRA_DEBUG_DPLANE) -+ zlog_debug("%s for %s(%u)", dplane_op2str(op), name, ifindex); -+ -+ ifp = if_lookup_by_name_per_ns(zns, name); -+ if (op == DPLANE_OP_INTF_DELETE) { -+ /* Delete interface notification from kernel */ -+ if (ifp == NULL) { -+ if (IS_ZEBRA_DEBUG_EVENT) -+ zlog_debug( -+ "Delete LINK received for unknown interface %s(%u)", -+ name, ifindex); -+ return; -+ } -+ -+ if (IS_ZEBRA_IF_BOND(ifp)) -+ zebra_l2if_update_bond(ifp, false); -+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) -+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, false); -+ /* Special handling for bridge or VxLAN interfaces. */ -+ if (IS_ZEBRA_IF_BRIDGE(ifp)) -+ zebra_l2_bridge_del(ifp); -+ else if (IS_ZEBRA_IF_VXLAN(ifp)) -+ zebra_l2_vxlanif_del(ifp); -+ -+ if_delete_update(&ifp); -+ -+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) -+ interface_vrf_change(op, ifindex, name, tableid, ns_id); -+ } else { -+ ifindex_t master_ifindex, bridge_ifindex, bond_ifindex, -+ link_ifindex; -+ enum zebra_slave_iftype zif_slave_type; -+ uint8_t bypass; -+ uint64_t flags; -+ vrf_id_t vrf_id; -+ uint32_t mtu; -+ ns_id_t link_nsid; -+ struct zebra_if *zif; -+ bool protodown, protodown_set, startup; -+ uint32_t rc_bitfield; -+ uint8_t old_hw_addr[INTERFACE_HWADDR_MAX]; -+ char *desc; -+ uint8_t family; -+ -+ /* If VRF, create or update the VRF structure itself. */ -+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) -+ interface_vrf_change(op, ifindex, name, tableid, ns_id); -+ -+ master_ifindex = dplane_ctx_get_ifp_master_ifindex(ctx); -+ zif_slave_type = dplane_ctx_get_ifp_zif_slave_type(ctx); -+ bridge_ifindex = dplane_ctx_get_ifp_bridge_ifindex(ctx); -+ bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); -+ bypass = dplane_ctx_get_ifp_bypass(ctx); -+ flags = dplane_ctx_get_ifp_flags(ctx); -+ vrf_id = dplane_ctx_get_ifp_vrf_id(ctx); -+ mtu = dplane_ctx_get_ifp_mtu(ctx); -+ link_ifindex = dplane_ctx_get_ifp_link_ifindex(ctx); -+ link_nsid = dplane_ctx_get_ifp_link_nsid(ctx); -+ protodown_set = dplane_ctx_get_ifp_protodown_set(ctx); -+ protodown = dplane_ctx_get_ifp_protodown(ctx); -+ rc_bitfield = dplane_ctx_get_ifp_rc_bitfield(ctx); -+ startup = dplane_ctx_get_ifp_startup(ctx); -+ desc = dplane_ctx_get_ifp_desc(ctx); -+ family = dplane_ctx_get_ifp_family(ctx); -+ -+#ifndef AF_BRIDGE -+ /* -+ * Work around to make free bsd happy at the moment -+ */ -+#define AF_BRIDGE 7 -+#endif -+ if (family == AF_BRIDGE) -+ return interface_bridge_handling(ctx, ifp, zif_type); -+ -+ if (ifp == NULL || -+ !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { -+ /* Add interface notification from kernel */ -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d sl_type %d master %u", -+ name, ifindex, vrf_id, zif_type, -+ zif_slave_type, master_ifindex); -+ -+ if (ifp == NULL) { -+ /* unknown interface */ -+ ifp = if_get_by_name(name, vrf_id, NULL); -+ } else { -+ /* pre-configured interface, learnt now */ -+ if (ifp->vrf->vrf_id != vrf_id) -+ if_update_to_new_vrf(ifp, vrf_id); -+ } -+ -+ /* Update interface information. */ -+ set_ifindex(ifp, ifindex, zns); -+ ifp->flags = flags; -+ ifp->mtu6 = ifp->mtu = mtu; -+ ifp->metric = 0; -+ ifp->speed = kernel_get_speed(ifp, NULL); -+ ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; -+ -+ /* Set interface type */ -+ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); -+ if (IS_ZEBRA_IF_VRF(ifp)) -+ SET_FLAG(ifp->status, -+ ZEBRA_INTERFACE_VRF_LOOPBACK); -+ -+ /* Update link. */ -+ zebra_if_update_link(ifp, link_ifindex, link_nsid); -+ -+ /* -+ * Just set the @link/lower-device ifindex. During -+ * nldump interfaces are not ordered in any fashion so -+ * we may end up getting upper devices before lower -+ * devices. We will setup the real linkage once the dump -+ * is complete. -+ */ -+ zif = (struct zebra_if *)ifp->info; -+ zif->link_ifindex = link_ifindex; -+ -+ ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx); -+ interface_update_hw_addr(ctx, ifp); -+ -+ /* Inform clients, install any configured addresses. */ -+ if_add_update(ifp); -+ -+ /* -+ * Extract and save L2 interface information, take -+ * additional actions. -+ */ -+ interface_update_l2info(ctx, ifp, zif_type, 1, -+ link_nsid); -+ if (IS_ZEBRA_IF_BOND(ifp)) -+ zebra_l2if_update_bond(ifp, true); -+ if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) -+ zebra_l2if_update_bridge_slave( -+ ifp, bridge_ifindex, ns_id, -+ ZEBRA_BRIDGE_NO_ACTION); -+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) -+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, -+ !!bypass); -+ -+ if (protodown_set) { -+ interface_if_protodown(ifp, protodown, -+ rc_bitfield); -+ if (startup) -+ if_sweep_protodown(zif); -+ } -+ -+ if (IS_ZEBRA_IF_BRIDGE(ifp)) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK ADD for %s(%u), vlan-aware %d", -+ name, ifp->ifindex, -+ IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( -+ zif)); -+ } -+ } else if (ifp->vrf->vrf_id != vrf_id) { -+ /* VRF change for an interface. */ -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK vrf-change for %s(%u) vrf_id %u -> %u", -+ name, ifp->ifindex, ifp->vrf->vrf_id, -+ vrf_id); -+ -+ if_handle_vrf_change(ifp, vrf_id); -+ } else { -+ bool was_bridge_slave, was_bond_slave; -+ uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION; -+ -+ zif = ifp->info; -+ -+ /* Interface update. */ -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK update for %s(%u) sl_type %d master %u", -+ name, ifp->ifindex, zif_slave_type, -+ master_ifindex); -+ -+ set_ifindex(ifp, ifindex, zns); -+ ifp->mtu6 = ifp->mtu = mtu; -+ ifp->metric = 0; -+ -+ /* -+ * Update interface type - NOTE: Only slave_type can -+ * change. -+ */ -+ was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); -+ was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp); -+ zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); -+ -+ memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX); -+ -+ /* Update link. */ -+ zebra_if_update_link(ifp, link_ifindex, link_nsid); -+ -+ ifp->ll_type = dplane_ctx_get_ifp_zltype(ctx); -+ interface_update_hw_addr(ctx, ifp); -+ -+ if (protodown_set) -+ interface_if_protodown(ifp, protodown, -+ rc_bitfield); -+ -+ if (if_is_no_ptm_operative(ifp)) { -+ bool is_up = if_is_operative(ifp); -+ -+ ifp->flags = flags; -+ if (!if_is_no_ptm_operative(ifp) || -+ CHECK_FLAG(zif->flags, -+ ZIF_FLAG_PROTODOWN)) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "Intf %s(%u) has gone DOWN", -+ name, ifp->ifindex); -+ if_down(ifp); -+ rib_update(RIB_UPDATE_KERNEL); -+ } else if (if_is_operative(ifp)) { -+ bool mac_updated = false; -+ -+ /* -+ * Must notify client daemons of new -+ * interface status. -+ */ -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "Intf %s(%u) PTM up, notifying clients", -+ name, ifp->ifindex); -+ if_up(ifp, !is_up); -+ -+ /* -+ * Update EVPN VNI when SVI MAC change -+ */ -+ if (memcmp(old_hw_addr, ifp->hw_addr, -+ INTERFACE_HWADDR_MAX)) -+ mac_updated = true; -+ if (IS_ZEBRA_IF_VLAN(ifp) && -+ mac_updated) { -+ struct interface *link_if; -+ -+ link_if = if_lookup_by_index_per_ns( -+ zebra_ns_lookup( -+ NS_DEFAULT), -+ link_ifindex); -+ if (link_if) -+ zebra_vxlan_svi_up( -+ ifp, link_if); -+ } else if (mac_updated && -+ IS_ZEBRA_IF_BRIDGE(ifp)) { -+ zlog_debug( -+ "Intf %s(%u) bridge changed MAC address", -+ name, ifp->ifindex); -+ chgflags = -+ ZEBRA_BRIDGE_MASTER_MAC_CHANGE; -+ } -+ } -+ } else { -+ ifp->flags = flags; -+ if (if_is_operative(ifp) && -+ !CHECK_FLAG(zif->flags, -+ ZIF_FLAG_PROTODOWN)) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "Intf %s(%u) has come UP", -+ name, ifp->ifindex); -+ if_up(ifp, true); -+ if (IS_ZEBRA_IF_BRIDGE(ifp)) -+ chgflags = -+ ZEBRA_BRIDGE_MASTER_UP; -+ } else { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "Intf %s(%u) has gone DOWN", -+ name, ifp->ifindex); -+ if_down(ifp); -+ rib_update(RIB_UPDATE_KERNEL); -+ } -+ } -+ -+ /* -+ * Extract and save L2 interface information, take -+ * additional actions. -+ */ -+ interface_update_l2info(ctx, ifp, zif_type, 0, -+ link_nsid); -+ if (IS_ZEBRA_IF_BRIDGE(ifp)) -+ zebra_l2if_update_bridge(ifp, chgflags); -+ if (IS_ZEBRA_IF_BOND(ifp)) -+ zebra_l2if_update_bond(ifp, true); -+ if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) -+ zebra_l2if_update_bridge_slave( -+ ifp, bridge_ifindex, ns_id, chgflags); -+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave) -+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, -+ !!bypass); -+ if (IS_ZEBRA_IF_BRIDGE(ifp)) { -+ if (IS_ZEBRA_DEBUG_KERNEL) -+ zlog_debug( -+ "RTM_NEWLINK update for %s(%u), vlan-aware %d", -+ name, ifp->ifindex, -+ IS_ZEBRA_IF_BRIDGE_VLAN_AWARE( -+ zif)); -+ } -+ } -+ -+ zif = ifp->info; -+ if (zif) { -+ XFREE(MTYPE_ZIF_DESC, zif->desc); -+ if (desc[0]) -+ zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc); -+ } -+ } -+} -+ - void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) - { - struct zebra_ns *zns; -@@ -1514,17 +2204,6 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) - } - - ifp = if_lookup_by_index_per_ns(zns, ifindex); -- if (ifp == NULL) { -- if (op != DPLANE_OP_INTF_NETCONFIG || -- (ifindex != -1 && ifindex != -2)) { -- if (IS_ZEBRA_DEBUG_KERNEL) -- zlog_debug( -- "%s: can't find ifp at nsid %u index %d", -- __func__, ns_id, ifindex); -- -- return; -- } -- } - - switch (op) { - case DPLANE_OP_INTF_ADDR_ADD: -@@ -1535,7 +2214,15 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx) - case DPLANE_OP_INTF_INSTALL: - case DPLANE_OP_INTF_UPDATE: - case DPLANE_OP_INTF_DELETE: -- zebra_if_update_ctx(ctx, ifp); -+ /* -+ * Queued from the dplane means it is something -+ * that we need to handle( create/delete the -+ * interface as needed ) -+ */ -+ if (dp_res == ZEBRA_DPLANE_REQUEST_QUEUED) -+ zebra_if_dplane_ifp_handling(ctx); -+ else -+ zebra_if_update_ctx(ctx, ifp); - break; - - case DPLANE_OP_INTF_NETCONFIG: -diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c -index 4cd84cada2..3756a4ab0c 100644 ---- a/zebra/kernel_netlink.c -+++ b/zebra/kernel_netlink.c -@@ -410,7 +410,7 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id, - case RTM_NEWLINK: - return netlink_link_change(h, ns_id, startup); - case RTM_DELLINK: -- return netlink_link_change(h, ns_id, startup); -+ return 0; - case RTM_NEWNEIGH: - case RTM_DELNEIGH: - case RTM_GETNEIGH: -@@ -482,6 +482,7 @@ static int dplane_netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id, - - case RTM_NEWLINK: - case RTM_DELLINK: -+ return netlink_link_change(h, ns_id, startup); - - default: - break; -@@ -1170,7 +1171,6 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), - h->nlmsg_type, h->nlmsg_len, - h->nlmsg_seq, h->nlmsg_pid); - -- - /* - * Ignore messages that maybe sent from - * other actors besides the kernel -@@ -1774,17 +1774,11 @@ void kernel_init(struct zebra_ns *zns) - * lead to confusion, so we need to convert the - * RTNLGRP_XXX to a bit position for ourself - */ -- groups = RTMGRP_LINK | -- RTMGRP_IPV4_ROUTE | -- RTMGRP_IPV4_IFADDR | -- RTMGRP_IPV6_ROUTE | -- RTMGRP_IPV6_IFADDR | -- RTMGRP_IPV4_MROUTE | -- RTMGRP_NEIGH | -- ((uint32_t) 1 << (RTNLGRP_IPV4_RULE - 1)) | -- ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) | -- ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1)) | -- ((uint32_t) 1 << (RTNLGRP_TC - 1)); -+ groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_IPV4_MROUTE | -+ RTMGRP_NEIGH | ((uint32_t)1 << (RTNLGRP_IPV4_RULE - 1)) | -+ ((uint32_t)1 << (RTNLGRP_IPV6_RULE - 1)) | -+ ((uint32_t)1 << (RTNLGRP_NEXTHOP - 1)) | -+ ((uint32_t)1 << (RTNLGRP_TC - 1)); - - dplane_groups = (RTMGRP_LINK | - RTMGRP_IPV4_IFADDR | -diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c -index f3462b9f22..98553edae6 100644 ---- a/zebra/kernel_socket.c -+++ b/zebra/kernel_socket.c -@@ -1482,6 +1482,14 @@ static void routing_socket(struct zebra_ns *zns) - thread_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL); - } - -+void interface_list_second(struct zebra_ns *zns) -+{ -+} -+ -+void interface_list_tunneldump(struct zebra_ns *zns) -+{ -+} -+ - /* Exported interface function. This function simply calls - routing_socket (). */ - void kernel_init(struct zebra_ns *zns) -diff --git a/zebra/rt.h b/zebra/rt.h -index 6f4dd48a54..3e91cdfffa 100644 ---- a/zebra/rt.h -+++ b/zebra/rt.h -@@ -99,6 +99,8 @@ extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); - * state. - */ - extern void interface_list(struct zebra_ns *zns); -+extern void interface_list_tunneldump(struct zebra_ns *zns); -+extern void interface_list_second(struct zebra_ns *zns); - extern void kernel_init(struct zebra_ns *zns); - extern void kernel_terminate(struct zebra_ns *zns, bool complete); - extern void macfdb_read(struct zebra_ns *zns); -diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c -index 135f065428..4cc4281c1e 100644 ---- a/zebra/rule_netlink.c -+++ b/zebra/rule_netlink.c -@@ -416,6 +416,7 @@ int netlink_rules_read(struct zebra_ns *zns) - - ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd, - &dp_info, 0, true); -+ - return ret; - } - -diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h -index c10482ed96..9f9496c8f4 100644 ---- a/zebra/zebra_dplane.h -+++ b/zebra/zebra_dplane.h -@@ -422,6 +422,19 @@ uint8_t dplane_ctx_get_ifp_family(const struct zebra_dplane_ctx *ctx); - struct zebra_vxlan_vni_array; - void dplane_ctx_set_ifp_vxlan_vni_array(struct zebra_dplane_ctx *ctx, - struct zebra_vxlan_vni_array *vniarray); -+ -+/* -+ * These defines mirror the values for bridge values in linux -+ * at this point since we only have a linux implementation -+ * we don't need to do any type of translation. Let's just -+ * pass these through and use them -+ */ -+#define DPLANE_BRIDGE_VLAN_INFO_PVID \ -+ (1 << 1) /* VLAN is PVID, ingress untagged */ -+#define DPLANE_BRIDGE_VLAN_INFO_RANGE_BEGIN \ -+ (1 << 3) /* VLAN is start of vlan range */ -+#define DPLANE_BRIDGE_VLAN_INFO_RANGE_END \ -+ (1 << 4) /* VLAN is end of vlan range */ - const struct zebra_vxlan_vni_array * - dplane_ctx_get_ifp_vxlan_vni_array(const struct zebra_dplane_ctx *ctx); - struct zebra_dplane_bridge_vlan_info { -diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c -index 07bbc6e3bc..4ad262a21d 100644 ---- a/zebra/zebra_l2.c -+++ b/zebra/zebra_l2.c -@@ -258,7 +258,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add) - * map slaves (if any) to the bridge. - */ - void zebra_l2_bridge_add_update(struct interface *ifp, -- struct zebra_l2info_bridge *bridge_info) -+ const struct zebra_l2info_bridge *bridge_info) - { - struct zebra_if *zif; - -@@ -293,7 +293,7 @@ void zebra_l2if_update_bridge(struct interface *ifp, uint8_t chgflags) - * VLAN Id and this cannot change. - */ - void zebra_l2_vlanif_update(struct interface *ifp, -- struct zebra_l2info_vlan *vlan_info) -+ const struct zebra_l2info_vlan *vlan_info) - { - struct zebra_if *zif; - -@@ -310,7 +310,7 @@ void zebra_l2_vlanif_update(struct interface *ifp, - * clients about GRE information. - */ - void zebra_l2_greif_add_update(struct interface *ifp, -- struct zebra_l2info_gre *gre_info, int add) -+ const struct zebra_l2info_gre *gre_info, int add) - { - struct zebra_if *zif; - struct in_addr old_vtep_ip; -@@ -337,7 +337,8 @@ void zebra_l2_greif_add_update(struct interface *ifp, - * IP and VLAN mapping, but the latter is handled separately. - */ - void zebra_l2_vxlanif_add_update(struct interface *ifp, -- struct zebra_l2info_vxlan *vxlan_info, int add) -+ const struct zebra_l2info_vxlan *vxlan_info, -+ int add) - { - struct zebra_if *zif; - struct in_addr old_vtep_ip; -diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h -index 8fef008f52..e3c5544f8f 100644 ---- a/zebra/zebra_l2.h -+++ b/zebra/zebra_l2.h -@@ -71,6 +71,18 @@ struct zebra_l2info_gre { - ns_id_t link_nsid; - }; - -+struct zebra_vxlan_vni { -+ vni_t vni; /* VNI */ -+ vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ -+ struct in_addr mcast_grp; -+ uint16_t flags; -+}; -+ -+struct zebra_vxlan_vni_array { -+ uint16_t count; -+ struct zebra_vxlan_vni vnis[0]; -+}; -+ - /* zebra L2 interface information - VXLAN interface */ - struct zebra_l2info_vxlan { - vni_t vni; /* VNI */ -@@ -108,17 +120,19 @@ extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave, - struct zebra_ns *zns); - extern void - zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave); --extern void zebra_l2_bridge_add_update(struct interface *ifp, -- struct zebra_l2info_bridge *bridge_info); -+extern void -+zebra_l2_bridge_add_update(struct interface *ifp, -+ const struct zebra_l2info_bridge *bridge_info); - extern void zebra_l2_bridge_del(struct interface *ifp); - extern void zebra_l2_vlanif_update(struct interface *ifp, -- struct zebra_l2info_vlan *vlan_info); -+ const struct zebra_l2info_vlan *vlan_info); - extern void zebra_l2_greif_add_update(struct interface *ifp, -- struct zebra_l2info_gre *vxlan_info, -+ const struct zebra_l2info_gre *vxlan_info, - int add); --extern void zebra_l2_vxlanif_add_update(struct interface *ifp, -- struct zebra_l2info_vxlan *vxlan_info, -- int add); -+extern void -+zebra_l2_vxlanif_add_update(struct interface *ifp, -+ const struct zebra_l2info_vxlan *vxlan_info, -+ int add); - extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, - vlanid_t access_vlan); - extern void zebra_l2_greif_del(struct interface *ifp); -diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c -index 7b076b8a4a..4714cdbff8 100644 ---- a/zebra/zebra_ns.c -+++ b/zebra/zebra_ns.c -@@ -38,6 +38,7 @@ - #include "rib.h" - #include "table_manager.h" - #include "zebra_errors.h" -+#include "zebra_dplane.h" - - extern struct zebra_privs_t zserv_privs; - -@@ -116,6 +117,35 @@ int zebra_ns_disabled(struct ns *ns) - return zebra_ns_disable_internal(zns, true); - } - -+void zebra_ns_startup_continue(struct zebra_dplane_ctx *ctx) -+{ -+ struct zebra_ns *zns = zebra_ns_lookup(dplane_ctx_get_ns_id(ctx)); -+ enum zebra_dplane_startup_notifications spot; -+ -+ if (!zns) { -+ zlog_err("%s: No Namespace associated with %u", __func__, -+ dplane_ctx_get_ns_id(ctx)); -+ return; -+ } -+ -+ spot = dplane_ctx_get_startup_spot(ctx); -+ -+ switch (spot) { -+ case ZEBRA_DPLANE_INTERFACES_READ: -+ interface_list_tunneldump(zns); -+ break; -+ case ZEBRA_DPLANE_TUNNELS_READ: -+ interface_list_second(zns); -+ break; -+ case ZEBRA_DPLANE_ADDRESSES_READ: -+ route_read(zns); -+ -+ kernel_read_pbr_rules(zns); -+ kernel_read_tc_qdisc(zns); -+ break; -+ } -+} -+ - /* Do global enable actions - open sockets, read kernel config etc. */ - int zebra_ns_enable(ns_id_t ns_id, void **info) - { -@@ -126,9 +156,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) - kernel_init(zns); - zebra_dplane_ns_enable(zns, true); - interface_list(zns); -- route_read(zns); -- kernel_read_pbr_rules(zns); -- kernel_read_tc_qdisc(zns); - - return 0; - } -diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h -index 7a0ffbc1ee..3d7d96c83f 100644 ---- a/zebra/zebra_ns.h -+++ b/zebra/zebra_ns.h -@@ -83,6 +83,8 @@ int zebra_ns_final_shutdown(struct ns *ns, - void **param_out __attribute__((unused))); - int zebra_ns_config_write(struct vty *vty, struct ns *ns); - -+void zebra_ns_startup_continue(struct zebra_dplane_ctx *ctx); -+ - #ifdef __cplusplus - } - #endif -diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index 201fc761ae..fd6df441c6 100644 ---- a/zebra/zebra_rib.c -+++ b/zebra/zebra_rib.c -@@ -4770,7 +4770,9 @@ static void rib_process_dplane_results(struct thread *thread) - case DPLANE_OP_NEIGH_TABLE_UPDATE: - case DPLANE_OP_GRE_SET: - case DPLANE_OP_NONE: -+ break; - case DPLANE_OP_STARTUP_STAGE: -+ zebra_ns_startup_continue(ctx); - break; - - } /* Dispatch by op code */ --- -2.17.1 - diff --git a/src/sonic-frr/patch/0019-zebra-remove-duplicated-nexthops-when-sending-fpm-msg.patch b/src/sonic-frr/patch/0019-zebra-remove-duplicated-nexthops-when-sending-fpm-msg.patch deleted file mode 100644 index 834ef899e72f..000000000000 --- a/src/sonic-frr/patch/0019-zebra-remove-duplicated-nexthops-when-sending-fpm-msg.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4aa1aace3e32039b668c04cd682b01e0397144ea Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E6=81=AD=E7=AE=80?= -Date: Wed, 26 Jul 2023 09:51:51 +0800 -Subject: [PATCH] zebra: remove duplicated nexthops when sending fpm msg -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When zebra send msg to fpm client, it doesn't handle duplicated nexthops especially, which means if zebra has a route with NUM1 recursive nexthops, each resolved to the same NUM2 connected nexthops, it will send to fpm client a route with NUM1*NUM2 nexthops. But actually there are only NUM2 useful nexthops, the left NUM1*NUM2-NUM2 nexthops are all duplicated nexthops. By the way, zebra has duplicated nexthop remove logic when sending msg to kernel. -Add duplicated nexthop remove logic to zebra when sending msg to fpm client. - -Signed-off-by: 恭简 - ---- - zebra/zebra_fpm_netlink.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c -index 06c45578a..231047143 100644 ---- a/zebra/zebra_fpm_netlink.c -+++ b/zebra/zebra_fpm_netlink.c -@@ -305,6 +305,8 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd, - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; -+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) -+ continue; - - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { - switch (nexthop->bh_type) { diff --git a/src/sonic-frr/patch/0020-zebra-Fix-non-notification-of-better-admin-won.patch b/src/sonic-frr/patch/0020-zebra-Fix-non-notification-of-better-admin-won.patch deleted file mode 100644 index 324242a48770..000000000000 --- a/src/sonic-frr/patch/0020-zebra-Fix-non-notification-of-better-admin-won.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 9513d3a158e493623a6bc1e5e3e44b6ed277ac28 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Tue, 14 Nov 2023 10:15:42 -0500 -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. - -Signed-off-by: Donald Sharp - -diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index 2c3bb28d6..d37fe98f8 100644 ---- a/zebra/zebra_rib.c -+++ b/zebra/zebra_rib.c -@@ -1227,6 +1227,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; - -@@ -1296,6 +1297,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; -@@ -1381,6 +1383,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 -@@ -1435,6 +1439,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 - diff --git a/src/sonic-frr/patch/0023-zebra-The-dplane_fpm_nl-return-path-leaks-memory.patch b/src/sonic-frr/patch/0023-zebra-The-dplane_fpm_nl-return-path-leaks-memory.patch deleted file mode 100644 index 980f1d87cdf7..000000000000 --- a/src/sonic-frr/patch/0023-zebra-The-dplane_fpm_nl-return-path-leaks-memory.patch +++ /dev/null @@ -1,58 +0,0 @@ -From bcb608d988b3de282ff832fd398e95080be8ad86 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Mon, 11 Dec 2023 13:41:36 -0500 -Subject: [PATCH] zebra: The dplane_fpm_nl return path leaks memory - -The route entry created when using a ctx to pass route -entry data backup to the master pthread in zebra is -being leaked. Prevent this from happening. - -Signed-off-by: Donald Sharp -(cherry picked from commit 7f9c5c7fa2d927033549a806fd9025a9459f22bc) - -diff --git a/zebra/rib.h b/zebra/rib.h -index a02a461e8..2e62148ea 100644 ---- a/zebra/rib.h -+++ b/zebra/rib.h -@@ -352,6 +352,8 @@ extern void _route_entry_dump(const char *func, union prefixconstptr pp, - union prefixconstptr src_pp, - const struct route_entry *re); - -+void zebra_rib_route_entry_free(struct route_entry *re); -+ - struct route_entry * - zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, uint8_t instance, - uint32_t flags, uint32_t nhe_id, uint32_t table_id, -diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c -index 6bdc15592..fc9e8c457 100644 ---- a/zebra/rt_netlink.c -+++ b/zebra/rt_netlink.c -@@ -1001,6 +1001,8 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, - re, ng, startup, ctx); - if (ng) - nexthop_group_delete(&ng); -+ if (ctx) -+ zebra_rib_route_entry_free(re); - } else { - /* - * I really don't see how this is possible -diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index 2b47e229a..1ff3d9854 100644 ---- a/zebra/zebra_rib.c -+++ b/zebra/zebra_rib.c -@@ -4178,6 +4178,12 @@ struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, - - return re; - } -+ -+void zebra_rib_route_entry_free(struct route_entry *re) -+{ -+ XFREE(MTYPE_RE, re); -+} -+ - /* - * Internal route-add implementation; there are a couple of different public - * signatures. Callers in this path are responsible for the memory they --- -2.17.1 - diff --git a/src/sonic-frr/patch/0024-lib-use-snmp-s-large-fd-sets-for-agentx.patch b/src/sonic-frr/patch/0024-lib-use-snmp-s-large-fd-sets-for-agentx.patch deleted file mode 100644 index ad3da2a0ad2e..000000000000 --- a/src/sonic-frr/patch/0024-lib-use-snmp-s-large-fd-sets-for-agentx.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 7e1857bf4315ae01e065fc8bc881338977c1ef87 Mon Sep 17 00:00:00 2001 -From: Edwin Brossette -Date: Fri, 8 Dec 2023 16:02:11 +0100 -Subject: [PATCH] lib: use snmp's large fd sets for agentx - -The maximum number of file descriptors in an fd set is limited by -FD_SETSIZE. This limitation is important because the libc macros -FD_SET(), FD_CLR() and FD_ISSET() will invoke a sigabort if the size of -the fd set given to them is above FD_SETSIZE. - -We ran into such a sigabort with bgpd because snmp can return an fd set -of size higher than FD_SETSIZE when calling snmp_select_info(). An -unfortunate FD_ISSET() call later causes the following abort: - -Received signal 6 at 1701115534 (si_addr 0xb94, PC 0x7ff289a16a7c); aborting... -/lib/x86_64-linux-gnu/libfrr.so.0(zlog_backtrace_sigsafe+0xb3) [0x7ff289d62bba] -/lib/x86_64-linux-gnu/libfrr.so.0(zlog_signal+0x1b4) [0x7ff289d62a1f] -/lib/x86_64-linux-gnu/libfrr.so.0(+0x102860) [0x7ff289da4860] -/lib/x86_64-linux-gnu/libc.so.6(+0x42520) [0x7ff2899c2520] -/lib/x86_64-linux-gnu/libc.so.6(pthread_kill+0x12c) [0x7ff289a16a7c] -/lib/x86_64-linux-gnu/libc.so.6(raise+0x16) [0x7ff2899c2476] -/lib/x86_64-linux-gnu/libc.so.6(abort+0xd3) [0x7ff2899a87f3] -/lib/x86_64-linux-gnu/libc.so.6(+0x896f6) [0x7ff289a096f6] -/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x2a) [0x7ff289ab676a] -/lib/x86_64-linux-gnu/libc.so.6(+0x1350c6) [0x7ff289ab50c6] -/lib/x86_64-linux-gnu/libc.so.6(+0x1366ab) [0x7ff289ab66ab] -/lib/x86_64-linux-gnu/libfrrsnmp.so.0(+0x36f5) [0x7ff2897736f5] -/lib/x86_64-linux-gnu/libfrrsnmp.so.0(+0x3c27) [0x7ff289773c27] -/lib/x86_64-linux-gnu/libfrr.so.0(thread_call+0x1c2) [0x7ff289dbe105] -/lib/x86_64-linux-gnu/libfrr.so.0(frr_run+0x257) [0x7ff289d56e69] -/usr/bin/bgpd(main+0x4f4) [0x560965c40488] -/lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7ff2899a9d90] -/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7ff2899a9e40] -/usr/bin/bgpd(_start+0x25) [0x560965c3e965] -in thread agentx_timeout scheduled from /build/make-pkg/output/_packages/cp-routing/src/lib/agentx.c:122 agentx_events_update() - -Also, the following error is logged by snmp just before the abort: -snmp[err]: Use snmp_sess_select_info2() for processing large file descriptors - -snmp uses a custom struct netsnmp_large_fd_set to work above the limit -imposed by FD_SETSIZE. It is noteworthy that, when calling -snmp_select_info() instead of snmp_select_info2(), snmp uses the same -code working with its custom, large structs, and copy/paste the result -to a regular, libc compatible fd_set. So there should be no downside -working with snmp_select_info2() instead of snmp_select_info(). - -Replace every use of the libc file descriptors sets by snmp's extended -file descriptors sets in agentx to acommodate for the high number of -file descriptors that can come out of snmp. This should prevent the -abort seen above. - -Signed-off-by: Edwin Brossette - -diff --git a/lib/agentx.c b/lib/agentx.c -index 5f6245980..be8277c53 100644 ---- a/lib/agentx.c -+++ b/lib/agentx.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "command.h" - #include "smux.h" -@@ -58,7 +59,7 @@ static void agentx_timeout(struct thread *t) - - static void agentx_read(struct thread *t) - { -- fd_set fds; -+ netsnmp_large_fd_set lfds; - int flags, new_flags = 0; - int nonblock = false; - struct listnode *ln = THREAD_ARG(t); -@@ -83,9 +84,9 @@ static void agentx_read(struct thread *t) - flog_err(EC_LIB_SYSTEM_CALL, "Failed to set snmp fd non blocking: %s(%d)", - strerror(errno), errno); - -- FD_ZERO(&fds); -- FD_SET(THREAD_FD(t), &fds); -- snmp_read(&fds); -+ netsnmp_large_fd_set_init(&lfds, FD_SETSIZE); -+ netsnmp_large_fd_setfd(t->u.fd, &lfds); -+ snmp_read2(&lfds); - - /* Reset the flag */ - if (!nonblock) { -@@ -100,6 +101,7 @@ static void agentx_read(struct thread *t) - - netsnmp_check_outstanding_agent_requests(); - agentx_events_update(); -+ netsnmp_large_fd_set_cleanup(&lfds); - } - - static void agentx_events_update(void) -@@ -107,15 +109,15 @@ static void agentx_events_update(void) - int maxfd = 0; - int block = 1; - struct timeval timeout = {.tv_sec = 0, .tv_usec = 0}; -- fd_set fds; -+ netsnmp_large_fd_set lfds; - struct listnode *ln; - struct thread **thr; - int fd, thr_fd; - - thread_cancel(&timeout_thr); - -- FD_ZERO(&fds); -- snmp_select_info(&maxfd, &fds, &timeout, &block); -+ netsnmp_large_fd_set_init(&lfds, FD_SETSIZE); -+ snmp_select_info2(&maxfd, &lfds, &timeout, &block); - - if (!block) { - thread_add_timer_tv(agentx_tm, agentx_timeout, NULL, &timeout, -@@ -133,7 +135,7 @@ static void agentx_events_update(void) - /* caught up */ - if (thr_fd == fd) { - struct listnode *nextln = listnextnode(ln); -- if (!FD_ISSET(fd, &fds)) { -+ if (!netsnmp_large_fd_is_set(fd, &lfds)) { - thread_cancel(thr); - XFREE(MTYPE_TMP, thr); - list_delete_node(events, ln); -@@ -143,7 +145,7 @@ static void agentx_events_update(void) - thr_fd = thr ? THREAD_FD(*thr) : -1; - } - /* need listener, but haven't hit one where it would be */ -- else if (FD_ISSET(fd, &fds)) { -+ else if (netsnmp_large_fd_is_set(fd, &lfds)) { - struct listnode *newln; - thr = XCALLOC(MTYPE_TMP, sizeof(struct thread *)); - -@@ -162,6 +164,7 @@ static void agentx_events_update(void) - list_delete_node(events, ln); - ln = nextln; - } -+ netsnmp_large_fd_set_cleanup(&lfds); - } - - /* AgentX node. */ --- -2.17.1 - diff --git a/src/sonic-frr/patch/0025-bgp-community-memory-leak-fix.patch b/src/sonic-frr/patch/0025-bgp-community-memory-leak-fix.patch index f8215e07f0f8..99ce9c3e8ca3 100644 --- a/src/sonic-frr/patch/0025-bgp-community-memory-leak-fix.patch +++ b/src/sonic-frr/patch/0025-bgp-community-memory-leak-fix.patch @@ -18,378 +18,16 @@ and the system will crash. Signed-off-by: Donald Sharp --- - bgpd/bgp_updgrp_adv.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c -index de2b3206b7..dcde4263da 100644 ---- a/bgpd/bgp_updgrp_adv.c -+++ b/bgpd/bgp_updgrp_adv.c -@@ -813,6 +813,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) - struct bgp *bgp; - struct attr attr; - struct attr *new_attr = &attr; -+ struct aspath *aspath; - struct prefix p; - struct peer *from; - struct bgp_dest *dest; -@@ -850,6 +851,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) - /* make coverity happy */ - assert(attr.aspath); - -+ aspath = attr.aspath; - attr.med = 0; - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - -@@ -1005,7 +1007,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) - } - } - -- aspath_unintern(&attr.aspath); -+ aspath_unintern(&aspath); - } - - /* --- -2.14.1 - - -From 07545c1879775f155f228c81393eed9697b699de Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Sat, 2 Mar 2024 09:42:30 -0500 -Subject: [PATCH 2/3] bgpd: Include unsuppress-map as a valid outgoing policy - -If unsuppress-map is setup for outgoing peers, consider that -policy is being applied as for RFC 8212. - -Signed-off-by: Donald Sharp ---- - bgpd/bgp_route.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index 473168d9be..fb14fc7f20 100644 ---- a/bgpd/bgp_route.c -+++ b/bgpd/bgp_route.c -@@ -5816,10 +5816,10 @@ bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter) - if (peer->sort == BGP_PEER_IBGP) - return true; - -- if (peer->sort == BGP_PEER_EBGP -- && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) -- || FILTER_LIST_OUT_NAME(filter) -- || DISTRIBUTE_OUT_NAME(filter))) -+ if (peer->sort == BGP_PEER_EBGP && -+ (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) || -+ FILTER_LIST_OUT_NAME(filter) || DISTRIBUTE_OUT_NAME(filter) || -+ UNSUPPRESS_MAP_NAME(filter))) - return true; - return false; - } --- -2.14.1 - - -From e3493d5be0156fa9c8c522b818ae6448dbe371f2 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Sat, 2 Mar 2024 09:50:38 -0500 -Subject: [PATCH 3/3] bgpd: Ensure community data is freed in some cases. - -Customer has this valgrind trace: - -Direct leak of 2829120 byte(s) in 70728 object(s) allocated from: - 0 in community_new ../bgpd/bgp_community.c:39 - 1 in community_uniq_sort ../bgpd/bgp_community.c:170 - 2 in route_set_community ../bgpd/bgp_routemap.c:2342 - 3 in route_map_apply_ext ../lib/routemap.c:2673 - 4 in subgroup_announce_check ../bgpd/bgp_route.c:2367 - 5 in subgroup_process_announce_selected ../bgpd/bgp_route.c:2914 - 6 in group_announce_route_walkcb ../bgpd/bgp_updgrp_adv.c:199 - 7 in hash_walk ../lib/hash.c:285 - 8 in update_group_af_walk ../bgpd/bgp_updgrp.c:2061 - 9 in group_announce_route ../bgpd/bgp_updgrp_adv.c:1059 - 10 in bgp_process_main_one ../bgpd/bgp_route.c:3221 - 11 in bgp_process_wq ../bgpd/bgp_route.c:3221 - 12 in work_queue_run ../lib/workqueue.c:282 - -The above leak detected by valgrind was from a screenshot so I copied it -by hand. Any mistakes in line numbers are purely from my transcription. -Additionally this is against a slightly modified 8.5.1 version of FRR. -Code inspection of 8.5.1 -vs- latest master shows the same problem -exists. Code should be able to be followed from there to here. - -What is happening: - -There is a route-map being applied that modifes the outgoing community -to a peer. This is saved in the attr copy created in -subgroup_process_announce_selected. This community pointer is not -interned. So the community->refcount is still 0. Normally when -a prefix is announced, the attr and the prefix are placed on a -adjency out structure where the attribute is interned. This will -cause the community to be saved in the community hash list as well. -In a non-normal operation when the decision to send is aborted after -the route-map application, the attribute is just dropped and the -pointer to the community is just dropped too, leading to situations -where the memory is leaked. The usage of bgp suppress-fib would -would be a case where the community is caused to be leaked. -Additionally the previous commit where an unsuppress-map is used -to modify the outgoing attribute but since unsuppress-map was -not considered part of outgoing policy the attribute would be dropped as -well. This pointer drop also extends to any dynamically allocated -memory saved by the attribute pointer that was not interned yet as well. - -So let's modify the return case where the decision is made to -not send the prefix to the peer to always just flush the attribute -to ensure memory is not leaked. - -Fixes: #15459 -Signed-off-by: Donald Sharp ---- - bgpd/bgp_conditional_adv.c | 5 ++-- - bgpd/bgp_route.c | 30 +++++++++++++----------- - bgpd/bgp_updgrp.h | 2 +- - bgpd/bgp_updgrp_adv.c | 58 +++++++++++++++++++++++++--------------------- - 4 files changed, 51 insertions(+), 44 deletions(-) - -diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c -index 24d822a745..edb9bc8bb7 100644 ---- a/bgpd/bgp_conditional_adv.c -+++ b/bgpd/bgp_conditional_adv.c -@@ -135,8 +135,9 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, - if (update_type == UPDATE_TYPE_ADVERTISE && - subgroup_announce_check(dest, pi, subgrp, dest_p, - &attr, &advmap_attr)) { -- bgp_adj_out_set_subgroup(dest, subgrp, &attr, -- pi); -+ if (!bgp_adj_out_set_subgroup(dest, subgrp, -+ &attr, pi)) -+ bgp_attr_flush(&attr); - } else { - /* If default originate is enabled for - * the peer, do not send explicit diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index fb14fc7f20..2976042dda 100644 +index fc776a4fd..a0113c04e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c -@@ -2879,7 +2879,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, - { - const struct prefix *p; - struct peer *onlypeer; -- struct attr attr; -+ struct attr attr = {0}, *pattr = &attr; - afi_t afi; - safi_t safi; - struct bgp *bgp; -@@ -2900,7 +2900,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, +@@ -3012,7 +3012,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, PEER_STATUS_ORF_WAIT_REFRESH)) return; - + - memset(&attr, 0, sizeof(attr)); + memset(pattr, 0, sizeof(*pattr)); /* It's initialized in bgp_announce_check() */ - - /* Announcement to the subgroup. If the route is filtered withdraw it. -@@ -2911,32 +2911,34 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, - advertise = bgp_check_advertise(bgp, dest); - - if (selected) { -- if (subgroup_announce_check(dest, selected, subgrp, p, &attr, -+ if (subgroup_announce_check(dest, selected, subgrp, p, pattr, - NULL)) { - /* Route is selected, if the route is already installed - * in FIB, then it is advertised - */ - if (advertise) { - if (!bgp_check_withdrawal(bgp, dest)) { -- struct attr *adv_attr = -- bgp_attr_intern(&attr); -- -- bgp_adj_out_set_subgroup(dest, subgrp, -- adv_attr, -- selected); -- } else -+ if (!bgp_adj_out_set_subgroup( -+ dest, subgrp, pattr, -+ selected)) -+ bgp_attr_flush(pattr); -+ } else { - bgp_adj_out_unset_subgroup( - dest, subgrp, 1, addpath_tx_id); -- } -- } else -+ bgp_attr_flush(pattr); -+ } -+ } else -+ bgp_attr_flush(pattr); -+ } else { - bgp_adj_out_unset_subgroup(dest, subgrp, 1, - addpath_tx_id); -+ bgp_attr_flush(pattr); -+ } - } - - /* If selected is NULL we must withdraw the path using addpath_tx_id */ -- else { -+ else - bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id); -- } - } - - /* -diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h -index e27c1e7b67..b7b6aa07e9 100644 ---- a/bgpd/bgp_updgrp.h -+++ b/bgpd/bgp_updgrp.h -@@ -458,7 +458,7 @@ extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp, - extern void bgp_adj_out_remove_subgroup(struct bgp_dest *dest, - struct bgp_adj_out *adj, - struct update_subgroup *subgrp); --extern void bgp_adj_out_set_subgroup(struct bgp_dest *dest, -+extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, - struct update_subgroup *subgrp, - struct attr *attr, - struct bgp_path_info *path); -diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c -index dcde4263da..7902d40bd9 100644 ---- a/bgpd/bgp_updgrp_adv.c -+++ b/bgpd/bgp_updgrp_adv.c -@@ -454,7 +454,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, - return next; - } - --void bgp_adj_out_set_subgroup(struct bgp_dest *dest, -+bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, - struct update_subgroup *subgrp, struct attr *attr, - struct bgp_path_info *path) - { -@@ -474,7 +474,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, - bgp = SUBGRP_INST(subgrp); - - if (DISABLE_BGP_ANNOUNCE) -- return; -+ return false; - - /* Look for adjacency information. */ - adj = adj_lookup( -@@ -490,7 +490,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, - bgp_addpath_id_for_peer(peer, afi, safi, - &path->tx_addpath)); - if (!adj) -- return; -+ return false; - - subgrp->pscount++; - } -@@ -529,7 +529,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, - * will never be able to coalesce the 3rd peer down - */ - subgrp->version = MAX(subgrp->version, dest->version); -- return; -+ return false; - } - - if (adj->adv) -@@ -576,6 +576,8 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, - bgp_adv_fifo_add_tail(&subgrp->sync->update, adv); - - subgrp->version = MAX(subgrp->version, dest->version); -+ -+ return true; - } - - /* The only time 'withdraw' will be false is if we are sending -@@ -668,7 +670,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp, - { - struct bgp_dest *dest; - struct bgp_path_info *ri; -- struct attr attr; -+ struct attr attr = {0}, *pattr = &attr; - struct peer *peer; - afi_t afi; - safi_t safi; -@@ -712,24 +714,25 @@ void subgroup_announce_table(struct update_subgroup *subgrp, - continue; - - if (subgroup_announce_check(dest, ri, subgrp, dest_p, -- &attr, NULL)) { -+ pattr, NULL)) { - /* Check if route can be advertised */ - if (advertise) { - if (!bgp_check_withdrawal(bgp, dest)) { -- struct attr *adv_attr = -- bgp_attr_intern(&attr); -- -- bgp_adj_out_set_subgroup( -- dest, subgrp, adv_attr, -- ri); -- } else -+ if (!bgp_adj_out_set_subgroup( -+ dest, subgrp, pattr, -+ ri)) -+ bgp_attr_flush(pattr); -+ } else { - bgp_adj_out_unset_subgroup( - dest, subgrp, 1, - bgp_addpath_id_for_peer( - peer, afi, - safi_rib, - &ri->tx_addpath)); -- } -+ bgp_attr_flush(pattr); -+ } -+ } else -+ bgp_attr_flush(pattr); - } else { - /* If default originate is enabled for - * the peer, do not send explicit -@@ -748,6 +751,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp, - bgp_addpath_id_for_peer( - peer, afi, safi_rib, - &ri->tx_addpath)); -+ bgp_attr_flush(pattr); - } - } - } -@@ -811,7 +815,7 @@ void subgroup_announce_route(struct update_subgroup *subgrp) - void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) - { - struct bgp *bgp; -- struct attr attr; -+ struct attr attr = {0}; - struct attr *new_attr = &attr; - struct aspath *aspath; - struct prefix p; -@@ -952,18 +956,18 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) - if (dest) { - for (pi = bgp_dest_get_bgp_path_info(dest); pi; - pi = pi->next) { -- if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) -- if (subgroup_announce_check( -- dest, pi, subgrp, -- bgp_dest_get_prefix(dest), -- &attr, NULL)) { -- struct attr *default_attr = -- bgp_attr_intern(&attr); -- -- bgp_adj_out_set_subgroup( -- dest, subgrp, -- default_attr, pi); -- } -+ if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) -+ continue; -+ -+ if (subgroup_announce_check( -+ dest, pi, subgrp, -+ bgp_dest_get_prefix(dest), &attr, -+ NULL)) { -+ if (!bgp_adj_out_set_subgroup( -+ dest, subgrp, &attr, pi)) -+ bgp_attr_flush(&attr); -+ } else -+ bgp_attr_flush(&attr); - } - bgp_dest_unlock_node(dest); - } --- -2.14.1 + /* Announcement to the subgroup. If the route is filtered withdraw it. diff --git a/src/sonic-frr/patch/0026-bgp-fib-suppress-announce-fix.patch b/src/sonic-frr/patch/0026-bgp-fib-suppress-announce-fix.patch deleted file mode 100644 index a6e9d4d4633e..000000000000 --- a/src/sonic-frr/patch/0026-bgp-fib-suppress-announce-fix.patch +++ /dev/null @@ -1,122 +0,0 @@ -From bf292bfd8b4e2d7ba181ce6efde4e43e066d1a88 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 28 Mar 2024 12:25:05 -0400 -Subject: [PATCH 1/2] bgpd: Note when receiving but not understanding a route - notification - -When BGP has been asked to wait for FIB installation, on route -removal a return call is likely to not have the dest since BGP -will have cleaned up the node, entirely. Let's just note that -the prefix cannot be found if debugs are turned on and move on. - -Signed-off-by: Donald Sharp ---- - bgpd/bgp_zebra.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index efcf497850..ff79746b4c 100644 ---- a/bgpd/bgp_zebra.c -+++ b/bgpd/bgp_zebra.c -@@ -2610,8 +2610,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient, - /* Find the bgp route node */ - dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p, - &bgp->vrf_prd); -- if (!dest) -+ if (!dest) { -+ if (BGP_DEBUG(zebra, ZEBRA)) -+ zlog_debug("%s: %pFX does not exist in the BGP table, nothing to do for %u", -+ __func__, &p, note); - return -1; -+ } - - switch (note) { - case ZAPI_ROUTE_INSTALLED: --- -2.17.1 - - -From ada2e1099373e69e0eb29f4b1f3ba79c0cacf75a Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 28 Mar 2024 12:27:38 -0400 -Subject: [PATCH 2/2] bgpd: Arrange peer notification to after zebra announce - -Currently BGP attempts to send route change information -to it's peers *before* the route is installed into zebra. -This creates a bug in suppress-fib-pending in the following -scenario: - -a) bgp suppress-fib-pending and bgp has a route with -2 way ecmp. -b) bgp receives a route withdraw from peer 1. BGP -will send the route to zebra and mark the route as -FIB_INSTALL_PENDING. -c) bgp receives a route withdraw from peer 2. BGP -will see the route has the FIB_INSTALL_PENDING and -not send the withdrawal of the route to the peer. -bgp will then send the route deletion to zebra and -clean up the bgp_path_info's. - -At this point BGP is stuck where it has not sent -a route withdrawal to downstream peers. - -Let's modify the code in bgp_process_main_one to -send the route notification to zebra first before -attempting to announce the route. The route withdrawal -will remove the FIB_INSTALL_PENDING flag from the dest -and this will allow group_announce_route to believe -it can send the route withdrawal. - -For the master branch this is ok because the recent -backpressure commits are in place and nothing is going -to change from an ordering perspective in that regards. -Ostensibly this fix is also for operators of Sonic and -will be backported to the 8.5 branch as well. This will -change the order of the send to peers to be after the -zebra installation but sonic users are using suppress-fib-pending -anyways so updates won't go out until rib ack has been -received anyways. - -Signed-off-by: Donald Sharp ---- - bgpd/bgp_route.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index 2976042dda..fbff57634a 100644 ---- a/bgpd/bgp_route.c -+++ b/bgpd/bgp_route.c -@@ -3297,14 +3297,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - } - #endif - -- group_announce_route(bgp, afi, safi, dest, new_select); -- -- /* unicast routes must also be annouced to labeled-unicast update-groups -- */ -- if (safi == SAFI_UNICAST) -- group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest, -- new_select); -- - /* FIB update. */ - if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) - && !bgp_option_check(BGP_OPT_NO_FIB)) { -@@ -3334,6 +3326,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - } - } - -+ group_announce_route(bgp, afi, safi, dest, new_select); -+ -+ /* unicast routes must also be annouced to labeled-unicast update-groups -+ */ -+ if (safi == SAFI_UNICAST) -+ group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest, -+ new_select); -+ -+ - bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select, - old_select); - --- -2.17.1 - diff --git a/src/sonic-frr/patch/0027-lib-Do-not-convert-EVPN-prefixes-into-IPv4-IPv6-if-n.patch b/src/sonic-frr/patch/0027-lib-Do-not-convert-EVPN-prefixes-into-IPv4-IPv6-if-n.patch deleted file mode 100644 index fd9ec4608dff..000000000000 --- a/src/sonic-frr/patch/0027-lib-Do-not-convert-EVPN-prefixes-into-IPv4-IPv6-if-n.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 37204cdc64999f8215deb99d4a5aa1a4222389af Mon Sep 17 00:00:00 2001 -From: Donatas Abraitis -Date: Thu, 15 Feb 2024 12:07:43 +0200 -Subject: [PATCH] lib: Do not convert EVPN prefixes into IPv4/IPv6 if not - needed - -Convert only when this is really needed, e.g. `match ip address prefix-list ...`. - -Otherwise, we can't have mixed match clauses, like: - -``` -match ip address prefix-list p1 -match evpn route-type prefix -``` - -This won't work, because the prefix is already converted, and we can't extract -route type, vni, etc. from the original EVPN prefix. - -Signed-off-by: Donatas Abraitis -(cherry picked from commit 439b739495e86912c8b9ec36b84e55311c549ba0) - -diff --git a/lib/routemap.c b/lib/routemap.c -index 683943eb6d..ed7c4ed72c 100644 ---- a/lib/routemap.c -+++ b/lib/routemap.c -@@ -2553,7 +2553,6 @@ route_map_result_t route_map_apply_ext(struct route_map *map, - struct route_map_index *index = NULL; - struct route_map_rule *set = NULL; - bool skip_match_clause = false; -- struct prefix conv; - - if (recursion > RMAP_RECURSION_LIMIT) { - flog_warn( -@@ -2571,27 +2570,14 @@ route_map_result_t route_map_apply_ext(struct route_map *map, - - map->applied++; - -- /* -- * Handling for matching evpn_routes in the prefix table. -- * -- * We convert type2/5 prefix to ipv4/6 prefix to do longest -- * prefix matching on. -- */ - if (prefix->family == AF_EVPN) { -- if (evpn_prefix2prefix(prefix, &conv) != 0) { -- zlog_debug( -- "Unable to convert EVPN prefix %pFX into IPv4/IPv6 prefix. Falling back to non-optimized route-map lookup", -- prefix); -- } else { -- zlog_debug( -- "Converted EVPN prefix %pFX into %pFX for optimized route-map lookup", -- prefix, &conv); -- -- prefix = &conv; -- } -+ index = map->head; -+ } else { -+ skip_match_clause = true; -+ index = route_map_get_index(map, prefix, match_object, -+ &match_ret); - } - -- index = route_map_get_index(map, prefix, match_object, &match_ret); - if (index) { - index->applied++; - if (rmap_debug) -@@ -2615,7 +2601,6 @@ route_map_result_t route_map_apply_ext(struct route_map *map, - ret = RMAP_DENYMATCH; - goto route_map_apply_end; - } -- skip_match_clause = true; - - for (; index; index = index->next) { - if (!skip_match_clause) { --- -2.17.1 - diff --git a/src/sonic-frr/patch/0029-zebra-nhg-fix-on-intf-up.patch b/src/sonic-frr/patch/0029-zebra-nhg-fix-on-intf-up.patch deleted file mode 100644 index 64e8ac5d5713..000000000000 --- a/src/sonic-frr/patch/0029-zebra-nhg-fix-on-intf-up.patch +++ /dev/null @@ -1,338 +0,0 @@ -From 4a58bc9e856c4ca953474548d61f06aad2fdf45b Mon Sep 17 00:00:00 2001 -From: Ashwini Reddy -Date: Wed, 19 Apr 2023 11:35:25 -0700 -Subject: [PATCH 1/3] zebra: re-install nhg on interface up - -Intermittently zebra and kernel are out of sync -when interface flaps and the add's/dels are in -same processing queue and zebra assumes no change in nexthop. -Hence we need to bring in a reinstall to kernel -of the nexthops and routes to sync their states. - -Upon interface flap kernel would have deleted NHGs -associated to a interface (the one flapped), -zebra retains NHGs for 3 mins even though upper -layer protocol removes the nexthops (associated NHG). -As part of interface address add , -re-add singleton NHGs associated to interface. - -Ticket: #3173663 -Issue: 3173663 - -Signed-off-by: Ashwini Reddy -Signed-off-by: Chirag Shah ---- - lib/nexthop.c | 9 +++++++++ - lib/nexthop.h | 3 +++ - zebra/redistribute.c | 4 ++++ - zebra/zebra_nhg.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ - zebra/zebra_nhg.h | 1 + - 5 files changed, 63 insertions(+) - -diff --git a/lib/nexthop.c b/lib/nexthop.c -index 52679388fd..e3bdbfb9e8 100644 ---- a/lib/nexthop.c -+++ b/lib/nexthop.c -@@ -1093,3 +1093,12 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea, - } - return -1; - } -+ -+bool nexthop_is_ifindex_type(const struct nexthop *nh) -+{ -+ if (nh->type == NEXTHOP_TYPE_IFINDEX || -+ nh->type == NEXTHOP_TYPE_IPV4_IFINDEX || -+ nh->type == NEXTHOP_TYPE_IPV6_IFINDEX) -+ return true; -+ return false; -+} -diff --git a/lib/nexthop.h b/lib/nexthop.h -index f6fb6ec2b7..a52ae02172 100644 ---- a/lib/nexthop.h -+++ b/lib/nexthop.h -@@ -260,6 +260,9 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, - extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, - struct nexthop *rparent); - -+/* Check nexthop of IFINDEX type */ -+extern bool nexthop_is_ifindex_type(const struct nexthop *nh); -+ - /* - * Parse one or more backup index values, as comma-separated numbers, - * into caller's array of uint8_ts. The array must be NEXTHOP_MAX_BACKUPS -diff --git a/zebra/redistribute.c b/zebra/redistribute.c -index 4a8fe938ed..fccbee7d85 100644 ---- a/zebra/redistribute.c -+++ b/zebra/redistribute.c -@@ -561,6 +561,10 @@ void zebra_interface_address_add_update(struct interface *ifp, - client, ifp, ifc); - } - } -+ /* interface associated NHGs may have been deleted, -+ * re-sync zebra -> dplane NHGs -+ */ -+ zebra_interface_nhg_reinstall(ifp); - } - - /* Interface address deletion. */ -diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c -index 54c66fbf18..753efef7f8 100644 ---- a/zebra/zebra_nhg.c -+++ b/zebra/zebra_nhg.c -@@ -3003,6 +3003,12 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe) - /* Resolve it first */ - nhe = zebra_nhg_resolve(nhe); - -+ if (zebra_nhg_set_valid_if_active(nhe)) { -+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) -+ zlog_debug("%s: valid flag set for nh %pNG", __func__, -+ nhe); -+ } -+ - /* Make sure all depends are installed/queued */ - frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) { - zebra_nhg_install_kernel(rb_node_dep->nhe); -@@ -3586,3 +3592,43 @@ static ssize_t printfrr_nhghe(struct fbuf *buf, struct printfrr_eargs *ea, - ret += bputs(buf, "]"); - return ret; - } -+ -+/* -+ * On interface add the nexthop that resolves to this intf needs -+ * a re-install. There are following scenarios when the nexthop group update -+ * gets skipped: -+ * 1. When upper level protocol sends removal of NHG, there is -+ * timer running to keep NHG for 180 seconds, during this interval, same route -+ * with same set of nexthops installation is given , the same NHG is used -+ * but since NHG is not reinstalled on interface address add, it is not aware -+ * in Dplan/Kernel. -+ * 2. Due to a quick port flap due to interface add and delete -+ * to be processed in same queue one after another. Zebra believes that -+ * there is no change in nhg in this case. Hence this re-install will -+ * make sure the nexthop group gets updated to Dplan/Kernel. -+ */ -+void zebra_interface_nhg_reinstall(struct interface *ifp) -+{ -+ struct nhg_connected *rb_node_dep = NULL; -+ struct zebra_if *zif = ifp->info; -+ struct nexthop *nh; -+ -+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) -+ zlog_debug( -+ "%s: Installing interface %s associated NHGs into kernel", -+ __func__, ifp->name); -+ -+ frr_each (nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) { -+ nh = rb_node_dep->nhe->nhg.nexthop; -+ if (zebra_nhg_set_valid_if_active(rb_node_dep->nhe)) { -+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) -+ zlog_debug( -+ "%s: Setting the valid flag for nhe %pNG, interface: %s", -+ __func__, rb_node_dep->nhe, ifp->name); -+ } -+ /* Check for singleton NHG associated to interface */ -+ if (nexthop_is_ifindex_type(nh) && -+ zebra_nhg_depends_is_empty(rb_node_dep->nhe)) -+ zebra_nhg_install_kernel(rb_node_dep->nhe); -+ } -+} -diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h -index 9b925bf10f..18914b7856 100644 ---- a/zebra/zebra_nhg.h -+++ b/zebra/zebra_nhg.h -@@ -374,6 +374,7 @@ extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, - /* Dataplane install/uninstall */ - extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe); - extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe); -+extern void zebra_interface_nhg_reinstall(struct interface *ifp); - - /* Forward ref of dplane update context type */ - struct zebra_dplane_ctx; --- -2.17.1 - - -From 2b99f5ccf7768eff1393e07db2b77abc104dbbd7 Mon Sep 17 00:00:00 2001 -From: Chirag Shah -Date: Fri, 28 Apr 2023 19:09:55 -0700 -Subject: [PATCH 2/3] zebra:re-install dependent nhgs on interface up - -Upon interface up associated singleton NHG's -dependent NHGs needs to be reinstalled as -kernel would have deleted if there is no route -referencing it. - -Ticket:#3416477 -Issue:3416477 -Testing Done: -flap interfaces which are part of route NHG, -upon interfaces up event, NHGs are resynced -into dplane. - -Signed-off-by: Chirag Shah ---- - zebra/zebra_nhg.c | 43 ++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 38 insertions(+), 5 deletions(-) - -diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c -index 753efef7f8..e5efbf8d5f 100644 ---- a/zebra/zebra_nhg.c -+++ b/zebra/zebra_nhg.c -@@ -1140,13 +1140,23 @@ static void zebra_nhg_handle_uninstall(struct nhg_hash_entry *nhe) - zebra_nhg_free(nhe); - } - --static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe) -+static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe, bool install) - { - /* Update validity of groups depending on it */ - struct nhg_connected *rb_node_dep; - -- frr_each_safe(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) -+ frr_each_safe (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) { - zebra_nhg_set_valid(rb_node_dep->nhe); -+ /* install dependent NHG into kernel */ -+ if (install) { -+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) -+ zlog_debug( -+ "%s nh id %u (flags 0x%x) associated dependent NHG %pNG install", -+ __func__, nhe->id, nhe->flags, -+ rb_node_dep->nhe); -+ zebra_nhg_install_kernel(rb_node_dep->nhe); -+ } -+ } - } - - /* -@@ -3035,7 +3045,7 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe) - break; - case ZEBRA_DPLANE_REQUEST_SUCCESS: - SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); -- zebra_nhg_handle_install(nhe); -+ zebra_nhg_handle_install(nhe, false); - break; - } - } -@@ -3109,7 +3119,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) - if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { - SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); - SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); -- zebra_nhg_handle_install(nhe); -+ zebra_nhg_handle_install(nhe, true); - - /* If daemon nhg, send it an update */ - if (PROTO_OWNED(nhe)) -@@ -3628,7 +3638,30 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) - } - /* Check for singleton NHG associated to interface */ - if (nexthop_is_ifindex_type(nh) && -- zebra_nhg_depends_is_empty(rb_node_dep->nhe)) -+ zebra_nhg_depends_is_empty(rb_node_dep->nhe)) { -+ struct nhg_connected *rb_node_dependent; -+ -+ if (IS_ZEBRA_DEBUG_NHG) -+ zlog_debug( -+ "%s install nhe %pNG nh type %u flags 0x%x", -+ __func__, rb_node_dep->nhe, nh->type, -+ rb_node_dep->nhe->flags); - zebra_nhg_install_kernel(rb_node_dep->nhe); -+ -+ /* mark depedent uninstall, when interface associated -+ * singleton is installed, install depedent -+ */ -+ frr_each_safe (nhg_connected_tree, -+ &rb_node_dep->nhe->nhg_dependents, -+ rb_node_dependent) { -+ if (IS_ZEBRA_DEBUG_NHG) -+ zlog_debug( -+ "%s dependent nhe %pNG unset installed flag", -+ __func__, -+ rb_node_dependent->nhe); -+ UNSET_FLAG(rb_node_dependent->nhe->flags, -+ NEXTHOP_GROUP_INSTALLED); -+ } -+ } - } - } --- -2.17.1 - - -From be767bd66143c2dcdd564a40a852400ae9e251e5 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Fri, 19 Apr 2024 12:13:32 -0400 -Subject: [PATCH 3/3] lib, zebra: Check for not being a blackhole route - -In zebra_interface_nhg_reinstall zebra is checking that the -nhg is a singleton and not a blackhole nhg. This was originally -done with checking that the nexthop is a NEXTHOP_TYPE_IFINDEX, -NEXTHOP_TYPE_IPV4_IFINDEX and NEXTHOP_TYPE_IPV6_IFINDEX. This -was excluding NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6. These -were both possible to be received and maintained from the upper -level protocol for when a route is being recursively resolved. -If we have gotten to this point in zebra_interface_nhg_reinstall -the nexthop group has already been installed at least once -and we *know* that it is actually a valid nexthop. What the -test is really trying to do is ensure that we are not reinstalling -a blackhole nexthop group( Which is not possible to even be -here by the way, but safety first! ). So let's change -to test for that instead. - -Signed-off-by: Donald Sharp ---- - lib/nexthop.c | 8 ++------ - lib/nexthop.h | 4 ++-- - zebra/zebra_nhg.c | 3 ++- - 3 files changed, 6 insertions(+), 9 deletions(-) - -diff --git a/lib/nexthop.c b/lib/nexthop.c -index e3bdbfb9e8..884255f158 100644 ---- a/lib/nexthop.c -+++ b/lib/nexthop.c -@@ -1094,11 +1094,7 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea, - return -1; - } - --bool nexthop_is_ifindex_type(const struct nexthop *nh) -+bool nexthop_is_blackhole(const struct nexthop *nh) - { -- if (nh->type == NEXTHOP_TYPE_IFINDEX || -- nh->type == NEXTHOP_TYPE_IPV4_IFINDEX || -- nh->type == NEXTHOP_TYPE_IPV6_IFINDEX) -- return true; -- return false; -+ return nh->type == NEXTHOP_TYPE_BLACKHOLE; - } -diff --git a/lib/nexthop.h b/lib/nexthop.h -index a52ae02172..bd1c0514fc 100644 ---- a/lib/nexthop.h -+++ b/lib/nexthop.h -@@ -260,8 +260,8 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, - extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, - struct nexthop *rparent); - --/* Check nexthop of IFINDEX type */ --extern bool nexthop_is_ifindex_type(const struct nexthop *nh); -+/* Is this nexthop a blackhole? */ -+extern bool nexthop_is_blackhole(const struct nexthop *nh); - - /* - * Parse one or more backup index values, as comma-separated numbers, -diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c -index e5efbf8d5f..33d2344f51 100644 ---- a/zebra/zebra_nhg.c -+++ b/zebra/zebra_nhg.c -@@ -3636,8 +3636,9 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) - "%s: Setting the valid flag for nhe %pNG, interface: %s", - __func__, rb_node_dep->nhe, ifp->name); - } -+ - /* Check for singleton NHG associated to interface */ -- if (nexthop_is_ifindex_type(nh) && -+ if (!nexthop_is_blackhole(nh) && - zebra_nhg_depends_is_empty(rb_node_dep->nhe)) { - struct nhg_connected *rb_node_dependent; - --- -2.17.1 - diff --git a/src/sonic-frr/patch/0030-zebra-backpressure-Zebra-push-back-on-Buffer-Stream-.patch b/src/sonic-frr/patch/0030-zebra-backpressure-Zebra-push-back-on-Buffer-Stream-.patch index 0bebd1ea12ba..f6de465595a5 100644 --- a/src/sonic-frr/patch/0030-zebra-backpressure-Zebra-push-back-on-Buffer-Stream-.patch +++ b/src/sonic-frr/patch/0030-zebra-backpressure-Zebra-push-back-on-Buffer-Stream-.patch @@ -50,10 +50,10 @@ Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja diff --git a/zebra/zserv.c b/zebra/zserv.c -index 2024f34534..de6e404fc4 100644 +index 6a64176d9..488712397 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c -@@ -318,6 +318,14 @@ zwrite_fail: +@@ -306,6 +306,14 @@ zwrite_fail: * this task reschedules itself. * * Any failure in any of these actions is handled by terminating the client. @@ -66,9 +66,9 @@ index 2024f34534..de6e404fc4 100644 + * The main thread processes the items in ibuf_fifo and always signals the + * client IO thread. */ - static void zserv_read(struct thread *thread) + static void zserv_read(struct event *thread) { -@@ -325,15 +333,25 @@ static void zserv_read(struct thread *thread) +@@ -313,16 +321,26 @@ static void zserv_read(struct event *thread) int sock; size_t already; struct stream_fifo *cache; @@ -80,7 +80,7 @@ index 2024f34534..de6e404fc4 100644 + int p2p_avail; /* How much space is available for p2p */ struct zmsghdr hdr; + size_t client_ibuf_fifo_cnt = stream_fifo_count_safe(client->ibuf_fifo); - + p2p_orig = atomic_load_explicit(&zrouter.packets_to_process, memory_order_relaxed); + p2p_avail = p2p_orig - client_ibuf_fifo_cnt; @@ -95,19 +95,21 @@ index 2024f34534..de6e404fc4 100644 + p2p = p2p_avail; cache = stream_fifo_new(); - p2p = p2p_orig; - sock = THREAD_FD(thread); - +- sock = EVENT_FD(thread); ++ sock = EVENT_FD(thread); + while (p2p) { -@@ -433,7 +451,7 @@ static void zserv_read(struct thread *thread) + ssize_t nb; +@@ -421,7 +439,7 @@ static void zserv_read(struct event *thread) p2p--; } - + - if (p2p < p2p_orig) { + if (p2p < (uint32_t)p2p_avail) { uint64_t time_now = monotime(NULL); - + /* update session statistics */ -@@ -447,19 +465,23 @@ static void zserv_read(struct thread *thread) +@@ -435,19 +453,23 @@ static void zserv_read(struct event *thread) while (cache->head) stream_fifo_push(client->ibuf_fifo, stream_fifo_pop(cache)); @@ -115,28 +117,28 @@ index 2024f34534..de6e404fc4 100644 + client_ibuf_fifo_cnt = + stream_fifo_count_safe(client->ibuf_fifo); } - + /* Schedule job to process those packets */ zserv_event(client, ZSERV_PROCESS_MESSAGES); - } - + if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug("Read %d packets from client: %s", p2p_orig - p2p, - zebra_route_string(client->proto)); + zlog_debug("Read %d packets from client: %s. Current ibuf fifo count: %zu. Conf P2p %d", + p2p_avail - p2p, zebra_route_string(client->proto), + client_ibuf_fifo_cnt, p2p_orig); - + - /* Reschedule ourselves */ - zserv_client_event(client, ZSERV_CLIENT_READ); + /* Reschedule ourselves since we have space in ibuf_fifo */ + if (client_ibuf_fifo_cnt < p2p_orig) + zserv_client_event(client, ZSERV_CLIENT_READ); - + stream_fifo_free(cache); - -@@ -495,14 +517,20 @@ static void zserv_client_event(struct zserv *client, + +@@ -483,14 +505,20 @@ static void zserv_client_event(struct zserv *client, * as the task argument. * * Each message is popped off the client's input queue and the action associated @@ -157,9 +159,9 @@ index 2024f34534..de6e404fc4 100644 + * items to the ibuf_fifo (until max limit) + * - the hidden config change (zebra zapi-packets <>) is taken into account. */ - static void zserv_process_messages(struct thread *thread) + static void zserv_process_messages(struct event *thread) { -@@ -538,6 +566,9 @@ static void zserv_process_messages(struct thread *thread) +@@ -524,6 +552,9 @@ static void zserv_process_messages(struct event *thread) /* Reschedule ourselves if necessary */ if (need_resched) zserv_event(client, ZSERV_PROCESS_MESSAGES); @@ -167,8 +169,5 @@ index 2024f34534..de6e404fc4 100644 + /* Ensure to include the read socket in the select/poll/etc.. */ + zserv_client_event(client, ZSERV_CLIENT_READ); } - - int zserv_send_message(struct zserv *client, struct stream *msg) --- -2.17.1 + int zserv_send_message(struct zserv *client, struct stream *msg) diff --git a/src/sonic-frr/patch/0031-bgpd-backpressure-Add-a-typesafe-list-for-Zebra-Anno.patch b/src/sonic-frr/patch/0031-bgpd-backpressure-Add-a-typesafe-list-for-Zebra-Anno.patch index 21a2b90f44f4..142ca6d0eff0 100644 --- a/src/sonic-frr/patch/0031-bgpd-backpressure-Add-a-typesafe-list-for-Zebra-Anno.patch +++ b/src/sonic-frr/patch/0031-bgpd-backpressure-Add-a-typesafe-list-for-Zebra-Anno.patch @@ -15,12 +15,12 @@ Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c -index 90ae580bab..e28dde5d16 100644 +index 851c4880c..44d5ee68c 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c -@@ -214,6 +214,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) +@@ -207,6 +207,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) bgp_evpn_mh_finish(); - bgp_l3nhg_finish(); + bgp_nhg_finish(); + zebra_announce_fini(&bm->zebra_announce_head); + @@ -28,19 +28,28 @@ index 90ae580bab..e28dde5d16 100644 bgp_dump_finish(); diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h -index 121afc481f..d43bf86eb9 100644 +index 5b4c3be21..67431ea4f 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h -@@ -101,6 +101,8 @@ struct bgp_node { +@@ -75,6 +75,9 @@ struct bgp_dest { + struct bgp_dest *pdest; STAILQ_ENTRY(bgp_dest) pq; - -+ struct zebra_announce_item zai; ++ struct bgp_path_info *za_bgp_pi; + ++ struct zebra_announce_item zai; + uint64_t version; - mpls_label_t local_label; -@@ -121,6 +123,8 @@ struct bgp_node { +@@ -91,12 +94,16 @@ struct bgp_dest { + #define BGP_NODE_LABEL_REQUESTED (1 << 7) + #define BGP_NODE_SOFT_RECONFIG (1 << 8) + #define BGP_NODE_PROCESS_CLEAR (1 << 9) ++#define BGP_NODE_SCHEDULE_FOR_INSTALL (1 << 10) ++#define BGP_NODE_SCHEDULE_FOR_DELETE (1 << 11) + + struct bgp_addpath_node_data tx_addpath; + enum bgp_path_selection_reason reason; }; @@ -50,10 +59,31 @@ index 121afc481f..d43bf86eb9 100644 /* * bgp_table_iter_t diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c -index 023047050b..392423e028 100644 +index 337879a2d..88d4201a9 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c -@@ -8017,6 +8017,8 @@ void bgp_master_init(struct thread_master *master, const int buffer_size, +@@ -3867,10 +3867,20 @@ int bgp_delete(struct bgp *bgp) + afi_t afi; + safi_t safi; + int i; ++ struct bgp_dest *dest = NULL; + struct graceful_restart_info *gr_info; + + assert(bgp); + ++ while (zebra_announce_count(&bm->zebra_announce_head)) { ++ dest = zebra_announce_pop(&bm->zebra_announce_head); ++ if (dest->za_bgp_pi->peer->bgp == bgp) { ++ bgp_path_info_unlock(dest->za_bgp_pi); ++ bgp_dest_unlock_node(dest); ++ } else ++ zebra_announce_add_tail(&bm->zebra_announce_head, dest); ++ } ++ + bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL); + + /* make sure we withdraw any exported routes */ +@@ -8296,6 +8306,8 @@ void bgp_master_init(struct event_loop *master, const int buffer_size, memset(&bgp_master, 0, sizeof(bgp_master)); bm = &bgp_master; @@ -62,23 +92,46 @@ index 023047050b..392423e028 100644 bm->bgp = list_new(); bm->listen_sockets = list_new(); bm->port = BGP_PORT_DEFAULT; +@@ -8314,6 +8326,7 @@ void bgp_master_init(struct event_loop *master, const int buffer_size, + bm->outq_limit = BM_DEFAULT_Q_LIMIT; + bm->t_bgp_sync_label_manager = NULL; + bm->t_bgp_start_label_manager = NULL; ++ bm->t_bgp_zebra_route = NULL; + + bgp_mac_init(); + /* init the rd id space. +@@ -8564,6 +8577,7 @@ void bgp_terminate(void) + EVENT_OFF(bm->t_rmap_update); + EVENT_OFF(bm->t_bgp_sync_label_manager); + EVENT_OFF(bm->t_bgp_start_label_manager); ++ EVENT_OFF(bm->t_bgp_zebra_route); + + bgp_mac_finish(); + } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h -index 72b5b50fb4..55f53bf9d3 100644 +index 0f6909532..a6b398a44 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h -@@ -32,6 +32,8 @@ - #include "srv6.h" +@@ -18,6 +18,8 @@ #include "iana_afi.h" + #include "asn.h" +PREDECL_LIST(zebra_announce); + /* For union sockunion. */ #include "queue.h" #include "sockunion.h" -@@ -180,6 +182,9 @@ struct bgp_master { +@@ -170,11 +172,16 @@ struct bgp_master { uint32_t inq_limit; uint32_t outq_limit; ++ struct event *t_bgp_zebra_route; ++ + struct event *t_bgp_sync_label_manager; + struct event *t_bgp_start_label_manager; + + bool v6_with_v4_nexthops; + + /* To preserve ordering of installations into zebra across all Vrfs */ + struct zebra_announce_head zebra_announce_head; + diff --git a/src/sonic-frr/patch/0032-bgpd-fix-flushing-ipv6-flowspec-entries-when-peering.patch b/src/sonic-frr/patch/0032-bgpd-fix-flushing-ipv6-flowspec-entries-when-peering.patch deleted file mode 100644 index bfefccceff10..000000000000 --- a/src/sonic-frr/patch/0032-bgpd-fix-flushing-ipv6-flowspec-entries-when-peering.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 69e38aa82f325129ebad4535be5d834c599b5c0b Mon Sep 17 00:00:00 2001 -From: Philippe Guibert -Date: Wed, 7 Feb 2024 22:34:34 +0100 -Subject: [PATCH 04/11] bgpd: fix flushing ipv6 flowspec entries when peering - stops - -When a BGP flowspec peering stops, the BGP RIB entries for IPv6 -flowspec entries are removed, but not the ZEBRA RIB IPv6 entries. - -Actually, when calling bgp_zebra_withdraw() function call, only -the AFI_IP parameter is passed to the bgp_pbr_update_entry() function -in charge of the Flowspec add/delete in zebra. Fix this by passing -the AFI parameter to the bgp_zebra_withdraw() function. - -Note that using topotest does not show up the problem as the -flowspec driver code is not present and was refused. Without that, -routes are not installed, and can not be uninstalled. - -Fixes: 529efa234655 ("bgpd: allow flowspec entries to be announced to zebra") -Link: https://github.com/FRRouting/frr/pull/2025 - -Signed-off-by: Philippe Guibert - -diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index fbff57634a..455cd6cdbb 100644 ---- a/bgpd/bgp_route.c -+++ b/bgpd/bgp_route.c -@@ -3312,7 +3312,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - */ - if (old_select && - is_route_parent_evpn(old_select)) -- bgp_zebra_withdraw(p, old_select, bgp, safi); -+ bgp_zebra_withdraw(p, old_select, bgp, afi, -+ safi); - - bgp_zebra_announce(dest, p, new_select, bgp, afi, safi); - } else { -@@ -3322,7 +3323,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - || old_select->sub_type == BGP_ROUTE_AGGREGATE - || old_select->sub_type == BGP_ROUTE_IMPORTED)) - -- bgp_zebra_withdraw(p, old_select, bgp, safi); -+ bgp_zebra_withdraw(p, old_select, bgp, afi, -+ safi); - } - } - -@@ -4201,7 +4203,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, - if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) { - if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) - /* remove from RIB previous entry */ -- bgp_zebra_withdraw(p, pi, bgp, safi); -+ bgp_zebra_withdraw(p, pi, bgp, afi, safi); - } - - if (peer->sort == BGP_PEER_EBGP) { -@@ -5841,7 +5843,7 @@ bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter) - } - - static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, -- safi_t safi) -+ afi_t afi, safi_t safi) - { - struct bgp_dest *dest; - struct bgp_path_info *pi; -@@ -5865,7 +5867,8 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, - || pi->sub_type == BGP_ROUTE_IMPORTED)) { - - if (bgp_fibupd_safi(safi)) -- bgp_zebra_withdraw(p, pi, bgp, safi); -+ bgp_zebra_withdraw(p, pi, bgp, afi, -+ safi); - } - - bgp_path_info_reap(dest, pi); -@@ -5882,7 +5885,7 @@ void bgp_cleanup_routes(struct bgp *bgp) - for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - if (afi == AFI_L2VPN) - continue; -- bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST], -+ bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST], afi, - SAFI_UNICAST); - /* - * VPN and ENCAP and EVPN tables are two-level (RD is top level) -@@ -5894,7 +5897,7 @@ void bgp_cleanup_routes(struct bgp *bgp) - dest = bgp_route_next(dest)) { - table = bgp_dest_get_bgp_table_info(dest); - if (table != NULL) { -- bgp_cleanup_table(bgp, table, safi); -+ bgp_cleanup_table(bgp, table, afi, safi); - bgp_table_finish(&table); - bgp_dest_set_bgp_table_info(dest, NULL); - bgp_dest_unlock_node(dest); -@@ -5905,7 +5908,7 @@ void bgp_cleanup_routes(struct bgp *bgp) - dest = bgp_route_next(dest)) { - table = bgp_dest_get_bgp_table_info(dest); - if (table != NULL) { -- bgp_cleanup_table(bgp, table, safi); -+ bgp_cleanup_table(bgp, table, afi, safi); - bgp_table_finish(&table); - bgp_dest_set_bgp_table_info(dest, NULL); - bgp_dest_unlock_node(dest); -@@ -5917,7 +5920,7 @@ void bgp_cleanup_routes(struct bgp *bgp) - dest = bgp_route_next(dest)) { - table = bgp_dest_get_bgp_table_info(dest); - if (table != NULL) { -- bgp_cleanup_table(bgp, table, SAFI_EVPN); -+ bgp_cleanup_table(bgp, table, afi, SAFI_EVPN); - bgp_table_finish(&table); - bgp_dest_set_bgp_table_info(dest, NULL); - bgp_dest_unlock_node(dest); -diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index ff79746b4c..69240a3b83 100644 ---- a/bgpd/bgp_zebra.c -+++ b/bgpd/bgp_zebra.c -@@ -1761,7 +1761,7 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, - } - - void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, -- struct bgp *bgp, safi_t safi) -+ struct bgp *bgp, afi_t afi, safi_t safi) - { - struct zapi_route api; - struct peer *peer; -@@ -1780,7 +1780,7 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, - - if (safi == SAFI_FLOWSPEC) { - peer = info->peer; -- bgp_pbr_update_entry(peer->bgp, p, info, AFI_IP, safi, false); -+ bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false); - return; - } - -@@ -1821,7 +1821,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa - if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) - && (pi->type == ZEBRA_ROUTE_BGP)) - bgp_zebra_withdraw(bgp_dest_get_prefix(dest), -- pi, bgp, safi); -+ pi, bgp, afi, safi); - } - } - } -diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h -index 0a41069411..a5fe8d7ace 100644 ---- a/bgpd/bgp_zebra.h -+++ b/bgpd/bgp_zebra.h -@@ -49,7 +49,7 @@ extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, - extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi); - extern void bgp_zebra_withdraw(const struct prefix *p, - struct bgp_path_info *path, struct bgp *bgp, -- safi_t safi); -+ afi_t afi, safi_t safi); - - /* Announce routes of any bgp subtype of a table to zebra */ - extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, --- -2.17.1 - diff --git a/src/sonic-frr/patch/0033-bgpd-backpressure-cleanup-bgp_zebra_XX-func-args.patch b/src/sonic-frr/patch/0033-bgpd-backpressure-cleanup-bgp_zebra_XX-func-args.patch index 16383dc95caa..126d3d05d669 100644 --- a/src/sonic-frr/patch/0033-bgpd-backpressure-cleanup-bgp_zebra_XX-func-args.patch +++ b/src/sonic-frr/patch/0033-bgpd-backpressure-cleanup-bgp_zebra_XX-func-args.patch @@ -15,10 +15,10 @@ Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index 455cd6cdbb..d19f27110e 100644 +index a0113c04e..99fb021b1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c -@@ -3214,8 +3214,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3419,8 +3419,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || new_select->sub_type == BGP_ROUTE_IMPORTED)) @@ -29,7 +29,7 @@ index 455cd6cdbb..d19f27110e 100644 } } -@@ -3312,10 +3312,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3529,10 +3529,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, */ if (old_select && is_route_parent_evpn(old_select)) @@ -42,7 +42,7 @@ index 455cd6cdbb..d19f27110e 100644 } else { /* Withdraw the route from the kernel. */ if (old_select && old_select->type == ZEBRA_ROUTE_BGP -@@ -3323,8 +3322,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3540,8 +3539,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || old_select->sub_type == BGP_ROUTE_AGGREGATE || old_select->sub_type == BGP_ROUTE_IMPORTED)) @@ -52,7 +52,7 @@ index 455cd6cdbb..d19f27110e 100644 } } -@@ -4203,7 +4201,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, +@@ -4446,7 +4444,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) /* remove from RIB previous entry */ @@ -61,7 +61,7 @@ index 455cd6cdbb..d19f27110e 100644 } if (peer->sort == BGP_PEER_EBGP) { -@@ -5867,8 +5865,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, +@@ -6072,8 +6070,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, || pi->sub_type == BGP_ROUTE_IMPORTED)) { if (bgp_fibupd_safi(safi)) @@ -70,13 +70,13 @@ index 455cd6cdbb..d19f27110e 100644 + bgp_zebra_withdraw(dest, pi, bgp); } - bgp_path_info_reap(dest, pi); + dest = bgp_path_info_reap(dest, pi); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index 69240a3b83..920df835a4 100644 +index fe29662e2..9b4b46b40 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c -@@ -1292,9 +1292,8 @@ static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr, - return true; +@@ -1507,9 +1507,8 @@ static void bgp_debug_zebra_nh(struct zapi_route *api) + } } -void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, @@ -85,18 +85,18 @@ index 69240a3b83..920df835a4 100644 +void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, + struct bgp *bgp) { + struct bgp_path_info *bpi_ultimate; struct zapi_route api = { 0 }; - struct zapi_nexthop *api_nh; -@@ -1321,6 +1320,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, - uint32_t ttl = 0; - uint32_t bos = 0; - uint32_t exp = 0; +@@ -1522,6 +1521,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, + bool is_add; + uint32_t nhg_id = 0; + uint32_t recursion_flag = 0; + struct bgp_table *table = bgp_dest_table(dest); + const struct prefix *p = bgp_dest_get_prefix(dest); /* * BGP is installing this route and bgp has been configured -@@ -1339,9 +1340,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, +@@ -1540,16 +1541,16 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, if (bgp->main_zebra_update_hold) return; @@ -105,11 +105,10 @@ index 69240a3b83..920df835a4 100644 - safi, true); + if (table->safi == SAFI_FLOWSPEC) { + bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi, -+ true); ++ true); return; } -@@ -1354,7 +1355,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, /* Make Zebra API structure. */ api.vrf_id = bgp->vrf_id; api.type = ZEBRA_ROUTE_BGP; @@ -118,23 +117,16 @@ index 69240a3b83..920df835a4 100644 api.prefix = *p; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); -@@ -1458,12 +1459,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, - } - } +@@ -1586,7 +1587,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, + metric = info->attr->med; -- if (bgp->table_map[afi][safi].name) { -+ if (bgp->table_map[table->afi][table->safi].name) { - /* Copy info and attributes, so the route-map - apply doesn't modify the BGP route info. */ - local_attr = *mpinfo->attr; - mpinfo_cp->attr = &local_attr; -- if (!bgp_table_map_apply(bgp->table_map[afi][safi].map, -+ if (!bgp_table_map_apply(bgp->table_map[table->afi] -+ [table->safi].map, - p, mpinfo_cp)) - continue; - -@@ -1619,7 +1621,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, + bgp_zebra_announce_parse_nexthop(info, p, bgp, &api, &valid_nh_count, +- afi, safi, &nhg_id, &metric, &tag, ++ table->afi, table->safi, &nhg_id, &metric, &tag, + &allow_recursion); + + is_add = (valid_nh_count || nhg_id) ? true : false; +@@ -1640,7 +1641,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api.tag = tag; } @@ -143,7 +135,7 @@ index 69240a3b83..920df835a4 100644 if (distance) { SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); api.distance = distance; -@@ -1731,9 +1733,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) +@@ -1689,9 +1690,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) && (pi->sub_type == BGP_ROUTE_NORMAL || pi->sub_type == BGP_ROUTE_IMPORTED))) @@ -154,7 +146,7 @@ index 69240a3b83..920df835a4 100644 } /* Announce routes of any bgp subtype of a table to zebra */ -@@ -1755,16 +1755,16 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, +@@ -1713,17 +1712,16 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && pi->type == ZEBRA_ROUTE_BGP) @@ -171,12 +163,13 @@ index 69240a3b83..920df835a4 100644 { struct zapi_route api; struct peer *peer; +- + struct bgp_table *table = bgp_dest_table(dest); + const struct prefix *p = bgp_dest_get_prefix(dest); - /* * If we are withdrawing the route, we don't need to have this -@@ -1778,16 +1778,17 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, + * flag set. So unset it. +@@ -1736,16 +1734,16 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, if (!bgp_install_info_to_zebra(bgp)) return; @@ -184,8 +177,7 @@ index 69240a3b83..920df835a4 100644 + if (table->safi == SAFI_FLOWSPEC) { peer = info->peer; - bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false); -+ bgp_pbr_update_entry(peer->bgp, p, info, table->afi, -+ table->safi, false); ++ bgp_pbr_update_entry(peer->bgp, p, info, table->afi, table->safi, false); return; } @@ -197,7 +189,7 @@ index 69240a3b83..920df835a4 100644 api.prefix = *p; if (info->attr->rmap_table_id) { -@@ -1820,8 +1821,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa +@@ -1778,8 +1776,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (pi->type == ZEBRA_ROUTE_BGP)) @@ -208,11 +200,11 @@ index 69240a3b83..920df835a4 100644 } } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h -index a5fe8d7ace..b77e423f8f 100644 +index 396c8335f..0facef5cc 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h -@@ -43,13 +43,11 @@ extern void bgp_zebra_destroy(void); - extern int bgp_zebra_get_table_range(uint32_t chunk_size, +@@ -28,13 +28,12 @@ extern void bgp_zebra_destroy(void); + extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size, uint32_t *start, uint32_t *end); extern int bgp_if_update_all(void); -extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, @@ -220,6 +212,7 @@ index a5fe8d7ace..b77e423f8f 100644 - afi_t afi, safi_t safi); +extern void bgp_zebra_announce(struct bgp_dest *dest, + struct bgp_path_info *path, struct bgp *bgp); ++ extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi); -extern void bgp_zebra_withdraw(const struct prefix *p, - struct bgp_path_info *path, struct bgp *bgp, @@ -230,5 +223,5 @@ index a5fe8d7ace..b77e423f8f 100644 /* Announce routes of any bgp subtype of a table to zebra */ extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, -- -2.17.1 +2.39.4 diff --git a/src/sonic-frr/patch/0034-gpd-backpressure-Handle-BGP-Zebra-Install-evt-Creat.patch b/src/sonic-frr/patch/0034-gpd-backpressure-Handle-BGP-Zebra-Install-evt-Creat.patch index 724cf1297a59..ff1dc62228d7 100644 --- a/src/sonic-frr/patch/0034-gpd-backpressure-Handle-BGP-Zebra-Install-evt-Creat.patch +++ b/src/sonic-frr/patch/0034-gpd-backpressure-Handle-BGP-Zebra-Install-evt-Creat.patch @@ -36,46 +36,45 @@ Ticket: #3390099 Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja +--- diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index d19f27110e..c29442d96c 100644 +index 99fb021b1..e45d4b1ff 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c -@@ -3214,8 +3214,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3419,8 +3419,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || new_select->sub_type == BGP_ROUTE_IMPORTED)) - bgp_zebra_announce(dest, old_select, - bgp); -+ bgp_zebra_route_install( -+ dest, old_select, bgp, true); ++ bgp_zebra_route_install(dest, old_select, ++ bgp, true); } } -@@ -3312,9 +3312,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3529,9 +3529,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, */ if (old_select && is_route_parent_evpn(old_select)) - bgp_zebra_withdraw(dest, old_select, bgp); -+ bgp_zebra_route_install(dest, old_select, bgp, -+ false); ++ bgp_zebra_route_install(dest, old_select, bgp, false); - bgp_zebra_announce(dest, new_select, bgp); + bgp_zebra_route_install(dest, new_select, bgp, true); } else { /* Withdraw the route from the kernel. */ if (old_select && old_select->type == ZEBRA_ROUTE_BGP -@@ -3322,7 +3323,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3539,7 +3539,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || old_select->sub_type == BGP_ROUTE_AGGREGATE || old_select->sub_type == BGP_ROUTE_IMPORTED)) - bgp_zebra_withdraw(dest, old_select, bgp); -+ bgp_zebra_route_install(dest, old_select, bgp, -+ false); ++ bgp_zebra_route_install(dest, old_select, bgp, false); } } -@@ -4201,7 +4203,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, +@@ -4444,7 +4444,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) /* remove from RIB previous entry */ @@ -84,43 +83,21 @@ index d19f27110e..c29442d96c 100644 } if (peer->sort == BGP_PEER_EBGP) { -@@ -5865,7 +5867,8 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, +@@ -6070,7 +6070,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, || pi->sub_type == BGP_ROUTE_IMPORTED)) { if (bgp_fibupd_safi(safi)) - bgp_zebra_withdraw(dest, pi, bgp); -+ bgp_zebra_withdraw_actual(dest, pi, -+ bgp); ++ bgp_zebra_withdraw_actual(dest, pi, bgp); } - bgp_path_info_reap(dest, pi); -diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h -index d43bf86eb9..45d61f8dfd 100644 ---- a/bgpd/bgp_table.h -+++ b/bgpd/bgp_table.h -@@ -102,6 +102,7 @@ struct bgp_node { - STAILQ_ENTRY(bgp_dest) pq; - - struct zebra_announce_item zai; -+ struct bgp_path_info *za_bgp_pi; - - uint64_t version; - -@@ -117,6 +118,8 @@ struct bgp_node { - #define BGP_NODE_FIB_INSTALLED (1 << 6) - #define BGP_NODE_LABEL_REQUESTED (1 << 7) - #define BGP_NODE_SOFT_RECONFIG (1 << 8) -+#define BGP_NODE_SCHEDULE_FOR_INSTALL (1 << 10) -+#define BGP_NODE_SCHEDULE_FOR_DELETE (1 << 11) - - struct bgp_addpath_node_data tx_addpath; - + dest = bgp_path_info_reap(dest, pi); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index 920df835a4..1162941ef1 100644 +index 9b4b46b40..31d981191 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c -@@ -1292,8 +1292,9 @@ static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr, - return true; +@@ -1507,8 +1507,9 @@ static void bgp_debug_zebra_nh(struct zapi_route *api) + } } -void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, @@ -129,9 +106,9 @@ index 920df835a4..1162941ef1 100644 +bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info, + struct bgp *bgp) { + struct bgp_path_info *bpi_ultimate; struct zapi_route api = { 0 }; - struct zapi_nexthop *api_nh; -@@ -1323,27 +1324,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1524,27 +1525,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, struct bgp_table *table = bgp_dest_table(dest); const struct prefix *p = bgp_dest_get_prefix(dest); @@ -154,27 +131,22 @@ index 920df835a4..1162941ef1 100644 - if (table->safi == SAFI_FLOWSPEC) { bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi, - true); + true); - return; + return ZCLIENT_SEND_SUCCESS; } - /* -@@ -1704,10 +1688,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, + /* Make Zebra API structure. */ +@@ -1661,7 +1645,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info, zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)", __func__, p, (recursion_flag ? "" : "NOT ")); } - zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, -- zclient, &api); + return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, -+ zclient, &api); + zclient, &api); } -+ - /* Announce all routes of a table to zebra */ - void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) - { -@@ -1733,7 +1718,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) +@@ -1690,7 +1674,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) && (pi->sub_type == BGP_ROUTE_NORMAL || pi->sub_type == BGP_ROUTE_IMPORTED))) @@ -183,7 +155,7 @@ index 920df835a4..1162941ef1 100644 } /* Announce routes of any bgp subtype of a table to zebra */ -@@ -1755,34 +1740,23 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, +@@ -1712,32 +1696,23 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && pi->type == ZEBRA_ROUTE_BGP) @@ -193,6 +165,7 @@ index 920df835a4..1162941ef1 100644 -void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info, - struct bgp *bgp) ++ +enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest, + struct bgp_path_info *info, + struct bgp *bgp) @@ -201,7 +174,6 @@ index 920df835a4..1162941ef1 100644 struct peer *peer; struct bgp_table *table = bgp_dest_table(dest); const struct prefix *p = bgp_dest_get_prefix(dest); - - /* - * If we are withdrawing the route, we don't need to have this - * flag set. So unset it. @@ -213,17 +185,16 @@ index 920df835a4..1162941ef1 100644 - */ - if (!bgp_install_info_to_zebra(bgp)) - return; -- + if (table->safi == SAFI_FLOWSPEC) { peer = info->peer; - bgp_pbr_update_entry(peer->bgp, p, info, table->afi, - table->safi, false); + bgp_pbr_update_entry(peer->bgp, p, info, table->afi, table->safi, false); - return; + return ZCLIENT_SEND_SUCCESS; } memset(&api, 0, sizeof(api)); -@@ -1800,7 +1774,172 @@ void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1755,7 +1730,172 @@ void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info, zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id, &api.prefix); @@ -291,7 +262,7 @@ index 920df835a4..1162941ef1 100644 + + if (status != ZCLIENT_SEND_BUFFERED && + zebra_announce_count(&bm->zebra_announce_head)) -+ thread_add_event(bm->master, ++ event_add_event(bm->master, + bgp_handle_route_announcements_to_zebra, NULL, + 0, &bm->t_bgp_zebra_route); +} @@ -392,12 +363,12 @@ index 920df835a4..1162941ef1 100644 + SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE); + } + -+ thread_add_event(bm->master, bgp_handle_route_announcements_to_zebra, ++ event_add_event(bm->master, bgp_handle_route_announcements_to_zebra, + NULL, 0, &bm->t_bgp_zebra_route); } /* Withdraw all entries in a BGP instances RIB table from Zebra */ -@@ -1821,7 +1960,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa +@@ -1776,7 +1916,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (pi->type == ZEBRA_ROUTE_BGP)) @@ -406,20 +377,20 @@ index 920df835a4..1162941ef1 100644 } } } -@@ -3470,6 +3609,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) +@@ -3449,6 +3589,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance) zclient = zclient_new(master, &zclient_options_default, bgp_handlers, array_size(bgp_handlers)); zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs); + zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready; zclient->zebra_connected = bgp_zebra_connected; - zclient->instance = instance; - } + zclient->zebra_capabilities = bgp_zebra_capabilities; + zclient->nexthop_update = bgp_nexthop_update; diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h -index b77e423f8f..45fcf7f514 100644 +index 0facef5cc..6bfa74f4c 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h -@@ -43,11 +43,10 @@ extern void bgp_zebra_destroy(void); - extern int bgp_zebra_get_table_range(uint32_t chunk_size, +@@ -28,12 +28,14 @@ extern void bgp_zebra_destroy(void); + extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size, uint32_t *start, uint32_t *end); extern int bgp_if_update_all(void); -extern void bgp_zebra_announce(struct bgp_dest *dest, @@ -427,80 +398,22 @@ index b77e423f8f..45fcf7f514 100644 +extern void bgp_zebra_route_install(struct bgp_dest *dest, + struct bgp_path_info *path, struct bgp *bgp, + bool install); + extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi); -extern void bgp_zebra_withdraw(struct bgp_dest *dest, - struct bgp_path_info *path, struct bgp *bgp); - - /* Announce routes of any bgp subtype of a table to zebra */ - extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, -@@ -131,4 +130,7 @@ extern int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type); - extern int bgp_zebra_stale_timer_update(struct bgp *bgp); - extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name); - extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name); +extern enum zclient_send_status +bgp_zebra_withdraw_actual(struct bgp_dest *dest, struct bgp_path_info *info, + struct bgp *bgp); - #endif /* _QUAGGA_BGP_ZEBRA_H */ -diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c -index 392423e028..da133d71c1 100644 ---- a/bgpd/bgpd.c -+++ b/bgpd/bgpd.c -@@ -3688,10 +3688,20 @@ int bgp_delete(struct bgp *bgp) - afi_t afi; - safi_t safi; - int i; -+ struct bgp_dest *dest = NULL; - struct graceful_restart_info *gr_info; - - assert(bgp); - -+ while (zebra_announce_count(&bm->zebra_announce_head)) { -+ dest = zebra_announce_pop(&bm->zebra_announce_head); -+ if (dest->za_bgp_pi->peer->bgp == bgp) { -+ bgp_path_info_unlock(dest->za_bgp_pi); -+ bgp_dest_unlock_node(dest); -+ } else -+ zebra_announce_add_tail(&bm->zebra_announce_head, dest); -+ } -+ - bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL); - - /* make sure we withdraw any exported routes */ -@@ -8035,6 +8045,7 @@ void bgp_master_init(struct thread_master *master, const int buffer_size, - bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL; - bm->inq_limit = BM_DEFAULT_Q_LIMIT; - bm->outq_limit = BM_DEFAULT_Q_LIMIT; -+ bm->t_bgp_zebra_route = NULL; - - bgp_mac_init(); - /* init the rd id space. -@@ -8278,6 +8289,7 @@ void bgp_terminate(void) - list_delete(&bm->listen_sockets); - - THREAD_OFF(bm->t_rmap_update); -+ THREAD_OFF(bm->t_bgp_zebra_route); - - bgp_mac_finish(); - } -diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h -index 55f53bf9d3..bdf31f5161 100644 ---- a/bgpd/bgpd.h -+++ b/bgpd/bgpd.h -@@ -182,6 +182,8 @@ struct bgp_master { - uint32_t inq_limit; - uint32_t outq_limit; - -+ struct thread *t_bgp_zebra_route; -+ - /* To preserve ordering of installations into zebra across all Vrfs */ - struct zebra_announce_head zebra_announce_head; + /* Announce routes of any bgp subtype of a table to zebra */ + extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, diff --git a/lib/zclient.c b/lib/zclient.c -index 0082b21485..c48c1c6ee4 100644 +index 6b35b569d..64515c754 100644 --- a/lib/zclient.c +++ b/lib/zclient.c -@@ -285,6 +285,7 @@ static void zclient_flush_data(struct thread *thread) - zclient->sock, &zclient->t_write); +@@ -282,6 +282,7 @@ static void zclient_flush_data(struct event *thread) + zclient->sock, &zclient->t_write); break; case BUFFER_EMPTY: + /* Currently only Sharpd and Bgpd has callbacks defined */ @@ -508,5 +421,5 @@ index 0082b21485..c48c1c6ee4 100644 (*zclient->zebra_buffer_write_ready)(); break; -- -2.17.1 +2.39.4 diff --git a/src/sonic-frr/patch/0035-bgpd-backpressure-Handle-BGP-Zebra-EPVN-Install-evt-.patch b/src/sonic-frr/patch/0035-bgpd-backpressure-Handle-BGP-Zebra-EPVN-Install-evt-.patch index e83526b6e8ef..1ef5f9c849d7 100644 --- a/src/sonic-frr/patch/0035-bgpd-backpressure-Handle-BGP-Zebra-EPVN-Install-evt-.patch +++ b/src/sonic-frr/patch/0035-bgpd-backpressure-Handle-BGP-Zebra-EPVN-Install-evt-.patch @@ -18,29 +18,315 @@ Ticket: #3390099 Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c -index 2b2cfa0f4c..622fd6afd2 100644 +index a846484f0..79e16d8f9 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c -@@ -863,11 +863,10 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn, +@@ -55,27 +55,25 @@ DEFINE_MTYPE_STATIC(BGPD, VRF_ROUTE_TARGET, "L3 Route Target"); + /* + * Static function declarations + */ +-static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *evpn); +-static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *evpn); +-static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_hash_init(struct bgpevpn *evpn); ++void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *evpn); ++void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, + struct bgp_path_info *pi); +-static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, + struct bgp_path_info *pi); +-static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, +- void (*func)(struct hash_bucket *, +- void *), +- void *arg); +-static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn); +-static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp, ++void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, ++ void (*func)(struct hash_bucket *,void *), void *arg); ++void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn); ++void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp, + struct bgpevpn *vpn); +-static unsigned int vni_svi_hash_key_make(const void *p); +-static bool vni_svi_hash_cmp(const void *p1, const void *p2); +-static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn, ++unsigned int vni_svi_hash_key_make(const void *p); ++bool vni_svi_hash_cmp(const void *p1, const void *p2); ++void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn, + struct ipaddr *addr, + bool resolve); +-static void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket, ++void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket, + void *args); +-static void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket, ++void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket, + void *args); + static struct in_addr zero_vtep_ip; + +@@ -86,7 +84,7 @@ static struct in_addr zero_vtep_ip; + /* + * Make vni hash key. + */ +-static unsigned int vni_hash_key_make(const void *p) ++unsigned int vni_hash_key_make(const void *p) + { + const struct bgpevpn *vpn = p; + return (jhash_1word(vpn->vni, 0)); +@@ -95,7 +93,7 @@ static unsigned int vni_hash_key_make(const void *p) + /* + * Comparison function for vni hash + */ +-static bool vni_hash_cmp(const void *p1, const void *p2) ++bool vni_hash_cmp(const void *p1, const void *p2) + { + const struct bgpevpn *vpn1 = p1; + const struct bgpevpn *vpn2 = p2; +@@ -114,7 +112,7 @@ int vni_list_cmp(void *p1, void *p2) + /* + * Make vrf import route target hash key. + */ +-static unsigned int vrf_import_rt_hash_key_make(const void *p) ++unsigned int vrf_import_rt_hash_key_make(const void *p) + { + const struct vrf_irt_node *irt = p; + const char *pnt = irt->rt.val; +@@ -125,7 +123,7 @@ static unsigned int vrf_import_rt_hash_key_make(const void *p) + /* + * Comparison function for vrf import rt hash + */ +-static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2) ++bool vrf_import_rt_hash_cmp(const void *p1, const void *p2) + { + const struct vrf_irt_node *irt1 = p1; + const struct vrf_irt_node *irt2 = p2; +@@ -136,7 +134,7 @@ static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2) + /* + * Create a new vrf import_rt in evpn instance + */ +-static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) ++struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) + { + struct bgp *bgp_evpn = NULL; + struct vrf_irt_node *irt; +@@ -163,7 +161,7 @@ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt) + /* + * Free the vrf import rt node + */ +-static void vrf_import_rt_free(struct vrf_irt_node *irt) ++void vrf_import_rt_free(struct vrf_irt_node *irt) + { + struct bgp *bgp_evpn = NULL; + +@@ -179,7 +177,7 @@ static void vrf_import_rt_free(struct vrf_irt_node *irt) + XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt); + } + +-static void hash_vrf_import_rt_free(struct vrf_irt_node *irt) ++void hash_vrf_import_rt_free(struct vrf_irt_node *irt) + { + XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt); + } +@@ -188,7 +186,7 @@ static void hash_vrf_import_rt_free(struct vrf_irt_node *irt) + * Function to lookup Import RT node - used to map a RT to set of + * VNIs importing routes with that RT. + */ +-static struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt) ++struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt) + { + struct bgp *bgp_evpn = NULL; + struct vrf_irt_node *irt; +@@ -211,7 +209,7 @@ static struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt) + /* + * Is specified VRF present on the RT's list of "importing" VRFs? + */ +-static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf) ++int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf) + { + struct listnode *node = NULL, *nnode = NULL; + struct bgp *tmp_bgp_vrf = NULL; +@@ -226,7 +224,7 @@ static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf) + /* + * Make import route target hash key. + */ +-static unsigned int import_rt_hash_key_make(const void *p) ++unsigned int import_rt_hash_key_make(const void *p) + { + const struct irt_node *irt = p; + const char *pnt = irt->rt.val; +@@ -237,7 +235,7 @@ static unsigned int import_rt_hash_key_make(const void *p) + /* + * Comparison function for import rt hash + */ +-static bool import_rt_hash_cmp(const void *p1, const void *p2) ++bool import_rt_hash_cmp(const void *p1, const void *p2) + { + const struct irt_node *irt1 = p1; + const struct irt_node *irt2 = p2; +@@ -248,7 +246,7 @@ static bool import_rt_hash_cmp(const void *p1, const void *p2) + /* + * Create a new import_rt + */ +-static struct irt_node *import_rt_new(struct bgp *bgp, ++struct irt_node *import_rt_new(struct bgp *bgp, + struct ecommunity_val *rt) + { + struct irt_node *irt; +@@ -267,14 +265,14 @@ static struct irt_node *import_rt_new(struct bgp *bgp, + /* + * Free the import rt node + */ +-static void import_rt_free(struct bgp *bgp, struct irt_node *irt) ++void import_rt_free(struct bgp *bgp, struct irt_node *irt) + { + hash_release(bgp->import_rt_hash, irt); + list_delete(&irt->vnis); + XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); + } + +-static void hash_import_rt_free(struct irt_node *irt) ++void hash_import_rt_free(struct irt_node *irt) + { + XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); + } +@@ -283,7 +281,7 @@ static void hash_import_rt_free(struct irt_node *irt) + * Function to lookup Import RT node - used to map a RT to set of + * VNIs importing routes with that RT. + */ +-static struct irt_node *lookup_import_rt(struct bgp *bgp, ++struct irt_node *lookup_import_rt(struct bgp *bgp, + struct ecommunity_val *rt) + { + struct irt_node *irt; +@@ -298,7 +296,7 @@ static struct irt_node *lookup_import_rt(struct bgp *bgp, + /* + * Is specified VNI present on the RT's list of "importing" VNIs? + */ +-static int is_vni_present_in_irt_vnis(struct list *vnis, struct bgpevpn *vpn) ++int is_vni_present_in_irt_vnis(struct list *vnis, struct bgpevpn *vpn) + { + struct listnode *node, *nnode; + struct bgpevpn *tmp_vpn; +@@ -384,7 +382,7 @@ int bgp_evpn_route_target_cmp(struct ecommunity *ecom1, + /* + * Compare L3 Route Targets. + */ +-static int evpn_vrf_route_target_cmp(struct vrf_route_target *rt1, ++int evpn_vrf_route_target_cmp(struct vrf_route_target *rt1, + struct vrf_route_target *rt2) + { + return bgp_evpn_route_target_cmp(rt1->ecom, rt2->ecom); +@@ -399,7 +397,7 @@ void bgp_evpn_xxport_delete_ecomm(void *val) + /* + * Delete l3 Route Target. + */ +-static void evpn_vrf_rt_del(void *val) ++void evpn_vrf_rt_del(void *val) + { + struct vrf_route_target *l3rt = val; + +@@ -411,7 +409,7 @@ static void evpn_vrf_rt_del(void *val) + /* + * Allocate a new l3 Route Target. + */ +-static struct vrf_route_target *evpn_vrf_rt_new(struct ecommunity *ecom) ++struct vrf_route_target *evpn_vrf_rt_new(struct ecommunity *ecom) + { + struct vrf_route_target *l3rt; + +@@ -446,7 +444,7 @@ static inline void mask_ecom_global_admin(struct ecommunity_val *dst, + * Converts the RT to Ecommunity Value and adjusts masking based + * on flags set for RT. + */ +-static void vrf_rt2ecom_val(struct ecommunity_val *to_eval, ++void vrf_rt2ecom_val(struct ecommunity_val *to_eval, + const struct vrf_route_target *l3rt, int iter) + { + const struct ecommunity_val *eval; +@@ -470,7 +468,7 @@ static void vrf_rt2ecom_val(struct ecommunity_val *to_eval, + * Map one RT to specified VRF. + * bgp_vrf = BGP vrf instance + */ +-static void map_vrf_to_rt(struct bgp *bgp_vrf, struct vrf_route_target *l3rt) ++void map_vrf_to_rt(struct bgp *bgp_vrf, struct vrf_route_target *l3rt) + { + uint32_t i = 0; + +@@ -499,7 +497,7 @@ static void map_vrf_to_rt(struct bgp *bgp_vrf, struct vrf_route_target *l3rt) + * VRFs for this RT, then the RT hash is deleted. + * bgp_vrf: BGP VRF specific instance + */ +-static void unmap_vrf_from_rt(struct bgp *bgp_vrf, ++void unmap_vrf_from_rt(struct bgp *bgp_vrf, + struct vrf_route_target *l3rt) + { + uint32_t i; +@@ -527,7 +525,7 @@ static void unmap_vrf_from_rt(struct bgp *bgp_vrf, + /* + * Map one RT to specified VNI. + */ +-static void map_vni_to_rt(struct bgp *bgp, struct bgpevpn *vpn, ++void map_vni_to_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity_val *eval) + { + struct irt_node *irt; +@@ -558,7 +556,7 @@ static void map_vni_to_rt(struct bgp *bgp, struct bgpevpn *vpn, + * Unmap specified VNI from specified RT. If there are no other + * VNIs for this RT, then the RT hash is deleted. + */ +-static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn, ++void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct irt_node *irt) + { + /* Delete VNI from hash list for this RT. */ +@@ -568,7 +566,7 @@ static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn, + } + } + +-static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn, ++void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct attr *attr, uint8_t flags) + { +@@ -609,7 +607,7 @@ static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn, + * VNIs but the same across routers (in the same AS) for a particular + * VNI. + */ +-static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl, ++void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl, + bool is_l3) + { + struct ecommunity_val eval; +@@ -657,7 +655,7 @@ static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl, + * Derive RD and RT for a VNI automatically. Invoked at the time of + * creation of a VNI. + */ +-static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn) ++void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + { + bgp_evpn_derive_auto_rd(bgp, vpn); + bgp_evpn_derive_auto_rt_import(bgp, vpn); +@@ -667,7 +665,7 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + /* + * Convert nexthop (remote VTEP IP) into an IPv6 address. + */ +-static void evpn_convert_nexthop_to_ipv6(struct attr *attr) ++void evpn_convert_nexthop_to_ipv6(struct attr *attr) + { + if (BGP_ATTR_NEXTHOP_AFI_IP6(attr)) + return; +@@ -892,7 +890,7 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn, /* * Add (update) or delete MACIP from zebra. */ -static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p, -- const struct ethaddr *mac, -- struct in_addr remote_vtep_ip, int add, -- uint8_t flags, uint32_t seq, esi_t *esi) -+static enum zclient_send_status bgp_zebra_send_remote_macip( -+ struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p, -+ const struct ethaddr *mac, struct in_addr remote_vtep_ip, int add, -+ uint8_t flags, uint32_t seq, esi_t *esi) - { - struct stream *s; - uint16_t ipa_len; -@@ -875,8 +874,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, ++enum zclient_send_status bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + const struct ethaddr *mac, + struct in_addr remote_vtep_ip, int add, +@@ -903,9 +901,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, + static struct in_addr zero_remote_vtep_ip; bool esi_valid; - - /* Check socket. */ + +- /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { @@ -49,33 +335,30 @@ index 2b2cfa0f4c..622fd6afd2 100644 + __func__); + return ZCLIENT_SEND_SUCCESS; + } - + /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { -@@ -884,7 +887,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, +@@ -913,7 +914,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, zlog_debug( "%s: No zebra instance to talk to, not installing remote macip", __func__); - return 0; + return ZCLIENT_SEND_SUCCESS; } - + if (!esi) -@@ -956,15 +959,20 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, +@@ -988,15 +989,18 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, /* * Add (update) or delete remote VTEP from zebra. */ -static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p, -- int flood_control, int add) -+static enum zclient_send_status -+bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, -+ const struct prefix_evpn *p, int flood_control, -+ int add) ++enum zclient_send_status bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + int flood_control, int add) { struct stream *s; - - /* Check socket. */ + +- /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { @@ -84,83 +367,95 @@ index 2b2cfa0f4c..622fd6afd2 100644 + __func__); + return ZCLIENT_SEND_SUCCESS; + } - + /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { -@@ -972,7 +980,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1004,7 +1008,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, zlog_debug( "%s: No zebra instance to talk to, not installing remote vtep", __func__); - return 0; + return ZCLIENT_SEND_SUCCESS; } - + s = zclient->obuf; -@@ -989,7 +997,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1021,7 +1025,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, EC_BGP_VTEP_INVALID, "Bad remote IP when trying to %s remote VTEP for VNI %u", - add ? "ADD" : "DEL", vpn->vni); + add ? "ADD" : "DEL", (vpn ? vpn->vni : 0)); - return -1; + return ZCLIENT_SEND_FAILURE; } stream_putl(s, flood_control); - -@@ -1222,14 +1230,15 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) + +@@ -1043,7 +1047,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, + /* + * Build extended communities for EVPN prefix route. + */ +-static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf, ++void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf, + struct attr *attr) + { + struct ecommunity ecom_encap; +@@ -1100,7 +1104,7 @@ static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf, + * added, if present, based on passed settings - only for non-link-local + * type-2 routes. + */ +-static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, ++void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, + int add_l3_ecomm, + struct ecommunity *macvrf_soo) + { +@@ -1209,7 +1213,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, + /* + * Add MAC mobility extended community to attribute. + */ +-static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) ++void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) + { + struct ecommunity ecom_tmp; + struct ecommunity_val eval; +@@ -1263,14 +1267,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) } - + /* Install EVPN route into zebra. */ -static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p, -- struct bgp_path_info *pi) -+enum zclient_send_status evpn_zebra_install(struct bgp *bgp, -+ struct bgpevpn *vpn, -+ const struct prefix_evpn *p, -+ struct bgp_path_info *pi) ++enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *pi) { - int ret; uint8_t flags; - int flood_control; + int flood_control = VXLAN_FLOOD_DISABLED; uint32_t seq; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { flags = 0; -@@ -1302,6 +1311,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, - flood_control = VXLAN_FLOOD_DISABLED; - break; - } -+ - ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1); - } - -@@ -1309,11 +1319,13 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1355,11 +1359,11 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, } - + /* Uninstall EVPN route from zebra. */ -static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p, -- struct bgp_path_info *pi, bool is_sync) -+enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp, -+ struct bgpevpn *vpn, -+ const struct prefix_evpn *p, -+ struct bgp_path_info *pi, -+ bool is_sync) ++enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *pi, bool is_sync) { - int ret; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) ret = bgp_zebra_send_remote_macip( -@@ -1328,7 +1340,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, - ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p); - else - ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, -- VXLAN_FLOOD_DISABLED, 0); -+ VXLAN_FLOOD_DISABLED, 0); - - return ret; - } -@@ -1419,12 +1431,18 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1384,7 +1388,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, + * by a "remote" best route. The prior route has to be deleted and withdrawn + * from peers. + */ +-static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, ++void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_dest *dest, + struct bgp_path_info *old_local, + struct bgp_path_info *new_select) +@@ -1465,12 +1469,17 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR) && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) { @@ -181,11 +476,10 @@ index 2b2cfa0f4c..622fd6afd2 100644 + bgp_zebra_route_install(dest, old_select, bgp, + true, vpn, false); + } -+ UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG); bgp_zebra_clear_route_change_flags(dest); -@@ -1456,10 +1474,14 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1502,10 +1511,14 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, if (new_select && new_select->type == ZEBRA_ROUTE_BGP && (new_select->sub_type == BGP_ROUTE_IMPORTED || bgp_evpn_attr_is_sync(new_select->attr))) { @@ -201,10 +495,10 @@ index 2b2cfa0f4c..622fd6afd2 100644 + else + bgp_zebra_route_install(dest, new_select, bgp, true, + vpn, false); - + /* If an old best existed and it was a "local" route, the only * reason -@@ -1476,13 +1498,20 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, +@@ -1522,13 +1535,20 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, evpn_delete_old_local_route(bgp, vpn, dest, old_select, new_select); } else { @@ -230,9 +524,72 @@ index 2b2cfa0f4c..622fd6afd2 100644 + false, vpn, false); + } } - + /* Clear any route change flags. */ -@@ -2012,9 +2041,19 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp, +@@ -1541,7 +1561,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, + return ret; + } + +-static struct bgp_path_info *bgp_evpn_route_get_local_path( ++struct bgp_path_info *bgp_evpn_route_get_local_path( + struct bgp *bgp, struct bgp_dest *dest) + { + struct bgp_path_info *tmp_pi; +@@ -1558,7 +1578,7 @@ static struct bgp_path_info *bgp_evpn_route_get_local_path( + return local_pi; + } + +-static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, ++int update_evpn_type5_route_entry(struct bgp *bgp_evpn, + struct bgp *bgp_vrf, afi_t afi, + safi_t safi, struct bgp_dest *dest, + struct attr *attr, int *route_changed) +@@ -1627,7 +1647,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, + } + + /* update evpn type-5 route entry */ +-static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, ++int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, + struct attr *src_attr, afi_t src_afi, + safi_t src_safi) + { +@@ -1732,7 +1752,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, + return 0; + } + +-static void bgp_evpn_get_sync_info(struct bgp *bgp, esi_t *esi, ++void bgp_evpn_get_sync_info(struct bgp *bgp, esi_t *esi, + struct bgp_dest *dest, uint32_t loc_seq, + uint32_t *max_sync_seq, bool *active_on_peer, + bool *peer_router, bool *proxy_from_peer, +@@ -1809,7 +1829,7 @@ static void bgp_evpn_get_sync_info(struct bgp *bgp, esi_t *esi, + * Note: The local path can only exist as a best path in the + * VPN route table. It will take precedence over all sync paths. + */ +-static void update_evpn_route_entry_sync_info(struct bgp *bgp, ++void update_evpn_route_entry_sync_info(struct bgp *bgp, + struct bgp_dest *dest, + struct attr *attr, + uint32_t loc_seq, bool setup_sync, +@@ -1879,7 +1899,7 @@ static void update_evpn_route_entry_sync_info(struct bgp *bgp, + * Create or update EVPN route entry. This could be in the VNI route tables + * or the global route table. + */ +-static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, ++int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + afi_t afi, safi_t safi, + struct bgp_dest *dest, struct attr *attr, + const struct ethaddr *mac, +@@ -2044,7 +2064,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + return route_change; + } + +-static void evpn_zebra_reinstall_best_route(struct bgp *bgp, ++void evpn_zebra_reinstall_best_route(struct bgp *bgp, + struct bgpevpn *vpn, + struct bgp_dest *dest) + { +@@ -2062,9 +2082,19 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp, if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP && (curr_select->sub_type == BGP_ROUTE_IMPORTED || bgp_evpn_attr_is_sync(curr_select->attr))) @@ -253,9 +610,36 @@ index 2b2cfa0f4c..622fd6afd2 100644 + true, vpn, false); + } } - + /* -@@ -2189,8 +2228,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, +@@ -2081,7 +2111,7 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp, + * additional handling to prevent bgp from injecting and holding on to a + * non-best local path. + */ +-static struct bgp_dest * ++struct bgp_dest * + evpn_cleanup_local_non_best_route(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_dest *dest, + struct bgp_path_info *local_pi) +@@ -2099,7 +2129,7 @@ evpn_cleanup_local_non_best_route(struct bgp *bgp, struct bgpevpn *vpn, + return bgp_path_info_reap(dest, local_pi); + } + +-static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn, ++inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn, + const struct prefix_evpn *p, + esi_t *esi) + { +@@ -2116,7 +2146,7 @@ static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn, + * Create or update EVPN route (of type based on prefix) for specified VNI + * and schedule for processing. + */ +-static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, ++int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, uint8_t flags, + uint32_t seq, esi_t *esi) + { +@@ -2245,8 +2275,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, * has been removed. */ new_is_sync = bgp_evpn_attr_is_sync(pi->attr); @@ -274,7 +658,33 @@ index 2b2cfa0f4c..622fd6afd2 100644 } } bgp_path_info_unlock(pi); -@@ -2444,8 +2491,16 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, +@@ -2308,7 +2346,7 @@ void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, + } + + /* Delete EVPN type5 route */ +-static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) ++int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) + { + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; +@@ -2339,7 +2377,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) + * Delete EVPN route (of type based on prefix) for specified VNI and + * schedule for processing. + */ +-static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, ++int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p) + { + struct bgp_dest *dest, *global_dest; +@@ -2408,6 +2446,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + int route_change; + bool old_is_sync = false; + struct ecommunity *macvrf_soo = NULL; ++ struct prefix_evpn p; + + if (CHECK_FLAG(local_pi->flags, BGP_PATH_REMOVED)) + return; +@@ -2512,8 +2551,16 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, * has been removed. */ new_is_sync = bgp_evpn_attr_is_sync(pi->attr); @@ -283,8 +693,8 @@ index 2b2cfa0f4c..622fd6afd2 100644 + if (!new_is_sync && old_is_sync) { + if (CHECK_FLAG(bgp->flags, + BGP_FLAG_DELETE_IN_PROGRESS)) -+ (void)evpn_zebra_uninstall( -+ bgp, vpn, &evp, pi, true); ++ evpn_zebra_uninstall(bgp, vpn, &p, pi, ++ true); + else + bgp_zebra_route_install(dest, pi, bgp, + false, vpn, @@ -292,10 +702,100 @@ index 2b2cfa0f4c..622fd6afd2 100644 + } } } - -@@ -2701,7 +2756,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + +@@ -2541,7 +2588,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + aspath_unintern(&attr.aspath); + } + +-static void update_type2_route(struct bgp *bgp, struct bgpevpn *vpn, ++void update_type2_route(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_dest *dest) + { + struct bgp_path_info *tmp_pi; +@@ -2571,7 +2618,7 @@ static void update_type2_route(struct bgp *bgp, struct bgpevpn *vpn, + * Update all type-2 (MACIP) local routes for this VNI - these should also + * be scheduled for advertise to peers. + */ +-static void update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + struct bgp_dest *dest; + +@@ -2592,7 +2639,7 @@ static void update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + * Delete all type-2 (MACIP) local routes for this VNI - only from the + * global routing table. These are also scheduled for withdraw from peers. + */ +-static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + afi_t afi; + safi_t safi; +@@ -2626,7 +2673,7 @@ static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + } + } + +-static struct bgp_dest *delete_vni_type2_route(struct bgp *bgp, ++struct bgp_dest *delete_vni_type2_route(struct bgp *bgp, + struct bgp_dest *dest) + { + struct bgp_path_info *pi; +@@ -2648,7 +2695,7 @@ static struct bgp_dest *delete_vni_type2_route(struct bgp *bgp, + return dest; + } + +-static void delete_vni_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void delete_vni_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + struct bgp_dest *dest; + +@@ -2672,7 +2719,7 @@ static void delete_vni_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + * Delete all type-2 (MACIP) local routes for this VNI - from the global + * table as well as the per-VNI route table. + */ +-static void delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + /* First, walk the global route table for this VNI's type-2 local + * routes. +@@ -2685,7 +2732,7 @@ static void delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) + /* + * Delete all routes in the per-VNI route table. + */ +-static void delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + struct bgp_dest *dest; + struct bgp_path_info *pi, *nextpi; +@@ -2716,7 +2763,7 @@ static void delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + } + + /* BUM traffic flood mode per-l2-vni */ +-static int bgp_evpn_vni_flood_mode_get(struct bgp *bgp, ++int bgp_evpn_vni_flood_mode_get(struct bgp *bgp, + struct bgpevpn *vpn) + { + /* if flooding has been globally disabled per-vni mode is +@@ -2766,7 +2813,7 @@ int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + /* Update Type-2/3 Routes for L2VNI. + * Called by hash_iterate() + */ +-static void update_routes_for_vni_hash(struct hash_bucket *bucket, ++void update_routes_for_vni_hash(struct hash_bucket *bucket, + struct bgp *bgp) + { + struct bgpevpn *vpn; +@@ -2784,7 +2831,7 @@ static void update_routes_for_vni_hash(struct hash_bucket *bucket, + * the per-VNI table. Invoked upon the VNI being deleted or EVPN + * (advertise-all-vni) being disabled. + */ +-static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) ++int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + { + int ret; + struct prefix_evpn p; +@@ -2795,7 +2842,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) delete_all_type2_routes(bgp, vpn); - + build_evpn_type3_prefix(&p, vpn->originator_ip); + + /* @@ -315,8 +815,519 @@ index 2b2cfa0f4c..622fd6afd2 100644 + UNSET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN); if (ret) return ret; - -@@ -6028,6 +6098,17 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, + +@@ -2809,7 +2871,7 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + * remove the type-3 route if any. A new type-3 route will be generated + * post tunnel_ip update if the new flood mode is head-end-replication. + */ +-static int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn, ++int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn, + struct in_addr mcast_grp) + { + struct prefix_evpn p; +@@ -2833,7 +2895,7 @@ static int bgp_evpn_mcast_grp_change(struct bgp *bgp, struct bgpevpn *vpn, + * Note: Route re-advertisement happens elsewhere after other processing + * other changes. + */ +-static void handle_tunnel_ip_change(struct bgp *bgp_vrf, struct bgp *bgp_evpn, ++void handle_tunnel_ip_change(struct bgp *bgp_vrf, struct bgp *bgp_evpn, + struct bgpevpn *vpn, + struct in_addr originator_ip) + { +@@ -2882,7 +2944,7 @@ static void handle_tunnel_ip_change(struct bgp *bgp_vrf, struct bgp *bgp_evpn, + return; + } + +-static struct bgp_path_info * ++struct bgp_path_info * + bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi, + struct bgp_dest *dest, struct attr *attr) + { +@@ -2918,7 +2980,7 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi, + /* + * Install route entry into the VRF routing table and invoke route selection. + */ +-static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, ++int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, + const struct prefix_evpn *evp, + struct bgp_path_info *parent_pi) + { +@@ -3102,7 +3164,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, + /* + * Common handling for vni route tables install/selection. + */ +-static int install_evpn_route_entry_in_vni_common( ++int install_evpn_route_entry_in_vni_common( + struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p, + struct bgp_dest *dest, struct bgp_path_info *parent_pi) + { +@@ -3202,7 +3264,7 @@ static int install_evpn_route_entry_in_vni_common( + /* + * Common handling for vni route tables uninstall/selection. + */ +-static int uninstall_evpn_route_entry_in_vni_common( ++int uninstall_evpn_route_entry_in_vni_common( + struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p, + struct bgp_dest *dest, struct bgp_path_info *parent_pi) + { +@@ -3243,7 +3305,7 @@ static int uninstall_evpn_route_entry_in_vni_common( + /* + * Install route entry into VNI IP table and invoke route selection. + */ +-static int install_evpn_route_entry_in_vni_ip(struct bgp *bgp, ++int install_evpn_route_entry_in_vni_ip(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) +@@ -3270,7 +3332,7 @@ static int install_evpn_route_entry_in_vni_ip(struct bgp *bgp, + /* + * Install route entry into VNI MAC table and invoke route selection. + */ +-static int install_evpn_route_entry_in_vni_mac(struct bgp *bgp, ++int install_evpn_route_entry_in_vni_mac(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) +@@ -3296,7 +3358,7 @@ static int install_evpn_route_entry_in_vni_mac(struct bgp *bgp, + /* + * Uninstall route entry from VNI IP table and invoke route selection. + */ +-static int uninstall_evpn_route_entry_in_vni_ip(struct bgp *bgp, ++int uninstall_evpn_route_entry_in_vni_ip(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) +@@ -3325,7 +3387,7 @@ static int uninstall_evpn_route_entry_in_vni_ip(struct bgp *bgp, + /* + * Uninstall route entry from VNI IP table and invoke route selection. + */ +-static int ++int + uninstall_evpn_route_entry_in_vni_mac(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) +@@ -3353,7 +3415,7 @@ uninstall_evpn_route_entry_in_vni_mac(struct bgp *bgp, struct bgpevpn *vpn, + * Uninstall route entry from the VRF routing table and send message + * to zebra, if appropriate. + */ +-static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, ++int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, + const struct prefix_evpn *evp, + struct bgp_path_info *parent_pi) + { +@@ -3445,7 +3507,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, + /* + * Install route entry into the VNI routing tables. + */ +-static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, ++int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) + { +@@ -3484,7 +3546,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + /* + * Uninstall route entry from the VNI routing tables. + */ +-static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, ++int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *parent_pi) + { +@@ -3524,7 +3586,7 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + * Given a route entry and a VRF, see if this route entry should be + * imported into the VRF i.e., RTs match + Site-of-Origin check passes. + */ +-static int is_route_matching_for_vrf(struct bgp *bgp_vrf, ++int is_route_matching_for_vrf(struct bgp *bgp_vrf, + struct bgp_path_info *pi) + { + struct attr *attr = pi->attr; +@@ -3591,7 +3653,7 @@ static int is_route_matching_for_vrf(struct bgp *bgp_vrf, + * Given a route entry and a VNI, see if this route entry should be + * imported into the VNI i.e., RTs match. + */ +-static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn, ++int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_path_info *pi) + { + struct attr *attr = pi->attr; +@@ -3654,7 +3716,7 @@ static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn, + return 0; + } + +-static bool bgp_evpn_route_matches_macvrf_soo(struct bgp_path_info *pi, ++bool bgp_evpn_route_matches_macvrf_soo(struct bgp_path_info *pi, + const struct prefix_evpn *evp) + { + struct bgp *bgp_evpn = bgp_get_evpn(); +@@ -3693,7 +3755,7 @@ static bool bgp_evpn_route_matches_macvrf_soo(struct bgp_path_info *pi, + * macthes with bgp instance router mac. It avoid installing + * route into bgp vrf table and remote rmac in bridge table. + */ +-static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf, ++int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf, + const struct prefix_evpn *evp, + struct bgp_path_info *pi) + { +@@ -3722,7 +3784,7 @@ static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf, + } + + /* don't import hosts that are locally attached */ +-static inline bool ++inline bool + bgp_evpn_skip_vrf_import_of_local_es(struct bgp *bgp_vrf, + const struct prefix_evpn *evp, + struct bgp_path_info *pi, int install) +@@ -3799,7 +3861,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, + * Install or uninstall mac-ip routes are appropriate for this + * particular VRF. + */ +-static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) ++int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) + { + afi_t afi; + safi_t safi; +@@ -3862,7 +3924,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) + * Install or uninstall routes of specified type that are appropriate for this + * particular VNI. + */ +-static int install_uninstall_routes_for_vni(struct bgp *bgp, ++int install_uninstall_routes_for_vni(struct bgp *bgp, + struct bgpevpn *vpn, + bgp_evpn_route_type rtype, + int install) +@@ -3948,7 +4010,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, + /* Install any existing remote routes applicable for this VRF into VRF RIB. This + * is invoked upon l3vni-add or l3vni import rt change + */ +-static int install_routes_for_vrf(struct bgp *bgp_vrf) ++int install_routes_for_vrf(struct bgp *bgp_vrf) + { + install_uninstall_routes_for_vrf(bgp_vrf, 1); + return 0; +@@ -3959,7 +4021,7 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf) + * routing table. This is invoked when a VNI becomes "live" or its Import + * RT is changed. + */ +-static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) ++int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + { + int ret; + +@@ -3981,7 +4043,7 @@ static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + } + + /* uninstall routes from l3vni vrf. */ +-static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) ++int uninstall_routes_for_vrf(struct bgp *bgp_vrf) + { + install_uninstall_routes_for_vrf(bgp_vrf, 0); + return 0; +@@ -3991,7 +4053,7 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) + * Uninstall any existing remote routes for this VNI. One scenario in which + * this is invoked is upon an import RT change. + */ +-static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) ++int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + { + int ret; + +@@ -4017,7 +4079,7 @@ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + /* + * Install or uninstall route in matching VRFs (list). + */ +-static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, ++int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, + safi_t safi, struct prefix_evpn *evp, + struct bgp_path_info *pi, + struct list *vrfs, int install) +@@ -4066,7 +4128,7 @@ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, + /* + * Install or uninstall route in matching VNIs (list). + */ +-static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, ++int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, + safi_t safi, struct prefix_evpn *evp, + struct bgp_path_info *pi, + struct list *vnis, int install) +@@ -4103,7 +4165,7 @@ static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, + /* + * Install or uninstall route for appropriate VNIs/ESIs. + */ +-static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi, ++int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi, + safi_t safi, const struct prefix *p, + struct bgp_path_info *pi, + int import, bool in_vni_rt, +@@ -4246,7 +4308,7 @@ static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi, + /* + * Install or uninstall route for appropriate VNIs/ESIs. + */ +-static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, ++int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, + const struct prefix *p, + struct bgp_path_info *pi, int import) + { +@@ -4270,7 +4332,7 @@ void bgp_evpn_import_type2_route(struct bgp_path_info *pi, int import) + * delete and withdraw all ipv4 and ipv6 routes in the vrf table as type-5 + * routes + */ +-static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) ++void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) + { + /* Delete ipv4 default route and withdraw from peers */ + if (evpn_default_originate_set(bgp_vrf, AFI_IP, SAFI_UNICAST)) +@@ -4329,7 +4391,7 @@ void update_advertise_vrf_routes(struct bgp *bgp_vrf) + * done in the global route table using the routes which already exist in the + * VRF routing table + */ +-static void update_router_id_vrf(struct bgp *bgp_vrf) ++void update_router_id_vrf(struct bgp *bgp_vrf) + { + /* skip if the RD is configured */ + if (is_vrf_rd_configured(bgp_vrf)) +@@ -4347,7 +4409,7 @@ static void update_router_id_vrf(struct bgp *bgp_vrf) + * This is invoked upon VRF RD change. The processing is done only from global + * table. + */ +-static void withdraw_router_id_vrf(struct bgp *bgp_vrf) ++void withdraw_router_id_vrf(struct bgp *bgp_vrf) + { + /* skip if the RD is configured */ + if (is_vrf_rd_configured(bgp_vrf)) +@@ -4357,7 +4419,7 @@ static void withdraw_router_id_vrf(struct bgp *bgp_vrf) + delete_withdraw_vrf_routes(bgp_vrf); + } + +-static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn, ++void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_dest *dest) + { + struct bgp_dest *global_dest; +@@ -4440,7 +4502,7 @@ static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn, + * change. Note that the processing is done only on the global route table + * using routes that already exist in the per-VNI table. + */ +-static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) ++void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + struct prefix_evpn p; + struct bgp_dest *dest, *global_dest; +@@ -4501,7 +4563,7 @@ static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + * Delete (and withdraw) local routes for a VNI - only from the global + * table. Invoked upon router-id change. + */ +-static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) ++int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + { + struct prefix_evpn p; + struct bgp_dest *global_dest; +@@ -4541,7 +4603,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) + * router-id. The routes in the per-VNI table are used to create routes in + * the global table and schedule them. + */ +-static void update_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) ++void update_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) + { + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + +@@ -4559,7 +4621,7 @@ static void update_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) + * the router-id and is done only on the global route table, the routes + * are needed in the per-VNI table to re-advertise with new router id. + */ +-static void withdraw_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) ++void withdraw_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) + { + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + +@@ -4574,7 +4636,7 @@ static void withdraw_router_id_vni(struct hash_bucket *bucket, struct bgp *bgp) + * Create RT-3 for a VNI and schedule for processing and advertisement. + * This is invoked upon flooding mode changing to head-end replication. + */ +-static void create_advertise_type3(struct hash_bucket *bucket, void *data) ++void create_advertise_type3(struct hash_bucket *bucket, void *data) + { + struct bgpevpn *vpn = bucket->data; + struct bgp *bgp = data; +@@ -4595,7 +4657,7 @@ static void create_advertise_type3(struct hash_bucket *bucket, void *data) + * Delete RT-3 for a VNI and schedule for processing and withdrawal. + * This is invoked upon flooding mode changing to drop BUM packets. + */ +-static void delete_withdraw_type3(struct hash_bucket *bucket, void *data) ++void delete_withdraw_type3(struct hash_bucket *bucket, void *data) + { + struct bgpevpn *vpn = bucket->data; + struct bgp *bgp = data; +@@ -4611,7 +4673,7 @@ static void delete_withdraw_type3(struct hash_bucket *bucket, void *data) + /* + * Process received EVPN type-2 route (advertise or withdraw). + */ +-static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, ++int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, uint8_t *pfx, int psize, + uint32_t addpath_id) + { +@@ -4740,7 +4802,7 @@ done: + /* + * Process received EVPN type-3 route (advertise or withdraw). + */ +-static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, ++int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, uint8_t *pfx, int psize, + uint32_t addpath_id) + { +@@ -4821,7 +4883,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, + /* + * Process received EVPN type-5 route (advertise or withdraw). + */ +-static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, ++int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, uint8_t *pfx, int psize, + uint32_t addpath_id) + { +@@ -4963,7 +5025,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, + return 0; + } + +-static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, ++void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, + const struct prefix_rd *prd, + mpls_label_t *label, uint32_t num_labels, + struct attr *attr) +@@ -5022,7 +5084,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, + /* + * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled. + */ +-static void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp) ++void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp) + { + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + +@@ -5038,7 +5100,7 @@ static void cleanup_vni_on_disable(struct hash_bucket *bucket, struct bgp *bgp) + /* + * Free a VNI entry; iterator function called during cleanup. + */ +-static void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp) ++void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp) + { + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; + +@@ -5049,7 +5111,7 @@ static void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp) + /* + * Derive AUTO import RT for BGP VRF - L3VNI + */ +-static void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf) ++void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf) + { + struct bgp *bgp_evpn = NULL; + +@@ -5067,7 +5129,7 @@ static void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf) + /* + * Delete AUTO import RT from BGP VRF - L3VNI + */ +-static void evpn_auto_rt_import_delete_for_vrf(struct bgp *bgp_vrf) ++void evpn_auto_rt_import_delete_for_vrf(struct bgp *bgp_vrf) + { + evpn_rt_delete_auto(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_import_rtl, + true); +@@ -5076,7 +5138,7 @@ static void evpn_auto_rt_import_delete_for_vrf(struct bgp *bgp_vrf) + /* + * Derive AUTO export RT for BGP VRF - L3VNI + */ +-static void evpn_auto_rt_export_add_for_vrf(struct bgp *bgp_vrf) ++void evpn_auto_rt_export_add_for_vrf(struct bgp *bgp_vrf) + { + form_auto_rt(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_export_rtl, true); + } +@@ -5084,13 +5146,13 @@ static void evpn_auto_rt_export_add_for_vrf(struct bgp *bgp_vrf) + /* + * Delete AUTO export RT from BGP VRF - L3VNI + */ +-static void evpn_auto_rt_export_delete_for_vrf(struct bgp *bgp_vrf) ++void evpn_auto_rt_export_delete_for_vrf(struct bgp *bgp_vrf) + { + evpn_rt_delete_auto(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_export_rtl, + true); + } + +-static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) ++void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) + { + struct bgp *bgp_evpn = NULL; + struct listnode *node = NULL; +@@ -5111,7 +5173,7 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) + /* + * Handle autort change for a given VNI. + */ +-static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) ++void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) + { + struct bgpevpn *vpn = bucket->data; + +@@ -5135,7 +5197,7 @@ static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) + /* + * Handle autort change for L3VNI. + */ +-static void update_autort_l3vni(struct bgp *bgp) ++void update_autort_l3vni(struct bgp *bgp) + { + if ((CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) + && (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD))) +@@ -5330,7 +5392,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, + } + } + +-static void rt_list_remove_node(struct list *rt_list, ++void rt_list_remove_node(struct list *rt_list, + struct ecommunity *ecomdel, bool is_l3) + { + struct listnode *node = NULL, *nnode = NULL, *node_to_del = NULL; +@@ -5379,7 +5441,7 @@ void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl, + ecommunity_free(&ecom_auto); + } + +-static void evpn_vrf_rt_routes_map(struct bgp *bgp_vrf) ++void evpn_vrf_rt_routes_map(struct bgp *bgp_vrf) + { + /* map VRFs to its RTs and install routes matching this new RT */ + if (is_l3vni_live(bgp_vrf)) { +@@ -5388,7 +5450,7 @@ static void evpn_vrf_rt_routes_map(struct bgp *bgp_vrf) + } + } + +-static void evpn_vrf_rt_routes_unmap(struct bgp *bgp_vrf) ++void evpn_vrf_rt_routes_unmap(struct bgp *bgp_vrf) + { + /* uninstall routes from vrf */ + if (is_l3vni_live(bgp_vrf)) +@@ -5398,7 +5460,7 @@ static void evpn_vrf_rt_routes_unmap(struct bgp *bgp_vrf) + bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf); + } + +-static bool rt_list_has_cfgd_rt(struct list *rt_list) ++bool rt_list_has_cfgd_rt(struct list *rt_list) + { + struct listnode *node = NULL, *nnode = NULL; + struct vrf_route_target *l3rt = NULL; +@@ -5411,7 +5473,7 @@ static bool rt_list_has_cfgd_rt(struct list *rt_list) + return false; + } + +-static void unconfigure_import_rt_for_vrf_fini(struct bgp *bgp_vrf) ++void unconfigure_import_rt_for_vrf_fini(struct bgp *bgp_vrf) + { + if (!bgp_vrf->vrf_import_rtl) + return; /* this should never fail */ +@@ -5424,7 +5486,7 @@ static void unconfigure_import_rt_for_vrf_fini(struct bgp *bgp_vrf) + evpn_auto_rt_import_add_for_vrf(bgp_vrf); + } + +-static void unconfigure_export_rt_for_vrf_fini(struct bgp *bgp_vrf) ++void unconfigure_export_rt_for_vrf_fini(struct bgp *bgp_vrf) + { + + if (!bgp_vrf->vrf_export_rtl) +@@ -6262,6 +6324,16 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, */ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) { @@ -330,52 +1341,240 @@ index 2b2cfa0f4c..622fd6afd2 100644 + } else + zebra_announce_add_tail(&bm->zebra_announce_head, dest); + } -+ bgp_evpn_remote_ip_hash_destroy(vpn); bgp_evpn_vni_es_cleanup(vpn); bgpevpn_unlink_from_l3vni(vpn); +@@ -6279,7 +6351,7 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) + XFREE(MTYPE_BGP_EVPN, vpn); + } + +-static void hash_evpn_free(struct bgpevpn *vpn) ++void hash_evpn_free(struct bgpevpn *vpn) + { + XFREE(MTYPE_BGP_EVPN, vpn); + } +@@ -6646,7 +6718,7 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, + return 0; + } + +-static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket, ++void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket, + struct bgp *bgp_vrf) + { + struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; +@@ -7265,7 +7337,7 @@ bool bgp_evpn_is_prefix_nht_supported(const struct prefix *pfx) + return false; + } + +-static void *bgp_evpn_remote_ip_hash_alloc(void *p) ++void *bgp_evpn_remote_ip_hash_alloc(void *p) + { + const struct evpn_remote_ip *key = (const struct evpn_remote_ip *)p; + struct evpn_remote_ip *ip; +@@ -7277,7 +7349,7 @@ static void *bgp_evpn_remote_ip_hash_alloc(void *p) + return ip; + } + +-static unsigned int bgp_evpn_remote_ip_hash_key_make(const void *p) ++unsigned int bgp_evpn_remote_ip_hash_key_make(const void *p) + { + const struct evpn_remote_ip *ip = p; + const struct ipaddr *addr = &ip->addr; +@@ -7289,7 +7361,7 @@ static unsigned int bgp_evpn_remote_ip_hash_key_make(const void *p) + array_size(addr->ipaddr_v6.s6_addr32), 0); + } + +-static bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2) ++bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2) + { + const struct evpn_remote_ip *ip1 = p1; + const struct evpn_remote_ip *ip2 = p2; +@@ -7297,7 +7369,7 @@ static bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2) + return !ipaddr_cmp(&ip1->addr, &ip2->addr); + } + +-static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn) ++void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn) + { + if (!evpn_resolve_overlay_index()) + return; +@@ -7307,7 +7379,7 @@ static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn) + "BGP EVPN remote IP hash"); + } + +-static void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args) ++void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args) + { + struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data; + struct bgpevpn *vpn = (struct bgpevpn *)args; +@@ -7320,7 +7392,7 @@ static void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args) + XFREE(MTYPE_EVPN_REMOTE_IP, ip); + } + +-static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn) ++void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn) + { + if (!evpn_resolve_overlay_index() || vpn->remote_ip_hash == NULL) + return; +@@ -7334,7 +7406,7 @@ static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn) + } + + /* Add a remote MAC/IP route to hash table */ +-static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, + struct bgp_path_info *pi) + { + struct evpn_remote_ip tmp; +@@ -7371,7 +7443,7 @@ static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn, + } + + /* Delete a remote MAC/IP route from hash table */ +-static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, + struct bgp_path_info *pi) + { + struct evpn_remote_ip tmp; +@@ -7403,7 +7475,7 @@ static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn, + } + } + +-static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, + void (*func)(struct hash_bucket *, + void *), + void *arg) +@@ -7414,7 +7486,7 @@ static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn, + hash_iterate(vpn->remote_ip_hash, func, arg); + } + +-static void show_remote_ip_entry(struct hash_bucket *bucket, void *args) ++void show_remote_ip_entry(struct hash_bucket *bucket, void *args) + { + char buf[INET6_ADDRSTRLEN]; + struct listnode *node = NULL; +@@ -7442,7 +7514,7 @@ void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args) + vty_out(vty, "\n"); + } + +-static void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket, ++void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket, + void *args) + { + struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data; +@@ -7451,7 +7523,7 @@ static void bgp_evpn_remote_ip_hash_link_nexthop(struct hash_bucket *bucket, + bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, true); + } + +-static void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket, ++void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket, + void *args) + { + struct evpn_remote_ip *ip = (struct evpn_remote_ip *)bucket->data; +@@ -7460,14 +7532,14 @@ static void bgp_evpn_remote_ip_hash_unlink_nexthop(struct hash_bucket *bucket, + bgp_evpn_remote_ip_process_nexthops(vpn, &ip->addr, false); + } + +-static unsigned int vni_svi_hash_key_make(const void *p) ++unsigned int vni_svi_hash_key_make(const void *p) + { + const struct bgpevpn *vpn = p; + + return jhash_1word(vpn->svi_ifindex, 0); + } + +-static bool vni_svi_hash_cmp(const void *p1, const void *p2) ++bool vni_svi_hash_cmp(const void *p1, const void *p2) + { + const struct bgpevpn *vpn1 = p1; + const struct bgpevpn *vpn2 = p2; +@@ -7475,7 +7547,7 @@ static bool vni_svi_hash_cmp(const void *p1, const void *p2) + return (vpn1->svi_ifindex == vpn2->svi_ifindex); + } + +-static struct bgpevpn *bgp_evpn_vni_svi_hash_lookup(struct bgp *bgp, ++struct bgpevpn *bgp_evpn_vni_svi_hash_lookup(struct bgp *bgp, + ifindex_t svi) + { + struct bgpevpn *vpn; +@@ -7487,7 +7559,7 @@ static struct bgpevpn *bgp_evpn_vni_svi_hash_lookup(struct bgp *bgp, + return vpn; + } + +-static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn) ++void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn) + { + if (vpn->svi_ifindex == 0) + return; +@@ -7495,7 +7567,7 @@ static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn) + (void)hash_get(bgp->vni_svi_hash, vpn, hash_alloc_intern); + } + +-static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp, ++void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp, + struct bgpevpn *vpn) + { + if (vpn->svi_ifindex == 0) +@@ -7572,7 +7644,7 @@ bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc) + } + + /* Resolve/Unresolve nexthops when a MAC/IP route is added/deleted */ +-static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn, ++void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn, + struct ipaddr *addr, + bool resolve) + { +@@ -7695,7 +7767,7 @@ vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi) + /* + * Returns true if the l3vni of any of this path doesn't match vrf's l3vni. + */ +-static bool bgp_evpn_path_is_dvni(const struct bgp *bgp_vrf, ++bool bgp_evpn_path_is_dvni(const struct bgp *bgp_vrf, + const struct bgp_path_info *pi) + { + vni_t vni = 0; +@@ -7781,4 +7853,5 @@ void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi, safi_t safi) + } + } + } +-} ++ return; ++} +\ No newline at end of file diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h -index 3cbc5af5af..bf1943a2db 100644 +index c641a64f6..db05293a4 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h -@@ -230,4 +230,12 @@ extern void +@@ -176,6 +176,14 @@ bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket, + extern void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket, void *arg); - +extern enum zclient_send_status evpn_zebra_install(struct bgp *bgp, -+ struct bgpevpn *vpn, -+ const struct prefix_evpn *p, -+ struct bgp_path_info *pi); ++ struct bgpevpn *vpn, ++ const struct prefix_evpn *p, ++ struct bgp_path_info *pi); +extern enum zclient_send_status +evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, struct bgp_path_info *pi, + bool is_sync); - #endif /* _QUAGGA_BGP_EVPN_H */ + extern mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels, + uint32_t num_labels); + extern vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi); diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c -index 552365959d..40687c558d 100644 +index d88c52d1f..f36d109b6 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c -@@ -56,13 +56,14 @@ static void bgp_evpn_local_es_down(struct bgp *bgp, - struct bgp_evpn_es *es); - static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp, - struct bgp_evpn_es *es); --static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, -+static struct bgp_evpn_es_vtep * -+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es, -+ struct in_addr vtep_ip, bool esr, uint8_t df_alg, -+ uint16_t df_pref, int *zret); -+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp, +@@ -49,8 +49,8 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es, struct in_addr vtep_ip, -- bool esr, uint8_t df_alg, + bool esr, uint8_t df_alg, - uint16_t df_pref); -static void bgp_evpn_es_vtep_del(struct bgp *bgp, -- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr); -+ bool esr); ++ uint16_t df_pref, int *zret); ++static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp, + struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr); static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es); static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es); - static struct bgp_evpn_es_evi * -@@ -105,6 +106,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, +@@ -94,6 +94,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, struct bgp_dest *dest) { int ret = 0; @@ -383,7 +1582,7 @@ index 552365959d..40687c558d 100644 afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; struct bgp_path_info *old_select; /* old best */ -@@ -131,7 +133,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, +@@ -120,7 +121,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop, true /*esr*/, old_select->attr->df_alg, @@ -392,7 +1591,7 @@ index 552365959d..40687c558d 100644 } UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(dest); -@@ -160,7 +162,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, +@@ -149,7 +150,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, && new_select->sub_type == BGP_ROUTE_IMPORTED) { bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop, true /*esr */, new_select->attr->df_alg, @@ -401,30 +1600,19 @@ index 552365959d..40687c558d 100644 } else { if (old_select && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_IMPORTED) -@@ -447,7 +449,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, - &attr->mp_nexthop_global_in); - } - -- /* Return back the route entry. */ -+ /* Return back th*e route entry. */ - *ri = tmp_pi; - return 0; - } -@@ -1366,23 +1368,28 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es, +@@ -1371,23 +1372,26 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es, } - + /* Send the remote ES to zebra for NHG programming */ -static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, -- struct bgp_evpn_es_vtep *es_vtep, bool add) -+static enum zclient_send_status -+bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, -+ bool add) ++static enum zclient_send_status bgp_zebra_send_remote_es_vtep(struct bgp *bgp, + struct bgp_evpn_es_vtep *es_vtep, bool add) { struct bgp_evpn_es *es = es_vtep->es; struct stream *s; uint32_t flags = 0; - - /* Check socket. */ + +- /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { @@ -433,7 +1621,7 @@ index 552365959d..40687c558d 100644 + __func__); + return ZCLIENT_SEND_SUCCESS; + } - + /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { if (BGP_DEBUG(zebra, ZEBRA)) @@ -442,263 +1630,230 @@ index 552365959d..40687c558d 100644 - return 0; + return ZCLIENT_SEND_SUCCESS; } - + if (es_vtep->flags & BGP_EVPNES_VTEP_ESR) -@@ -1413,12 +1420,12 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, +@@ -1418,12 +1422,13 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, return zclient_send_message(zclient); } - + -static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, -- struct bgp_evpn_es_vtep *es_vtep, -- bool param_change) -+static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active( -+ struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, bool param_change) ++static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, + struct bgp_evpn_es_vtep *es_vtep, + bool param_change) { bool old_active; bool new_active; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE); /* currently we need an active EVI reference to use the VTEP as -@@ -1440,7 +1447,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, +@@ -1445,7 +1450,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, es_vtep->df_alg, es_vtep->df_pref); - + /* send remote ES to zebra */ - bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active); + ret = bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active); - + /* The NHG is updated first for efficient failover handling. * Note the NHG can be de-activated while there are bgp -@@ -1452,13 +1459,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, +@@ -1457,13 +1462,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, /* queue up the es for background consistency checks */ bgp_evpn_es_cons_checks_pend_add(es_vtep->es); } -+ + return ret; } - --static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, -- struct bgp_evpn_es *es, -- struct in_addr vtep_ip, -- bool esr, uint8_t df_alg, + + static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, + struct bgp_evpn_es *es, + struct in_addr vtep_ip, + bool esr, uint8_t df_alg, - uint16_t df_pref) -+static struct bgp_evpn_es_vtep * -+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es, -+ struct in_addr vtep_ip, bool esr, uint8_t df_alg, -+ uint16_t df_pref, int *zret) ++ uint16_t df_pref, int *zret) { struct bgp_evpn_es_vtep *es_vtep; bool param_change = false; -@@ -1485,15 +1493,17 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, +@@ -1490,15 +1496,16 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, ++es_vtep->evi_cnt; } - + - bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); + *zret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); - + return es_vtep; } - + -static void bgp_evpn_es_vtep_do_del(struct bgp *bgp, -- struct bgp_evpn_es_vtep *es_vtep, bool esr) -+static enum zclient_send_status -+bgp_evpn_es_vtep_do_del(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, -+ bool esr) ++static enum zclient_send_status bgp_evpn_es_vtep_do_del(struct bgp *bgp, + struct bgp_evpn_es_vtep *es_vtep, bool esr) { bool param_change = false; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str, -@@ -1510,18 +1520,25 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp, +@@ -1515,18 +1522,21 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp, --es_vtep->evi_cnt; } - + - bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); + ret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); bgp_evpn_es_vtep_free(es_vtep); -+ + return ret; } - + -static void bgp_evpn_es_vtep_del(struct bgp *bgp, -- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr) +static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp, -+ struct bgp_evpn_es *es, -+ struct in_addr vtep_ip, -+ bool esr) + struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr) { struct bgp_evpn_es_vtep *es_vtep; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip); if (es_vtep) - bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr); + ret = bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr); -+ + return ret; } - + /********************** ES MAC-IP paths ************************************* -@@ -3382,12 +3399,14 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find( +@@ -3399,12 +3409,13 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find( /* A VTEP can be added as "active" attach to an ES if EAD-per-ES and * EAD-per-EVI routes are rxed from it. */ -static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, -- struct bgp_evpn_es_evi_vtep *evi_vtep) -+static enum zclient_send_status -+bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, -+ struct bgp_evpn_es_evi_vtep *evi_vtep) ++static enum zclient_send_status bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, + struct bgp_evpn_es_evi_vtep *evi_vtep) { bool old_active; bool new_active; uint32_t ead_activity_flags; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE); - -@@ -3408,7 +3427,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, + +@@ -3425,7 +3436,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE); - + if (old_active == new_active) - return; + return ret; - + if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("es %s evi %u vtep %pI4 %s", -@@ -3417,24 +3436,26 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, - new_active ? "active" : "inactive"); - - /* add VTEP to parent es */ -- if (new_active) -+ if (new_active) { +@@ -3437,19 +3448,20 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, + if (new_active) evi_vtep->es_vtep = bgp_evpn_es_vtep_add( bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip, - false /*esr*/, 0, 0); -- else { + false /*esr*/, 0, 0, &ret); -+ } else { + else { if (evi_vtep->es_vtep) { - bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep, -- false /*esr*/); + ret = bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep, -+ false /*esr*/); + false /*esr*/); evi_vtep->es_vtep = NULL; } } /* queue up the parent es for background consistency checks */ bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es); -+ + return ret; } - + -static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp, -- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, -- bool ead_es) -+static enum zclient_send_status -+bgp_evpn_es_evi_vtep_add(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi, -+ struct in_addr vtep_ip, bool ead_es) ++static enum zclient_send_status bgp_evpn_es_evi_vtep_add(struct bgp *bgp, + struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, + bool ead_es) { - struct bgp_evpn_es_evi_vtep *evi_vtep; - -@@ -3454,18 +3475,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp, +@@ -3475,18 +3487,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp, else SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI); - + - bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); + return bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); } - + -static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp, -- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, -- bool ead_es) -+static enum zclient_send_status -+bgp_evpn_es_evi_vtep_del(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi, -+ struct in_addr vtep_ip, bool ead_es) ++static enum zclient_send_status bgp_evpn_es_evi_vtep_del(struct bgp *bgp, + struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, + bool ead_es) { struct bgp_evpn_es_evi_vtep *evi_vtep; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip); if (!evi_vtep) - return; + return ret; - + if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("del es %s evi %u vtep %pI4 %s", -@@ -3478,8 +3500,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp, +@@ -3503,8 +3516,9 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp, else UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI); - + - bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); + ret = bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); bgp_evpn_es_evi_vtep_free(evi_vtep); -+ + return ret; } - + /* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */ -@@ -3755,18 +3779,20 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni) +@@ -3780,7 +3794,7 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni) /* Add remote ES-EVI entry. This is actually the remote VTEP add and the * ES-EVI is implicity created on first VTEP's reference. */ -int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p) -+enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp, -+ struct bgpevpn *vpn, -+ const struct prefix_evpn *p) ++enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p) { char buf[ESI_STR_LEN]; - struct bgp_evpn_es *es; +@@ -3788,10 +3802,11 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, struct bgp_evpn_es_evi *es_evi; bool ead_es; const esi_t *esi = &p->prefix.ead_addr.esi; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + if (!vpn) /* local EAD-ES need not be sent back to zebra */ - return 0; + return ret; - + if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("add remote %s es %s evi %u vtep %pI4", -@@ -3783,27 +3809,29 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, +@@ -3808,27 +3823,28 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, es_evi = bgp_evpn_es_evi_new(es, vpn); - + ead_es = !!p->prefix.ead_addr.eth_tag; - bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, -- ead_es); -+ ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi, -+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es); - ++ ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, + ead_es); + bgp_evpn_es_evi_remote_info_re_eval(es_evi); - return 0; + return ret; } - + /* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the * parent es-evi freed up implicitly in last VTEP's deref. */ -int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, -- const struct prefix_evpn *p) -+enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp, -+ struct bgpevpn *vpn, -+ const struct prefix_evpn *p) ++enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p) { char buf[ESI_STR_LEN]; struct bgp_evpn_es *es; struct bgp_evpn_es_evi *es_evi; bool ead_es; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; - + if (!vpn) /* local EAD-ES need not be sent back to zebra */ - return 0; + return ret; - + if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug( -@@ -3822,7 +3850,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, +@@ -3847,7 +3863,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)), vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4); @@ -707,31 +1862,29 @@ index 552365959d..40687c558d 100644 } es_evi = bgp_evpn_es_evi_find(es, vpn); if (!es_evi) { -@@ -3835,14 +3863,15 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, +@@ -3860,14 +3876,14 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, sizeof(buf)), vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4); - return 0; + return ret; } - + ead_es = !!p->prefix.ead_addr.eth_tag; - bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, -- ead_es); -+ ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi, -+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es); ++ ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, + ead_es); bgp_evpn_es_evi_remote_info_re_eval(es_evi); - return 0; -+ + return ret; } - + /* If a VNI is being deleted we need to force del all remote VTEPs */ diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h -index 11030e323f..d6e77e982f 100644 +index cebabb9fd..5d393c37a 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h -@@ -434,10 +434,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, +@@ -418,10 +418,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi); extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni); extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni); @@ -749,99 +1902,89 @@ index 11030e323f..d6e77e982f 100644 extern void bgp_evpn_mh_finish(void); void bgp_evpn_vni_es_init(struct bgpevpn *vpn); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index c29442d96c..679abba463 100644 +index e45d4b1ff..3dff073a3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c -@@ -3213,9 +3213,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, - && (new_select->sub_type == BGP_ROUTE_NORMAL - || new_select->sub_type +@@ -3420,7 +3420,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, == BGP_ROUTE_IMPORTED)) -- - bgp_zebra_route_install( -- dest, old_select, bgp, true); -+ dest, old_select, bgp, true, -+ NULL, false); + + bgp_zebra_route_install(dest, old_select, +- bgp, true); ++ bgp, true, NULL, false); } } - -@@ -3313,9 +3313,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, + +@@ -3529,9 +3529,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, + */ if (old_select && is_route_parent_evpn(old_select)) - bgp_zebra_route_install(dest, old_select, bgp, -- false); -+ false, NULL, false); - +- bgp_zebra_route_install(dest, old_select, bgp, false); ++ bgp_zebra_route_install(dest, old_select, bgp, false, NULL, false); + - bgp_zebra_route_install(dest, new_select, bgp, true); -+ bgp_zebra_route_install(dest, new_select, bgp, true, -+ NULL, false); ++ bgp_zebra_route_install(dest, new_select, bgp, true, NULL, false); } else { /* Withdraw the route from the kernel. */ if (old_select && old_select->type == ZEBRA_ROUTE_BGP -@@ -3324,7 +3325,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3539,7 +3539,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, + || old_select->sub_type == BGP_ROUTE_AGGREGATE || old_select->sub_type == BGP_ROUTE_IMPORTED)) - - bgp_zebra_route_install(dest, old_select, bgp, -- false); -+ false, NULL, false); + +- bgp_zebra_route_install(dest, old_select, bgp, false); ++ bgp_zebra_route_install(dest, old_select, bgp, false, NULL, false); } } - -@@ -4203,7 +4204,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, + +@@ -4444,7 +4444,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) /* remove from RIB previous entry */ - bgp_zebra_route_install(dest, pi, bgp, false); -+ bgp_zebra_route_install(dest, pi, bgp, false, NULL, -+ false); ++ bgp_zebra_route_install(dest, pi, bgp, false, NULL, false); } - + if (peer->sort == BGP_PEER_EBGP) { diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h -index 45d61f8dfd..9eb681ea3f 100644 +index 67431ea4f..1550d00ad 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h -@@ -103,6 +103,8 @@ struct bgp_node { - +@@ -75,10 +75,10 @@ struct bgp_dest { + struct bgp_dest *pdest; + + STAILQ_ENTRY(bgp_dest) pq; +- struct bgp_path_info *za_bgp_pi; +- struct zebra_announce_item zai; - struct bgp_path_info *za_bgp_pi; +- ++ struct bgp_path_info *za_bgp_pi; + struct bgpevpn *za_vpn; + bool za_is_sync; - uint64_t version; - + + mpls_label_t local_label; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index 1162941ef1..b81acaf8ec 100644 +index 064f23350..cab758fca 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c -@@ -1713,12 +1713,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) - for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) - for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && -- -- (pi->type == ZEBRA_ROUTE_BGP -- && (pi->sub_type == BGP_ROUTE_NORMAL -- || pi->sub_type == BGP_ROUTE_IMPORTED))) -- +@@ -1674,7 +1674,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) + && (pi->sub_type == BGP_ROUTE_NORMAL + || pi->sub_type == BGP_ROUTE_IMPORTED))) + - bgp_zebra_route_install(dest, pi, bgp, true); -+ (pi->type == ZEBRA_ROUTE_BGP && -+ (pi->sub_type == BGP_ROUTE_NORMAL || -+ pi->sub_type == BGP_ROUTE_IMPORTED))) -+ bgp_zebra_route_install(dest, pi, bgp, true, -+ NULL, false); ++ bgp_zebra_route_install(dest, pi, bgp, true, NULL, false); } - + /* Announce routes of any bgp subtype of a table to zebra */ -@@ -1740,7 +1739,8 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, +@@ -1696,7 +1696,7 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && pi->type == ZEBRA_ROUTE_BGP) - bgp_zebra_route_install(dest, pi, bgp, true); -+ bgp_zebra_route_install(dest, pi, bgp, true, -+ NULL, false); ++ bgp_zebra_route_install(dest, pi, bgp, true, NULL, false); } - - enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest, -@@ -1793,6 +1793,7 @@ enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest, + + +@@ -1749,6 +1749,7 @@ enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest, #define ZEBRA_ANNOUNCEMENTS_LIMIT 1000 static void bgp_handle_route_announcements_to_zebra(struct thread *e) { @@ -849,19 +1992,19 @@ index 1162941ef1..b81acaf8ec 100644 uint32_t count = 0; struct bgp_dest *dest = NULL; struct bgp_table *table = NULL; -@@ -1808,6 +1809,9 @@ static void bgp_handle_route_announcements_to_zebra(struct thread *e) +@@ -1764,6 +1765,9 @@ static void bgp_handle_route_announcements_to_zebra(struct thread *e) table = bgp_dest_table(dest); install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); + if (table && table->afi == AFI_L2VPN && + table->safi == SAFI_EVPN) + is_evpn = true; - + if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug( -@@ -1816,17 +1820,33 @@ static void bgp_handle_route_announcements_to_zebra(struct thread *e) +@@ -1772,17 +1776,32 @@ static void bgp_handle_route_announcements_to_zebra(struct thread *e) table->bgp->name_pretty, dest, dest->flags); - + if (install) { - status = bgp_zebra_announce_actual( - dest, dest->za_bgp_pi, table->bgp); @@ -887,23 +2030,21 @@ index 1162941ef1..b81acaf8ec 100644 + else + status = bgp_zebra_withdraw_actual( + dest, dest->za_bgp_pi, table->bgp); -+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE); } - + bgp_path_info_unlock(dest->za_bgp_pi); dest->za_bgp_pi = NULL; + dest->za_vpn = NULL; bgp_dest_unlock_node(dest); - + if (status == ZCLIENT_SEND_BUFFERED) -@@ -1880,8 +1900,16 @@ static void bgp_zebra_buffer_write_ready(void) +@@ -1836,8 +1855,14 @@ static void bgp_zebra_buffer_write_ready(void) * withdrawn. */ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, - struct bgp *bgp, bool install) -+ struct bgp *bgp, bool install, struct bgpevpn *vpn, -+ bool is_sync) ++ struct bgp *bgp, bool install, struct bgpevpn *vpn, bool is_sync) { + bool is_evpn = false; + struct bgp_table *table = NULL; @@ -911,41 +2052,40 @@ index 1162941ef1..b81acaf8ec 100644 + table = bgp_dest_table(dest); + if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) + is_evpn = true; -+ /* * BGP is installing this route and bgp has been configured * to suppress announcements until the route has been installed -@@ -1891,7 +1919,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1847,7 +1872,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, if (BGP_SUPPRESS_FIB_ENABLED(bgp)) SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); - + - if (bgp->main_zebra_update_hold) + if (bgp->main_zebra_update_hold && !is_evpn) return; } else { UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); -@@ -1901,7 +1929,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1857,7 +1882,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, * Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. */ - if (!bgp_install_info_to_zebra(bgp)) + if (!bgp_install_info_to_zebra(bgp) && !is_evpn) return; - + if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) && -@@ -1922,7 +1950,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1878,7 +1903,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, dest->za_bgp_pi = info; } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) { assert(dest->za_bgp_pi); - if (install) + if (install & !is_evpn) bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp); - + bgp_path_info_unlock(dest->za_bgp_pi); -@@ -1930,6 +1958,11 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1886,6 +1911,11 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, dest->za_bgp_pi = info; } - + + if (is_evpn) { + dest->za_vpn = vpn; + dest->za_is_sync = is_sync; @@ -954,42 +2094,40 @@ index 1162941ef1..b81acaf8ec 100644 if (install) { UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE); SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); -@@ -1960,7 +1993,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa +@@ -1916,7 +1946,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (pi->type == ZEBRA_ROUTE_BGP)) - bgp_zebra_route_install(dest, pi, bgp, false); -+ bgp_zebra_route_install(dest, pi, bgp, false, -+ NULL, false); ++ bgp_zebra_route_install(dest, pi, bgp, false, NULL, false); } } } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h -index 45fcf7f514..5186b7454e 100644 +index 83197c28e..92971b51f 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h -@@ -45,7 +45,8 @@ extern int bgp_zebra_get_table_range(uint32_t chunk_size, +@@ -30,7 +30,7 @@ extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size, extern int bgp_if_update_all(void); extern void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *path, struct bgp *bgp, - bool install); -+ bool install, struct bgpevpn *vpn, -+ bool is_sync); ++ bool install, struct bgpevpn *vpn, bool is_sync); + extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi); - - /* Announce routes of any bgp subtype of a table to zebra */ + extern enum zclient_send_status diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h -index bdf31f5161..dc660fb8f0 100644 +index a088a2e11..214a2f9b0 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h -@@ -512,6 +512,7 @@ struct bgp { - #define BGP_FLAG_HARD_ADMIN_RESET (1ULL << 31) - /* Evaluate the AIGP attribute during the best path selection process */ - #define BGP_FLAG_COMPARE_AIGP (1ULL << 32) +@@ -529,6 +529,7 @@ struct bgp { + #define BGP_FLAG_LU_IPV6_EXPLICIT_NULL (1ULL << 34) + #define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35) + #define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36) +#define BGP_FLAG_VNI_DOWN (1ULL << 38) - + /* BGP default address-families. * New peers inherit enabled afi/safis from bgp instance. --- -2.17.1 +-- +2.39.4 diff --git a/src/sonic-frr/patch/0037-bgpd-Increase-install-uninstall-speed-of-evpn-vpn-vn.patch b/src/sonic-frr/patch/0037-bgpd-Increase-install-uninstall-speed-of-evpn-vpn-vn.patch index a360a3101599..fa1a742b1a88 100644 --- a/src/sonic-frr/patch/0037-bgpd-Increase-install-uninstall-speed-of-evpn-vpn-vn.patch +++ b/src/sonic-frr/patch/0037-bgpd-Increase-install-uninstall-speed-of-evpn-vpn-vn.patch @@ -19,21 +19,18 @@ Signed-off-by: Rajasekar Raja Signed-off-by: Donald Sharp diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c -index 622fd6afd2..eb5aa9f077 100644 +index 79e16d8f9..00a45a819 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c -@@ -3752,9 +3752,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) - * particular VNI. +@@ -3926,7 +3926,6 @@ int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) */ - static int install_uninstall_routes_for_vni(struct bgp *bgp, -- struct bgpevpn *vpn, + int install_uninstall_routes_for_vni(struct bgp *bgp, + struct bgpevpn *vpn, - bgp_evpn_route_type rtype, -- int install) -+ struct bgpevpn *vpn, int install) + int install) { afi_t afi; - safi_t safi; -@@ -3785,7 +3783,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, +@@ -3958,7 +3957,9 @@ int install_uninstall_routes_for_vni(struct bgp *bgp, (const struct prefix_evpn *)bgp_dest_get_prefix( dest); @@ -44,19 +41,19 @@ index 622fd6afd2..eb5aa9f077 100644 continue; for (pi = bgp_dest_get_bgp_path_info(dest); pi; -@@ -3812,7 +3812,8 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, - bgp->vrf_id, - install ? "install" - : "uninstall", -- rtype == BGP_EVPN_MAC_IP_ROUTE +@@ -3991,7 +3992,8 @@ int install_uninstall_routes_for_vni(struct bgp *bgp, + bgp->vrf_id, + install ? "install" + : "uninstall", +- rtype == BGP_EVPN_MAC_IP_ROUTE + evp->prefix.route_type == + BGP_EVPN_MAC_IP_ROUTE - ? "MACIP" - : "IMET", - vpn->vni); -@@ -3845,23 +3846,11 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf) + ? "MACIP" + : "IMET", + vpn->vni); +@@ -4023,23 +4025,11 @@ int install_routes_for_vrf(struct bgp *bgp_vrf) */ - static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - @@ -81,9 +78,9 @@ index 622fd6afd2..eb5aa9f077 100644 } /* uninstall routes from l3vni vrf. */ -@@ -3877,25 +3866,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) +@@ -4055,25 +4045,11 @@ int uninstall_routes_for_vrf(struct bgp *bgp_vrf) */ - static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) + int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - @@ -112,5 +109,5 @@ index 622fd6afd2..eb5aa9f077 100644 /* -- -2.17.1 +2.39.4 diff --git a/src/sonic-frr/patch/0040-bgpd-backpressure-Fix-to-withdraw-evpn-type-5-routes.patch b/src/sonic-frr/patch/0040-bgpd-backpressure-Fix-to-withdraw-evpn-type-5-routes.patch index b74d86881ae5..9c4be324fb6a 100644 --- a/src/sonic-frr/patch/0040-bgpd-backpressure-Fix-to-withdraw-evpn-type-5-routes.patch +++ b/src/sonic-frr/patch/0040-bgpd-backpressure-Fix-to-withdraw-evpn-type-5-routes.patch @@ -17,38 +17,38 @@ Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c -index 679abba463..e28069767f 100644 +index 3dff073a3..26089e326 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c -@@ -3312,8 +3312,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, +@@ -3529,7 +3529,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, */ if (old_select && is_route_parent_evpn(old_select)) -- bgp_zebra_route_install(dest, old_select, bgp, -- false, NULL, false); +- bgp_zebra_route_install(dest, old_select, bgp, false, NULL, false); + bgp_zebra_withdraw_actual(dest, old_select, bgp); - - bgp_zebra_route_install(dest, new_select, bgp, true, - NULL, false); + + bgp_zebra_route_install(dest, new_select, bgp, true, NULL, false); + } else { diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c -index 524551b1e0..5d5525156b 100644 +index f0fe0ec5c..c0733dfe3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c -@@ -1889,11 +1889,9 @@ static void bgp_zebra_buffer_write_ready(void) +@@ -1844,11 +1844,10 @@ static void bgp_zebra_buffer_write_ready(void) * save new pi, mark as going to be * withdrawan, remove install flag * - * Withdrawal Install Special case, send withdrawal immediately - * Leave dest on list, release old pi, ++ * + * Withdrawal Install Leave dest on list, release old pi, * save new pi, mark as going to be - * installed. -+ * installed. ++ * installed * Withdrawal Withdrawal Leave dest on list, release old pi, * save new pi, mark as going to be * withdrawn. -@@ -1949,9 +1947,6 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, +@@ -1902,9 +1901,6 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, dest->za_bgp_pi = info; } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) { assert(dest->za_bgp_pi); @@ -58,6 +58,6 @@ index 524551b1e0..5d5525156b 100644 bgp_path_info_unlock(dest->za_bgp_pi); bgp_path_info_lock(info); dest->za_bgp_pi = info; --- -2.43.2 +-- +2.39.4 diff --git a/src/sonic-frr/patch/0042-zebra-Use-built-in-data-structure-counter.patch b/src/sonic-frr/patch/0042-zebra-Use-built-in-data-structure-counter.patch index 3401dae27158..b5dac2ba5897 100644 --- a/src/sonic-frr/patch/0042-zebra-Use-built-in-data-structure-counter.patch +++ b/src/sonic-frr/patch/0042-zebra-Use-built-in-data-structure-counter.patch @@ -12,19 +12,19 @@ to the queue. Signed-off-by: Donald Sharp diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c -index caa2f988e2..bc9815bb10 100644 +index b2fee4ff7..f45003cd2 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c -@@ -135,8 +135,6 @@ struct fpm_nl_ctx { - +@@ -133,8 +133,6 @@ struct fpm_nl_ctx { + /* Amount of data plane context processed. */ _Atomic uint32_t dplane_contexts; - /* Amount of data plane contexts enqueued. */ - _Atomic uint32_t ctxqueue_len; /* Peak amount of data plane contexts enqueued. */ _Atomic uint32_t ctxqueue_len_peak; - -@@ -311,6 +309,12 @@ DEFUN(fpm_show_counters, fpm_show_counters_cmd, + +@@ -328,6 +326,12 @@ DEFUN(fpm_show_counters, fpm_show_counters_cmd, FPM_STR "FPM statistic counters\n") { @@ -35,9 +35,9 @@ index caa2f988e2..bc9815bb10 100644 + } + vty_out(vty, "%30s\n%30s\n", "FPM counters", "============"); - + #define SHOW_COUNTER(label, counter) \ -@@ -324,8 +328,7 @@ DEFUN(fpm_show_counters, fpm_show_counters_cmd, +@@ -341,8 +345,7 @@ DEFUN(fpm_show_counters, fpm_show_counters_cmd, SHOW_COUNTER("Connection errors", gfnc->counters.connection_errors); SHOW_COUNTER("Data plane items processed", gfnc->counters.dplane_contexts); @@ -47,7 +47,7 @@ index caa2f988e2..bc9815bb10 100644 SHOW_COUNTER("Data plane items queue peak", gfnc->counters.ctxqueue_len_peak); SHOW_COUNTER("Buffer full hits", gfnc->counters.buffer_full); -@@ -344,6 +347,12 @@ DEFUN(fpm_show_counters_json, fpm_show_counters_json_cmd, +@@ -361,6 +364,12 @@ DEFUN(fpm_show_counters_json, fpm_show_counters_json_cmd, "FPM statistic counters\n" JSON_STR) { @@ -58,9 +58,9 @@ index caa2f988e2..bc9815bb10 100644 + } + struct json_object *jo; - + jo = json_object_new_object(); -@@ -357,8 +366,7 @@ DEFUN(fpm_show_counters_json, fpm_show_counters_json_cmd, +@@ -374,8 +383,7 @@ DEFUN(fpm_show_counters_json, fpm_show_counters_json_cmd, gfnc->counters.connection_errors); json_object_int_add(jo, "data-plane-contexts", gfnc->counters.dplane_contexts); @@ -70,25 +70,25 @@ index caa2f988e2..bc9815bb10 100644 json_object_int_add(jo, "data-plane-contexts-queue-peak", gfnc->counters.ctxqueue_len_peak); json_object_int_add(jo, "buffer-full-hits", gfnc->counters.buffer_full); -@@ -1380,8 +1388,6 @@ static void fpm_process_queue(struct thread *t) - +@@ -1427,8 +1435,6 @@ static void fpm_process_queue(struct event *t) + /* Account the processed entries. */ processed_contexts++; - atomic_fetch_sub_explicit(&fnc->counters.ctxqueue_len, 1, - memory_order_relaxed); - + dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS); dplane_provider_enqueue_out_ctx(fnc->prov, ctx); -@@ -1550,7 +1556,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) +@@ -1602,7 +1608,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) struct zebra_dplane_ctx *ctx; struct fpm_nl_ctx *fnc; int counter, limit; - uint64_t cur_queue, peak_queue = 0, stored_peak_queue; + uint64_t cur_queue = 0, peak_queue = 0, stored_peak_queue; - + fnc = dplane_provider_get_data(prov); limit = dplane_provider_get_work_limit(prov); -@@ -1564,20 +1570,12 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) +@@ -1616,20 +1622,12 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) * anyway. */ if (fnc->socket != -1 && fnc->connecting == false) { @@ -104,32 +104,32 @@ index caa2f988e2..bc9815bb10 100644 + cur_queue = + dplane_ctx_queue_count(&fnc->ctxqueue); } - + - cur_queue = atomic_load_explicit( - &fnc->counters.ctxqueue_len, - memory_order_relaxed); if (peak_queue < cur_queue) peak_queue = cur_queue; continue; -@@ -1594,9 +1592,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) +@@ -1646,9 +1644,7 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov) atomic_store_explicit(&fnc->counters.ctxqueue_len_peak, peak_queue, memory_order_relaxed); - + - if (atomic_load_explicit(&fnc->counters.ctxqueue_len, - memory_order_relaxed) - > 0) + if (cur_queue > 0) - thread_add_timer(fnc->fthread->master, fpm_process_queue, - fnc, 0, &fnc->t_dequeue); - + event_add_event(fnc->fthread->master, fpm_process_queue, fnc, 0, + &fnc->t_dequeue); + diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c -index 59b8d6cc63..c252a370b8 100644 +index 70ce555b1..a53bf8b25 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c -@@ -969,6 +969,11 @@ struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q) +@@ -956,6 +956,11 @@ struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_list_head *q) return ctx; } - + +uint32_t dplane_ctx_queue_count(struct dplane_ctx_list_head *q) +{ + return dplane_ctx_list_count(q); @@ -139,18 +139,18 @@ index 59b8d6cc63..c252a370b8 100644 * Accessors for information from the context object */ diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h -index 9f9496c8f4..c29e05bbc9 100644 +index 2f7d21850..51c1bff5d 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h -@@ -324,6 +324,8 @@ struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q); +@@ -316,6 +316,8 @@ struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_list_head *q); /* Init a list of contexts */ void dplane_ctx_q_init(struct dplane_ctx_list_head *q); - + +uint32_t dplane_ctx_queue_count(struct dplane_ctx_list_head *q); + /* * Accessors for information from the context object */ --- -2.43.2 +-- +2.39.4 diff --git a/src/sonic-frr/patch/0046-zebra-Modify-show-zebra-dplane-providers-to-give-mor.patch b/src/sonic-frr/patch/0046-zebra-Modify-show-zebra-dplane-providers-to-give-mor.patch index e865b861d192..847a63797fd3 100644 --- a/src/sonic-frr/patch/0046-zebra-Modify-show-zebra-dplane-providers-to-give-mor.patch +++ b/src/sonic-frr/patch/0046-zebra-Modify-show-zebra-dplane-providers-to-give-mor.patch @@ -20,42 +20,42 @@ r1# Signed-off-by: Donald Sharp diff --git a/zebra/rib.h b/zebra/rib.h -index 2e62148ea0..b78cd218f6 100644 +index a721f4bac..15f877b66 100644 --- a/zebra/rib.h +++ b/zebra/rib.h -@@ -630,6 +630,7 @@ static inline struct nexthop_group *rib_get_fib_backup_nhg( - } - +@@ -628,6 +628,7 @@ extern int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto, + uint8_t instance); + extern void zebra_vty_init(void); +extern uint32_t zebra_rib_dplane_results_count(void); - + extern pid_t pid; - + diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c -index f0e1ff6f27..21c73a3796 100644 +index e077c28d1..efa795331 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c -@@ -5998,12 +5998,14 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) +@@ -6089,12 +6089,14 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) struct zebra_dplane_provider *prov; uint64_t in, in_q, in_max, out, out_q, out_max; - + - vty_out(vty, "Zebra dataplane providers:\n"); - DPLANE_LOCK(); prov = dplane_prov_list_first(&zdplane_info.dg_providers); + in = dplane_ctx_queue_count(&zdplane_info.dg_update_list); DPLANE_UNLOCK(); - + + vty_out(vty, "dataplane Incoming Queue from Zebra: %" PRIu64 "\n", in); + vty_out(vty, "Zebra dataplane providers:\n"); + /* Show counters, useful info from each registered provider */ while (prov) { dplane_provider_lock(prov); -@@ -6022,13 +6024,19 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) +@@ -6113,13 +6115,19 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) out_max = atomic_load_explicit(&prov->dp_out_max, memory_order_relaxed); - + - vty_out(vty, "%s (%u): in: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64"\n", - prov->dp_name, prov->dp_id, in, in_q, in_max, - out, out_q, out_max); @@ -65,24 +65,24 @@ index f0e1ff6f27..21c73a3796 100644 + ", q_max: %" PRIu64 "\n", + prov->dp_name, prov->dp_id, in, in_q, in_max, out, + out_q, out_max); - + prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov); } - + + out = zebra_rib_dplane_results_count(); + vty_out(vty, "dataplane Outgoing Queue to Zebra: %" PRIu64 "\n", out); + return CMD_SUCCESS; } - + diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c -index 1ff3d98545..ae051d37eb 100644 +index 5b95d8668..430878daf 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c -@@ -4874,6 +4874,17 @@ static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist) +@@ -5001,6 +5001,17 @@ static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist) return 0; } - + +uint32_t zebra_rib_dplane_results_count(void) +{ + uint32_t count; @@ -97,6 +97,6 @@ index 1ff3d98545..ae051d37eb 100644 /* * Ensure there are no empty slots in the route_info array. * Every route type in zebra should be present there. --- -2.43.2 +-- +2.39.4 diff --git a/src/sonic-frr/patch/0048-bgpd-backpressure-fix-to-properly-remove-dest-for-bg.patch b/src/sonic-frr/patch/0048-bgpd-backpressure-fix-to-properly-remove-dest-for-bg.patch index 1731b6d21f31..e98f867fa9af 100644 --- a/src/sonic-frr/patch/0048-bgpd-backpressure-fix-to-properly-remove-dest-for-bg.patch +++ b/src/sonic-frr/patch/0048-bgpd-backpressure-fix-to-properly-remove-dest-for-bg.patch @@ -22,16 +22,16 @@ Signed-off-by: Chirag Shah Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c -index 2243ffdc77..b1f8f19594 100644 +index 5e62854ed..c517a67f5 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c -@@ -6074,16 +6074,16 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, +@@ -6301,16 +6301,16 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) { struct bgp_dest *dest = NULL; - uint32_t ann_count = zebra_announce_count(&bm->zebra_announce_head); + struct bgp_dest *dest_next = NULL; - + - while (ann_count) { - dest = zebra_announce_pop(&bm->zebra_announce_head); - ann_count--; @@ -46,13 +46,13 @@ index 2243ffdc77..b1f8f19594 100644 + zebra_announce_del(&bm->zebra_announce_head, dest); + } } - bgp_evpn_remote_ip_hash_destroy(vpn); + bgp_evpn_vni_es_cleanup(vpn); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c -index 492566f8c8..e16a58b443 100644 +index 4348a60c5..24577768f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c -@@ -3689,19 +3689,25 @@ int bgp_delete(struct bgp *bgp) +@@ -3868,19 +3868,25 @@ int bgp_delete(struct bgp *bgp) safi_t safi; int i; struct bgp_dest *dest = NULL; @@ -60,9 +60,9 @@ index 492566f8c8..e16a58b443 100644 + struct bgp_table *dest_table = NULL; struct graceful_restart_info *gr_info; - uint32_t ann_count = zebra_announce_count(&bm->zebra_announce_head); - + assert(bgp); - + - while (ann_count) { - dest = zebra_announce_pop(&bm->zebra_announce_head); - ann_count--; @@ -83,8 +83,8 @@ index 492566f8c8..e16a58b443 100644 + zebra_announce_del(&bm->zebra_announce_head, dest); + } } - + bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL); --- -2.43.2 +-- +2.39.4 diff --git a/src/sonic-frr/patch/0050-bgpd-backpressure-Avoid-use-after-free.patch b/src/sonic-frr/patch/0050-bgpd-backpressure-Avoid-use-after-free.patch index 878d60eb5e37..f4f1b6b3b42c 100644 --- a/src/sonic-frr/patch/0050-bgpd-backpressure-Avoid-use-after-free.patch +++ b/src/sonic-frr/patch/0050-bgpd-backpressure-Avoid-use-after-free.patch @@ -14,10 +14,10 @@ Ticket :#4001204 Signed-off-by: Rajasekar Raja diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c -index b1f8f19594..bb3cd62950 100644 +index c517a67f5..63e2e1c05 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c -@@ -6080,9 +6080,9 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) +@@ -6307,9 +6307,9 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) dest = dest_next) { dest_next = zebra_announce_next(&bm->zebra_announce_head, dest); if (dest->za_vpn == vpn) { @@ -27,12 +27,12 @@ index b1f8f19594..bb3cd62950 100644 - zebra_announce_del(&bm->zebra_announce_head, dest); } } - + bgp_evpn_remote_ip_hash_destroy(vpn); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c -index 2e1c5e555b..342982069b 100644 +index 8132d0515..8ebfde10c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c -@@ -3706,9 +3706,9 @@ int bgp_delete(struct bgp *bgp) +@@ -3885,9 +3885,9 @@ int bgp_delete(struct bgp *bgp) dest_next = zebra_announce_next(&bm->zebra_announce_head, dest); dest_table = bgp_dest_table(dest); if (dest_table->bgp == bgp) { @@ -42,7 +42,7 @@ index 2e1c5e555b..342982069b 100644 - zebra_announce_del(&bm->zebra_announce_head, dest); } } - --- -2.43.2 + +-- +2.39.4 diff --git a/src/sonic-frr/patch/0053-bgpd-Set-md5-TCP-socket-option-for-outgoing-connections-on-listener.patch b/src/sonic-frr/patch/0053-bgpd-Set-md5-TCP-socket-option-for-outgoing-connections-on-listener.patch deleted file mode 100644 index 791f52de3966..000000000000 --- a/src/sonic-frr/patch/0053-bgpd-Set-md5-TCP-socket-option-for-outgoing-connections-on-listener.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c -index 76bb9949d..974a57ef2 100644 ---- a/bgpd/bgp_network.c -+++ b/bgpd/bgp_network.c -@@ -774,6 +774,9 @@ int bgp_connect(struct peer *peer) - ? IPV4_MAX_BITLEN - : IPV6_MAX_BITLEN; - -+ if (!BGP_PEER_SU_UNSPEC(peer)) -+ bgp_md5_set(peer); -+ - bgp_md5_set_connect(peer->fd, &peer->su, prefixlen, - peer->password); - } diff --git a/src/sonic-frr/patch/build-dplane-fpm-sonic-module.patch b/src/sonic-frr/patch/0054-build-dplane-fpm-sonic-module.patch similarity index 62% rename from src/sonic-frr/patch/build-dplane-fpm-sonic-module.patch rename to src/sonic-frr/patch/0054-build-dplane-fpm-sonic-module.patch index 1ada5d9604df..03af6cad3143 100644 --- a/src/sonic-frr/patch/build-dplane-fpm-sonic-module.patch +++ b/src/sonic-frr/patch/0054-build-dplane-fpm-sonic-module.patch @@ -1,43 +1,46 @@ -Build dplane_fpm_sonic module +From 9e789e450003b9d2c7347c9f9b0d29d9b84d525f Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 1 Oct 2024 02:28:17 -0700 +Subject: [PATCH] Build dplane_fpm_sonic module From: Carmine Scarpitta Signed-off-by: Carmine Scarpitta --- - debian/frr.install | 1 + - redhat/frr.spec.in | 1 + - zebra/subdir.am | 6 ++++++ + debian/frr.install | 1 + + redhat/frr.spec.in | 1 + + zebra/subdir.am | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/debian/frr.install b/debian/frr.install -index 044b48498..f53b874e3 100644 +index d4b904b6e..375f0dadd 100644 --- a/debian/frr.install +++ b/debian/frr.install -@@ -10,6 +10,7 @@ usr/lib/*/frr/libfrrcares.* - usr/lib/*/frr/libfrrospfapiclient.* +@@ -11,6 +11,7 @@ usr/lib/*/frr/libfrrospfapiclient.* + usr/lib/*/frr/libmgmt_be_nb.* usr/lib/*/frr/modules/bgpd_bmp.so usr/lib/*/frr/modules/dplane_fpm_nl.so +usr/lib/*/frr/modules/dplane_fpm_sonic.so usr/lib/*/frr/modules/zebra_cumulus_mlag.so usr/lib/*/frr/modules/zebra_fpm.so - usr/lib/*/frr/modules/zebra_irdp.so + usr/lib/*/frr/modules/pathd_pcep.so diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in -index 4afd562a8..2eab817c9 100644 +index 13d5b8689..ffbe872c4 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in -@@ -714,6 +714,7 @@ fi +@@ -723,6 +723,7 @@ fi %endif %{_libdir}/frr/modules/zebra_cumulus_mlag.so %{_libdir}/frr/modules/dplane_fpm_nl.so +%{_libdir}/frr/modules/dplane_fpm_sonic.so - %{_libdir}/frr/modules/zebra_irdp.so %{_libdir}/frr/modules/bgpd_bmp.so - %{_bindir}/* + %{_libdir}/libfrr_pb.so* + %{_libdir}/libfrrfpm_pb.so* diff --git a/zebra/subdir.am b/zebra/subdir.am -index 5c4a87b93..3f1807d26 100644 +index d9c8d9045..ecc7195ae 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am -@@ -236,6 +236,12 @@ zebra_dplane_fpm_nl_la_LDFLAGS = $(MODULE_LDFLAGS) +@@ -245,6 +245,12 @@ zebra_dplane_fpm_nl_la_LDFLAGS = $(MODULE_LDFLAGS) zebra_dplane_fpm_nl_la_LIBADD = endif @@ -50,3 +53,6 @@ index 5c4a87b93..3f1807d26 100644 if NETLINK_DEBUG zebra_zebra_SOURCES += \ zebra/debug_nl.c \ +-- +2.39.4 + diff --git a/src/sonic-frr/patch/bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch b/src/sonic-frr/patch/0055-bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch similarity index 54% rename from src/sonic-frr/patch/bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch rename to src/sonic-frr/patch/0055-bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch index 161a0454b3c5..ce4ee66ab317 100644 --- a/src/sonic-frr/patch/bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch +++ b/src/sonic-frr/patch/0055-bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch @@ -6,47 +6,12 @@ Subject: [PATCH 1/5] lib: Include SID structure in seg6local nexthop Include SID structure information in seg6local nexthop data structure. Signed-off-by: Carmine Scarpitta ---- - lib/srv6.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/srv6.h b/lib/srv6.h -index acfb0631cc..3749b01563 100644 ---- a/lib/srv6.h -+++ b/lib/srv6.h -@@ -72,6 +72,10 @@ struct seg6local_context { - struct in_addr nh4; - struct in6_addr nh6; - uint32_t table; -+ uint8_t block_len; -+ uint8_t node_len; -+ uint8_t function_len; -+ uint8_t argument_len; - }; - - struct srv6_locator { --- -2.45.2 - - -From ebea171cadaae63d89c41fdd5e4d507cf9084e42 Mon Sep 17 00:00:00 2001 -From: Carmine Scarpitta -Date: Sun, 15 Sep 2024 18:53:35 +0200 -Subject: [PATCH 2/5] bgpd: Include structure when installing End.DT4/6 SID - -Include SID structure information when installing an SRv6 End.DT6 or End.DT4 SID -in the forwarding plane. - -Signed-off-by: Carmine Scarpitta ---- - bgpd/bgp_mplsvpn.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c -index 2af553d982..b9eef35812 100644 +index 58e3097e1..ef8ca39e8 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c -@@ -393,6 +393,18 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi) +@@ -381,6 +381,19 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi) if (!vrf) return; @@ -62,31 +27,11 @@ index 2af553d982..b9eef35812 100644 + bgp->vpn_policy[afi] + .tovpn_sid_locator->argument_bits_length; + } ++ ctx.table = vrf->data.l.table_id; act = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4 : ZEBRA_SEG6_LOCAL_ACTION_END_DT6; --- -2.45.2 - - -From f5c7cf0edc25905d357effe54ece27ed5db0ae6b Mon Sep 17 00:00:00 2001 -From: Carmine Scarpitta -Date: Sun, 15 Sep 2024 18:54:55 +0200 -Subject: [PATCH 3/5] bgpd: Include structure when installing End.DT46 SID - -Include SID structure information when installing an SRv6 End.DT46 SID -in the forwarding plane. - -Signed-off-by: Carmine Scarpitta ---- - bgpd/bgp_mplsvpn.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c -index b9eef35812..005a54ec1b 100644 ---- a/bgpd/bgp_mplsvpn.c -+++ b/bgpd/bgp_mplsvpn.c -@@ -453,6 +453,12 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp) +@@ -432,6 +445,13 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp) if (!vrf) return; @@ -96,31 +41,11 @@ index b9eef35812..005a54ec1b 100644 + ctx.function_len = bgp->tovpn_sid_locator->function_bits_length; + ctx.argument_len = bgp->tovpn_sid_locator->argument_bits_length; + } ++ ctx.table = vrf->data.l.table_id; act = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx); --- -2.45.2 - - -From e2428a573321cb5909a3858008df2968b655a086 Mon Sep 17 00:00:00 2001 -From: Carmine Scarpitta -Date: Sun, 15 Sep 2024 18:56:21 +0200 -Subject: [PATCH 4/5] bgpd: Include structure when removing End.DT4/6 SID - -Include SID structure information when removing an SRv6 End.DT4 or End.DT6 SID -from the forwarding plane. - -Signed-off-by: Carmine Scarpitta ---- - bgpd/bgp_mplsvpn.c | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c -index 005a54ec1b..aba1b4febe 100644 ---- a/bgpd/bgp_mplsvpn.c -+++ b/bgpd/bgp_mplsvpn.c -@@ -495,6 +495,7 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi) +@@ -470,6 +490,7 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi) void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) { int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); @@ -128,7 +53,7 @@ index 005a54ec1b..aba1b4febe 100644 if (bgp->vrf_id == VRF_UNKNOWN) { if (debug) -@@ -507,9 +508,22 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) +@@ -482,9 +503,23 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) zlog_debug("%s: deleting sid for vrf %s afi (id=%d)", __func__, bgp->name_pretty, bgp->vrf_id); @@ -144,37 +69,17 @@ index 005a54ec1b..aba1b4febe 100644 + bgp->vpn_policy[afi] + .tovpn_sid_locator->argument_bits_length; + } ++ zclient_send_localsid(zclient, - bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent, - bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL); -+ bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent, -+ bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, -+ &seg6localctx); ++ bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent, ++ bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, ++ &seg6localctx); XFREE(MTYPE_BGP_SRV6_SID, bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); - } --- -2.45.2 - - -From 8d148b738cdf8b987a67e13979331d91337494f3 Mon Sep 17 00:00:00 2001 -From: Carmine Scarpitta -Date: Sun, 15 Sep 2024 18:56:48 +0200 -Subject: [PATCH 5/5] bgpd: Include structure when removing End.DT46 SID - -Include SID structure information when removing an SRv6 End.DT46 SID -from the forwarding plane. - -Signed-off-by: Carmine Scarpitta ---- - bgpd/bgp_mplsvpn.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c -index aba1b4febe..6589f3e388 100644 ---- a/bgpd/bgp_mplsvpn.c -+++ b/bgpd/bgp_mplsvpn.c -@@ -535,6 +535,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = NULL; +@@ -497,6 +532,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi) void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) { int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL); @@ -182,7 +87,7 @@ index aba1b4febe..6589f3e388 100644 if (bgp->vrf_id == VRF_UNKNOWN) { if (debug) -@@ -548,9 +549,18 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) +@@ -510,9 +546,19 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp) zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__, bgp->name_pretty, bgp->vrf_id); @@ -195,13 +100,26 @@ index aba1b4febe..6589f3e388 100644 + seg6localctx.argument_len = + bgp->tovpn_sid_locator->argument_bits_length; + } ++ zclient_send_localsid(zclient, bgp->tovpn_zebra_vrf_sid_last_sent, bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, - NULL); + &seg6localctx); XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); + bgp->tovpn_zebra_vrf_sid_last_sent = NULL; } +diff --git a/lib/srv6.h b/lib/srv6.h +index 433c5c14f..53f5119aa 100644 +--- a/lib/srv6.h ++++ b/lib/srv6.h +@@ -103,6 +103,10 @@ struct seg6local_context { + struct in_addr nh4; + struct in6_addr nh6; + uint32_t table; ++ uint8_t block_len; ++ uint8_t node_len; ++ uint8_t function_len; ++ uint8_t argument_len; + struct seg6local_flavors_info flv; + }; --- -2.45.2 - diff --git a/src/sonic-frr/patch/0056-zebra-do-not-send-local-routes-to-fpm.patch b/src/sonic-frr/patch/0056-zebra-do-not-send-local-routes-to-fpm.patch new file mode 100644 index 000000000000..85f98f58ea41 --- /dev/null +++ b/src/sonic-frr/patch/0056-zebra-do-not-send-local-routes-to-fpm.patch @@ -0,0 +1,80 @@ +From 94d88c9e9155756fce152141e0d0d86e64a6981d Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Mon, 25 Nov 2024 01:32:36 -0800 +Subject: [PATCH] https://github.com/FRRouting/frr/pull/12600, we are now + installing a new host route for every connected route (along with the subnet + route). However, the orchagent already installs a host route for a connected + interface address. Hence, not sending the connected host route to the FPM. + +--- + zebra/connected.c | 4 ++-- + zebra/zebra_rib.c | 16 ++++++++++++++-- + 2 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/zebra/connected.c b/zebra/connected.c +index 404f892f6..2c698bed1 100644 +--- a/zebra/connected.c ++++ b/zebra/connected.c +@@ -191,7 +191,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) + uint32_t flags = 0; + uint32_t count = 0; + struct connected *c; +- bool install_local = true; ++ bool install_local = false; + + zvrf = ifp->vrf->info; + if (!zvrf) { +@@ -394,7 +394,7 @@ void connected_down(struct interface *ifp, struct connected *ifc) + struct zebra_vrf *zvrf; + uint32_t count = 0; + struct connected *c; +- bool remove_local = true; ++ bool remove_local = false; + + zvrf = ifp->vrf->info; + if (!zvrf) { +diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c +index 5b95d8668..b0921f657 100644 +--- a/zebra/zebra_rib.c ++++ b/zebra/zebra_rib.c +@@ -701,6 +701,12 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, + /* Update fib selection */ + dest->selected_fib = re; + ++ /* Do not install local routes to FIB */ ++ if (re->type == ZEBRA_ROUTE_LOCAL) { ++ zlog_debug("Not installing local route re %p (%s)", ++ re, zebra_route_string(re->type)); ++ return; ++ } + /* + * Make sure we update the FPM any time we send new information to + * the kernel. +@@ -762,6 +768,12 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) + return; + } + ++ /* Do not uninstall local routes to FIB */ ++ if (re->type == ZEBRA_ROUTE_LOCAL) { ++ zlog_debug("Not uninstalling local route re %p (%s)", ++ re, zebra_route_string(re->type)); ++ return; ++ } + /* + * Make sure we update the FPM any time we send new information to + * the dataplane. +@@ -1196,9 +1208,9 @@ static struct route_entry *rib_choose_best(struct route_entry *current, + * or loopback interface. If not, pick the last connected + * route of the set of lowest metric connected routes. + */ +- possible = rib_choose_best_type(ZEBRA_ROUTE_LOCAL, current, alternate); ++ /*possible = rib_choose_best_type(ZEBRA_ROUTE_LOCAL, current, alternate); + if (possible) +- return possible; ++ return possible; */ + + possible = rib_choose_best_type(ZEBRA_ROUTE_CONNECT, current, alternate); + if (possible) +-- +2.39.4 + diff --git a/src/sonic-frr/patch/0057-Adding-changes-to-write-ip-nht-resolve-via-default-c.patch b/src/sonic-frr/patch/0057-Adding-changes-to-write-ip-nht-resolve-via-default-c.patch new file mode 100644 index 000000000000..1e832b803e78 --- /dev/null +++ b/src/sonic-frr/patch/0057-Adding-changes-to-write-ip-nht-resolve-via-default-c.patch @@ -0,0 +1,85 @@ +From 274386fbefc83dc4f2f3184637db3c973f8200b6 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Wed, 13 Nov 2024 23:12:22 -0800 +Subject: [PATCH] Adding changes to write ip nht resolve-via-default + configuration for VRF in zebra + +--- + zebra/zebra_vrf.c | 34 +++++++++++++++++++++++++++++++++++ + zebra/zebra_vrf.h | 1 + + zebra/zebra_vty.c | 2 ++ + 3 files changed, 37 insertions(+) + +diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c +index e464e47b1..ae8624a5e 100644 +--- a/zebra/zebra_vrf.c ++++ b/zebra/zebra_vrf.c +@@ -541,6 +541,40 @@ int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, + return CMD_SUCCESS; + } + ++void zebra_vrf_config_write(struct vty *vty) ++{ ++ struct vrf *vrf; ++ struct zebra_vrf *zvrf; ++ ++ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { ++ zvrf = vrf->info; ++ ++ if (!zvrf) ++ continue; ++ ++ if (zvrf_id(zvrf) == VRF_DEFAULT) { ++ if (zvrf->zebra_rnh_ip_default_route) ++ vty_out(vty, "ip nht resolve-via-default\n"); ++ ++ if (zvrf->zebra_rnh_ipv6_default_route) ++ vty_out(vty, "ipv6 nht resolve-via-default\n"); ++ } else { ++ vty_frame(vty, "vrf %s\n", zvrf_name(zvrf)); ++ if (zvrf->zebra_rnh_ip_default_route) ++ vty_out(vty, " ip nht resolve-via-default\n"); ++ ++ if (zvrf->zebra_rnh_ipv6_default_route) ++ vty_out(vty, " ipv6 nht resolve-via-default\n"); ++ } ++ if (zvrf_id(zvrf) != VRF_DEFAULT) ++ vty_endframe(vty, "exit-vrf\n!\n"); ++ else ++ vty_out(vty, "!\n"); ++ } ++ return 0; ++ ++} ++ + /* Zebra VRF initialization. */ + void zebra_vrf_init(void) + { +diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h +index 5cbfab1dd..36f42a3db 100644 +--- a/zebra/zebra_vrf.h ++++ b/zebra/zebra_vrf.h +@@ -246,6 +246,7 @@ extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *); + extern vrf_id_t zebra_vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id); + extern struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf); + extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t); ++extern void zebra_vrf_config_write(struct vty *vty); + + /* + * API to associate a VRF with a NETNS. +diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c +index 9a68d5ae9..ce772b818 100644 +--- a/zebra/zebra_vty.c ++++ b/zebra/zebra_vty.c +@@ -3809,6 +3809,8 @@ static int config_write_protocol(struct vty *vty) + + zebra_pbr_config_write(vty); + ++ zebra_vrf_config_write(vty); ++ + if (!zebra_vxlan_get_accept_bgp_seq()) + vty_out(vty, "no evpn accept-bgp-seq\n"); + +-- +2.39.4 + diff --git a/src/sonic-frr/patch/0058-When-the-file-is-config-replayed-we-cannot-handle-th.patch b/src/sonic-frr/patch/0058-When-the-file-is-config-replayed-we-cannot-handle-th.patch new file mode 100644 index 000000000000..a952c0a609b3 --- /dev/null +++ b/src/sonic-frr/patch/0058-When-the-file-is-config-replayed-we-cannot-handle-th.patch @@ -0,0 +1,71 @@ +From 83714071c68c588c66972fc0fe0f5f2a57a7dd55 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Thu, 21 Nov 2024 20:57:11 -0800 +Subject: [PATCH] When the file is config replayed, we cannot handle the errors + in command execution. We would let all commands in the file to complete, + irrespective of some of them failing. Also, certain protocols like RIP, RIPng + are not supported in SONIC. So, it is expected that their configuration files + will not be present. + +--- + lib/vty.c | 16 +++++++++++++--- + mgmtd/mgmt_be_adapter.c | 2 +- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/lib/vty.c b/lib/vty.c +index 1c9cff478..017e0c7c4 100644 +--- a/lib/vty.c ++++ b/lib/vty.c +@@ -2654,7 +2654,9 @@ void vty_read_file_finish(struct vty *vty, struct nb_config *config) + nl = strchr(ve->error_buf, '\n'); + if (nl) + *nl = '\0'; +- flog_err(EC_LIB_VTY, "%s on config line %u: %s", message, ++ /* When the file is config replayed, we cannot handle the errors in command execution. ++ We would let all commands in the file to complete, irrespective of some of them failing. */ ++ flog_warn(EC_LIB_VTY, "%s on config line %u: %s", message, + ve->line_num, ve->error_buf); + } + +@@ -2773,7 +2775,11 @@ FILE *vty_open_config(const char *config_file, char *config_default_dir) + flog_warn(EC_LIB_BACKUP_CONFIG, + "using backup configuration file!"); + else { +- flog_err( ++ /* There are few protocols e.g. RIP, RIPng, which are ununsed in SONIC. ++ So, there will not be any config file for them. ++ Flagging error, will be considered a breakage by loganalyzer, whereas ++ it is valid for these protocol config file to be not present. */ ++ flog_warn( + EC_LIB_VTY, + "%s: can't open configuration file [%s]", + __func__, config_file); +@@ -2822,7 +2828,11 @@ FILE *vty_open_config(const char *config_file, char *config_default_dir) + "using backup configuration file!"); + fullpath = config_default_dir; + } else { +- flog_err(EC_LIB_VTY, ++ /* There are few protocols e.g. RIP, RIPng, which are ununsed in SONIC. ++ So, there will not be any config file for them. ++ Flagging error, will be considered a breakage by loganalyzer, whereas ++ it is valid for these protocol config file to be not present. */ ++ flog_warn(EC_LIB_VTY, + "can't open configuration file [%s]", + config_default_dir); + goto tmp_free_and_out; +diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c +index b311bf469..58f866115 100644 +--- a/mgmtd/mgmt_be_adapter.c ++++ b/mgmtd/mgmt_be_adapter.c +@@ -732,7 +732,7 @@ static void mgmt_be_adapter_conn_init(struct event *thread) + * transaction in progress. + */ + if (mgmt_txn_notify_be_adapter_conn(adapter, true) != 0) { +- zlog_err("XXX txn in progress, retry init"); ++ zlog_warn("XXX txn in progress, retry init"); + mgmt_be_adapter_sched_init_event(adapter); + return; + } +-- +2.39.4 + diff --git a/src/sonic-frr/patch/0059-Fix-BGP-reset-on-suppress-fib-pending-configuration.patch b/src/sonic-frr/patch/0059-Fix-BGP-reset-on-suppress-fib-pending-configuration.patch new file mode 100644 index 000000000000..9d3962f55183 --- /dev/null +++ b/src/sonic-frr/patch/0059-Fix-BGP-reset-on-suppress-fib-pending-configuration.patch @@ -0,0 +1,32 @@ +From 8f6adef67c93d04a9eefa1404db0c8de9877fb38 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 26 Nov 2024 00:40:46 -0800 +Subject: [PATCH] Pull request: https://github.com/FRRouting/frr/pull/17487 + bgpd: Do not reset peers on suppress-fib toggling If the desired state is the + same - do nothing instead of resetting once again. + +Fixes: bdb5ae8 (bgpd: Make suppress-fib-pending clear peering) + +Signed-off-by: Donatas Abraitis +--- + bgpd/bgpd.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c +index d6d874be2..0b2bf821e 100644 +--- a/bgpd/bgpd.c ++++ b/bgpd/bgpd.c +@@ -461,6 +461,10 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set) + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return; + ++ /* Do nothing if already in a desired state */ ++ if (set == !!CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING)) ++ return; ++ + if (set) { + SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING); + /* Send msg to zebra for the first instance of bgp enabled +-- +2.39.4 + diff --git a/src/sonic-frr/patch/0060-bgpd-Validate-both-nexthop-information-NEXTHOP-and-N.patch b/src/sonic-frr/patch/0060-bgpd-Validate-both-nexthop-information-NEXTHOP-and-N.patch new file mode 100644 index 000000000000..c1088df457b9 --- /dev/null +++ b/src/sonic-frr/patch/0060-bgpd-Validate-both-nexthop-information-NEXTHOP-and-N.patch @@ -0,0 +1,106 @@ +From 4e3f27fec6a3b4c0b853ad30f73bf0d34003e23f Mon Sep 17 00:00:00 2001 +From: sk408845 +Date: Tue, 26 Nov 2024 07:33:58 +0000 +Subject: [PATCH] Port https://github.com/FRRouting/frr/pull/17435/ bgpd: + Validate both nexthop information (NEXTHOP and NLRI) If we receive an IPv6 + prefix e.g.: 2001:db8:100::/64 with nextop: 0.0.0.0, and mp_nexthop: fc00::2, + we should not treat this with an invalid nexthop because of 0.0.0.0. We MUST + check for MP_REACH attribute also and decide later if we have at least one a + valid nexthop. + +Signed-off-by: Donatas Abraitis +--- + bgpd/bgp_route.c | 50 ++++++++++++++++++++++-------------------------- + 1 file changed, 23 insertions(+), 27 deletions(-) + +diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c +index 26089e326..e05507c52 100644 +--- a/bgpd/bgp_route.c ++++ b/bgpd/bgp_route.c +@@ -4032,7 +4032,7 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, + uint8_t type, uint8_t stype, struct attr *attr, + struct bgp_dest *dest) + { +- bool ret = false; ++ bool nh_invalid = false; + bool is_bgp_static_route = + (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true + : false; +@@ -4054,12 +4054,16 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, + (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)) + return false; + +- /* If NEXT_HOP is present, validate it. */ +- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { +- if (!ipv4_unicast_valid(&attr->nexthop) || +- bgp_nexthop_self(bgp, afi, type, stype, attr, dest)) +- return true; +- } ++ /* If NEXT_HOP is present, validate it: ++ * The route can have both nexthop + mp_nexthop encoded as multiple NLRIs, ++ * and we MUST check if at least one of them is valid. ++ * E.g.: IPv6 prefix can be with nexthop: 0.0.0.0, and mp_nexthop: fc00::1. ++ */ ++ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))) ++ nh_invalid = (attr->nexthop.s_addr == INADDR_ANY || ++ !ipv4_unicast_valid(&attr->nexthop) || ++ bgp_nexthop_self(bgp, afi, type, stype, attr, dest)); ++ + + /* If MP_NEXTHOP is present, validate it. */ + /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; +@@ -4074,39 +4078,31 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, + switch (attr->mp_nexthop_len) { + case BGP_ATTR_NHLEN_IPV4: + case BGP_ATTR_NHLEN_VPNV4: +- ret = (attr->mp_nexthop_global_in.s_addr == +- INADDR_ANY || +- !ipv4_unicast_valid( +- &attr->mp_nexthop_global_in) || +- bgp_nexthop_self(bgp, afi, type, stype, attr, +- dest)); ++ nh_invalid = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY || ++ !ipv4_unicast_valid(&attr->mp_nexthop_global_in) || ++ bgp_nexthop_self(bgp, afi, type, stype, attr, dest)); + break; + + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: +- ret = (IN6_IS_ADDR_UNSPECIFIED( +- &attr->mp_nexthop_global) +- || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) +- || IN6_IS_ADDR_MULTICAST( +- &attr->mp_nexthop_global) +- || bgp_nexthop_self(bgp, afi, type, stype, attr, +- dest)); ++ nh_invalid = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global) || ++ IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) || ++ IN6_IS_ADDR_MULTICAST(&attr->mp_nexthop_global) || ++ bgp_nexthop_self(bgp, afi, type, stype, attr, dest)); + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: +- ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) +- || IN6_IS_ADDR_MULTICAST( +- &attr->mp_nexthop_global) +- || bgp_nexthop_self(bgp, afi, type, stype, attr, +- dest)); ++ nh_invalid = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) || ++ IN6_IS_ADDR_MULTICAST(&attr->mp_nexthop_global) || ++ bgp_nexthop_self(bgp, afi, type, stype, attr, dest)); + break; + + default: +- ret = true; ++ nh_invalid = true; + break; + } + } + +- return ret; ++ return nh_invalid; + } + + static void bgp_attr_add_no_export_community(struct attr *attr) +-- +2.20.1 + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 0cb3259b47d9..e84597a45aed 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -6,30 +6,13 @@ 0006-Link-local-scope-was-not-set-while-binding-socket-for-bgp-ipv6-link-local-neighbors.patch 0007-ignore-route-from-default-table.patch 0008-Use-vrf_id-for-vrf-not-tabled_id.patch -0009-bgpd-Ensure-suppress-fib-pending-works-with-network-.patch 0010-bgpd-Change-log-level-for-graceful-restart-events.patch -0011-zebra-Static-routes-async-notification-do-not-need-t.patch -0012-zebra-Rename-vrf_lookup_by_tableid-to-zebra_vrf_look.patch -0013-zebra-Move-protodown_r_bit-to-a-better-spot.patch -0014-zebra-Remove-unused-dplane_intf_delete.patch -0015-zebra-Remove-unused-add-variable.patch -0016-zebra-Remove-duplicate-function-for-netlink-interfac.patch -0017-zebra-Add-code-to-get-set-interface-to-pass-up-from-.patch -0018-zebra-Use-zebra-dplane-for-RTM-link-and-addr.patch -0019-zebra-remove-duplicated-nexthops-when-sending-fpm-msg.patch -0020-zebra-Fix-non-notification-of-better-admin-won.patch 0021-Disable-ipv6-src-address-test-in-pceplib.patch 0022-cross-compile-changes.patch -0023-zebra-The-dplane_fpm_nl-return-path-leaks-memory.patch -0024-lib-use-snmp-s-large-fd-sets-for-agentx.patch 0025-bgp-community-memory-leak-fix.patch -0026-bgp-fib-suppress-announce-fix.patch -0027-lib-Do-not-convert-EVPN-prefixes-into-IPv4-IPv6-if-n.patch 0028-zebra-fix-parse-attr-problems-for-encap.patch -0029-zebra-nhg-fix-on-intf-up.patch 0030-zebra-backpressure-Zebra-push-back-on-Buffer-Stream-.patch 0031-bgpd-backpressure-Add-a-typesafe-list-for-Zebra-Anno.patch -0032-bgpd-fix-flushing-ipv6-flowspec-entries-when-peering.patch 0033-bgpd-backpressure-cleanup-bgp_zebra_XX-func-args.patch 0034-gpd-backpressure-Handle-BGP-Zebra-Install-evt-Creat.patch 0035-bgpd-backpressure-Handle-BGP-Zebra-EPVN-Install-evt-.patch @@ -50,6 +33,10 @@ 0050-bgpd-backpressure-Avoid-use-after-free.patch 0051-bgpd-backpressure-fix-ret-value-evpn_route_select_in.patch 0052-bgpd-backpressure-log-error-for-evpn-when-route-inst.patch -0053-bgpd-Set-md5-TCP-socket-option-for-outgoing-connections-on-listener.patch -build-dplane-fpm-sonic-module.patch -bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch +0054-build-dplane-fpm-sonic-module.patch +0055-bgpd-lib-Include-SID-structure-in-seg6local-nexthop.patch +0056-zebra-do-not-send-local-routes-to-fpm.patch +0057-Adding-changes-to-write-ip-nht-resolve-via-default-c.patch +0058-When-the-file-is-config-replayed-we-cannot-handle-th.patch +0059-Fix-BGP-reset-on-suppress-fib-pending-configuration.patch +0060-bgpd-Validate-both-nexthop-information-NEXTHOP-and-N.patch