diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 index b5891b9695a..cdcca95766f 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 @@ -11,7 +11,7 @@ ip prefix-list PL_LoopbackV4 permit {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/32 ! {% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} -{% if ( ('localhost' in DEVICE_METADATA) and ('bgp_adv_lo_prefix_as_128' in DEVICE_METADATA['localhost']) and +{% if ( ('localhost' in DEVICE_METADATA) and ('bgp_adv_lo_prefix_as_128' in DEVICE_METADATA['localhost']) and (DEVICE_METADATA['localhost']['bgp_adv_lo_prefix_as_128'] == 'true') ) %} ipv6 prefix-list PL_LoopbackV6 permit {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip_network }}/128 {% else %} @@ -77,6 +77,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} bgp graceful-restart bgp graceful-restart preserve-fw-state bgp graceful-restart select-defer-time {{ constants.bgp.graceful_restart.select_defer_time | default(45) }} +{% if DEVICE_METADATA['localhost']['bgp-suppress-fib-pending'] == 'enabled' -%} + bgp suppress-fib-pending +{% endif -%} {% endif %} ! {# set router-id #} @@ -94,7 +97,7 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} ! {% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} address-family ipv6 -{% if ( ('localhost' in DEVICE_METADATA) and ('bgp_adv_lo_prefix_as_128' in DEVICE_METADATA['localhost']) and +{% if ( ('localhost' in DEVICE_METADATA) and ('bgp_adv_lo_prefix_as_128' in DEVICE_METADATA['localhost']) and (DEVICE_METADATA['localhost']['bgp_adv_lo_prefix_as_128'] == 'true') ) %} network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/128 {% else %} diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index fec72db761c..422bfd99e84 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -30,7 +30,10 @@ stderr_logfile=syslog dependent_startup=true [program:zebra] -command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M fpm -M snmp +{% if DEVICE_METADATA['localhost']['bgp-suppress-fib-pending'] == 'enabled' -%} +{% set zebra_extra_arguments = "--asic-offload=notify_on_offload" %} +{% endif -%} +command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M dplane_fpm_nl -M snmp {{ zebra_extra_arguments }} priority=4 autostart=false autorestart=false diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 index 51d998e90d3..f5a56c316d4 100644 --- a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 @@ -6,6 +6,13 @@ ! {% endblock banner %} ! +{% block fpm %} +! Uses the old known FPM behavior of including next hop information in the route (e.g. RTM_NEWROUTE) messages +no fpm use-next-hop-groups +! +fpm address 127.0.0.1 +{% endblock fpm %} +! {% include "common/daemons.common.conf.j2" %} ! {% include "zebra.interfaces.conf.j2" %} diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf index 7b7987650d6..1b1aa992e2d 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf @@ -4,6 +4,11 @@ ! file: zebra.conf ! ! +! Uses the old known FPM behavior of including next hop information in the route (e.g. RTM_NEWROUTE) messages +no fpm use-next-hop-groups +! +fpm address 127.0.0.1 +! ! template: common/daemons.common.conf.j2 ! hostname SpineFront01 diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf index fc8a8a2fb3b..65c43fd706b 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf @@ -4,6 +4,11 @@ ! file: zebra.conf ! ! +! Uses the old known FPM behavior of including next hop information in the route (e.g. RTM_NEWROUTE) messages +no fpm use-next-hop-groups +! +fpm address 127.0.0.1 +! ! template: common/daemons.common.conf.j2 ! hostname SpineFront01 diff --git a/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf index f596c5579d3..5661b25dac9 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf @@ -4,6 +4,11 @@ ! file: zebra.conf ! ! +! Uses the old known FPM behavior of including next hop information in the route (e.g. RTM_NEWROUTE) messages +no fpm use-next-hop-groups +! +fpm address 127.0.0.1 +! ! template: common/daemons.common.conf.j2 ! hostname switch-t0 diff --git a/src/sonic-frr/patch/0003-Use-vrf_id-for-vrf-not-tabled_id.patch b/src/sonic-frr/patch/0003-Use-vrf_id-for-vrf-not-tabled_id.patch deleted file mode 100644 index f815cf38455..00000000000 --- a/src/sonic-frr/patch/0003-Use-vrf_id-for-vrf-not-tabled_id.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 39bb40dc4bad4462e4ae9c98580d75fa2c92e032 Mon Sep 17 00:00:00 2001 -From: Pavel Shirshov -Date: Mon, 16 Nov 2020 18:29:46 -0800 -Subject: [PATCH 3/8] Use vrf_id for vrf, not tabled_id - ---- - zebra/zebra_fpm_netlink.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c -index ec22c5dd4..aad0156b3 100644 ---- a/zebra/zebra_fpm_netlink.c -+++ b/zebra/zebra_fpm_netlink.c -@@ -287,7 +287,7 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd, - ri->nlmsg_pid = zvrf->zns->netlink_dplane_out.snl.nl_pid; - - ri->nlmsg_type = cmd; -- ri->rtm_table = table_info->table_id; -+ ri->rtm_table = zvrf_id(rib_dest_vrf(dest)); - ri->rtm_protocol = RTPROT_UNSPEC; - - /* --- -2.12.2 - diff --git a/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch b/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch deleted file mode 100644 index 5097ad513ef..00000000000 --- a/src/sonic-frr/patch/0007-Add-support-of-bgp-l3vni-evpn.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 74ee34e4990dbd168b7b8072894eb0cf8927f9d1 Mon Sep 17 00:00:00 2001 -From: Kishore Kunal -Date: Fri, 15 Jan 2021 15:52:13 -0800 -Subject: [PATCH 7/8] This is temp patch till Prefix to ARP indirection is - add in neighorch - ---- - lib/nexthop.c | 2 ++ - lib/nexthop.h | 6 ++++++ - zebra/rt_netlink.c | 2 +- - zebra/zapi_msg.c | 4 ++++ - zebra/zebra_dplane.c | 1 + - zebra/zebra_fpm_netlink.c | 20 ++++++++++++++++++++ - 6 files changed, 34 insertions(+), 1 deletion(-) - -diff --git a/lib/nexthop.c b/lib/nexthop.c -index a1ce22e3b..6f3fe2a5f 100644 ---- a/lib/nexthop.c -+++ b/lib/nexthop.c -@@ -813,6 +813,8 @@ void nexthop_copy_no_recurse(struct nexthop *copy, - memcpy(©->src, &nexthop->src, sizeof(nexthop->src)); - memcpy(©->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src)); - copy->rparent = rparent; -+ memcpy(©->nh_encap.encap_data.rmac, &nexthop->nh_encap.encap_data.rmac, ETH_ALEN); -+ - if (nexthop->nh_label) - nexthop_add_labels(copy, nexthop->nh_label_type, - nexthop->nh_label->num_labels, -diff --git a/lib/nexthop.h b/lib/nexthop.h -index 320b46315..0f98dc3c2 100644 ---- a/lib/nexthop.h -+++ b/lib/nexthop.h -@@ -66,6 +66,11 @@ enum nh_encap_type { - /* Backup index value is limited */ - #define NEXTHOP_BACKUP_IDX_MAX 255 - -+struct vxlan_nh_encap { -+ vni_t vni; -+ struct ethaddr rmac; -+}; -+ - /* Nexthop structure. */ - struct nexthop { - struct nexthop *next; -@@ -136,6 +141,7 @@ struct nexthop { - enum nh_encap_type nh_encap_type; - union { - vni_t vni; -+ struct vxlan_nh_encap encap_data; - } nh_encap; - - /* SR-TE color used for matching SR-TE policies */ -diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c -index 24c01b7f5..5e0f4cd8f 100644 ---- a/zebra/rt_netlink.c -+++ b/zebra/rt_netlink.c -@@ -1856,7 +1856,7 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen, - return false; - - if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, -- nh->nh_encap.vni)) -+ nh->nh_encap.encap_data.vni)) - return false; - nl_attr_nest_end(n, nest); - break; -diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c -index 5cf7d815d..529cbb44b 100644 ---- a/zebra/zapi_msg.c -+++ b/zebra/zapi_msg.c -@@ -1577,6 +1577,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, - vtep_ip.ipa_type = IPADDR_V4; - memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4), - sizeof(struct in_addr)); -+ memcpy(&(nexthop->nh_encap.encap_data.rmac), -+ &api_nh->rmac, ETH_ALEN); - zebra_rib_queue_evpn_route_add( - api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); - } -@@ -1610,6 +1612,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, - vtep_ip.ipa_type = IPADDR_V6; - memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), - sizeof(struct in6_addr)); -+ memcpy(&(nexthop->nh_encap.encap_data.rmac), -+ &api_nh->rmac, ETH_ALEN); - zebra_rib_queue_evpn_route_add( - api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); - } -diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c -index 656ebcf3b..8d125d77e 100644 ---- a/zebra/zebra_dplane.c -+++ b/zebra/zebra_dplane.c -@@ -2421,6 +2421,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, - if (zl3vni && is_l3vni_oper_up(zl3vni)) { - nexthop->nh_encap_type = NET_VXLAN; - nexthop->nh_encap.vni = zl3vni->vni; -+ nexthop->nh_encap.encap_data.vni = zl3vni->vni; - } - } - -diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c -index aad0156b3..34be9fb39 100644 ---- a/zebra/zebra_fpm_netlink.c -+++ b/zebra/zebra_fpm_netlink.c -@@ -95,10 +95,12 @@ static const char *fpm_nh_encap_type_to_str(enum fpm_nh_encap_type_t encap_type) - - struct vxlan_encap_info_t { - vni_t vni; -+ struct ethaddr rmac; - }; - - enum vxlan_encap_info_type_t { - VXLAN_VNI = 0, -+ VXLAN_RMAC = 1, - }; - - struct fpm_nh_encap_info_t { -@@ -234,6 +236,9 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, - } - - nhi.encap_info.vxlan_encap.vni = vni; -+ memcpy(&nhi.encap_info.vxlan_encap.rmac, -+ &(nexthop->nh_encap.encap_data.rmac), -+ ETH_ALEN); - } - - /* -@@ -456,9 +461,16 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, - nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE, - encap); - vxlan = &nhi->encap_info.vxlan_encap; -+ char buf[ETHER_ADDR_STRLEN]; -+ -+ zfpm_debug( -+ "%s: VNI:%d RMAC:%s", __func__, vxlan->vni, -+ prefix_mac2str(&vxlan->rmac, buf, sizeof(buf))); - nest = nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP); - nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI, - vxlan->vni); -+ nl_attr_put(&req->n, in_buf_len, VXLAN_RMAC, -+ &vxlan->rmac, sizeof(vxlan->rmac)); - nl_attr_nest_end(&req->n, nest); - break; - } -@@ -494,10 +506,18 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, - nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE, - encap); - vxlan = &nhi->encap_info.vxlan_encap; -+ char rmac_buf[ETHER_ADDR_STRLEN]; -+ -+ zfpm_debug("%s: Multi VNI:%d RMAC:%s", __func__, -+ vxlan->vni, -+ prefix_mac2str(&vxlan->rmac, rmac_buf, -+ sizeof(rmac_buf))); - inner_nest = - nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP); - nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI, - vxlan->vni); -+ nl_attr_put(&req->n, in_buf_len, VXLAN_RMAC, -+ &vxlan->rmac, sizeof(vxlan->rmac)); - nl_attr_nest_end(&req->n, inner_nest); - break; - } --- -2.12.2 - diff --git a/src/sonic-frr/patch/0009-ignore-route-from-default-table.patch b/src/sonic-frr/patch/0009-ignore-route-from-default-table.patch deleted file mode 100644 index ec41da74dad..00000000000 --- a/src/sonic-frr/patch/0009-ignore-route-from-default-table.patch +++ /dev/null @@ -1,30 +0,0 @@ -From bb3b003840959adf5b5be52e91bc798007c9857a Mon Sep 17 00:00:00 2001 -From: Ying Xie -Date: Thu, 8 Sep 2022 04:20:36 +0000 -Subject: [PATCH] From 776a29e8ab32c1364ee601a8730aabb773b0c86b Mon Sep 17 - 00:00:00 2001 Subject: [PATCH] ignore route from default table - -Signed-off-by: Ying Xie ---- - zebra/zebra_fpm_netlink.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c -index 34be9fb39..d6c875a7e 100644 ---- a/zebra/zebra_fpm_netlink.c -+++ b/zebra/zebra_fpm_netlink.c -@@ -283,6 +283,11 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd, - rib_table_info(rib_dest_table(dest)); - struct zebra_vrf *zvrf = table_info->zvrf; - -+ if (table_info->table_id == RT_TABLE_DEFAULT) { -+ zfpm_debug("%s: Discard default table route", __func__); -+ return 0; -+ } -+ - memset(ri, 0, sizeof(*ri)); - - ri->prefix = rib_dest_prefix(dest); --- -2.17.1 - diff --git a/src/sonic-frr/patch/Add-ability-for-dplane_fpm_nl-to-receive-RTM_NEWROUT.patch b/src/sonic-frr/patch/Add-ability-for-dplane_fpm_nl-to-receive-RTM_NEWROUT.patch new file mode 100644 index 00000000000..6dddf723a41 --- /dev/null +++ b/src/sonic-frr/patch/Add-ability-for-dplane_fpm_nl-to-receive-RTM_NEWROUT.patch @@ -0,0 +1,674 @@ +From 40064cc962db5b7537eee86dbdb984d84a2ec130 Mon Sep 17 00:00:00 2001 +From: Stepan Blyschak +Date: Thu, 20 Oct 2022 13:04:45 +0000 +Subject: [PATCH 2/4] Add ability for dplane_fpm_nl to receive RTM_NEWROUTE + netlink messages that signal route handling in the asic + +Signed-off-by: Donald Sharp +--- + doc/developer/fpm.rst | 16 ++++++ + zebra/dplane_fpm_nl.c | 95 +++++++++++++++++++++++++++++++---- + zebra/rt_netlink.c | 31 +++++++++--- + zebra/rt_netlink.h | 4 ++ + zebra/zebra_dplane.c | 96 +++++++++++++++++++++++++++-------- + zebra/zebra_dplane.h | 18 +++++++ + zebra/zebra_rib.c | 114 ++++++++++++++++++++++++++---------------- + zebra/zebra_router.c | 11 ++++ + zebra/zebra_router.h | 8 +++ + zebra/zebra_vty.c | 9 ++++ + 10 files changed, 319 insertions(+), 83 deletions(-) + +diff --git a/doc/developer/fpm.rst b/doc/developer/fpm.rst +index 984986913..56d33671d 100644 +--- a/doc/developer/fpm.rst ++++ b/doc/developer/fpm.rst +@@ -101,3 +101,19 @@ Data + ^^^^ + + The netlink or protobuf message payload. ++ ++ ++Route Status Notification from ASIC ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++The dplane_fpm_nl has the ability to read route netlink messages ++from the underlying fpm implementation that can tell zebra ++whether or not the route has been Offloaded/Failed or Trapped. ++The end developer must send the data up the same socket that has ++been created to listen for FPM messages from Zebra. The data sent ++must have a Frame Header with Version set to 1, Message Type set to 1 ++and an appropriate message Length. The message data must contain ++a RTM_NEWROUTE netlink message that sends the prefix and nexthops ++associated with the route. Finally rtm_flags must contain ++RTM_F_OFFLOAD, RTM_F_TRAP and or RTM_F_OFFLOAD_FAILED to signify ++what has happened to the route in the ASIC. +diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c +index 3b02128c9..912d08e6b 100644 +--- a/zebra/dplane_fpm_nl.c ++++ b/zebra/dplane_fpm_nl.c +@@ -51,6 +51,7 @@ + #include "zebra/kernel_netlink.h" + #include "zebra/rt_netlink.h" + #include "zebra/debug.h" ++#include "fpm/fpm.h" + + #define SOUTHBOUND_DEFAULT_ADDR INADDR_LOOPBACK + #define SOUTHBOUND_DEFAULT_PORT 2620 +@@ -461,18 +462,15 @@ static void fpm_reconnect(struct fpm_nl_ctx *fnc) + static int fpm_read(struct thread *t) + { + struct fpm_nl_ctx *fnc = THREAD_ARG(t); ++ fpm_msg_hdr_t fpm; + ssize_t rv; ++ char buf[8192]; ++ struct nlmsghdr *hdr; ++ struct zebra_dplane_ctx *ctx; + + /* Let's ignore the input at the moment. */ + rv = stream_read_try(fnc->ibuf, fnc->socket, + STREAM_WRITEABLE(fnc->ibuf)); +- /* We've got an interruption. */ +- if (rv == -2) { +- /* Schedule next read. */ +- thread_add_read(fnc->fthread->master, fpm_read, fnc, +- fnc->socket, &fnc->t_read); +- return 0; +- } + if (rv == 0) { + atomic_fetch_add_explicit(&fnc->counters.connection_closes, 1, + memory_order_relaxed); +@@ -491,15 +489,92 @@ static int fpm_read(struct thread *t) + FPM_RECONNECT(fnc); + return 0; + } +- stream_reset(fnc->ibuf); ++ ++ /* Schedule the next read */ ++ thread_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket, ++ &fnc->t_read); ++ ++ /* We've got an interruption. */ ++ if (rv == -2) ++ return 0; + + /* Account all bytes read. */ + atomic_fetch_add_explicit(&fnc->counters.bytes_read, rv, + memory_order_relaxed); + +- thread_add_read(fnc->fthread->master, fpm_read, fnc, fnc->socket, +- &fnc->t_read); ++ while (rv) { ++ if (rv < (ssize_t)FPM_MSG_HDR_LEN) { ++ stream_reset(fnc->ibuf); ++ zlog_warn( ++ "%s: Received %zd bytes but cannot even read fpm header, ignoring", ++ __func__, rv); ++ ++ FPM_RECONNECT(fnc); ++ return 0; ++ } ++ ++ fpm.version = stream_getc(fnc->ibuf); ++ fpm.msg_type = stream_getc(fnc->ibuf); ++ fpm.msg_len = stream_getw(fnc->ibuf); ++ ++ if (fpm.version != FPM_PROTO_VERSION && ++ fpm.msg_type != FPM_MSG_TYPE_NETLINK) { ++ stream_reset(fnc->ibuf); ++ zlog_warn( ++ "%s: Received version/msg_type %u/%u, expected 1/1", ++ __func__, fpm.version, fpm.msg_type); + ++ FPM_RECONNECT(fnc); ++ return 0; ++ } ++ ++ if (fpm.msg_len != rv) { ++ stream_reset(fnc->ibuf); ++ zlog_warn( ++ "%s: Received message length %u but read only got %zd, ignoring message", ++ __func__, fpm.msg_len, rv); ++ ++ FPM_RECONNECT(fnc); ++ return 0; ++ } ++ ++ /* ++ * Place the data from the stream into a buffer ++ */ ++ hdr = (struct nlmsghdr *)buf; ++ if (sizeof(buf) < fpm.msg_len) { ++ stream_reset(fnc->ibuf); ++ zlog_warn( ++ "%s: Received unexpected large message data: %u", ++ __func__, fpm.msg_len); ++ FPM_RECONNECT(fnc); ++ return 0; ++ } ++ ++ stream_get(buf, fnc->ibuf, fpm.msg_len - FPM_MSG_HDR_LEN); ++ rv -= fpm.msg_len; ++ ++ switch (hdr->nlmsg_type) { ++ case RTM_NEWROUTE: ++ ctx = dplane_ctx_alloc(); ++ dplane_ctx_set_op(ctx, DPLANE_OP_ROUTE_NOTIFY); ++ if (netlink_route_change_read_unicast_internal( ++ hdr, 0, false, ctx) != 1) { ++ dplane_ctx_fini(&ctx); ++ stream_pulldown(fnc->ibuf); ++ return 0; ++ } ++ break; ++ default: ++ if (IS_ZEBRA_DEBUG_FPM) ++ zlog_debug( ++ "%s: Received message type %u which is not currently handled", ++ __func__, hdr->nlmsg_type); ++ break; ++ } ++ } ++ ++ stream_reset(fnc->ibuf); + return 0; + } + +diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c +index 0a9fdb909..4dd73fe90 100644 +--- a/zebra/rt_netlink.c ++++ b/zebra/rt_netlink.c +@@ -691,8 +691,9 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, + } + + /* Looking up routing table by netlink interface. */ +-static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, +- int startup) ++int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, ++ ns_id_t ns_id, int startup, ++ struct zebra_dplane_ctx *ctx) + { + int len; + struct rtmsg *rtm; +@@ -764,9 +765,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, + + selfroute = is_selfroute(rtm->rtm_protocol); + +- if (!startup && selfroute +- && h->nlmsg_type == RTM_NEWROUTE +- && !zrouter.asic_offloaded) { ++ if (!startup && selfroute && h->nlmsg_type == RTM_NEWROUTE && ++ !zrouter.asic_offloaded && !ctx) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Route type: %d Received that we think we have originated, ignoring", + rtm->rtm_protocol); +@@ -996,12 +996,20 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, + } + + if (nhe_id || ng) +- rib_add_multipath(afi, SAFI_UNICAST, &p, +- &src_p, re, ng); ++ dplane_rib_add_multipath(afi, SAFI_UNICAST, &p, ++ &src_p, re, ng, ++ startup, ctx); + else + XFREE(MTYPE_RE, re); + } + } else { ++ if (ctx) { ++ zlog_err( ++ "%s: %pFX RTM_DELROUTE received but received a context as well", ++ __func__, &p); ++ return 0; ++ } ++ + if (nhe_id) { + rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, + &p, &src_p, NULL, nhe_id, table, metric, +@@ -1026,7 +1034,14 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, + } + } + +- return 0; ++ return 1; ++} ++ ++static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, ++ int startup) ++{ ++ return netlink_route_change_read_unicast_internal(h, ns_id, startup, ++ NULL); + } + + static struct mcast_route_data *mroute = NULL; +diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h +index 93c06e555..da044c2c4 100644 +--- a/zebra/rt_netlink.h ++++ b/zebra/rt_netlink.h +@@ -122,6 +122,10 @@ netlink_put_lsp_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); + extern enum netlink_msg_status + netlink_put_pw_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); + ++int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, ++ ns_id_t ns_id, int startup, ++ struct zebra_dplane_ctx *ctx); ++ + #ifdef NETLINK_DEBUG + const char *nlmsg_type2str(uint16_t type); + const char *af_type2str(int type); +diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c +index 656ebcf3b..336056abb 100644 +--- a/zebra/zebra_dplane.c ++++ b/zebra/zebra_dplane.c +@@ -132,6 +132,8 @@ struct dplane_route_info { + uint32_t zd_mtu; + uint32_t zd_nexthop_mtu; + ++ uint32_t zd_flags; ++ + /* Nexthop hash entry info */ + struct dplane_nexthop_info nhe; + +@@ -1323,6 +1325,20 @@ uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx) + return ctx->u.rinfo.zd_old_instance; + } + ++uint32_t dplane_ctx_get_flags(const struct zebra_dplane_ctx *ctx) ++{ ++ DPLANE_CTX_VALID(ctx); ++ ++ return ctx->u.rinfo.zd_flags; ++} ++ ++void dplane_ctx_set_flags(struct zebra_dplane_ctx *ctx, uint32_t flags) ++{ ++ DPLANE_CTX_VALID(ctx); ++ ++ ctx->u.rinfo.zd_flags = flags; ++} ++ + uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx) + { + DPLANE_CTX_VALID(ctx); +@@ -2318,25 +2334,16 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, + return AOK; + } + +-/* +- * Initialize a context block for a route update from zebra data structs. +- */ +-int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, +- struct route_node *rn, struct route_entry *re) ++int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx, ++ enum dplane_op_e op, struct route_entry *re, ++ const struct prefix *p, ++ const struct prefix_ipv6 *src_p, afi_t afi, ++ safi_t safi) + { + int ret = EINVAL; +- const struct route_table *table = NULL; +- const struct rib_table_info *info; +- const struct prefix *p, *src_p; +- struct zebra_ns *zns; +- struct zebra_vrf *zvrf; +- struct nexthop *nexthop; +- struct zebra_l3vni *zl3vni; +- const struct interface *ifp; +- struct dplane_intf_extra *if_extra; + +- if (!ctx || !rn || !re) +- goto done; ++ if (!ctx || !re) ++ return ret; + + TAILQ_INIT(&ctx->u.rinfo.intf_extra_q); + +@@ -2346,9 +2353,6 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + ctx->u.rinfo.zd_type = re->type; + ctx->u.rinfo.zd_old_type = re->type; + +- /* Prefixes: dest, and optional source */ +- srcdest_rnode_prefixes(rn, &p, &src_p); +- + prefix_copy(&(ctx->u.rinfo.zd_dest), p); + + if (src_p) +@@ -2358,6 +2362,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + + ctx->zd_table_id = re->table; + ++ ctx->u.rinfo.zd_flags = re->flags; + ctx->u.rinfo.zd_metric = re->metric; + ctx->u.rinfo.zd_old_metric = re->metric; + ctx->zd_vrf_id = re->vrf_id; +@@ -2368,11 +2373,46 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + ctx->u.rinfo.zd_old_tag = re->tag; + ctx->u.rinfo.zd_distance = re->distance; + ++ ctx->u.rinfo.zd_afi = afi; ++ ctx->u.rinfo.zd_safi = safi; ++ ++ return AOK; ++} ++ ++/* ++ * Initialize a context block for a route update from zebra data structs. ++ */ ++int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ++ struct route_node *rn, struct route_entry *re) ++{ ++ int ret = EINVAL; ++ const struct route_table *table = NULL; ++ const struct rib_table_info *info; ++ const struct prefix *p; ++ const struct prefix_ipv6 *src_p; ++ struct zebra_ns *zns; ++ struct zebra_vrf *zvrf; ++ struct nexthop *nexthop; ++ struct zebra_l3vni *zl3vni; ++ const struct interface *ifp; ++ struct dplane_intf_extra *if_extra; ++ ++ if (!ctx || !rn || !re) ++ return ret; ++ ++ /* ++ * Let's grab the data from the route_node ++ * so that we can call a helper function ++ */ ++ ++ /* Prefixes: dest, and optional source */ ++ srcdest_rnode_prefixes(rn, &p, (const struct prefix **)&src_p); + table = srcdest_rnode_table(rn); + info = table->info; + +- ctx->u.rinfo.zd_afi = info->afi; +- ctx->u.rinfo.zd_safi = info->safi; ++ if (dplane_ctx_route_init_basic(ctx, op, re, p, src_p, info->afi, ++ info->safi) != AOK) ++ return ret; + + /* Copy nexthops; recursive info is included too */ + copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), +@@ -5281,6 +5321,20 @@ kernel_dplane_process_ipset_entry(struct zebra_dplane_provider *prov, + dplane_provider_enqueue_out_ctx(prov, ctx); + } + ++void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, ++ struct prefix_ipv6 *src_p, struct route_entry *re, ++ struct nexthop_group *ng, int startup, ++ struct zebra_dplane_ctx *ctx) ++{ ++ if (!ctx) ++ rib_add_multipath(afi, safi, p, src_p, re, ng); ++ else { ++ dplane_ctx_route_init_basic(ctx, dplane_ctx_get_op(ctx), re, p, ++ src_p, afi, safi); ++ dplane_provider_enqueue_to_zebra(ctx); ++ } ++} ++ + /* + * Kernel provider callback + */ +diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h +index 1d5518138..c3fe3ba40 100644 +--- a/zebra/zebra_dplane.h ++++ b/zebra/zebra_dplane.h +@@ -343,6 +343,8 @@ route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx); + uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx); + void dplane_ctx_set_instance(struct zebra_dplane_ctx *ctx, uint16_t instance); + uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx); ++uint32_t dplane_ctx_get_flags(const struct zebra_dplane_ctx *ctx); ++void dplane_ctx_set_flags(struct zebra_dplane_ctx *ctx, uint32_t flags); + uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx); + uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx); + uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx); +@@ -772,6 +774,12 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset); + int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + struct route_node *rn, struct route_entry *re); + ++int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx, ++ enum dplane_op_e op, struct route_entry *re, ++ const struct prefix *p, ++ const struct prefix_ipv6 *src_p, afi_t afi, ++ safi_t safi); ++ + /* Encode next hop information into data plane context. */ + int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + struct nhg_hash_entry *nhe); +@@ -930,6 +938,16 @@ void zebra_dplane_pre_finish(void); + void zebra_dplane_finish(void); + void zebra_dplane_shutdown(void); + ++/* ++ * decision point for sending a routing update through the old ++ * straight to zebra master pthread or through the dplane to ++ * the master pthread for handling ++ */ ++void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, ++ struct prefix_ipv6 *src_p, struct route_entry *re, ++ struct nexthop_group *ng, int startup, ++ struct zebra_dplane_ctx *ctx); ++ + #ifdef __cplusplus + } + #endif +diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c +index cf1baf077..50f19adcc 100644 +--- a/zebra/zebra_rib.c ++++ b/zebra/zebra_rib.c +@@ -1403,8 +1403,7 @@ static bool rib_route_match_ctx(const struct route_entry *re, + } + + done: +- +- return (result); ++ return result; + } + + static void zebra_rib_fixup_system(struct route_node *rn) +@@ -2139,8 +2138,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) + } + + /* Ensure we clear the QUEUED flag */ +- if (!zrouter.asic_offloaded) +- UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); ++ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); + + /* Is this a notification that ... matters? We mostly care about + * the route that is currently selected for installation; we may also +@@ -2183,6 +2181,19 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) + dplane_ctx_get_type(ctx))); + } + goto done; ++ } else { ++ uint32_t flags = dplane_ctx_get_flags(ctx); ++ ++ if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED)) { ++ UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED); ++ SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED); ++ } ++ if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED)) { ++ UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED); ++ SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED); ++ } ++ if (CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED)) ++ SET_FLAG(re->flags, ZEBRA_FLAG_TRAPPED); + } + + /* We'll want to determine whether the installation status of the +@@ -2216,55 +2227,70 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) + /* Various fib transitions: changed nexthops; from installed to + * not-installed; or not-installed to installed. + */ +- if (start_count > 0 && end_count > 0) { +- if (debug_p) +- zlog_debug( +- "%s(%u:%u):%pRN applied nexthop changes from dplane notification", +- VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), +- dplane_ctx_get_table(ctx), rn); ++ if (zrouter.asic_notification_nexthop_control) { ++ if (start_count > 0 && end_count > 0) { ++ if (debug_p) ++ zlog_debug( ++ "%s(%u:%u):%pRN applied nexthop changes from dplane notification", ++ VRF_LOGNAME(vrf), ++ dplane_ctx_get_vrf(ctx), ++ dplane_ctx_get_table(ctx), rn); + +- /* Changed nexthops - update kernel/others */ +- dplane_route_notif_update(rn, re, +- DPLANE_OP_ROUTE_UPDATE, ctx); ++ /* Changed nexthops - update kernel/others */ ++ dplane_route_notif_update(rn, re, ++ DPLANE_OP_ROUTE_UPDATE, ctx); + +- } else if (start_count == 0 && end_count > 0) { +- if (debug_p) +- zlog_debug( +- "%s(%u:%u):%pRN installed transition from dplane notification", +- VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), +- dplane_ctx_get_table(ctx), rn); ++ } else if (start_count == 0 && end_count > 0) { ++ if (debug_p) ++ zlog_debug( ++ "%s(%u:%u):%pRN installed transition from dplane notification", ++ VRF_LOGNAME(vrf), ++ dplane_ctx_get_vrf(ctx), ++ dplane_ctx_get_table(ctx), rn); + +- /* We expect this to be the selected route, so we want +- * to tell others about this transition. +- */ +- SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); ++ /* We expect this to be the selected route, so we want ++ * to tell others about this transition. ++ */ ++ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + +- /* Changed nexthops - update kernel/others */ +- dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_UPDATE, ctx); ++ /* Changed nexthops - update kernel/others */ ++ dplane_route_notif_update(rn, re, ++ DPLANE_OP_ROUTE_UPDATE, ctx); + +- /* Redistribute, lsp, and nht update */ +- redistribute_update(rn, re, NULL); ++ /* Redistribute, lsp, and nht update */ ++ redistribute_update(rn, re, NULL); + +- } else if (start_count > 0 && end_count == 0) { +- if (debug_p) +- zlog_debug( +- "%s(%u:%u):%pRN un-installed transition from dplane notification", +- VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), +- dplane_ctx_get_table(ctx), rn); ++ } else if (start_count > 0 && end_count == 0) { ++ if (debug_p) ++ zlog_debug( ++ "%s(%u:%u):%pRN un-installed transition from dplane notification", ++ VRF_LOGNAME(vrf), ++ dplane_ctx_get_vrf(ctx), ++ dplane_ctx_get_table(ctx), rn); + +- /* Transition from _something_ installed to _nothing_ +- * installed. +- */ +- /* We expect this to be the selected route, so we want +- * to tell others about this transistion. +- */ +- UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); ++ /* Transition from _something_ installed to _nothing_ ++ * installed. ++ */ ++ /* We expect this to be the selected route, so we want ++ * to tell others about this transistion. ++ */ ++ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + +- /* Changed nexthops - update kernel/others */ +- dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_DELETE, ctx); ++ /* Changed nexthops - update kernel/others */ ++ dplane_route_notif_update(rn, re, ++ DPLANE_OP_ROUTE_DELETE, ctx); + +- /* Redistribute, lsp, and nht update */ +- redistribute_delete(rn, re, NULL); ++ /* Redistribute, lsp, and nht update */ ++ redistribute_delete(rn, re, NULL); ++ } ++ } ++ ++ if (!zebra_router_notify_on_ack()) { ++ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) ++ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED); ++ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED)) ++ zsend_route_notify_owner_ctx(ctx, ++ ZAPI_ROUTE_FAIL_INSTALL); + } + + /* Make any changes visible for lsp and nexthop-tracking processing */ +diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c +index 92a3b9424..d47517bbb 100644 +--- a/zebra/zebra_router.c ++++ b/zebra/zebra_router.c +@@ -304,6 +304,17 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack) + zrouter.asic_offloaded = asic_offload; + zrouter.notify_on_ack = notify_on_ack; + ++ /* ++ * If you start using asic_notification_nexthop_control ++ * come talk to the FRR community about what you are doing ++ * We would like to know. ++ */ ++#if CONFDATE > 20251231 ++ CPP_NOTICE( ++ "Remove zrouter.asic_notification_nexthop_control as that it's not being maintained or used"); ++#endif ++ zrouter.asic_notification_nexthop_control = false; ++ + #ifdef HAVE_SCRIPTING + zebra_script_init(); + #endif +diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h +index c0eab9cd6..583bd0038 100644 +--- a/zebra/zebra_router.h ++++ b/zebra/zebra_router.h +@@ -209,6 +209,14 @@ struct zebra_router { + */ + bool asic_offloaded; + bool notify_on_ack; ++ ++ /* ++ * If the asic is notifying us about successful nexthop ++ * allocation/control. Some developers have made their ++ * asic take control of how many nexthops/ecmp they can ++ * have and will report what is successfull or not ++ */ ++ bool asic_notification_nexthop_control; + }; + + #define GRACEFUL_RESTART_TIME 60 +diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c +index 0a3d676a9..a7eb09df0 100644 +--- a/zebra/zebra_vty.c ++++ b/zebra/zebra_vty.c +@@ -3972,6 +3972,15 @@ DEFUN (show_zebra, + if (zrouter.asic_offloaded) + vty_out(vty, "Asic Offload is being used\n"); + ++ /* ++ * Do not display this unless someone is actually using it ++ * ++ * Why this distinction? I think this is effectively dead code ++ * and should not be exposed. Maybe someone proves me wrong. ++ */ ++ if (zrouter.asic_notification_nexthop_control) ++ vty_out(vty, "ASIC offload and nexthop control is being used"); ++ + vty_out(vty, + " Route Route Neighbor LSP LSP\n"); + vty_out(vty, +-- +2.30.2 + diff --git a/src/sonic-frr/patch/Added-support-for-L3VNI-for-EVPN.patch b/src/sonic-frr/patch/Added-support-for-L3VNI-for-EVPN.patch new file mode 100644 index 00000000000..21a72342199 --- /dev/null +++ b/src/sonic-frr/patch/Added-support-for-L3VNI-for-EVPN.patch @@ -0,0 +1,127 @@ +From 9cb41b6c92ffcc613554b2535c118224c982c57a Mon Sep 17 00:00:00 2001 +From: Stepan Blyschak +Date: Thu, 20 Oct 2022 13:19:31 +0000 +Subject: [PATCH 3/3] Added support for L3VNI for EVPN + +This is temp patch till Prefix to ARP indirection is add in neighorch + +Signed-off-by: Kishore Kunal +Signed-off-by: Stepan Blyschak +--- + lib/nexthop.c | 1 + + lib/nexthop.h | 7 ++++++- + zebra/rt_netlink.c | 15 ++++++++++++++- + zebra/zapi_msg.c | 4 ++++ + zebra/zebra_dplane.c | 2 +- + 5 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/lib/nexthop.c b/lib/nexthop.c +index e17eeb830..6ed83b84f 100644 +--- a/lib/nexthop.c ++++ b/lib/nexthop.c +@@ -813,6 +813,7 @@ void nexthop_copy_no_recurse(struct nexthop *copy, + memcpy(©->src, &nexthop->src, sizeof(nexthop->src)); + memcpy(©->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src)); + copy->rparent = rparent; ++ memcpy(©->nh_encap.encap_data.rmac, &nexthop->nh_encap.encap_data.rmac, ETH_ALEN); + if (nexthop->nh_label) + nexthop_add_labels(copy, nexthop->nh_label_type, + nexthop->nh_label->num_labels, +diff --git a/lib/nexthop.h b/lib/nexthop.h +index 320b46315..77eea3674 100644 +--- a/lib/nexthop.h ++++ b/lib/nexthop.h +@@ -66,6 +66,11 @@ enum nh_encap_type { + /* Backup index value is limited */ + #define NEXTHOP_BACKUP_IDX_MAX 255 + ++struct vxlan_nh_encap { ++ vni_t vni; ++ struct ethaddr rmac; ++}; ++ + /* Nexthop structure. */ + struct nexthop { + struct nexthop *next; +@@ -135,7 +140,7 @@ struct nexthop { + /* Encapsulation information. */ + enum nh_encap_type nh_encap_type; + union { +- vni_t vni; ++ struct vxlan_nh_encap encap_data; + } nh_encap; + + /* SR-TE color used for matching SR-TE policies */ +diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c +index 4dd73fe90..a2fcd6cfc 100644 +--- a/zebra/rt_netlink.c ++++ b/zebra/rt_netlink.c +@@ -1893,6 +1893,7 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen, + struct nexthop *nh) + { + struct rtattr *nest; ++ struct vxlan_nh_encap* encap_data; + + switch (nh->nh_encap_type) { + case NET_VXLAN: +@@ -1903,9 +1904,21 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen, + if (!nest) + return false; + ++ encap_data = &nh->nh_encap.encap_data; ++ + if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, +- nh->nh_encap.vni)) ++ encap_data->vni)) ++ return false; ++ ++ if (ZEBRA_DEBUG_KERNEL) ++ zlog_debug( ++ "%s: VNI:%d RMAC:%pEA", __func__, encap_data->vni, ++ &encap_data->rmac); ++ ++ if (!nl_attr_put(n, nlen, 1 /* VXLAN_RMAC */, ++ &encap_data->rmac, sizeof(encap_data->rmac))) + return false; ++ + nl_attr_nest_end(n, nest); + break; + } +diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c +index 5cf7d815d..529cbb44b 100644 +--- a/zebra/zapi_msg.c ++++ b/zebra/zapi_msg.c +@@ -1577,6 +1577,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, + vtep_ip.ipa_type = IPADDR_V4; + memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4), + sizeof(struct in_addr)); ++ memcpy(&(nexthop->nh_encap.encap_data.rmac), ++ &api_nh->rmac, ETH_ALEN); + zebra_rib_queue_evpn_route_add( + api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); + } +@@ -1610,6 +1612,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, + vtep_ip.ipa_type = IPADDR_V6; + memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), + sizeof(struct in6_addr)); ++ memcpy(&(nexthop->nh_encap.encap_data.rmac), ++ &api_nh->rmac, ETH_ALEN); + zebra_rib_queue_evpn_route_add( + api_nh->vrf_id, &api_nh->rmac, &vtep_ip, p); + } +diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c +index 336056abb..c79e7cc27 100644 +--- a/zebra/zebra_dplane.c ++++ b/zebra/zebra_dplane.c +@@ -2460,7 +2460,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + zl3vni = zl3vni_from_vrf(nexthop->vrf_id); + if (zl3vni && is_l3vni_oper_up(zl3vni)) { + nexthop->nh_encap_type = NET_VXLAN; +- nexthop->nh_encap.vni = zl3vni->vni; ++ nexthop->nh_encap.encap_data.vni = zl3vni->vni; + } + } + +-- +2.30.2 + diff --git a/src/sonic-frr/patch/bgpd-Allow-network-XXX-to-work-with-bgp-suppress-fib.patch b/src/sonic-frr/patch/bgpd-Allow-network-XXX-to-work-with-bgp-suppress-fib.patch new file mode 100644 index 00000000000..3e2eac63c99 --- /dev/null +++ b/src/sonic-frr/patch/bgpd-Allow-network-XXX-to-work-with-bgp-suppress-fib.patch @@ -0,0 +1,186 @@ +From 4801fc4670020406fc609dedabc7482d88e3b656 Mon Sep 17 00:00:00 2001 +From: Donald Sharp +Date: Wed, 12 Oct 2022 14:53:21 -0400 +Subject: [PATCH] bgpd: Allow `network XXX` to work with bgp + suppress-fib-pending + +When bgp is using `bgp suppress-fib-pending` and the end +operator is using network statements, bgp was not sending +the network'ed prefix'es to it's peers. Fix this. + +Also update the test cases for bgp_suppress_fib to test +this new corner case( I am sure that there are going to +be others that will need to be added ). + +Fixes: #12112 +Signed-off-by: Donald Sharp +--- + bgpd/bgp_route.h | 20 ++++++++++++++-- + .../bgp_suppress_fib/r1/bgp_ipv4_allowas.json | 2 +- + .../bgp_suppress_fib/r2/bgp_ipv4_allowas.json | 2 +- + tests/topotests/bgp_suppress_fib/r2/bgpd.conf | 2 ++ + .../topotests/bgp_suppress_fib/r2/zebra.conf | 3 +++ + .../bgp_suppress_fib/r3/v4_route3.json | 23 +++++++++++++++++++ + .../bgp_suppress_fib/test_bgp_suppress_fib.py | 14 ++++++++--- + 7 files changed, 59 insertions(+), 7 deletions(-) + create mode 100644 tests/topotests/bgp_suppress_fib/r3/v4_route3.json + +diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h +index ddef4ca1bbf..1107e3e33e7 100644 +--- a/bgpd/bgp_route.h ++++ b/bgpd/bgp_route.h +@@ -608,19 +608,35 @@ static inline bool bgp_check_advertise(struct bgp *bgp, struct bgp_dest *dest) + */ + static inline bool bgp_check_withdrawal(struct bgp *bgp, struct bgp_dest *dest) + { +- struct bgp_path_info *pi; ++ struct bgp_path_info *pi, *selected = NULL; + + if (!BGP_SUPPRESS_FIB_ENABLED(bgp)) + return false; + + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { +- if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) ++ if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { ++ selected = pi; + continue; ++ } + + if (pi->sub_type != BGP_ROUTE_NORMAL) + return true; + } + ++ /* ++ * pi is selected and bgp is dealing with a static route ++ * ( ie a network statement of some sort ). FIB installed ++ * is irrelevant ++ * ++ * I am not sure what the above for loop is wanted in this ++ * manner at this point. But I do know that if I have ++ * a static route that is selected and it's the one ++ * being checked for should I withdrawal we do not ++ * want to withdraw the route on installation :) ++ */ ++ if (selected && selected->sub_type == BGP_ROUTE_STATIC) ++ return false; ++ + if (CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)) + return false; + +diff --git a/tests/topotests/bgp_suppress_fib/r1/bgp_ipv4_allowas.json b/tests/topotests/bgp_suppress_fib/r1/bgp_ipv4_allowas.json +index bc4d0f4796b..1a5ede276d8 100644 +--- a/tests/topotests/bgp_suppress_fib/r1/bgp_ipv4_allowas.json ++++ b/tests/topotests/bgp_suppress_fib/r1/bgp_ipv4_allowas.json +@@ -32,7 +32,7 @@ + ], + "peer":{ + "peerId":"10.0.0.2", +- "routerId":"10.0.0.9", ++ "routerId":"60.0.0.1", + "type":"external" + } + } +diff --git a/tests/topotests/bgp_suppress_fib/r2/bgp_ipv4_allowas.json b/tests/topotests/bgp_suppress_fib/r2/bgp_ipv4_allowas.json +index 16561ce837f..4a35abfd6fd 100644 +--- a/tests/topotests/bgp_suppress_fib/r2/bgp_ipv4_allowas.json ++++ b/tests/topotests/bgp_suppress_fib/r2/bgp_ipv4_allowas.json +@@ -61,7 +61,7 @@ + ], + "peer":{ + "peerId":"0.0.0.0", +- "routerId":"10.0.0.9" ++ "routerId":"60.0.0.1" + } + } + ] +diff --git a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf +index ebef2012a80..010e86aad70 100644 +--- a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf ++++ b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf +@@ -7,3 +7,5 @@ router bgp 2 + bgp suppress-fib-pending + neighbor 10.0.0.1 remote-as 1 + neighbor 10.0.0.10 remote-as 3 ++ address-family ipv4 uni ++ network 60.0.0.0/24 +\ No newline at end of file +diff --git a/tests/topotests/bgp_suppress_fib/r2/zebra.conf b/tests/topotests/bgp_suppress_fib/r2/zebra.conf +index 443fffc7032..6e8bce0450d 100644 +--- a/tests/topotests/bgp_suppress_fib/r2/zebra.conf ++++ b/tests/topotests/bgp_suppress_fib/r2/zebra.conf +@@ -1,4 +1,7 @@ + ! ++interface lo ++ ip address 60.0.0.1/24 ++! + interface r2-eth0 + ip address 10.0.0.2/30 + ! +diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route3.json b/tests/topotests/bgp_suppress_fib/r3/v4_route3.json +new file mode 100644 +index 00000000000..ab8c3aa5e51 +--- /dev/null ++++ b/tests/topotests/bgp_suppress_fib/r3/v4_route3.json +@@ -0,0 +1,23 @@ ++{ ++ "60.0.0.0/24":[ ++ { ++ "prefix":"60.0.0.0/24", ++ "protocol":"bgp", ++ "selected":true, ++ "destSelected":true, ++ "distance":20, ++ "metric":0, ++ "installed":true, ++ "table":254, ++ "nexthops":[ ++ { ++ "fib":true, ++ "ip":"10.0.0.9", ++ "afi":"ipv4", ++ "interfaceName":"r3-eth0", ++ "active":true ++ } ++ ] ++ } ++ ] ++} +diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py +index 2c87d9d7b0f..96a294cae34 100644 +--- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py ++++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py +@@ -84,8 +84,6 @@ def test_bgp_route(): + + r3 = tgen.gears["r3"] + +- sleep(5) +- + json_file = "{}/r3/v4_route.json".format(CWD) + expected = json.loads(open(json_file).read()) + +@@ -95,7 +93,7 @@ def test_bgp_route(): + "show ip route 40.0.0.0 json", + expected, + ) +- _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5) ++ _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5) + assertmsg = '"r3" JSON output mismatches' + assert result is None, assertmsg + +@@ -112,6 +110,16 @@ def test_bgp_route(): + assertmsg = '"r3" JSON output mismatches' + assert result is None, assertmsg + ++ json_file = "{}/r3/v4_route3.json".format(CWD) ++ expected = json.loads(open(json_file).read()) ++ ++ test_func = partial( ++ topotest.router_json_cmp, ++ r3, ++ "show ip route 10.0.0.3 json", ++ expected, ++ ) ++ _, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5) + + def test_bgp_better_admin_won(): + "A better Admin distance protocol may come along and knock us out" diff --git a/src/sonic-frr/patch/dplane_fpm_nl-ignore-route-from-default-table.patch b/src/sonic-frr/patch/dplane_fpm_nl-ignore-route-from-default-table.patch new file mode 100644 index 00000000000..118a96595cd --- /dev/null +++ b/src/sonic-frr/patch/dplane_fpm_nl-ignore-route-from-default-table.patch @@ -0,0 +1,33 @@ +From 88aaa7b28f1660c82bb03d86ee5718cf96459386 Mon Sep 17 00:00:00 2001 +From: Stepan Blyschak +Date: Thu, 20 Oct 2022 13:07:18 +0000 +Subject: [PATCH 3/4] [dplane_fpm_nl] ignore route from default table + +Signed-off-by: Stepan Blyschak +--- + zebra/dplane_fpm_nl.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c +index 912d08e6b..a8f60310a 100644 +--- a/zebra/dplane_fpm_nl.c ++++ b/zebra/dplane_fpm_nl.c +@@ -774,6 +774,15 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) + || op == DPLANE_OP_NH_UPDATE)) + return 0; + ++ /* ++ * Ignore route from default table, because when mgmt port goes down, ++ * zebra will remove the default route and causing ASIC to blackhole IO. ++ */ ++ if (dplane_ctx_get_table(ctx) == RT_TABLE_DEFAULT) { ++ zlog_debug("%s: discard default table route", __func__); ++ return 0; ++ } ++ + nl_buf_len = 0; + + frr_mutex_lock_autounlock(&fnc->obuf_mutex); +-- +2.30.2 + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index c62bd218c7e..4237c63a1b4 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -1,13 +1,14 @@ 0001-Add-support-of-bgp-tcp-DSCP-value.patch 0002-Reduce-severity-of-Vty-connected-from-message.patch -0003-Use-vrf_id-for-vrf-not-tabled_id.patch 0004-Allow-BGP-attr-NEXT_HOP-to-be-0.0.0.0-due-to-allevia.patch 0005-nexthops-compare-vrf-only-if-ip-type.patch 0006-frr-remove-frr-log-outchannel-to-var-log-frr.log.patch -0007-Add-support-of-bgp-l3vni-evpn.patch 0008-Link-local-scope-was-not-set-while-binding-socket-for-bgp-ipv6-link-local-neighbors.patch Disable-ipv6-src-address-test-in-pceplib.patch cross-compile-changes.patch -0009-ignore-route-from-default-table.patch -0010-zebra-Note-when-the-netlink-DUMP-command-is-interrup.patch +bgpd-Allow-network-XXX-to-work-with-bgp-suppress-fib.patch +Add-ability-for-dplane_fpm_nl-to-receive-RTM_NEWROUT.patch +use-vrf-id-instead-of-table-id.patch +dplane_fpm_nl-ignore-route-from-default-table.patch +Added-support-for-L3VNI-for-EVPN.patch 0011-bgpd-enhanced-capability-is-always-turned-on-for-int.patch diff --git a/src/sonic-frr/patch/use-vrf-id-instead-of-table-id.patch b/src/sonic-frr/patch/use-vrf-id-instead-of-table-id.patch new file mode 100644 index 00000000000..d2f0a25a0d0 --- /dev/null +++ b/src/sonic-frr/patch/use-vrf-id-instead-of-table-id.patch @@ -0,0 +1,103 @@ +From c721612eb8e9fb33c688e4ac1b11e7dbcedf293a Mon Sep 17 00:00:00 2001 +From: Stepan Blyschak +Date: Thu, 20 Oct 2022 11:03:14 +0000 +Subject: [PATCH 1/4] use vrf id instead of table id + +Signed-off-by: Stepan Blyschak +--- + zebra/rt_netlink.c | 64 ++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 51 insertions(+), 13 deletions(-) + +diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c +index 24c01b7f5..0a9fdb909 100644 +--- a/zebra/rt_netlink.c ++++ b/zebra/rt_netlink.c +@@ -388,6 +388,30 @@ vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) + return VRF_DEFAULT; + } + ++static uint32_t table_lookup_by_vrf(vrf_id_t vrf_id, ns_id_t ns_id) ++{ ++ struct vrf *vrf; ++ struct zebra_vrf *zvrf; ++ ++ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { ++ zvrf = vrf->info; ++ if (zvrf == NULL) ++ continue; ++ /* case vrf with netns : match the netnsid */ ++ if (vrf_is_backend_netns()) { ++ if (ns_id == zvrf_id(zvrf)) ++ return zvrf->table_id; ++ } else { ++ /* VRF is VRF_BACKEND_VRF_LITE */ ++ if (zvrf_id(zvrf) != vrf_id) ++ continue; ++ return zvrf->table_id; ++ } ++ } ++ ++ return RT_TABLE_UNSPEC; ++} ++ + /** + * @parse_encap_mpls() - Parses encapsulated mpls attributes + * @tb: Pointer to rtattr to look for nested items in. +@@ -754,14 +778,23 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, + if (rtm->rtm_family == AF_MPLS) + return 0; + +- /* Table corresponding to route. */ +- if (tb[RTA_TABLE]) +- table = *(int *)RTA_DATA(tb[RTA_TABLE]); +- else +- table = rtm->rtm_table; ++ if (!ctx) { ++ /* Table corresponding to route. */ ++ if (tb[RTA_TABLE]) ++ table = *(int *)RTA_DATA(tb[RTA_TABLE]); ++ else ++ table = rtm->rtm_table; ++ ++ /* Map to VRF */ ++ vrf_id = vrf_lookup_by_table(table, ns_id); ++ } else { ++ /* With FPM, rtm_table contains vrf id, see netlink_route_multipath_msg_encode */ ++ vrf_id = rtm->rtm_table; ++ ++ /* Map to table */ ++ table = table_lookup_by_vrf(vrf_id, ns_id); ++ } + +- /* Map to VRF */ +- vrf_id = 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)) +@@ -1969,12 +2002,17 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, + #endif + /* Table corresponding to this route. */ + table_id = dplane_ctx_get_table(ctx); +- if (table_id < 256) +- req->r.rtm_table = table_id; +- else { +- 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; ++ else { ++ req->r.rtm_table = RT_TABLE_UNSPEC; ++ if (!nl_attr_put32(&req->n, datalen, RTA_TABLE, table_id)) ++ return 0; ++ } ++ } else { ++ /* Put vrf if_index instead of table id */ ++ req->r.rtm_table = dplane_ctx_get_vrf(ctx); + } + + if (IS_ZEBRA_DEBUG_KERNEL) +-- +2.30.2 + diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index b620438451a..a84e4aefa19 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -78,6 +78,7 @@ def run(self): cmdclass={'build_py': my_build_py}, data_files=[ ('yang-models', ['./yang-models/sonic-acl.yang', + './yang-models/sonic-app-state-logging.yang', './yang-models/sonic-auto_techsupport.yang', './yang-models/sonic-bgp-common.yang', './yang-models/sonic-bgp-device-global.yang', diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 9dec93b5203..f8f1c1fc0d8 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -2054,7 +2054,7 @@ "enabled": "yes" } }, - "STATIC_ROUTE": { + "STATIC_ROUTE": { "default|20.20.20.0/24": { "blackhole": "false", "distance": "1", @@ -2063,6 +2063,10 @@ "nexthop-vrf": "default" } }, + "APP_STATE_LOGGING": { + "ROUTE_TABLE": { + "state": "enabled" + }, "KUBERNETES_MASTER": { "SERVER": { "disable": "True", diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/app-state-logging.json b/src/sonic-yang-models/tests/yang_model_tests/tests/app-state-logging.json new file mode 100644 index 00000000000..47612bd3c3d --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/app-state-logging.json @@ -0,0 +1,12 @@ +{ + "APP_STATE_LOGGING_ENABLED": { + "desc": "Configure an entry in APP_STATE_LOGGING table with enabled state" + }, + "APP_STATE_LOGGING_DISABLED": { + "desc": "Configure an entry in APP_STATE_LOGGING table with disabled state" + }, + "APP_STATE_LOGGING_INVALID_FIELD": { + "desc": "Configuration of APP_STATE_LOGGING state field with an incorrect value", + "eStr" : ["Invalid value"] + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json b/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json index 8a562ef536a..6348b1d22f7 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json @@ -116,6 +116,19 @@ }, "DEVICE_METADATA_ADVERTISE_LO_PREFIX_AS_128": { "desc": "Verifying advertising lo prefix as /128." + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED": { + "desc": "Enable bgp-suppress-fib-pending" + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_DISABLED": { + "desc": "Disable bgp-suppress-fib-pending" + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED_SYNCHRONOUS_MODE_DISABLED": { + "desc": "Enable bgp-suppress-fib-pending when synchronous mode is disabled", + "eStr": ["ASIC synchronous mode and APP_STATE_LOGGING for ROUTE_TABLE must be enabled in order to enable BGP suppress FIB pending feature"] + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED_ROUTE_LOGGING_DISABLED": { + "desc": "Enable bgp-suppress-fib-pending when ROUTE_TABLE logging is disabled", + "eStr": ["ASIC synchronous mode and APP_STATE_LOGGING for ROUTE_TABLE must be enabled in order to enable BGP suppress FIB pending feature"] } - } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/app-state-logging.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/app-state-logging.json new file mode 100644 index 00000000000..ab11a866cc5 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/app-state-logging.json @@ -0,0 +1,30 @@ +{ + "APP_STATE_LOGGING_ENABLED": { + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "enabled" + } + } + } + }, + "APP_STATE_LOGGING_DISABLED": { + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "enabled" + } + } + } + }, + "APP_STATE_LOGGING_INVALID_FIELD": { + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "abcd" + } + } + } + } +} + diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json index ece046f2afb..ade77cbc820 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json @@ -321,5 +321,66 @@ } } } + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "synchronous_mode": "enable", + "bgp-suppress-fib-pending": "enabled" + } + } + }, + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "enabled" + } + } + } + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_DISABLED": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "synchronous_mode": "disable", + "bgp-suppress-fib-pending": "disabled" + } + } + } + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED_SYNCHRONOUS_MODE_DISABLED": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "synchronous_mode": "disable", + "bgp-suppress-fib-pending": "enabled" + } + } + }, + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "enabled" + } + } + } + }, + "DEVICE_METADATA_BGP_SUPPRESS_FIB_PENDING_ENABLED_ROUTE_LOGGING_DISABLED": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "synchronous_mode": "enable", + "bgp-suppress-fib-pending": "enabled" + } + } + }, + "sonic-app-state-logging:sonic-app-state-logging": { + "sonic-app-state-logging:APP_STATE_LOGGING": { + "sonic-app-state-logging:ROUTE_TABLE": { + "state": "disabled" + } + } + } } } diff --git a/src/sonic-yang-models/yang-models/sonic-app-state-logging.yang b/src/sonic-yang-models/yang-models/sonic-app-state-logging.yang new file mode 100644 index 00000000000..79168197d28 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-app-state-logging.yang @@ -0,0 +1,35 @@ +module sonic-app-state-logging { + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-app-state-logging"; + prefix app-state-logging; + + description "APP_STATE_LOGGING YANG module for SONiC OS"; + + revision 2022-09-15 { + description "Initial revision"; + } + + container sonic-app-state-logging { + container APP_STATE_LOGGING { + description "Controls the enablement of a response channel per APPL_DB table"; + + container ROUTE_TABLE { + description "Configure response channel for ASIC route configuration"; + + leaf state { + description "Enablement state of response channel for the given table"; + type enumeration { + enum enabled; + enum disabled; + } + default disabled; + } + } + /* end of container ROUTE_TABLE */ + } + /* end of container APP_STATE_LOGGING */ + } + /* end of container of top level container */ +} +/* end of module sonic-app-state-logging */ diff --git a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang index b04f929cddc..24ff7a1c665 100644 --- a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang +++ b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang @@ -17,10 +17,14 @@ module sonic-device_metadata { prefix stypes; } + import sonic-app-state-logging { + prefix app-state-logging; + } + description "DEVICE_METADATA YANG Module for SONiC OS"; - + revision 2021-02-27 { - description "Added frr_mgmt_framework_config field to handle BGP + description "Added frr_mgmt_framework_config field to handle BGP config DB schema events to configure FRR protocols."; } @@ -106,7 +110,7 @@ module sonic-device_metadata { leaf frr_mgmt_framework_config { type boolean; - description "FRR configurations are handled by sonic-frr-mgmt-framework module when set to true, + description "FRR configurations are handled by sonic-frr-mgmt-framework module when set to true, otherwise, sonic-bgpcfgd handles the FRR configurations based on the predefined templates."; default "false"; } @@ -194,6 +198,21 @@ module sonic-device_metadata { description "Advertise Loopback0 interface IPv6 /128 subnet address as it is with set to true. By default SONiC advertises /128 subnet prefix in Loopback0 as /64 subnet route"; } + + leaf bgp-suppress-fib-pending { + description "Enable BGP suppress FIB pending feature. BGP will wait for route + FIB intallation before announcing routes. This configuration requires + restarting BGP sessions."; + type enumeration { + enum enabled; + enum disabled; + } + default disabled; + + must "((current() = 'disabled') or (current() = 'enabled' and ../synchronous_mode = 'enable' and /app-state-logging:sonic-app-state-logging/app-state-logging:APP_STATE_LOGGING/app-state-logging:ROUTE_TABLE/app-state-logging:state = 'enabled'))" { + error-message "ASIC synchronous mode and APP_STATE_LOGGING for ROUTE_TABLE must be enabled in order to enable BGP suppress FIB pending feature"; + } + } } /* end of container localhost */ }