diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 index 4543ad8f974e..86cf8de60df3 100644 --- a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 @@ -7,10 +7,17 @@ {% 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 +zebra nexthop kernel enable +fpm use-next-hop-groups +{% else %} ! Force disable next hop group support no zebra nexthop kernel enable ! 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 +no fpm use-next-hop-groupss +{% endif %} ! fpm address 127.0.0.1 {% endblock fpm %} diff --git a/sonic-buildimage_libnl3_35dc1736e.patch b/sonic-buildimage_libnl3_35dc1736e.patch new file mode 100644 index 000000000000..393cc94df9f2 --- /dev/null +++ b/sonic-buildimage_libnl3_35dc1736e.patch @@ -0,0 +1,168 @@ +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 000000000..09ceed803 +--- /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 4508b1dd6..4c7c2d8e2 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/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/yang-models/sonic-device_metadata.yang b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang index 02f81283cf7d..10b4d1a0f8f3 100644 --- a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang +++ b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang @@ -254,6 +254,16 @@ module sonic-device_metadata { type inet:ipv4-address; description "BGP Router identifier"; } + + 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 */ }