diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 index f5a56c316d41..673918b3d948 100644 --- a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 @@ -7,8 +7,14 @@ {% endblock banner %} ! {% block fpm %} +{% if ( ('localhost' in DEVICE_METADATA) and ('nexthop_group' in DEVICE_METADATA['localhost']) and + (DEVICE_METADATA['localhost']['nexthop_group'] == 'enabled') ) %} +! enable next hop group support +fpm use-next-hop-groups +{% else %} ! 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 +{% endif %} ! fpm address 127.0.0.1 {% endblock fpm %} diff --git a/src/libnl3/patch/0003-Adding-support-for-RTA_NH_ID-attribute.patch b/src/libnl3/patch/0003-Adding-support-for-RTA_NH_ID-attribute.patch new file mode 100644 index 000000000000..80f94a2a02b7 --- /dev/null +++ b/src/libnl3/patch/0003-Adding-support-for-RTA_NH_ID-attribute.patch @@ -0,0 +1,154 @@ +From 70e995bd076b5027414e1332a453f366f20c7002 Mon Sep 17 00:00:00 2001 +From: Fernando +Date: Mon, 19 Sep 2022 12:56:46 -0300 +Subject: Adding support for RTA_NH_ID attribute + +--- + include/netlink-private/types.h | 1 + + include/netlink/route/route.h | 2 ++ + lib/route/route_obj.c | 23 +++++++++++++++++++++++ + 3 files changed, 26 insertions(+) + +diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h +index 97af3e5..51e58b1 100644 +--- a/include/netlink-private/types.h ++++ b/include/netlink-private/types.h +@@ -348,6 +348,7 @@ struct rtnl_route + uint32_t rt_metrics[RTAX_MAX]; + uint32_t rt_metrics_mask; + uint32_t rt_nr_nh; ++ uint32_t rt_nh_id; + struct nl_addr * rt_pref_src; + struct nl_list_head rt_nexthops; + struct rtnl_rtcacheinfo rt_cacheinfo; +diff --git a/include/netlink/route/route.h b/include/netlink/route/route.h +index 824dae3..9cfa393 100644 +--- a/include/netlink/route/route.h ++++ b/include/netlink/route/route.h +@@ -93,6 +93,8 @@ extern int rtnl_route_set_pref_src(struct rtnl_route *, struct nl_addr *); + extern struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *); + extern void rtnl_route_set_iif(struct rtnl_route *, int); + extern int rtnl_route_get_iif(struct rtnl_route *); ++extern void rtnl_route_set_nh_id(struct rtnl_route *, uint32_t); ++extern uint32_t rtnl_route_get_nh_id(struct rtnl_route *); + extern int rtnl_route_get_src_len(struct rtnl_route *); + extern void rtnl_route_set_ttl_propagate(struct rtnl_route *route, + uint8_t ttl_prop); +diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c +index bacabe8..5d9d4ce 100644 +--- a/lib/route/route_obj.c ++++ b/lib/route/route_obj.c +@@ -65,6 +65,7 @@ + #define ROUTE_ATTR_REALMS 0x010000 + #define ROUTE_ATTR_CACHEINFO 0x020000 + #define ROUTE_ATTR_TTL_PROPAGATE 0x040000 ++#define ROUTE_ATTR_NH_ID 0x080000 + /** @endcond */ + + static void route_constructor(struct nl_object *c) +@@ -252,6 +253,8 @@ static void route_dump_details(struct nl_object *a, struct nl_dump_params *p) + nl_dump(p, " ttl-propagate %s", + r->rt_ttl_propagate ? "enabled" : "disabled"); + } ++ if (r->ce_mask & ROUTE_ATTR_NH_ID) ++ nl_dump(p, "nh id %d ", r->rt_nh_id); + + nl_dump(p, "\n"); + +@@ -391,6 +394,7 @@ static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b, + b->rt_pref_src)); + diff |= ROUTE_DIFF(TTL_PROPAGATE, + a->rt_ttl_propagate != b->rt_ttl_propagate); ++ diff |= ROUTE_DIFF(NH_ID, a->rt_nh_id != b->rt_nh_id); + + if (flags & LOOSE_COMPARISON) { + nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) { +@@ -589,6 +593,7 @@ static const struct trans_tbl route_attrs[] = { + __ADD(ROUTE_ATTR_REALMS, realms), + __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo), + __ADD(ROUTE_ATTR_TTL_PROPAGATE, ttl_propagate), ++ __ADD(ROUTE_ATTR_NH_ID, nh_id), + }; + + static char *route_attrs2str(int attrs, char *buf, size_t len) +@@ -862,6 +867,17 @@ int rtnl_route_get_iif(struct rtnl_route *route) + return route->rt_iif; + } + ++void rtnl_route_set_nh_id(struct rtnl_route *route, uint32_t nhid) ++{ ++ route->rt_nh_id = nhid; ++ route->ce_mask |= ROUTE_ATTR_NH_ID; ++} ++ ++uint32_t rtnl_route_get_nh_id(struct rtnl_route *route) ++{ ++ return route->rt_nh_id; ++} ++ + void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) + { + nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops); +@@ -1018,6 +1034,7 @@ static struct nla_policy route_policy[RTA_MAX+1] = { + [RTA_TTL_PROPAGATE] = { .type = NLA_U8 }, + [RTA_ENCAP] = { .type = NLA_NESTED }, + [RTA_ENCAP_TYPE] = { .type = NLA_U16 }, ++ [RTA_NH_ID] = { .type = NLA_U32 }, + }; + + static int parse_multipath(struct rtnl_route *route, struct nlattr *attr) +@@ -1201,6 +1218,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) + nl_addr_put(addr); + } + ++ if (tb[RTA_NH_ID]) ++ rtnl_route_set_nh_id(route, nla_get_u32(tb[RTA_NH_ID])); ++ + if (tb[RTA_METRICS]) { + struct nlattr *mtb[RTAX_MAX + 1]; + int i; +@@ -1404,6 +1424,9 @@ int rtnl_route_build_msg(struct nl_msg *msg, struct rtnl_route *route) + if (route->ce_mask & ROUTE_ATTR_TTL_PROPAGATE) + NLA_PUT_U8(msg, RTA_TTL_PROPAGATE, route->rt_ttl_propagate); + ++ if (route->ce_mask & ROUTE_ATTR_NH_ID) ++ NLA_PUT_U32(msg, RTA_NH_ID, route->rt_nh_id); ++ + if (route->rt_nmetrics > 0) { + uint32_t val; + +-- +2.25.1 + +diff --git a/include/linux-private/linux/rtnetlink.h b/include/linux-private/linux/rtnetlink.h +index 8c1d600..82fb56b 100644 +--- a/include/linux-private/linux/rtnetlink.h ++++ b/include/linux-private/linux/rtnetlink.h +@@ -342,6 +342,7 @@ enum rtattr_type_t { + RTA_IP_PROTO, + RTA_SPORT, + RTA_DPORT, ++ RTA_NH_ID, + __RTA_MAX + }; + +diff --git a/libnl-route-3.sym b/libnl-route-3.sym +index ce6d714..fb81b7f 100644 +--- a/libnl-route-3.sym ++++ b/libnl-route-3.sym +@@ -690,6 +690,7 @@ global: + rtnl_route_get_family; + rtnl_route_get_flags; + rtnl_route_get_iif; ++ rtnl_route_get_nh_id; + rtnl_route_get_metric; + rtnl_route_get_nexthops; + rtnl_route_get_nnexthops; +@@ -732,6 +733,7 @@ global: + rtnl_route_set_family; + rtnl_route_set_flags; + rtnl_route_set_iif; ++ rtnl_route_set_nh_id; + rtnl_route_set_metric; + rtnl_route_set_pref_src; + rtnl_route_set_priority; diff --git a/src/libnl3/patch/series b/src/libnl3/patch/series index 4508b1dd652a..4c7c2d8e25a5 100644 --- a/src/libnl3/patch/series +++ b/src/libnl3/patch/series @@ -1,2 +1,3 @@ 0001-mpls-encap-accessors.patch 0002-mpls-remove-nl_addr_valid.patch +0003-Adding-support-for-RTA_NH_ID-attribute.patch 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 1439a78c5f23..e58850709cb1 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -377,7 +377,8 @@ "timezone": "Europe/Kiev", "bgp_router_id": "8.8.8.8", "chassis_hostname": "str-sonic-chassis-1", - "slice_type": "AZNG_Production" + "slice_type": "AZNG_Production", + "nexthop_group": "disabled" } }, "VLAN": { 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 bd3a44c3764f..119e5b7cec44 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 @@ -178,5 +178,8 @@ }, "DEVICE_METADATA_VALID_SLICE_TYPE": { "desc": "Verifying valid slice_type configuration." - } + }, + "DEVICE_METADATA_VALID_NEXTHOP_GROUP": { + "desc": "Verifying nexthop_group configuration." + } } 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 3d5adcabc4ea..5d0e0201b4ff 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 @@ -490,5 +490,14 @@ } } } + }, + "DEVICE_METADATA_VALID_NEXTHOP_GROUP": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "nexthop_group": "disabled" + } + } + } } } 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 5c5abdeb1a6f..c097da81a870 100644 --- a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang +++ b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang @@ -265,6 +265,15 @@ module sonic-device_metadata { type string; } + leaf nexthop_group { + description "Enable or disable Nexthop Group feature. This value only takes effect during boot time."; + type enumeration { + enum enabled; + enum disabled; + } + default disabled; + } + } /* end of container localhost */ }