From 1c33160aea35b3aa8a5d3db0f378c079aef9f0bb Mon Sep 17 00:00:00 2001 From: Brad House Date: Fri, 7 Feb 2025 09:36:58 -0500 Subject: [PATCH] FRR: upgrade to libyang3 This also backports a series of commits from FRR to support libyang3, upgrading FRR itself isn't currently in scope: * https://github.com/FRRouting/frr/commit/290c6e3184a8f6c4c5c39fc45dcec81508e3858b * https://github.com/FRRouting/frr/commit/8e2b2caf6592b587749777f00778bf48fa164ed5 * https://github.com/FRRouting/frr/commit/22eccbfab916b2c6b64037e872a5c5a870d1a4d6 * https://github.com/FRRouting/frr/commit/87c9060f90b6b9b5a69ad1e6ba6e8ebc58d94374 We also omit the _UNINSTALLS because it messes up dependency tracking with other packages that depend on libyang3 --- rules/docker-fpm-frr.mk | 4 +- rules/frr.mk | 5 +- .../patch/0081-backport-libyang3.patch | 230 ++++++++++++++++++ src/sonic-frr/patch/series | 1 + 4 files changed, 235 insertions(+), 5 deletions(-) create mode 100644 src/sonic-frr/patch/0081-backport-libyang3.patch diff --git a/rules/docker-fpm-frr.mk b/rules/docker-fpm-frr.mk index edfa17f5eb68..1ccebd8b9a30 100644 --- a/rules/docker-fpm-frr.mk +++ b/rules/docker-fpm-frr.mk @@ -7,10 +7,10 @@ DOCKER_FPM_FRR_DBG = $(DOCKER_FPM_FRR_STEM)-$(DBG_IMAGE_MARK).gz $(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/$(DOCKER_FPM_FRR_STEM) $(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) $(SONIC_FRR_MGMT_FRAMEWORK) -$(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG2) $(SONIC_RSYSLOG_PLUGIN) +$(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG3) $(SONIC_RSYSLOG_PLUGIN) $(DOCKER_FPM_FRR)_DBG_DEPENDS = $($(DOCKER_SWSS_LAYER_BOOKWORM)_DBG_DEPENDS) $(DOCKER_FPM_FRR)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) \ - $(FRR_DBG) $(FRR_SNMP_DBG) $(LIBYANG2_DBG) $(SONIC_RSYSLOG_PLUGIN) + $(FRR_DBG) $(FRR_SNMP_DBG) $(SONIC_RSYSLOG_PLUGIN) $(DOCKER_FPM_FRR)_DBG_IMAGE_PACKAGES = $($(DOCKER_SWSS_LAYER_BOOKWORM)_DBG_IMAGE_PACKAGES) diff --git a/rules/frr.mk b/rules/frr.mk index ff3c3ea4ab17..291ea5c46666 100644 --- a/rules/frr.mk +++ b/rules/frr.mk @@ -8,9 +8,8 @@ export FRR_VERSION FRR_SUBVERSION FRR_BRANCH FRR_TAG FRR = frr_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_$(CONFIGURED_ARCH).deb -$(FRR)_DEPENDS += $(LIBSNMP_DEV) $(LIBYANG2) $(LIBYANG2_DEV) -$(FRR)_RDEPENDS += $(LIBYANG2) -$(FRR)_UNINSTALLS = $(LIBYANG2_DEV) $(LIBYANG2) +$(FRR)_DEPENDS += $(LIBSNMP_DEV) $(LIBYANG3) $(LIBYANG3_DEV) +$(FRR)_RDEPENDS += $(LIBYANG3) $(FRR)_SRC_PATH = $(SRC_PATH)/sonic-frr SONIC_MAKE_DEBS += $(FRR) diff --git a/src/sonic-frr/patch/0081-backport-libyang3.patch b/src/sonic-frr/patch/0081-backport-libyang3.patch new file mode 100644 index 000000000000..ad61de12eb84 --- /dev/null +++ b/src/sonic-frr/patch/0081-backport-libyang3.patch @@ -0,0 +1,230 @@ +diff --git a/debian/control b/debian/control +index 4784e6b23..ef8895a41 100644 +--- a/debian/control ++++ b/debian/control +@@ -23,7 +23,7 @@ Build-Depends: bison, + librtr-dev (>= 0.8.0~) , + libsnmp-dev, + libssh-dev , +- libyang2-dev (>= 2.1.128), ++ libyang2-dev (>= 2.1.128) | libyang-dev ( >= 3.0.3), + lsb-base, + pkg-config, + protobuf-c-compiler, +diff --git a/lib/vty.c b/lib/vty.c +index 1c9cff478..d3e617f88 100644 +--- a/lib/vty.c ++++ b/lib/vty.c +@@ -39,6 +39,7 @@ + #include "libfrr.h" + #include "frrstr.h" + #include "lib_errors.h" ++#include + #include "northbound_cli.h" + #include "printfrr.h" + #include "json.h" +@@ -3668,15 +3669,24 @@ static ssize_t vty_mgmt_libyang_print(void *user_data, const void *buf, + } + + static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, +- struct ly_err_item *ei) ++ const struct ly_err_item *ei) + { ++#if (LY_VERSION_MAJOR < 3) ++#define data_path path ++#else ++#define data_path data_path ++#endif + bool have_apptag = ei->apptag && ei->apptag[0] != 0; +- bool have_path = ei->path && ei->path[0] != 0; ++ bool have_path = ei->data_path && ei->data_path[0] != 0; + bool have_msg = ei->msg && ei->msg[0] != 0; + const char *severity = NULL; + const char *evalid = NULL; + const char *ecode = NULL; ++#if (LY_VERSION_MAJOR < 3) + LY_ERR err = ei->no; ++#else ++ LY_ERR err = ei->err; ++#endif + + if (ei->level == LY_LLERR) + severity = "error"; +@@ -3701,7 +3711,8 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, + vty_out(vty, "%s\n", + evalid); + if (have_path) +- vty_out(vty, "%s\n", ei->path); ++ vty_out(vty, "%s\n", ++ ei->data_path); + if (have_apptag) + vty_out(vty, "%s\n", + ei->apptag); +@@ -3720,7 +3731,7 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, + if (evalid) + vty_out(vty, ", \"error-validation\": \"%s\"", evalid); + if (have_path) +- vty_out(vty, ", \"error-path\": \"%s\"", ei->path); ++ vty_out(vty, ", \"error-path\": \"%s\"", ei->data_path); + if (have_apptag) + vty_out(vty, ", \"error-app-tag\": \"%s\"", ei->apptag); + if (have_msg) +@@ -3737,18 +3748,19 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, + if (evalid) + vty_out(vty, " invalid: %s", evalid); + if (have_path) +- vty_out(vty, " path: %s", ei->path); ++ vty_out(vty, " path: %s", ei->data_path); + if (have_apptag) + vty_out(vty, " app-tag: %s", ei->apptag); + if (have_msg) + vty_out(vty, " msg: %s", ei->msg); + break; + } ++#undef data_path + } + + static uint vty_out_yang_errors(struct vty *vty, LYD_FORMAT format) + { +- struct ly_err_item *ei = ly_err_first(ly_native_ctx); ++ const struct ly_err_item *ei = ly_err_first(ly_native_ctx); + uint count; + + if (!ei) +diff --git a/lib/yang.c b/lib/yang.c +index 03044fc29..2c09d37ba 100644 +--- a/lib/yang.c ++++ b/lib/yang.c +@@ -11,6 +11,7 @@ + #include "lib_errors.h" + #include "yang.h" + #include "yang_translator.h" ++#include + #include "northbound.h" + + #include "lib/config_paths.h" +@@ -18,6 +19,17 @@ + DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module"); + DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure"); + ++/* Safe to remove after libyang 2.2.8 */ ++#if (LY_VERSION_MAJOR < 3) ++#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ ++ set) \ ++ lyd_find_xpath3(ctx_node, tree, xpath, vars, set) ++#else ++#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ ++ set) \ ++ lyd_find_xpath3(ctx_node, tree, xpath, LY_VALUE_JSON, NULL, vars, set) ++#endif ++ + /* libyang container. */ + struct ly_ctx *ly_native_ctx; + +@@ -691,7 +703,12 @@ struct yang_data *yang_data_list_find(const struct list *list, + } + + /* Make libyang log its errors using FRR logging infrastructure. */ +-static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) ++static void ly_zlog_cb(LY_LOG_LEVEL level, const char *msg, const char *data_path ++#if !(LY_VERSION_MAJOR < 3) ++ , ++ const char *schema_path, uint64_t line ++#endif ++) + { + int priority = LOG_ERR; + +@@ -708,8 +725,14 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) + break; + } + +- if (path) +- zlog(priority, "libyang: %s (%s)", msg, path); ++ if (data_path) ++ zlog(priority, "libyang: %s (%s)", msg, data_path); ++#if !(LY_VERSION_MAJOR < 3) ++ else if (schema_path) ++ zlog(priority, "libyang %s (%s)\n", msg, schema_path); ++ else if (line) ++ zlog(priority, "libyang %s (line %" PRIu64 ")\n", msg, line); ++#endif + else + zlog(priority, "libyang: %s", msg); + } +@@ -736,7 +759,8 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, + return err; + } + +- err = lyd_find_xpath3(NULL, tree, xpath, NULL, &set); ++ err = yang_lyd_find_xpath3(NULL, tree, xpath, LY_VALUE_JSON, NULL, NULL, ++ &set); + if (err) { + zlog_err("Failed to parse notification: %s", ly_last_errmsg()); + lyd_free_all(tree); +@@ -795,7 +819,7 @@ char *yang_convert_lyd_format(const char *data, size_t data_len, + + assert(out_format != LYD_LYB); + +- if (in_format != LYD_LYB && !MGMT_MSG_VALIDATE_NUL_TERM(data, data_len)) { ++ if (in_format != LYD_LYB && (!data_len || data[data_len - 1] != 0)) { + zlog_err("Corrupt input data, no NUL terminating byte"); + return NULL; + } +@@ -829,23 +853,29 @@ char *yang_convert_lyd_format(const char *data, size_t data_len, + + const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len) + { +- struct ly_err_item *ei; ++ const struct ly_err_item *ei; + + ei = ly_err_first(ly_ctx); + if (!ei) + return ""; + + strlcpy(buf, "YANG error(s):\n", buf_len); ++#if (LY_VERSION_MAJOR < 3) ++#define data_path path ++#else ++#define data_path data_path ++#endif + for (; ei; ei = ei->next) { +- if (ei->path) { ++ if (ei->data_path) { + strlcat(buf, " Path: ", buf_len); +- strlcat(buf, ei->path, buf_len); ++ strlcat(buf, ei->data_path, buf_len); + strlcat(buf, "\n", buf_len); + } + strlcat(buf, " Error: ", buf_len); + strlcat(buf, ei->msg, buf_len); + strlcat(buf, "\n", buf_len); + } ++#undef data_path + + ly_err_clean(ly_ctx, NULL); + +@@ -897,7 +927,12 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) + void yang_init(bool embedded_modules, bool defer_compile) + { + /* Initialize libyang global parameters that affect all containers. */ +- ly_set_log_clb(ly_log_cb, 1); ++ ly_set_log_clb(ly_zlog_cb ++#if (LY_VERSION_MAJOR < 3) ++ , ++ 1 ++#endif ++ ); + ly_log_options(LY_LOLOG | LY_LOSTORE); + + /* Initialize libyang container for native models. */ +@@ -1209,7 +1244,8 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath) + + *root = lyd_first_sibling(*root); + +- err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set); ++ err = yang_lyd_find_xpath3(NULL, *root, xpath, LY_VALUE_JSON, NULL, ++ NULL, &set); + if (err) { + flog_err_sys(EC_LIB_LIBYANG, + "cannot obtain specific result for xpath \"%s\": %s", diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 427df08d8af4..75546b9ad4cf 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -61,3 +61,4 @@ 0078-vtysh-de-conditionalize-and-reorder-install-node.patch 0079-staticd-add-support-for-srv6.patch 0080-SRv6-vpn-route-and-sidlist-install.patch +0081-backport-libyang3.patch