From 710339685befca1dd5543d3e4766d93a96a89db6 Mon Sep 17 00:00:00 2001 From: sudhanshukumar22 Date: Thu, 12 Sep 2024 02:09:11 -0700 Subject: [PATCH] upgrade FRR to version 10.0.1, upgrade libyang2 to 2.1.148. Tested using basic BGP neighborship formation with routes using BGP docker --- .../frr/supervisord/supervisord.conf.j2 | 11 + platform/vs/docker-sonic-vs/Dockerfile.j2 | 4 +- .../vs/docker-sonic-vs/supervisord.conf.j2 | 11 + rules/frr.mk | 6 +- rules/libyang2.mk | 10 +- sonic-slave-bookworm/Dockerfile.j2 | 4 +- sonic-slave-bullseye/Dockerfile.j2 | 2 + sonic-slave-buster/Dockerfile.j2 | 2 + src/libyang2/Makefile | 8 +- .../dplane_fpm_sonic/dplane_fpm_sonic.c | 262 +-- ...008-Use-vrf_id-for-vrf-not-tabled_id.patch | 40 +- ...og-level-for-graceful-restart-events.patch | 96 +- .../0025-bgp-community-memory-leak-fix.patch | 390 +--- ...re-Zebra-push-back-on-Buffer-Stream-.patch | 45 +- ...ssure-cleanup-bgp_zebra_XX-func-args.patch | 99 +- ...e-Handle-BGP-Zebra-Install-evt-Creat.patch | 214 +- ...e-Handle-BGP-Zebra-EPVN-Install-evt-.patch | 1838 ++++++++++++++--- ...stall-uninstall-speed-of-evpn-vpn-vn.patch | 56 +- ...e-Fix-to-withdraw-evpn-type-5-routes.patch | 42 +- ...-Use-built-in-data-structure-counter.patch | 76 +- ...w-zebra-dplane-providers-to-give-mor.patch | 56 +- ...e-fix-to-properly-remove-dest-for-bg.patch | 38 +- ...pd-backpressure-Avoid-use-after-free.patch | 31 +- ...ile-to-header-for-compilation-errors.patch | 26 + .../patch/build-dplane-fpm-sonic-module.patch | 34 +- src/sonic-frr/patch/series | 20 +- 26 files changed, 2152 insertions(+), 1269 deletions(-) create mode 100644 src/sonic-frr/patch/0054-Added-file-to-header-for-compilation-errors.patch diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index 15aa2ed55110..0e3410f20930 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 6caa69b301f9..c8b888b4c9cc 100644 --- a/platform/vs/docker-sonic-vs/Dockerfile.j2 +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -67,7 +67,9 @@ RUN apt-get install -y net-tools \ # For libkrb5-dev comerr-dev \ libgssrpc4 \ - libkdb5-10 + libkdb5-10 \ + libprotobuf-c-dev \ + protobuf-c-compiler RUN apt-get install -y -t bullseye-backports iproute2 diff --git a/platform/vs/docker-sonic-vs/supervisord.conf.j2 b/platform/vs/docker-sonic-vs/supervisord.conf.j2 index d8d9ce390cb8..b898aaf8d482 100644 --- a/platform/vs/docker-sonic-vs/supervisord.conf.j2 +++ b/platform/vs/docker-sonic-vs/supervisord.conf.j2 @@ -163,6 +163,17 @@ 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=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 --asic-offload=notify_on_offload priority=13 diff --git a/rules/frr.mk b/rules/frr.mk index da42179a0312..d57ed10855dc 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..5cfd31c3a6b4 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.1 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 92a15eaf9972..159bbfe3bf87 100644 --- a/sonic-slave-bookworm/Dockerfile.j2 +++ b/sonic-slave-bookworm/Dockerfile.j2 @@ -144,6 +144,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 \ @@ -750,4 +752,4 @@ RUN mkdir -p /.cargo && $RUST_ROOT/bin/rustup target add armv7-unknown-linux-gnu RUN mkdir -p /.cargo && $RUST_ROOT/bin/rustup target add aarch64-unknown-linux-gnu && echo "[target.aarch64-unknown-linux-gnu]\nlinker = \"aarch64-linux-gnu-gcc\"" >> /.cargo/config.toml {% endif -%} ENV RUSTUP_HOME $RUST_ROOT -ENV PATH $PATH:$RUST_ROOT/bin \ No newline at end of file +ENV PATH $PATH:$RUST_ROOT/bin 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..22af265ca11b 100644 --- a/src/libyang2/Makefile +++ b/src/libyang2/Makefile @@ -2,10 +2,10 @@ SHELL = /bin/bash .SHELLFLAGS += -e -LIBYANG_URL = https://sonicstorage.blob.core.windows.net/debian/pool/main/liby/libyang +LIBYANG_URL = https://deb.debian.org/debian/pool/main/liby/libyang2 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/dplane_fpm_sonic/dplane_fpm_sonic.c b/src/sonic-frr/dplane_fpm_sonic/dplane_fpm_sonic.c index c87a913acb1c..efce0f30e5e0 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" @@ -165,22 +166,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 +239,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 +314,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 +329,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 +343,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 +359,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 +371,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 +492,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 +520,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 +565,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 +694,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 +730,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 +792,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 +811,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 +837,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 +845,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 +857,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 +887,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 +911,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 +976,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; @@ -1204,8 +1205,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; @@ -1214,7 +1216,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); @@ -1232,7 +1234,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; @@ -1293,13 +1295,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; + } } } } @@ -1350,7 +1358,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((const struct seg6_seg_stack *)nexthop->nh_srv6->seg6_segs)) { if (!netlink_srv6_vpn_route_msg_encode( cmd, ctx, data, datalen, fpm, force_nhg)) return 0; @@ -1419,7 +1427,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", @@ -1450,7 +1458,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", @@ -1515,7 +1523,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; @@ -1612,7 +1620,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; @@ -1649,9 +1657,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; @@ -1667,11 +1675,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); } } @@ -1709,9 +1717,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; @@ -1728,19 +1736,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; @@ -1770,7 +1778,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; } @@ -1787,7 +1795,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); } @@ -1807,6 +1815,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; @@ -1818,16 +1827,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; } @@ -1842,11 +1852,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); @@ -1868,14 +1878,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); } /* @@ -1888,23 +1898,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; @@ -1923,7 +1933,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); } /* @@ -1943,20 +1953,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; @@ -1999,7 +2009,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); /* @@ -2015,10 +2025,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: @@ -2102,19 +2112,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); @@ -2203,7 +2213,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 */ @@ -2213,7 +2223,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/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..a7c4a43974bc 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 @@ -1,19 +1,11 @@ -From 44f3736ee601e06e43e978fa075402c3da4823bd Mon Sep 17 00:00:00 2001 -From: Stepan Blyschak -Date: Mon, 16 Jan 2023 11:45:19 +0000 -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 +29,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 +51,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 +62,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 +78,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 +97,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/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..efe734044a22 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 @@ -1,51 +1,40 @@ -From a05f213343ee7ee5dbfcfd1984c40db5c262db3c Mon Sep 17 00:00:00 2001 -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 +51,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/0025-bgp-community-memory-leak-fix.patch b/src/sonic-frr/patch/0025-bgp-community-memory-leak-fix.patch index f8215e07f0f8..def913576be6 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 @@ -1,395 +1,13 @@ -From 92323cf4b506c40376be74e955836da30980ae54 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Wed, 13 Mar 2024 10:26:58 -0400 -Subject: [PATCH 1/3] bgpd: Ensure that the correct aspath is free'd - -Currently in subgroup_default_originate the attr.aspath -is set in bgp_attr_default_set, which hashs the aspath -and creates a refcount for it. If this is a withdraw -the subgroup_announce_check and bgp_adj_out_set_subgroup -is called which will intern the attribute. This will -cause the the attr.aspath to be set to a new value -finally at the bottom of the function it intentionally -uninterns the aspath which is not the one that was -created for this function. This reduces the other -aspath's refcount by 1 and if a clear bgp * is issued -fast enough the aspath for that will be removed -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/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/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..125e342ab170 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 @@ -1,7 +1,10 @@ -From 679ad9ee5f3c15570d697506183d37aa29f6ebf2 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 25 Jan 2024 13:07:37 -0500 -Subject: [PATCH 05/11] bgpd: backpressure - cleanup bgp_zebra_XX func args +From 879558ccd9b0f4f43c708f43a3e0fcf38bebeab7 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Wed, 18 Sep 2024 23:10:13 -0700 +Subject: [PATCH] Date: Fri, 13 Sep 2024 09:36:37 +0000 Subject: [PATCH] From + 679ad9ee5f3c15570d697506183d37aa29f6ebf2 Mon Sep 17 00:00:00 2001 From: + Donald Sharp Date: Thu, 25 Jan 2024 13:07:37 -0500 + Subject: [PATCH 05/11] bgpd: backpressure - cleanup bgp_zebra_XX func args Since installing/withdrawing routes into zebra is going to be changed around to be dest based in a list, @@ -13,12 +16,17 @@ Ticket: #3390099 Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_route.c | 17 +++++++---------- + bgpd/bgp_zebra.c | 43 ++++++++++++++++++++----------------------- + bgpd/bgp_zebra.h | 11 +++++------ + 3 files changed, 32 insertions(+), 39 deletions(-) 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 +37,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 +50,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 +60,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 +69,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 +78,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 +93,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 +113,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 +125,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 +143,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 +154,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 +171,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 +185,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 +197,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 +208,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 +220,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 +231,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..68591181bda5 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 @@ -1,8 +1,10 @@ -From 6d5604a9315801e9380c11357d663ad6537ed8ab Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Fri, 26 Jan 2024 14:48:53 -0500 -Subject: [PATCH 06/11] bgpd : backpressure - Handle BGP-Zebra Install evt - Creation +From 7117be5a328d2e7d964477f52497f1e1075cc3a2 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Wed, 18 Sep 2024 23:20:55 -0700 +Subject: [PATCH] From 6d5604a9315801e9380c11357d663ad6537ed8ab Mon Sep 17 + 00:00:00 2001 From: Donald Sharp Date: Fri, 26 Jan 2024 + 14:48:53 -0500 Subject: [PATCH 06/11] bgpd : backpressure - Handle BGP-Zebra + Install evt Creation BGP is now keeping a list of dests with the dest having a pointer to the bgp_path_info that it will be working on. @@ -36,46 +38,67 @@ Ticket: #3390099 Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_main.c | 2 + + bgpd/bgp_route.c | 14 +-- + bgpd/bgp_table.h | 7 ++ + bgpd/bgp_zebra.c | 219 ++++++++++++++++++++++++++++++++++++++--------- + bgpd/bgp_zebra.h | 10 ++- + bgpd/bgpd.c | 14 +++ + bgpd/bgpd.h | 7 ++ + lib/zclient.c | 1 + + 8 files changed, 224 insertions(+), 50 deletions(-) +diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c +index 851c4880c..44d5ee68c 100644 +--- a/bgpd/bgp_main.c ++++ b/bgpd/bgp_main.c +@@ -207,6 +207,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status) + bgp_evpn_mh_finish(); + bgp_nhg_finish(); + ++ zebra_announce_fini(&bm->zebra_announce_head); ++ + /* reverse bgp_dump_init */ + bgp_dump_finish(); + 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 +107,52 @@ 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); + dest = bgp_path_info_reap(dest, pi); diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h -index d43bf86eb9..45d61f8dfd 100644 +index 5b4c3be21..67431ea4f 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h -@@ -102,6 +102,7 @@ struct bgp_node { - STAILQ_ENTRY(bgp_dest) pq; +@@ -75,6 +75,9 @@ struct bgp_dest { + struct bgp_dest *pdest; - struct zebra_announce_item zai; + STAILQ_ENTRY(bgp_dest) pq; + struct bgp_path_info *za_bgp_pi; ++ ++ struct zebra_announce_item zai; uint64_t version; -@@ -117,6 +118,8 @@ struct bgp_node { - #define BGP_NODE_FIB_INSTALLED (1 << 6) +@@ -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; + }; + ++DECLARE_LIST(zebra_announce, struct bgp_dest, zai); ++ + extern void bgp_delete_listnode(struct bgp_dest *dest); + /* + * bgp_table_iter_t 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 +161,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 +186,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 +210,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 +220,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 +229,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 +240,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 +317,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 +418,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 +432,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,25 +453,21 @@ 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 */ + + /* 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/bgpd/bgpd.c b/bgpd/bgpd.c -index 392423e028..da133d71c1 100644 +index 337879a2d..88d4201a9 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c -@@ -3688,10 +3688,20 @@ int bgp_delete(struct bgp *bgp) +@@ -3867,10 +3867,20 @@ int bgp_delete(struct bgp *bgp) afi_t afi; safi_t safi; int i; @@ -466,41 +488,67 @@ index 392423e028..da133d71c1 100644 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; +@@ -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; ++ ++ zebra_announce_init(&bm->zebra_announce_head); + 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. -@@ -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); +@@ -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 55f53bf9d3..bdf31f5161 100644 +index 0f6909532..a6b398a44 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h -@@ -182,6 +182,8 @@ struct bgp_master { +@@ -18,6 +18,8 @@ + #include "iana_afi.h" + #include "asn.h" + ++PREDECL_LIST(zebra_announce); ++ + /* For union sockunion. */ + #include "queue.h" + #include "sockunion.h" +@@ -170,11 +172,16 @@ struct bgp_master { uint32_t inq_limit; uint32_t outq_limit; -+ struct thread *t_bgp_zebra_route; ++ struct event *t_bgp_zebra_route; + - /* To preserve ordering of installations into zebra across all Vrfs */ - struct zebra_announce_head zebra_announce_head; + 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; ++ + QOBJ_FIELDS; + }; + DECLARE_QOBJ_TYPE(bgp_master); 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 +556,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..c26c7bb0a678 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 @@ -1,7 +1,10 @@ -From 84f7778808b7fee771f26c3cae46292ef85f06c0 Mon Sep 17 00:00:00 2001 -From: Rajasekar Raja -Date: Thu, 15 Feb 2024 11:23:51 -0800 -Subject: [PATCH 07/11] bgpd : backpressure - Handle BGP-Zebra(EPVN) Install +From 2552ac0c492cdec01e36b48b63c057c6ad162701 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Mon, 16 Sep 2024 23:08:55 -0700 +Subject: [PATCH] Subject: [PATCH] From + 84f7778808b7fee771f26c3cae46292ef85f06c0 Mon Sep 17 00:00:00 2001 From: + Rajasekar Raja Date: Thu, 15 Feb 2024 11:23:51 -0800 + Subject: [PATCH 07/11] bgpd : backpressure - Handle BGP-Zebra(EPVN) Install evt Creation Current changes deals with EVPN routes installation to zebra. @@ -16,31 +19,328 @@ of the code. Ticket: #3390099 Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_evpn.c | 447 ++++++++++++++++++++++++++------------------- + bgpd/bgp_evpn.h | 8 + + bgpd/bgp_evpn_mh.c | 88 +++++---- + bgpd/bgp_evpn_mh.h | 10 +- + bgpd/bgp_route.c | 10 +- + bgpd/bgp_table.h | 6 +- + bgpd/bgp_zebra.c | 52 ++++-- + bgpd/bgp_zebra.h | 2 +- + bgpd/bgpd.h | 1 + + 9 files changed, 377 insertions(+), 247 deletions(-) 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 +349,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 +381,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 +490,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 +509,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 +538,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 +624,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 +672,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 +707,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 +716,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 +829,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 +1355,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 +1596,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 +1605,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 +1614,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 +1635,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 +1644,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 +1876,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 +1916,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 +2006,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 +2044,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 +2066,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 +2108,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..5512da7c1ba0 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 @@ -1,8 +1,10 @@ -From 7166c2222cb82885510c3e8c7906c1d7de950f9b Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 11 Apr 2024 13:28:30 -0400 -Subject: [PATCH 09/11] bgpd: Increase install/uninstall speed of evpn vpn - vni's +From c95dd083b98c65ac848f60ebd76730f83cd3bde5 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Wed, 18 Sep 2024 23:25:10 -0700 +Subject: [PATCH] From 7166c2222cb82885510c3e8c7906c1d7de950f9b Mon Sep 17 + 00:00:00 2001 From: Donald Sharp Date: Thu, 11 Apr 2024 + 13:28:30 -0400 Subject: [PATCH 09/11] bgpd: Increase install/uninstall speed + of evpn vpn vni's BGP receives notification from zebra about an vpn that needs to be installed into the evpn tables. Unfortunately @@ -17,23 +19,23 @@ scenario. Signed-off-by: Rajasekar Raja Signed-off-by: Donald Sharp +--- + bgpd/bgp_evpn.c | 48 ++++++++++++------------------------------------ + 1 file changed, 12 insertions(+), 36 deletions(-) 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 +46,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 +83,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 +114,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..d79bdccc4ebc 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 @@ -1,8 +1,10 @@ -From f3ec35b461a06f1278383d2347dfbc611b6a91a6 Mon Sep 17 00:00:00 2001 -From: Rajasekar Raja -Date: Fri, 17 May 2024 12:36:31 -0700 -Subject: [PATCH] bgpd: backpressure - Fix to withdraw evpn type-5 routes - immediately +From b6151be854f00f6eb5823e9408c65f00bbdd949f Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 17 Sep 2024 02:45:34 -0700 +Subject: [PATCH] From f3ec35b461a06f1278383d2347dfbc611b6a91a6 Mon Sep 17 + 00:00:00 2001 From: Rajasekar Raja Date: Fri, 17 May + 2024 12:36:31 -0700 Subject: [PATCH] bgpd: backpressure - Fix to withdraw + evpn type-5 routes immediately As part of backpressure changes, there is a bug where immediate withdraw is to be sent for evpn imported type-5 prefix to clear the nh neigh and @@ -15,40 +17,44 @@ Ticket: #3905571 Signed-off-by: Donald Sharp Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_route.c | 2 +- + bgpd/bgp_zebra.c | 10 +++------- + 2 files changed, 4 insertions(+), 8 deletions(-) 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 +64,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..7c3631ce968e 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 @@ -1,7 +1,10 @@ -From 529cdfa09065c6c77aff4a96a52f0d3bcb385b6f Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Thu, 13 Jun 2024 15:30:00 -0400 -Subject: [PATCH 1/5] zebra: Use built in data structure counter +From 1d441b6b3e45bb2000ec4d29fada07857c7305b4 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 17 Sep 2024 03:05:40 -0700 +Subject: [PATCH] From 529cdfa09065c6c77aff4a96a52f0d3bcb385b6f Mon Sep 17 + 00:00:00 2001 From: Donald Sharp Date: Thu, 13 Jun 2024 + 15:30:00 -0400 Subject: [PATCH 1/5] zebra: Use built in data structure + counter Instead of keeping a counter that is independent of the queue's data structure. Just use the queue's @@ -10,21 +13,26 @@ keeping it wrapped inside the mutex for adding/deleting to the queue. Signed-off-by: Donald Sharp +--- + zebra/dplane_fpm_nl.c | 40 ++++++++++++++++++---------------------- + zebra/zebra_dplane.c | 5 +++++ + zebra/zebra_dplane.h | 2 ++ + 3 files changed, 25 insertions(+), 22 deletions(-) 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 +43,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 +55,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 +66,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 +78,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 +112,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 +147,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..ce5db4986214 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 @@ -1,8 +1,9 @@ -From d695dfb88418834f0054255dd4385b293efb5a17 Mon Sep 17 00:00:00 2001 -From: Donald Sharp -Date: Mon, 17 Jun 2024 10:42:41 -0400 -Subject: [PATCH 5/5] zebra: Modify show `zebra dplane providers` to give more - data +From 08d8e53948d91bdaa98c8179616503908323544c Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 17 Sep 2024 03:24:51 -0700 +Subject: [PATCH] From d695dfb88418834f0054255dd4385b293efb5a17 Mon Sep 17 + 00:00:00 2001 From: Donald Sharp Date: Mon, 17 Jun 2024 + 10:42:41 -0400 Subject: [PATCH 5/5] zebra: Modify show to give more data The show zebra dplane provider command was ommitting the input and output queues to the dplane itself. @@ -18,44 +19,49 @@ dataplane Outgoing Queue to Zebra: 43 r1# Signed-off-by: Donald Sharp +--- + zebra/rib.h | 1 + + zebra/zebra_dplane.c | 18 +++++++++++++----- + zebra/zebra_rib.c | 11 +++++++++++ + 3 files changed, 25 insertions(+), 5 deletions(-) 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 +71,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 +103,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..01c7bfce3ac2 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 @@ -1,8 +1,10 @@ -From 05d2c5b3ba6f83cd42a4dd5f9e40959fc438b0a6 Mon Sep 17 00:00:00 2001 -From: Rajasekar Raja -Date: Wed, 10 Jul 2024 16:46:29 -0700 -Subject: [PATCH 1/2] bgpd: backpressure - fix to properly remove dest for bgp - under deletion +From 9139ebe729804de71b13510d61bd0e273f6f2918 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 17 Sep 2024 03:45:43 -0700 +Subject: [PATCH] From 05d2c5b3ba6f83cd42a4dd5f9e40959fc438b0a6 Mon Sep 17 + 00:00:00 2001 From: Rajasekar Raja Date: Wed, 10 Jul + 2024 16:46:29 -0700 Subject: [PATCH 1/2] bgpd: backpressure - fix to properly + remove dest for bgp under deletion In case of imported routes (L3vni/vrf leaks), when a bgp instance is being deleted, the peer->bgp comparision with the incoming bgp to remove @@ -20,18 +22,22 @@ Ticket :#3980988 Signed-off-by: Chirag Shah Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_evpn.c | 12 ++++++------ + bgpd/bgpd.c | 20 +++++++++++++------- + 2 files changed, 19 insertions(+), 13 deletions(-) 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 +52,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 +66,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 +89,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..39eeaef512ab 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 @@ -1,7 +1,10 @@ -From df1d28fcc12d4f5541c9335115887d31e6197b80 Mon Sep 17 00:00:00 2001 -From: Rajasekar Raja -Date: Mon, 22 Jul 2024 10:13:19 -0700 -Subject: [PATCH] bgpd: backpressure - Avoid use after free +From b1e6d39d38f42c21870fa4f027e4e63f4ddf898e Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Tue, 17 Sep 2024 04:13:38 -0700 +Subject: [PATCH] From df1d28fcc12d4f5541c9335115887d31e6197b80 Mon Sep 17 + 00:00:00 2001 From: Rajasekar Raja Date: Mon, 22 Jul + 2024 10:13:19 -0700 Subject: [PATCH] bgpd: backpressure - Avoid use after + free Coverity complains there is a use after free (1598495 and 1598496) At this point, most likely dest->refcount cannot go 1 and free up @@ -12,12 +15,16 @@ Fixing this with a simple order change (no harm fix). Ticket :#4001204 Signed-off-by: Rajasekar Raja +--- + bgpd/bgp_evpn.c | 2 +- + bgpd/bgpd.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) 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 +34,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 +49,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/0054-Added-file-to-header-for-compilation-errors.patch b/src/sonic-frr/patch/0054-Added-file-to-header-for-compilation-errors.patch new file mode 100644 index 000000000000..56701a49b9f2 --- /dev/null +++ b/src/sonic-frr/patch/0054-Added-file-to-header-for-compilation-errors.patch @@ -0,0 +1,26 @@ +From 40d1062ec3c2b5bf4720f072510a0ef7473ff07b Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Thu, 3 Oct 2024 06:08:01 -0700 +Subject: [PATCH] Added file to header for compilation errors + +--- + zebra/zebra_evpn.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h +index c946425dd..cd2ed648a 100644 +--- a/zebra/zebra_evpn.h ++++ b/zebra/zebra_evpn.h +@@ -122,7 +122,8 @@ struct zebra_from_svi_param { + }; + + struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if); +- ++extern struct zebra_vxlan_vni * ++zebra_vxlan_if_vni_find(const struct zebra_if *zif, vni_t vni); + static inline struct interface *zevpn_map_to_svi(struct zebra_evpn *zevpn) + { + struct interface *ifp; +-- +2.39.4 + diff --git a/src/sonic-frr/patch/build-dplane-fpm-sonic-module.patch b/src/sonic-frr/patch/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/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/series b/src/sonic-frr/patch/series index c14a56f5b10f..2814d36bc731 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -6,30 +6,12 @@ 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,5 +32,5 @@ 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 +0054-Added-file-to-header-for-compilation-errors.patch build-dplane-fpm-sonic-module.patch