From 8e384489574c99018c8dceea2308f8d7fad17725 Mon Sep 17 00:00:00 2001 From: squirrelking57 <1248756005hfh@gmail.com> Date: Tue, 26 Mar 2024 00:53:36 +0300 Subject: [PATCH] isisd: added managed redistribution in ISIS added command "route_leanking ipv4/ipv6 level's route-map name" in cli according to RFC5302 Signed-off-by: squirrelking57 <1248756005hfh@gmail.com> --- isisd/isis_cli.c | 389 +++++++++++++++++++++++++---------------- isisd/isis_constants.h | 8 + isisd/isis_lsp.c | 73 +++++++- isisd/isis_nb.c | 90 ++++++++++ isisd/isis_nb.h | 51 +++++- isisd/isis_nb_config.c | 377 +++++++++++++++++++++++++++++++-------- isisd/isis_redist.c | 250 +++++++++++++++++++++++++- isisd/isis_redist.h | 47 ++++- isisd/isisd.c | 12 ++ isisd/isisd.h | 3 + lib/command.h | 2 + yang/frr-isisd.yang | 70 ++++++++ 12 files changed, 1128 insertions(+), 244 deletions(-) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 2b19cbba849d..cb3bf3fc5a7f 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -85,13 +85,13 @@ void cli_show_router_isis(struct vty *vty, const struct lyd_node *dnode, { const char *vrf = NULL; - vrf = yang_dnode_get_string(dnode, "vrf"); + vrf = yang_dnode_get_string(dnode, "./vrf"); vty_out(vty, "!\n"); vty_out(vty, "router isis %s", - yang_dnode_get_string(dnode, "area-tag")); + yang_dnode_get_string(dnode, "./area-tag")); if (!strmatch(vrf, VRF_DEFAULT_NAME)) - vty_out(vty, " vrf %s", yang_dnode_get_string(dnode, "vrf")); + vty_out(vty, " vrf %s", yang_dnode_get_string(dnode, "./vrf")); vty_out(vty, "\n"); } @@ -172,7 +172,7 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, * If both ipv4 and ipv6 are off delete the interface isis container. */ if (strmatch(ip, "ipv6")) { - if (!yang_dnode_get_bool(dnode, "ipv4-routing")) + if (!yang_dnode_get_bool(dnode, "./ipv4-routing")) nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_DESTROY, NULL); else @@ -180,7 +180,7 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd, "./frr-isisd:isis/ipv6-routing", NB_OP_MODIFY, "false"); } else { - if (!yang_dnode_get_bool(dnode, "ipv6-routing")) + if (!yang_dnode_get_bool(dnode, "./ipv6-routing")) nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_DESTROY, NULL); else @@ -280,16 +280,16 @@ void cli_show_ip_isis_bfd_monitoring(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - if (!yang_dnode_get_bool(dnode, "enabled")) { + if (!yang_dnode_get_bool(dnode, "./enabled")) { if (show_defaults) vty_out(vty, " no isis bfd\n"); } else { vty_out(vty, " isis bfd\n"); } - if (yang_dnode_exists(dnode, "profile")) + if (yang_dnode_exists(dnode, "./profile")) vty_out(vty, " isis bfd profile %s\n", - yang_dnode_get_string(dnode, "profile")); + yang_dnode_get_string(dnode, "./profile")); } /* @@ -300,12 +300,8 @@ DEFPY_YANG(net, net_cmd, "[no] net WORD", "A Network Entity Title for this process (OSI only)\n" "XX.XXXX. ... .XXX.XX Network entity title (NET)\n") { - char xpath[XPATH_MAXLEN]; - - snprintf(xpath, XPATH_MAXLEN, "./area-address[.='%s']", net); - - nb_cli_enqueue_change(vty, xpath, no ? NB_OP_DESTROY : NB_OP_CREATE, - NULL); + nb_cli_enqueue_change(vty, "./area-address", + no ? NB_OP_DESTROY : NB_OP_CREATE, net); return nb_cli_apply_changes(vty, NULL); } @@ -592,9 +588,9 @@ void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode, const char *snp; vty_out(vty, " area-password %s %s", - yang_dnode_get_string(dnode, "password-type"), - yang_dnode_get_string(dnode, "password")); - snp = yang_dnode_get_string(dnode, "authenticate-snp"); + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); + snp = yang_dnode_get_string(dnode, "./authenticate-snp"); if (!strmatch("none", snp)) vty_out(vty, " authenticate snp %s", snp); vty_out(vty, "\n"); @@ -642,9 +638,9 @@ void cli_show_isis_domain_pwd(struct vty *vty, const struct lyd_node *dnode, const char *snp; vty_out(vty, " domain-password %s %s", - yang_dnode_get_string(dnode, "password-type"), - yang_dnode_get_string(dnode, "password")); - snp = yang_dnode_get_string(dnode, "authenticate-snp"); + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); + snp = yang_dnode_get_string(dnode, "./authenticate-snp"); if (!strmatch("none", snp)) vty_out(vty, " authenticate snp %s", snp); vty_out(vty, "\n"); @@ -865,17 +861,17 @@ void cli_show_isis_lsp_timers(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { const char *l1_refresh = - yang_dnode_get_string(dnode, "level-1/refresh-interval"); + yang_dnode_get_string(dnode, "./level-1/refresh-interval"); const char *l2_refresh = - yang_dnode_get_string(dnode, "level-2/refresh-interval"); + yang_dnode_get_string(dnode, "./level-2/refresh-interval"); const char *l1_lifetime = - yang_dnode_get_string(dnode, "level-1/maximum-lifetime"); + yang_dnode_get_string(dnode, "./level-1/maximum-lifetime"); const char *l2_lifetime = - yang_dnode_get_string(dnode, "level-2/maximum-lifetime"); + yang_dnode_get_string(dnode, "./level-2/maximum-lifetime"); const char *l1_gen = - yang_dnode_get_string(dnode, "level-1/generation-interval"); + yang_dnode_get_string(dnode, "./level-1/generation-interval"); const char *l2_gen = - yang_dnode_get_string(dnode, "level-2/generation-interval"); + yang_dnode_get_string(dnode, "./level-2/generation-interval"); if (strmatch(l1_refresh, l2_refresh) && strmatch(l1_lifetime, l2_lifetime) && strmatch(l1_gen, l2_gen)) vty_out(vty, @@ -984,8 +980,8 @@ void cli_show_isis_spf_min_interval(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " spf-interval %s\n", l1); @@ -1055,11 +1051,11 @@ void cli_show_isis_spf_ietf_backoff(struct vty *vty, { vty_out(vty, " spf-delay-ietf init-delay %s short-delay %s long-delay %s holddown %s time-to-learn %s\n", - yang_dnode_get_string(dnode, "init-delay"), - yang_dnode_get_string(dnode, "short-delay"), - yang_dnode_get_string(dnode, "long-delay"), - yang_dnode_get_string(dnode, "hold-down"), - yang_dnode_get_string(dnode, "time-to-learn")); + yang_dnode_get_string(dnode, "./init-delay"), + yang_dnode_get_string(dnode, "./short-delay"), + yang_dnode_get_string(dnode, "./long-delay"), + yang_dnode_get_string(dnode, "./hold-down"), + yang_dnode_get_string(dnode, "./time-to-learn")); } /* @@ -1368,15 +1364,15 @@ static void vty_print_def_origin(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " default-information originate %s %s", family, level); - if (yang_dnode_get_bool(dnode, "always")) + if (yang_dnode_get_bool(dnode, "./always")) vty_out(vty, " always"); - if (yang_dnode_exists(dnode, "route-map")) + if (yang_dnode_exists(dnode, "./route-map")) vty_out(vty, " route-map %s", - yang_dnode_get_string(dnode, "route-map")); - if (show_defaults || !yang_dnode_is_default(dnode, "metric")) + yang_dnode_get_string(dnode, "./route-map")); + if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) vty_out(vty, " metric %s", - yang_dnode_get_string(dnode, "metric")); + yang_dnode_get_string(dnode, "./metric")); vty_out(vty, "\n"); } @@ -1385,7 +1381,7 @@ void cli_show_isis_def_origin_ipv4(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *level = yang_dnode_get_string(dnode, "level"); + const char *level = yang_dnode_get_string(dnode, "./level"); vty_print_def_origin(vty, dnode, "ipv4", level, show_defaults); } @@ -1394,7 +1390,7 @@ void cli_show_isis_def_origin_ipv6(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *level = yang_dnode_get_string(dnode, "level"); + const char *level = yang_dnode_get_string(dnode, "./level"); vty_print_def_origin(vty, dnode, "ipv6", level, show_defaults); } @@ -1429,9 +1425,43 @@ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd, metric_str ? metric_str : NULL); } - return nb_cli_apply_changes( - vty, "./redistribute/%s[protocol='%s'][level='%s']", ip, proto, - level); + return nb_cli_apply_changes(vty, + "./redistribute/%s[protocol='%s'][level='%s']", + ip, proto, level); +} + +/* + * XPath: /frr-isisd:isis/instance/route_leanking + */ +DEFPY_YANG(isis_leanking, isis_leanking_cmd, + "[no] route_leanking $ip" + "$level" + "[{metric (0-16777215)|route-map RMAP_NAME$route_map}]", + NO_STR LEANKING_STR "Redistribute IPv4 routes\n" + "Redistribute IPv6 routes\n" + "Redistribute level-1 into level-2\n" + "Redistribute level-2 into level-2\n" + "Metric for redistributed routes\n" + "IS-IS default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + char proto[] = "isis"; + + if (no) + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + else { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./route-map", + route_map ? NB_OP_MODIFY : NB_OP_DESTROY, + route_map ? route_map : NULL); + nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, + metric_str ? metric_str : NULL); + } + + return nb_cli_apply_changes(vty, + "./route_leanking/%s[protocol='%s'][level='%s']", + ip, proto, level); } /* @@ -1509,27 +1539,72 @@ static void vty_print_redistribute(struct vty *vty, const struct lyd_node *dnode if (table) { level = yang_dnode_get_string(dnode, "../level"); - tableid = yang_dnode_get_uint16(dnode, "table"); + tableid = yang_dnode_get_uint16(dnode, "./table"); vty_out(vty, " redistribute %s table %d ", family, tableid); } else { - protocol = yang_dnode_get_string(dnode, "protocol"); + protocol = yang_dnode_get_string(dnode, "./protocol"); if (!table && strmatch(protocol, "table")) return; - level = yang_dnode_get_string(dnode, "level"); + level = yang_dnode_get_string(dnode, "./level"); vty_out(vty, " redistribute %s %s ", family, protocol); } vty_out(vty, "%s", level); - if (show_defaults || !yang_dnode_is_default(dnode, "metric")) + if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) vty_out(vty, " metric %s", - yang_dnode_get_string(dnode, "%s", "metric")); + yang_dnode_get_string(dnode, "%s", "./metric")); - if (yang_dnode_exists(dnode, "route-map")) - routemap = yang_dnode_get_string(dnode, "route-map"); + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); if (routemap) vty_out(vty, " route-map %s", routemap); vty_out(vty, "\n"); } +static void vty_print_route_leanking(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults, const char *family, + bool table) +{ + const char *level; + const char *protocol = NULL; + const char *routemap = NULL; + uint16_t tableid; + + if (table) { + level = yang_dnode_get_string(dnode, "../level"); + tableid = yang_dnode_get_uint16(dnode, "./table"); + vty_out(vty, " route_leanking %s table %d ", family, tableid); + } else { + protocol = yang_dnode_get_string(dnode, "./protocol"); + if (!table && strmatch(protocol, "table")) + return; + level = yang_dnode_get_string(dnode, "./level"); + vty_out(vty, " route_leanking %s %s ", family, protocol); + } + vty_out(vty, "%s", level); + if (show_defaults || !yang_dnode_is_default(dnode, "./metric")) + vty_out(vty, " metric %s", + yang_dnode_get_string(dnode, "%s", "./metric")); + + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); + if (routemap) + vty_out(vty, " route-map %s", routemap); + vty_out(vty, "\n"); +} + +void cli_show_isis_leanking_ipv4(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_route_leanking(vty, dnode, show_defaults, "ipv4", false); +} + +void cli_show_isis_leanking_ipv6(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_route_leanking(vty, dnode, show_defaults, "ipv6", false); +} + void cli_show_isis_redistribute_ipv4(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) @@ -1548,21 +1623,44 @@ void cli_show_isis_redistribute_ipv4_table(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - vty_print_redistribute(vty, dnode, show_defaults, "ipv4", true); + vty_print_route_leanking(vty, dnode, show_defaults, "ipv4", true); } void cli_show_isis_redistribute_ipv6_table(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - vty_print_redistribute(vty, dnode, show_defaults, "ipv6", true); + vty_print_route_leanking(vty, dnode, show_defaults, "ipv6", true); } int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1, const struct lyd_node *dnode2) { - uint16_t table1 = yang_dnode_get_uint16(dnode1, "table"); - uint16_t table2 = yang_dnode_get_uint16(dnode2, "table"); + uint16_t table1 = yang_dnode_get_uint16(dnode1, "./table"); + uint16_t table2 = yang_dnode_get_uint16(dnode2, "./table"); + + return table1 - table2; +} + +void cli_show_isis_route_leanking_ipv4_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv4", true); +} + +void cli_show_isis_route_leanking_ipv6_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_print_redistribute(vty, dnode, show_defaults, "ipv6", true); +} + +int cli_cmp_isis_route_leanking_table(const struct lyd_node *dnode1, + const struct lyd_node *dnode2) +{ + uint16_t table1 = yang_dnode_get_uint16(dnode1, "./table"); + uint16_t table2 = yang_dnode_get_uint16(dnode2, "./table"); return table1 - table2; } @@ -1623,7 +1721,7 @@ void cli_show_isis_mt_ipv4_multicast(struct vty *vty, bool show_defaults) { vty_out(vty, " topology ipv4-multicast"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1632,7 +1730,7 @@ void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " topology ipv4-mgmt"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1642,7 +1740,7 @@ void cli_show_isis_mt_ipv6_unicast(struct vty *vty, bool show_defaults) { vty_out(vty, " topology ipv6-unicast"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1652,7 +1750,7 @@ void cli_show_isis_mt_ipv6_multicast(struct vty *vty, bool show_defaults) { vty_out(vty, " topology ipv6-multicast"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1661,7 +1759,7 @@ void cli_show_isis_mt_ipv6_mgmt(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " topology ipv6-mgmt"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1670,7 +1768,7 @@ void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " topology ipv6-dstsrc"); - if (yang_dnode_get_bool(dnode, "overload")) + if (yang_dnode_get_bool(dnode, "./overload")) vty_out(vty, " overload"); vty_out(vty, "\n"); } @@ -1775,13 +1873,13 @@ void cli_show_isis_label_blocks(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " segment-routing global-block %s %s", - yang_dnode_get_string(dnode, "srgb/lower-bound"), - yang_dnode_get_string(dnode, "srgb/upper-bound")); - if (!yang_dnode_is_default(dnode, "srlb/lower-bound") - || !yang_dnode_is_default(dnode, "srlb/upper-bound")) + yang_dnode_get_string(dnode, "./srgb/lower-bound"), + yang_dnode_get_string(dnode, "./srgb/upper-bound")); + if (!yang_dnode_is_default(dnode, "./srlb/lower-bound") || + !yang_dnode_is_default(dnode, "./srlb/upper-bound")) vty_out(vty, " local-block %s %s", - yang_dnode_get_string(dnode, "srlb/lower-bound"), - yang_dnode_get_string(dnode, "srlb/upper-bound")); + yang_dnode_get_string(dnode, "./srlb/lower-bound"), + yang_dnode_get_string(dnode, "./srlb/upper-bound")); vty_out(vty, "\n"); } @@ -1903,11 +2001,11 @@ void cli_show_isis_prefix_sid(struct vty *vty, const struct lyd_node *dnode, const char *sid_value; bool n_flag_clear; - prefix = yang_dnode_get_string(dnode, "prefix"); - lh_behavior = yang_dnode_get_string(dnode, "last-hop-behavior"); - sid_value_type = yang_dnode_get_string(dnode, "sid-value-type"); - sid_value = yang_dnode_get_string(dnode, "sid-value"); - n_flag_clear = yang_dnode_get_bool(dnode, "n-flag-clear"); + prefix = yang_dnode_get_string(dnode, "./prefix"); + lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior"); + sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type"); + sid_value = yang_dnode_get_string(dnode, "./sid-value"); + n_flag_clear = yang_dnode_get_bool(dnode, "./n-flag-clear"); vty_out(vty, " segment-routing prefix %s", prefix); if (strmatch(sid_value_type, "absolute")) @@ -2017,12 +2115,12 @@ void cli_show_isis_prefix_sid_algorithm(struct vty *vty, bool n_flag_clear; uint32_t algorithm; - prefix = yang_dnode_get_string(dnode, "prefix"); - sid_value_type = yang_dnode_get_string(dnode, "sid-value-type"); - sid_value = yang_dnode_get_string(dnode, "sid-value"); - algorithm = yang_dnode_get_uint32(dnode, "algo"); - lh_behavior = yang_dnode_get_string(dnode, "last-hop-behavior"); - n_flag_clear = yang_dnode_get_bool(dnode, "n-flag-clear"); + prefix = yang_dnode_get_string(dnode, "./prefix"); + sid_value_type = yang_dnode_get_string(dnode, "./sid-value-type"); + sid_value = yang_dnode_get_string(dnode, "./sid-value"); + algorithm = yang_dnode_get_uint32(dnode, "./algo"); + lh_behavior = yang_dnode_get_string(dnode, "./last-hop-behavior"); + n_flag_clear = yang_dnode_get_bool(dnode, "./n-flag-clear"); vty_out(vty, " segment-routing prefix %s", prefix); vty_out(vty, " algorithm %u", algorithm); @@ -2224,22 +2322,22 @@ void cli_show_isis_srv6_node_msd(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " node-msd\n"); - if (yang_dnode_get_uint8(dnode, "max-segs-left") != + if (yang_dnode_get_uint8(dnode, "./max-segs-left") != yang_get_default_uint8("%s/msd/node-msd/max-segs-left", ISIS_SRV6)) vty_out(vty, " max-segs-left %u\n", - yang_dnode_get_uint8(dnode, "max-segs-left")); - if (yang_dnode_get_uint8(dnode, "max-end-pop") != + yang_dnode_get_uint8(dnode, "./max-segs-left")); + if (yang_dnode_get_uint8(dnode, "./max-end-pop") != yang_get_default_uint8("%s/msd/node-msd/max-end-pop", ISIS_SRV6)) vty_out(vty, " max-end-pop %u\n", - yang_dnode_get_uint8(dnode, "max-end-pop")); - if (yang_dnode_get_uint8(dnode, "max-h-encaps") != + yang_dnode_get_uint8(dnode, "./max-end-pop")); + if (yang_dnode_get_uint8(dnode, "./max-h-encaps") != yang_get_default_uint8("%s/msd/node-msd/max-h-encaps", ISIS_SRV6)) vty_out(vty, " max-h-encaps %u\n", - yang_dnode_get_uint8(dnode, "max-h-encaps")); - if (yang_dnode_get_uint8(dnode, "max-end-d") != + yang_dnode_get_uint8(dnode, "./max-h-encaps")); + if (yang_dnode_get_uint8(dnode, "./max-end-d") != yang_get_default_uint8("%s/msd/node-msd/max-end-d", ISIS_SRV6)) vty_out(vty, " max-end-d %u\n", - yang_dnode_get_uint8(dnode, "max-end-d")); + yang_dnode_get_uint8(dnode, "./max-end-d")); } /* @@ -2385,8 +2483,8 @@ void cli_show_isis_frr_lfa_tiebreaker(struct vty *vty, bool show_defaults) { vty_out(vty, " fast-reroute lfa tiebreaker %s index %s %s\n", - yang_dnode_get_string(dnode, "type"), - yang_dnode_get_string(dnode, "index"), + yang_dnode_get_string(dnode, "./type"), + yang_dnode_get_string(dnode, "./index"), dnode->parent->parent->schema->name); } @@ -2558,8 +2656,8 @@ void cli_show_ip_isis_password(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { vty_out(vty, " isis password %s %s\n", - yang_dnode_get_string(dnode, "password-type"), - yang_dnode_get_string(dnode, "password")); + yang_dnode_get_string(dnode, "./password-type"), + yang_dnode_get_string(dnode, "./password")); } /* @@ -2605,8 +2703,8 @@ DEFPY_YANG(no_isis_metric, no_isis_metric_cmd, void cli_show_ip_isis_metric(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis metric %s\n", l1); @@ -2664,8 +2762,8 @@ void cli_show_ip_isis_hello_interval(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis hello-interval %s\n", l1); @@ -2722,8 +2820,8 @@ DEFPY_YANG(no_isis_hello_multiplier, no_isis_hello_multiplier_cmd, void cli_show_ip_isis_hello_multi(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis hello-multiplier %s\n", l1); @@ -2841,8 +2939,8 @@ void cli_show_ip_isis_csnp_interval(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis csnp-interval %s\n", l1); @@ -2900,8 +2998,8 @@ void cli_show_ip_isis_psnp_interval(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis psnp-interval %s\n", l1); @@ -3058,16 +3156,12 @@ void cli_show_ip_isis_circ_type(struct vty *vty, const struct lyd_node *dnode, } static int ag_change(struct vty *vty, int argc, struct cmd_token **argv, - const char *xpath_base, bool no, int start_idx) + const char *xpath, bool no, int start_idx) { - char xpath[XPATH_MAXLEN]; - - for (int i = start_idx; i < argc; i++) { - snprintf(xpath, XPATH_MAXLEN, "%s[.='%s']", xpath_base, - argv[i]->arg); + for (int i = start_idx; i < argc; i++) nb_cli_enqueue_change(vty, xpath, - no ? NB_OP_DESTROY : NB_OP_CREATE, NULL); - } + no ? NB_OP_DESTROY : NB_OP_CREATE, + argv[i]->arg); return nb_cli_apply_changes(vty, NULL); } @@ -3148,8 +3242,8 @@ DEFPY_YANG(no_isis_priority, no_isis_priority_cmd, void cli_show_ip_isis_priority(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - const char *l1 = yang_dnode_get_string(dnode, "level-1"); - const char *l2 = yang_dnode_get_string(dnode, "level-2"); + const char *l1 = yang_dnode_get_string(dnode, "./level-1"); + const char *l2 = yang_dnode_get_string(dnode, "./level-2"); if (strmatch(l1, l2)) vty_out(vty, " isis priority %s\n", l1); @@ -3170,8 +3264,8 @@ void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode, bool l1_link_fallback, l2_link_fallback; /* Classic LFA */ - l1_enabled = yang_dnode_get_bool(dnode, "level-1/lfa/enable"); - l2_enabled = yang_dnode_get_bool(dnode, "level-2/lfa/enable"); + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/lfa/enable"); if (l1_enabled || l2_enabled) { if (l1_enabled == l2_enabled) { @@ -3188,8 +3282,8 @@ void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode, } /* Remote LFA */ - l1_enabled = yang_dnode_get_bool(dnode, "level-1/remote-lfa/enable"); - l2_enabled = yang_dnode_get_bool(dnode, "level-2/remote-lfa/enable"); + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/remote-lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/remote-lfa/enable"); if (l1_enabled || l2_enabled) { if (l1_enabled == l2_enabled) { @@ -3207,16 +3301,16 @@ void cli_show_ip_isis_frr(struct vty *vty, const struct lyd_node *dnode, } /* TI-LFA */ - l1_enabled = yang_dnode_get_bool(dnode, "level-1/ti-lfa/enable"); - l2_enabled = yang_dnode_get_bool(dnode, "level-2/ti-lfa/enable"); + l1_enabled = yang_dnode_get_bool(dnode, "./level-1/ti-lfa/enable"); + l2_enabled = yang_dnode_get_bool(dnode, "./level-2/ti-lfa/enable"); l1_node_protection = - yang_dnode_get_bool(dnode, "level-1/ti-lfa/node-protection"); + yang_dnode_get_bool(dnode, "./level-1/ti-lfa/node-protection"); l2_node_protection = - yang_dnode_get_bool(dnode, "level-2/ti-lfa/node-protection"); + yang_dnode_get_bool(dnode, "./level-2/ti-lfa/node-protection"); l1_link_fallback = - yang_dnode_get_bool(dnode, "level-1/ti-lfa/link-fallback"); + yang_dnode_get_bool(dnode, "./level-1/ti-lfa/link-fallback"); l2_link_fallback = - yang_dnode_get_bool(dnode, "level-2/ti-lfa/link-fallback"); + yang_dnode_get_bool(dnode, "./level-2/ti-lfa/link-fallback"); if (l1_enabled || l2_enabled) { @@ -3310,27 +3404,27 @@ DEFPY(isis_lfa_exclude_interface, isis_lfa_exclude_interface_cmd, "Exclude an interface from computation\n" "Interface name\n") { - char xpath[XPATH_MAXLEN]; - if (!level || strmatch(level, "level-1")) { - snprintf(xpath, sizeof(xpath), - "./frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface[.='%s']", - ifname); - - if (no) - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - else - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + if (no) { + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface", + NB_OP_DESTROY, ifname); + } else { + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/fast-reroute/level-1/lfa/exclude-interface", + NB_OP_CREATE, ifname); + } } if (!level || strmatch(level, "level-2")) { - snprintf(xpath, sizeof(xpath), - "./frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface[.='%s']", - ifname); - - if (no) - nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); - else - nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + if (no) { + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface", + NB_OP_DESTROY, ifname); + } else { + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/fast-reroute/level-2/lfa/exclude-interface", + NB_OP_CREATE, ifname); + } } return nb_cli_apply_changes(vty, NULL); @@ -3878,24 +3972,24 @@ void cli_show_isis_flex_algo(struct vty *vty, const struct lyd_node *dnode, uint32_t priority; char type_str[10]; - algorithm = yang_dnode_get_uint32(dnode, "flex-algo"); + algorithm = yang_dnode_get_uint32(dnode, "./flex-algo"); vty_out(vty, " flex-algo %u\n", algorithm); - if (yang_dnode_exists(dnode, "advertise-definition")) + if (yang_dnode_exists(dnode, "./advertise-definition")) vty_out(vty, " advertise-definition\n"); - if (yang_dnode_exists(dnode, "dplane-sr-mpls")) + if (yang_dnode_exists(dnode, "./dplane-sr-mpls")) vty_out(vty, " dataplane sr-mpls\n"); - if (yang_dnode_exists(dnode, "dplane-srv6")) + if (yang_dnode_exists(dnode, "./dplane-srv6")) vty_out(vty, " dataplane srv6\n"); - if (yang_dnode_exists(dnode, "dplane-ip")) + if (yang_dnode_exists(dnode, "./dplane-ip")) vty_out(vty, " dataplane ip\n"); - if (yang_dnode_exists(dnode, "prefix-metric")) + if (yang_dnode_exists(dnode, "./prefix-metric")) vty_out(vty, " prefix-metric\n"); - if (yang_dnode_exists(dnode, "metric-type")) { - metric_type = yang_dnode_get_enum(dnode, "metric-type"); + if (yang_dnode_exists(dnode, "./metric-type")) { + metric_type = yang_dnode_get_enum(dnode, "./metric-type"); if (metric_type != MT_IGP) { flex_algo_metric_type_print(type_str, sizeof(type_str), metric_type); @@ -3903,8 +3997,8 @@ void cli_show_isis_flex_algo(struct vty *vty, const struct lyd_node *dnode, } } - if (yang_dnode_exists(dnode, "priority")) { - priority = yang_dnode_get_uint32(dnode, "priority"); + if (yang_dnode_exists(dnode, "./priority")) { + priority = yang_dnode_get_uint32(dnode, "./priority"); if (priority != FLEX_ALGO_PRIO_DEFAULT) vty_out(vty, " priority %u\n", priority); } @@ -4018,6 +4112,7 @@ void isis_cli_init(void) install_element(ISIS_NODE, &isis_redistribute_cmd); install_element(ISIS_NODE, &isis_redistribute_table_cmd); + install_element(ISIS_NODE, &isis_leanking_cmd); install_element(ISIS_NODE, &isis_topology_cmd); install_element(ISIS_NODE, &isis_sr_enable_cmd); diff --git a/isisd/isis_constants.h b/isisd/isis_constants.h index b2be28229f8b..0541453c1d28 100644 --- a/isisd/isis_constants.h +++ b/isisd/isis_constants.h @@ -41,6 +41,14 @@ #define ISIS_LEVEL1 1 #define ISIS_LEVEL2 2 +/* + * implementation specific route-leanking values + */ + +#define LEVEL2_TO_LEVEL1 4 +#define LEVEL1_TO_LEVEL2 5 +#define LVL_ISIS_LEANKING_1 0 +#define LVL_ISIS_LEANKING_2 1 /* * Default values * ISO - 10589 Section 7.3.21 - Parameters diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 77573cdfacb4..840c01cba1b2 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -938,7 +938,6 @@ static void lsp_build_internal_reach_ipv6(struct isis_lsp *lsp, metric, false, pcfgs); } - static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area) { @@ -1034,6 +1033,71 @@ static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, } } +static void lsp_build_leanking_reach_ipv4(struct isis_lsp *lsp, + struct isis_area *area, + struct prefix_leanking *leanking) +{ + struct prefix_ipv4 *ipv4 = (struct prefix_ipv4 *)leanking->prefix; + + if (area->oldmetric) + isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4, + leanking->metric); + if (area->newmetric) { + struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = { NULL }; + + if (area->srdb.enabled) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported(i, area)) + continue; +#endif /* ifndef FABRICD */ + pcfgs[i] = isis_sr_cfg_prefix_find(area, ipv4, + i); + } + isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, + leanking->metric, true, pcfgs); + } +} + +static void lsp_build_leanking_reach_ipv6(struct isis_lsp *lsp, + struct isis_area *area, + struct prefix_leanking *leanking) +{ + struct prefix_ipv6 *ipv6 = (struct prefix_ipv6 *)leanking->prefix; + struct sr_prefix_cfg *pcfgs[SR_ALGORITHM_COUNT] = { NULL }; + + if (area->srdb.enabled) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported(i, area)) + continue; +#endif /* ifndef FABRICD */ + pcfgs[i] = isis_sr_cfg_prefix_find(area, ipv6, i); + } + isis_tlvs_add_ipv6_reach(lsp->tlvs, isis_area_ipv6_topology(area), ipv6, + leanking->metric, true, pcfgs); +} + +static void lsp_build_leanking_reach(struct isis_lsp *lsp, + struct isis_area *area) +{ + struct listnode *node; + struct prefix_leanking *leanking; + + for (ALL_LIST_ELEMENTS_RO(area->leanking_list[lsp->level - 1], node, + leanking)) { + if (leanking->prefix->family == AF_INET) + lsp_build_leanking_reach_ipv4(lsp, area, leanking); + if (leanking->prefix->family == AF_INET6) + lsp_build_leanking_reach_ipv6(lsp, area, leanking); + } + + list_delete_all_node(area->leanking_list[LVL_ISIS_LEANKING_1]); + list_delete_all_node(area->leanking_list[LVL_ISIS_LEANKING_2]); +} + static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area) { lsp_build_ext_reach_ipv4(lsp, area); @@ -1437,7 +1501,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) } } + struct listnode *node_redist; + struct isis_leanking *redist; + + for (ALL_LIST_ELEMENTS_RO(area->leanking_settings, node_redist, redist)) + iteration_in_spftree(area, redist); + lsp_build_ext_reach(lsp, area); + lsp_build_leanking_reach(lsp, area); struct isis_tlvs *tlvs = lsp->tlvs; lsp->tlvs = NULL; diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 16cafa2ff034..7c45b450452c 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -408,6 +408,96 @@ const struct frr_yang_module_info frr_isisd_info = { .modify = isis_instance_redistribute_ipv4_metric_modify, }, }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4", + .cbs = { + .apply_finish = leanking_ipv4_apply_finish, + .cli_show = cli_show_isis_leanking_ipv4, + .create = isis_instance_leanking_ipv4_create, + .destroy = isis_instance_leanking_ipv4_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4/route-map", + .cbs = { + .destroy = isis_instance_route_leanking_ipv4_route_map_destroy, + .modify = isis_instance_route_leanking_ipv4_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4/metric", + .cbs = { + .destroy = isis_instance_route_leanking_ipv4_metric_destroy, + .modify = isis_instance_route_leanking_ipv4_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4/table", + .cbs = { + .cli_show = cli_show_isis_route_leanking_ipv4_table, + .cli_cmp = cli_cmp_isis_route_leanking_table, + .create = isis_instance_route_leanking_ipv4_table_create, + .destroy = isis_instance_route_leanking_ipv4_table_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4/table/route-map", + .cbs = { + .destroy = isis_instance_route_leanking_ipv4_route_map_destroy, + .modify = isis_instance_route_leanking_ipv4_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv4/table/metric", + .cbs = { + .modify = isis_instance_route_leanking_ipv4_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv6", + .cbs = { + .apply_finish = leanking_ipv6_apply_finish, + .cli_show = cli_show_isis_leanking_ipv6, + .create = isis_instance_leanking_ipv6_create, + .destroy = isis_instance_leanking_ipv6_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv6/route-map", + .cbs = { + .destroy = isis_instance_route_leanking_ipv6_route_map_destroy, + .modify = isis_instance_route_leanking_ipv6_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/route_leanking/ipv6/metric", + .cbs = { + .destroy = isis_instance_route_leanking_ipv6_metric_destroy, + .modify = isis_instance_route_leanking_ipv6_metric_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table", + .cbs = { + .cli_show = cli_show_isis_route_leanking_ipv6_table, + .cli_cmp = cli_cmp_isis_route_leanking_table, + .create = isis_instance_route_leanking_ipv6_table_create, + .destroy = isis_instance_route_leanking_ipv6_table_destroy, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/route-map", + .cbs = { + .destroy = isis_instance_route_leanking_ipv6_route_map_destroy, + .modify = isis_instance_route_leanking_ipv6_route_map_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/metric", + .cbs = { + .modify = isis_instance_route_leanking_ipv6_metric_modify, + }, + }, { .xpath = "/frr-isisd:isis/instance/redistribute/ipv6", .cbs = { diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index c04a006a2e3c..78fd5dcf41bf 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -114,7 +114,12 @@ int isis_instance_default_information_originate_ipv6_route_map_destroy( int isis_instance_default_information_originate_ipv6_metric_modify( struct nb_cb_modify_args *args); int isis_instance_redistribute_ipv4_create(struct nb_cb_create_args *args); +int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args); int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args); +int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args); +int isis_instance_leanking_ipv4_create(struct nb_cb_create_args *args); +int isis_instance_leanking_ipv4_destroy(struct nb_cb_destroy_args *args); +int isis_instance_leanking_ipv4_create(struct nb_cb_create_args *args); int isis_instance_redistribute_ipv4_route_map_modify( struct nb_cb_modify_args *args); int isis_instance_redistribute_ipv4_route_map_destroy( @@ -126,8 +131,9 @@ int isis_instance_redistribute_ipv4_metric_destroy( int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args); int isis_instance_redistribute_ipv4_table_destroy( struct nb_cb_destroy_args *args); -int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args); -int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args); +int isis_instance_leanking_ipv6_create(struct nb_cb_create_args *args); +int isis_instance_leanking_ipv6_destroy(struct nb_cb_destroy_args *args); +int isis_instance_leanking_ipv6_metric_modify(struct nb_cb_modify_args *args); int isis_instance_redistribute_ipv6_route_map_modify( struct nb_cb_modify_args *args); int isis_instance_redistribute_ipv6_route_map_destroy( @@ -528,13 +534,39 @@ void default_info_origin_ipv6_apply_finish( void redistribute_apply_finish(const struct lyd_node *dnode, int family); void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args); void redistribute_ipv6_apply_finish(struct nb_cb_apply_finish_args *args); +void leanking_ipv4_apply_finish(struct nb_cb_apply_finish_args *args); +void leanking_ipv6_apply_finish(struct nb_cb_apply_finish_args *args); +void leanking_apply_finish(const struct lyd_node *dnode, int family); void isis_instance_segment_routing_srgb_apply_finish( struct nb_cb_apply_finish_args *args); void isis_instance_segment_routing_srlb_apply_finish( struct nb_cb_apply_finish_args *args); void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish( struct nb_cb_apply_finish_args *args); - +int isis_instance_route_leanking_ipv4_route_map_modify( + struct nb_cb_modify_args *args); +int isis_instance_route_leanking_ipv4_route_map_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv4_metric_modify( + struct nb_cb_modify_args *args); +int isis_instance_route_leanking_ipv4_metric_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv4_table_create( + struct nb_cb_create_args *args); +int isis_instance_route_leanking_ipv4_table_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv6_table_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv6_table_create( + struct nb_cb_create_args *args); +int isis_instance_route_leanking_ipv6_metric_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv6_metric_modify( + struct nb_cb_modify_args *args); +int isis_instance_route_leanking_ipv6_route_map_destroy( + struct nb_cb_destroy_args *args); +int isis_instance_route_leanking_ipv6_route_map_modify( + struct nb_cb_modify_args *args); /* Optional 'cli_show' callbacks. */ void cli_show_router_isis(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); @@ -618,6 +650,10 @@ void cli_show_isis_redistribute_ipv4(struct vty *vty, void cli_show_isis_redistribute_ipv6(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_leanking_ipv4(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_leanking_ipv6(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults); void cli_show_isis_mt_ipv4_multicast(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); @@ -627,6 +663,12 @@ void cli_show_isis_redistribute_ipv4_table(struct vty *vty, void cli_show_isis_redistribute_ipv6_table(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_route_leanking_ipv4_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); +void cli_show_isis_route_leanking_ipv6_table(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode, bool show_defaults); void cli_show_isis_mt_ipv6_unicast(struct vty *vty, @@ -785,7 +827,8 @@ void isis_notif_own_lsp_purge(const struct isis_circuit *circuit, /* cmp */ int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1, const struct lyd_node *dnode2); - +int cli_cmp_isis_route_leanking_table(const struct lyd_node *dnode1, + const struct lyd_node *dnode2); /* We also declare hook for every notification */ DECLARE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area)); diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 5794e16a115b..748e0a807112 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -60,8 +60,8 @@ int isis_instance_create(struct nb_cb_create_args *args) if (args->event != NB_EV_APPLY) return NB_OK; - vrf_name = yang_dnode_get_string(args->dnode, "vrf"); - area_tag = yang_dnode_get_string(args->dnode, "area-tag"); + vrf_name = yang_dnode_get_string(args->dnode, "./vrf"); + area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); area = isis_area_lookup_by_vrf(area_tag, vrf_name); if (area) @@ -650,12 +650,11 @@ int isis_instance_lsp_generation_interval_level_2_modify( */ void ietf_backoff_delay_apply_finish(struct nb_cb_apply_finish_args *args) { - long init_delay = yang_dnode_get_uint16(args->dnode, "init-delay"); - long short_delay = yang_dnode_get_uint16(args->dnode, "short-delay"); - long long_delay = yang_dnode_get_uint16(args->dnode, "long-delay"); - long holddown = yang_dnode_get_uint16(args->dnode, "hold-down"); - long timetolearn = - yang_dnode_get_uint16(args->dnode, "time-to-learn"); + long init_delay = yang_dnode_get_uint16(args->dnode, "./init-delay"); + long short_delay = yang_dnode_get_uint16(args->dnode, "./short-delay"); + long long_delay = yang_dnode_get_uint16(args->dnode, "./long-delay"); + long holddown = yang_dnode_get_uint16(args->dnode, "./hold-down"); + long timetolearn = yang_dnode_get_uint16(args->dnode, "./time-to-learn"); struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true); size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx"); char *buf = XCALLOC(MTYPE_TMP, bufsiz); @@ -926,11 +925,11 @@ int isis_instance_spf_prefix_priorities_medium_access_list_name_destroy( */ void area_password_apply_finish(struct nb_cb_apply_finish_args *args) { - const char *password = yang_dnode_get_string(args->dnode, "password"); + const char *password = yang_dnode_get_string(args->dnode, "./password"); struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true); - int pass_type = yang_dnode_get_enum(args->dnode, "password-type"); - uint8_t snp_auth = - yang_dnode_get_enum(args->dnode, "authenticate-snp"); + int pass_type = yang_dnode_get_enum(args->dnode, "./password-type"); + uint8_t snp_auth = yang_dnode_get_enum(args->dnode, + "./authenticate-snp"); switch (pass_type) { case ISIS_PASSWD_TYPE_CLEARTXT: @@ -997,11 +996,11 @@ int isis_instance_area_password_authenticate_snp_modify( */ void domain_password_apply_finish(struct nb_cb_apply_finish_args *args) { - const char *password = yang_dnode_get_string(args->dnode, "password"); + const char *password = yang_dnode_get_string(args->dnode, "./password"); struct isis_area *area = nb_running_get_entry(args->dnode, NULL, true); - int pass_type = yang_dnode_get_enum(args->dnode, "password-type"); - uint8_t snp_auth = - yang_dnode_get_enum(args->dnode, "authenticate-snp"); + int pass_type = yang_dnode_get_enum(args->dnode, "./password-type"); + uint8_t snp_auth = yang_dnode_get_enum(args->dnode, + "./authenticate-snp"); switch (pass_type) { case ISIS_PASSWD_TYPE_CLEARTXT: @@ -1073,9 +1072,9 @@ void default_info_origin_apply_finish(const struct lyd_node *dnode, int family) unsigned long metric = 0; const char *routemap = NULL; struct isis_area *area = nb_running_get_entry(dnode, NULL, true); - int level = yang_dnode_get_enum(dnode, "level"); + int level = yang_dnode_get_enum(dnode, "./level"); - if (yang_dnode_get_bool(dnode, "always")) { + if (yang_dnode_get_bool(dnode, "./always")) { originate_type = DEFAULT_ORIGINATE_ALWAYS; } else if (family == AF_INET6) { zlog_warn( @@ -1083,10 +1082,10 @@ void default_info_origin_apply_finish(const struct lyd_node *dnode, int family) __func__); } - if (yang_dnode_exists(dnode, "metric")) - metric = yang_dnode_get_uint32(dnode, "metric"); - if (yang_dnode_exists(dnode, "route-map")) - routemap = yang_dnode_get_string(dnode, "route-map"); + if (yang_dnode_exists(dnode, "./metric")) + metric = yang_dnode_get_uint32(dnode, "./metric"); + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, originate_type, 0); @@ -1119,7 +1118,7 @@ int isis_instance_default_information_originate_ipv4_destroy( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - level = yang_dnode_get_enum(args->dnode, "level"); + level = yang_dnode_get_enum(args->dnode, "./level"); isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE, 0); return NB_OK; @@ -1182,7 +1181,7 @@ int isis_instance_default_information_originate_ipv6_destroy( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - level = yang_dnode_get_enum(args->dnode, "level"); + level = yang_dnode_get_enum(args->dnode, "./level"); isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE, 0); return NB_OK; @@ -1225,6 +1224,192 @@ int isis_instance_default_information_originate_ipv6_metric_modify( return NB_OK; } +/* + * XPath: /frr-isisd:isis/intance/route_leanking/ipv4 + */ +void leanking_apply_finish(const struct lyd_node *dnode, int family) +{ + assert(family == AF_INET || family == AF_INET6); + int type, level; + unsigned long metric = 0; + const char *routemap = NULL; + struct isis_area *area; + + type = yang_dnode_get_enum(dnode, "./protocol"); + level = yang_dnode_get_enum(dnode, "./level"); + area = nb_running_get_entry(dnode, NULL, true); + + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); + + isis_redist_set_route_leanking(area, level, family, type, metric, + routemap, 0, 0); + + lsp_regenerate_schedule(area, IS_LEVEL_1, 0); + lsp_regenerate_schedule(area, IS_LEVEL_2, 0); +} + +void leanking_ipv4_apply_finish(struct nb_cb_apply_finish_args *args) +{ + leanking_apply_finish(args->dnode, AF_INET); +} + +void leanking_ipv6_apply_finish(struct nb_cb_apply_finish_args *args) +{ + leanking_apply_finish(args->dnode, AF_INET6); +} + +int isis_instance_leanking_ipv4_create(struct nb_cb_create_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/route_leanking/ipv6 + */ + +int isis_instance_leanking_ipv6_create(struct nb_cb_create_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} +/* + * XPath: /frr-isisd:isis/instance/route_leanking/ipv4/route-map + * XPath: /frr-isisd:isis/instance/route_leanking/ipv4/table/route-map + */ +int isis_instance_route_leanking_ipv4_route_map_modify( + struct nb_cb_modify_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_route_leanking_ipv4_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/route_leanking/ipv4/metric + * XPath: /frr-isisd:isis/instance/route_leanking/ipv4/table/metric + */ +int isis_instance_route_leanking_ipv4_metric_modify(struct nb_cb_modify_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_route_leanking_ipv4_metric_destroy( + struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv4/table + */ +int isis_instance_route_leanking_ipv4_table_create(struct nb_cb_create_args *args) +{ + uint16_t table; + int type, level; + unsigned long metric = 0; + const char *routemap = NULL; + struct isis_area *area; + + table = 0; + if (args->event != NB_EV_APPLY) + return NB_OK; + + type = yang_dnode_get_enum(args->dnode, "../protocol"); + level = yang_dnode_get_enum(args->dnode, "../level"); + area = nb_running_get_entry(args->dnode, "../.", true); + if (yang_dnode_exists(args->dnode, "route-map")) + routemap = yang_dnode_get_string(args->dnode, "route-map"); + + isis_redist_set_route_leanking(area, level, AF_INET, type, metric, + routemap, 0, table); + + return NB_OK; +} + +int isis_instance_route_leanking_ipv4_table_destroy( + struct nb_cb_destroy_args *args) +{ + struct isis_area *area; + const char *routemap = NULL; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(args->dnode, "../.", true); + + if (yang_dnode_exists(args->dnode, "route-map")) + routemap = yang_dnode_get_string(args->dnode, "route-map"); + + isis_leanking_unset(area, routemap); + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map + */ +int isis_instance_route_leanking_ipv6_route_map_modify( + struct nb_cb_modify_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_route_leanking_ipv6_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric + */ +int isis_instance_route_leanking_ipv6_metric_modify(struct nb_cb_modify_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +int isis_instance_route_leanking_ipv6_metric_destroy( + struct nb_cb_destroy_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/table + */ +int isis_instance_route_leanking_ipv6_table_create(struct nb_cb_create_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* TODO */ + return NB_OK; +} + +int isis_instance_route_leanking_ipv6_table_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* TODO */ + return NB_OK; +} + /* * XPath: /frr-isisd:isis/instance/redistribute/ipv4 */ @@ -1236,14 +1421,12 @@ void redistribute_apply_finish(const struct lyd_node *dnode, int family) const char *routemap = NULL; struct isis_area *area; - type = yang_dnode_get_enum(dnode, "protocol"); - level = yang_dnode_get_enum(dnode, "level"); + type = yang_dnode_get_enum(dnode, "./protocol"); + level = yang_dnode_get_enum(dnode, "./level"); area = nb_running_get_entry(dnode, NULL, true); - if (yang_dnode_exists(dnode, "metric")) - metric = yang_dnode_get_uint32(dnode, "metric"); - if (yang_dnode_exists(dnode, "route-map")) - routemap = yang_dnode_get_string(dnode, "route-map"); + if (yang_dnode_exists(dnode, "./route-map")) + routemap = yang_dnode_get_string(dnode, "./route-map"); isis_redist_set(area, level, family, type, metric, routemap, 0, 0); } @@ -1264,6 +1447,24 @@ int isis_instance_redistribute_ipv4_create(struct nb_cb_create_args *args) return NB_OK; } +int isis_instance_leanking_ipv4_destroy(struct nb_cb_destroy_args *args) +{ + struct isis_area *area; + const char *routemap = NULL; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(args->dnode, NULL, true); + + if (yang_dnode_exists(args->dnode, "route-map")) + routemap = yang_dnode_get_string(args->dnode, "route-map"); + + isis_leanking_unset(area, routemap); + + return NB_OK; +} + int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args) { struct isis_area *area; @@ -1273,8 +1474,8 @@ int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args) return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - level = yang_dnode_get_enum(args->dnode, "level"); - type = yang_dnode_get_enum(args->dnode, "protocol"); + level = yang_dnode_get_enum(args->dnode, "./level"); + type = yang_dnode_get_enum(args->dnode, "./protocol"); isis_redist_unset(area, level, AF_INET, type, 0); return NB_OK; @@ -1333,12 +1534,12 @@ int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args) level = yang_dnode_get_enum(args->dnode, "../level"); area = nb_running_get_entry(args->dnode, "../.", true); - if (yang_dnode_exists(args->dnode, "metric")) - metric = yang_dnode_get_uint32(args->dnode, "metric"); - if (yang_dnode_exists(args->dnode, "route-map")) - routemap = yang_dnode_get_string(args->dnode, "route-map"); + if (yang_dnode_exists(args->dnode, "./metric")) + metric = yang_dnode_get_uint32(args->dnode, "./metric"); + if (yang_dnode_exists(args->dnode, "./route-map")) + routemap = yang_dnode_get_string(args->dnode, "./route-map"); - table = yang_dnode_get_uint16(args->dnode, "table"); + table = yang_dnode_get_uint16(args->dnode, "./table"); isis_redist_set(area, level, AF_INET, type, metric, routemap, 0, table); return NB_OK; @@ -1355,7 +1556,7 @@ int isis_instance_redistribute_ipv4_table_destroy(struct nb_cb_destroy_args *arg area = nb_running_get_entry(args->dnode, "../.", true); level = yang_dnode_get_enum(args->dnode, "../level"); type = yang_dnode_get_enum(args->dnode, "../protocol"); - table = yang_dnode_get_uint16(args->dnode, "table"); + table = yang_dnode_get_uint16(args->dnode, "./table"); isis_redist_unset(area, level, AF_INET, type, table); return NB_OK; @@ -1370,6 +1571,24 @@ int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args) return NB_OK; } +int isis_instance_leanking_ipv6_destroy(struct nb_cb_destroy_args *args) +{ + struct isis_area *area; + const char *routemap = NULL; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + area = nb_running_get_entry(args->dnode, NULL, true); + + if (yang_dnode_exists(args->dnode, "route-map")) + routemap = yang_dnode_get_string(args->dnode, "route-map"); + + isis_leanking_unset(area, routemap); + + return NB_OK; +} + int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args) { struct isis_area *area; @@ -1379,12 +1598,20 @@ int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args) return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - level = yang_dnode_get_enum(args->dnode, "level"); - type = yang_dnode_get_enum(args->dnode, "protocol"); + level = yang_dnode_get_enum(args->dnode, "./level"); + type = yang_dnode_get_enum(args->dnode, "./protocol"); isis_redist_unset(area, level, AF_INET6, type, 0); return NB_OK; } +/* + * XPath: /frr-isisd:isis/instance/redistribute/ipv6/metric + */ +int isis_instance_leanking_ipv6_metric_modify(struct nb_cb_modify_args *args) +{ + /* It's all done by redistribute_apply_finish */ + return NB_OK; +} /* * XPath: /frr-isisd:isis/instance/redistribute/ipv6/route-map @@ -1732,8 +1959,8 @@ int isis_instance_fast_reroute_level_1_lfa_tiebreaker_create( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - index = yang_dnode_get_uint8(args->dnode, "index"); - type = yang_dnode_get_enum(args->dnode, "type"); + index = yang_dnode_get_uint8(args->dnode, "./index"); + type = yang_dnode_get_enum(args->dnode, "./type"); tie_b = isis_lfa_tiebreaker_add(area, ISIS_LEVEL1, index, type); nb_running_set_entry(args->dnode, tie_b); @@ -1881,8 +2108,8 @@ int isis_instance_fast_reroute_level_2_lfa_tiebreaker_create( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - index = yang_dnode_get_uint8(args->dnode, "index"); - type = yang_dnode_get_enum(args->dnode, "type"); + index = yang_dnode_get_uint8(args->dnode, "./index"); + type = yang_dnode_get_enum(args->dnode, "./type"); tie_b = isis_lfa_tiebreaker_add(area, ISIS_LEVEL2, index, type); nb_running_set_entry(args->dnode, tie_b); @@ -2212,10 +2439,10 @@ int isis_instance_segment_routing_label_blocks_pre_validate( uint32_t srlb_lbound; uint32_t srlb_ubound; - srgb_lbound = yang_dnode_get_uint32(args->dnode, "srgb/lower-bound"); - srgb_ubound = yang_dnode_get_uint32(args->dnode, "srgb/upper-bound"); - srlb_lbound = yang_dnode_get_uint32(args->dnode, "srlb/lower-bound"); - srlb_ubound = yang_dnode_get_uint32(args->dnode, "srlb/upper-bound"); + srgb_lbound = yang_dnode_get_uint32(args->dnode, "./srgb/lower-bound"); + srgb_ubound = yang_dnode_get_uint32(args->dnode, "./srgb/upper-bound"); + srlb_lbound = yang_dnode_get_uint32(args->dnode, "./srlb/lower-bound"); + srlb_ubound = yang_dnode_get_uint32(args->dnode, "./srlb/upper-bound"); /* Check that the block size does not exceed 65535 */ if ((srgb_ubound - srgb_lbound + 1) > 65535) { @@ -2255,8 +2482,8 @@ void isis_instance_segment_routing_srgb_apply_finish( uint32_t lower_bound, upper_bound; area = nb_running_get_entry(args->dnode, NULL, true); - lower_bound = yang_dnode_get_uint32(args->dnode, "lower-bound"); - upper_bound = yang_dnode_get_uint32(args->dnode, "upper-bound"); + lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound"); + upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound"); isis_sr_cfg_srgb_update(area, lower_bound, upper_bound); } @@ -2321,8 +2548,8 @@ void isis_instance_segment_routing_srlb_apply_finish( uint32_t lower_bound, upper_bound; area = nb_running_get_entry(args->dnode, NULL, true); - lower_bound = yang_dnode_get_uint32(args->dnode, "lower-bound"); - upper_bound = yang_dnode_get_uint32(args->dnode, "upper-bound"); + lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound"); + upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound"); isis_sr_cfg_srlb_update(area, lower_bound, upper_bound); } @@ -2428,7 +2655,7 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); pcfg = isis_sr_cfg_prefix_add(area, &prefix, SR_ALGORITHM_SPF); nb_running_set_entry(args->dnode, pcfg); @@ -2466,13 +2693,13 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate( enum sr_sid_value_type sid_type; struct isis_prefix_sid psid = {}; - yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); srgb_lbound = yang_dnode_get_uint32( args->dnode, "../../label-blocks/srgb/lower-bound"); srgb_ubound = yang_dnode_get_uint32( args->dnode, "../../label-blocks/srgb/upper-bound"); - sid = yang_dnode_get_uint32(args->dnode, "sid-value"); - sid_type = yang_dnode_get_enum(args->dnode, "sid-value-type"); + sid = yang_dnode_get_uint32(args->dnode, "./sid-value"); + sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type"); /* Check for invalid indexes/labels. */ srgb_range = srgb_ubound - srgb_lbound + 1; @@ -2636,8 +2863,8 @@ int isis_instance_segment_routing_algorithm_prefix_sid_create( return NB_OK; area = nb_running_get_entry(args->dnode, NULL, true); - yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); - algorithm = yang_dnode_get_uint32(args->dnode, "algo"); + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); + algorithm = yang_dnode_get_uint32(args->dnode, "./algo"); pcfg = isis_sr_cfg_prefix_add(area, &prefix, algorithm); pcfg->algorithm = algorithm; @@ -2676,13 +2903,13 @@ int isis_instance_segment_routing_algorithm_prefix_sid_pre_validate( enum sr_sid_value_type sid_type; struct isis_prefix_sid psid = {}; - yang_dnode_get_prefix(&prefix, args->dnode, "prefix"); + yang_dnode_get_prefix(&prefix, args->dnode, "./prefix"); srgb_lbound = yang_dnode_get_uint32( args->dnode, "../../label-blocks/srgb/lower-bound"); srgb_ubound = yang_dnode_get_uint32( args->dnode, "../../label-blocks/srgb/upper-bound"); - sid = yang_dnode_get_uint32(args->dnode, "sid-value"); - sid_type = yang_dnode_get_enum(args->dnode, "sid-value-type"); + sid = yang_dnode_get_uint32(args->dnode, "./sid-value"); + sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type"); /* Check for invalid indexes/labels. */ srgb_range = srgb_ubound - srgb_lbound + 1; @@ -2840,8 +3067,8 @@ int isis_instance_flex_algo_create(struct nb_cb_create_args *args) uint32_t priority = FLEX_ALGO_PRIO_DEFAULT; struct isis_flex_algo_alloc_arg arg; - algorithm = yang_dnode_get_uint32(args->dnode, "flex-algo"); - advertise = yang_dnode_exists(args->dnode, "advertise-definition"); + algorithm = yang_dnode_get_uint32(args->dnode, "./flex-algo"); + advertise = yang_dnode_exists(args->dnode, "./advertise-definition"); switch (args->event) { case NB_EV_APPLY: @@ -2875,7 +3102,7 @@ int isis_instance_flex_algo_destroy(struct nb_cb_destroy_args *args) struct isis_area *area; uint32_t algorithm; - algorithm = yang_dnode_get_uint32(args->dnode, "flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./flex-algo"); area = nb_running_get_entry(args->dnode, NULL, true); switch (args->event) { @@ -2904,8 +3131,8 @@ int isis_instance_flex_algo_advertise_definition_modify( uint32_t algorithm; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); - advertise = yang_dnode_exists(args->dnode, "../advertise-definition"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); + advertise = yang_dnode_exists(args->dnode, "./../advertise-definition"); switch (args->event) { case NB_EV_APPLY: @@ -2937,7 +3164,7 @@ int isis_instance_flex_algo_advertise_definition_destroy( area = nb_running_get_entry(args->dnode, NULL, true); - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); switch (args->event) { case NB_EV_APPLY: @@ -3153,7 +3380,7 @@ int isis_instance_flex_algo_prefix_metric_create(struct nb_cb_create_args *args) if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); switch (args->event) { case NB_EV_APPLY: @@ -3188,7 +3415,7 @@ int isis_instance_flex_algo_prefix_metric_destroy( if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); switch (args->event) { case NB_EV_APPLY: @@ -3223,7 +3450,7 @@ static int isis_instance_flex_algo_dplane_set(struct nb_cb_create_args *args, if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); switch (args->event) { case NB_EV_APPLY: @@ -3265,7 +3492,7 @@ static int isis_instance_flex_algo_dplane_unset(struct nb_cb_destroy_args *args, if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); switch (args->event) { case NB_EV_APPLY: @@ -3348,7 +3575,7 @@ int isis_instance_flex_algo_metric_type_modify(struct nb_cb_modify_args *args) if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); metric_type = yang_dnode_get_enum(args->dnode, NULL); switch (args->event) { @@ -3388,7 +3615,7 @@ int isis_instance_flex_algo_priority_modify(struct nb_cb_modify_args *args) if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); priority = yang_dnode_get_uint32(args->dnode, NULL); switch (args->event) { @@ -3424,7 +3651,7 @@ int isis_instance_flex_algo_priority_destroy(struct nb_cb_destroy_args *args) if (!area) return NB_ERR_RESOURCE; - algorithm = yang_dnode_get_uint32(args->dnode, "../flex-algo"); + algorithm = yang_dnode_get_uint32(args->dnode, "./../flex-algo"); priority = yang_dnode_get_uint32(args->dnode, NULL); switch (args->event) { @@ -3754,7 +3981,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args) { struct interface *ifp; struct isis_circuit *circuit = NULL; - const char *area_tag = yang_dnode_get_string(args->dnode, "area-tag"); + const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag"); switch (args->event) { case NB_EV_PREPARE: diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index 2cb08db27bd7..9445fcfec3d5 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -27,6 +27,9 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" +#include "isisd/isis_redist.h" +#include "isisd/isis_spf.h" +#include "isisd/isis_spf_private.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route"); DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info"); @@ -62,9 +65,8 @@ static struct route_table *get_ext_info(struct isis *i, int family) return i->ext_info[protocol]; } -static struct isis_redist *isis_redist_lookup(struct isis_area *area, - int family, int type, int level, - uint16_t table) +struct isis_redist *isis_redist_lookup(struct isis_area *area, int family, + int type, int level, uint16_t table) { int protocol = redist_protocol(family); struct listnode *node; @@ -174,8 +176,6 @@ static void isis_redist_uninstall(struct isis_area *area, int level, lsp_regenerate_schedule(area, level, 0); } -/* Update external reachability info of area for a given level - * and prefix, using the given redistribution settings. */ static void isis_redist_update_ext_reach(struct isis_area *area, int level, struct isis_redist *redist, const struct prefix *p, @@ -198,7 +198,6 @@ static void isis_redist_update_ext_reach(struct isis_area *area, int level, if (area_info.origin == DEFAULT_ROUTE && redist->redist != DEFAULT_ORIGINATE_ALWAYS) area_info.distance = 255; - if (area_info.distance < 255) isis_redist_install(area, level, p, src_p, &area_info); else @@ -285,6 +284,94 @@ bool isis_redist_table_is_present(const struct vty *vty, return rtda->rtda_found; } +int compare_prefix(struct list *leanking_list, struct prefix *prefix) +{ + struct listnode *node; + struct prefix_leanking *leanking; + + for (ALL_LIST_ELEMENTS_RO(leanking_list, node, leanking)) { + if (prefix_same(leanking->prefix, prefix)) + return 1; + } + return 0; +} + +/* + * Route_leanking functions + */ +void isis_redist_update_route_leanking(struct isis_area *area, + struct isis_leanking *redist, + struct prefix *prefix) +{ + route_map_result_t map_ret; + struct isis_ext_info area_info; + + area_info.metric = redist->metric; + + if (redist->map_name) { + map_ret = route_map_apply(redist->map, prefix, &area_info); + if (map_ret == RMAP_PERMITMATCH) { + if (compare_prefix(area->leanking_list[redist->level], + prefix) == 0) { + struct prefix_leanking *leanking = + (struct prefix_leanking *) + calloc(1, sizeof(*leanking)); + leanking->metric = area_info.metric; + leanking->prefix = prefix; + listnode_add(area->leanking_list[redist->level], + leanking); + } + } + } +} + +void iteration_in_spftree(struct isis_area *area, struct isis_leanking *redist) +{ + struct route_node *rn; + + if (redist->protocol == 0) { + for (rn = route_top(area->spftree[SPFTREE_IPV4][redist->level_tmp] + ->route_table); + rn; rn = srcdest_route_next(rn)) { + isis_redist_update_route_leanking(area, redist, &rn->p); + } + } + if (redist->protocol == 1) { + for (rn = route_top(area->spftree[SPFTREE_IPV6][redist->level_tmp] + ->route_table); + rn; rn = srcdest_route_next(rn)) + isis_redist_update_route_leanking(area, redist, &rn->p); + } +} + +void isis_redist_set_route_leanking(struct isis_area *area, int level, + int family, int type, uint32_t metric, + const char *routemap, int originate_type, + uint16_t table) +{ + struct isis_leanking *redist = + (struct isis_leanking *)calloc(1, sizeof(*redist)); + + redist->protocol = redist_protocol(family); + redist->type = type; + redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1; + redist->metric = metric; + redist->map = route_map_lookup_by_name(routemap); + redist->table = table; + redist->map_name = (char *)routemap; + + if (level == LEVEL2_TO_LEVEL1) { + redist->level_tmp = LVL_ISIS_LEANKING_2; + redist->level = LVL_ISIS_LEANKING_1; + } else { + redist->level_tmp = LVL_ISIS_LEANKING_1; + redist->level = LVL_ISIS_LEANKING_2; + } + + listnode_add(area->leanking_settings, redist); + iteration_in_spftree(area, redist); +} + /* Handle notification about route being added */ void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, @@ -449,7 +536,6 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, if (!area->ext_reach[protocol][level - 1]) { area->ext_reach[protocol][level - 1] = srcdest_table_init(); } - for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) { if (!area->isis->ext_info[i]) { area->isis->ext_info[i] = srcdest_table_init(); @@ -488,6 +574,25 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, } } +void isis_leanking_unset(struct isis_area *area, const char *routemap) +{ + struct listnode *node; + struct isis_leanking *redist_tmp = + (struct isis_leanking *)calloc(1, sizeof(*redist_tmp)); + + for (ALL_LIST_ELEMENTS_RO(area->leanking_settings, node, redist_tmp)) { + if (redist_tmp->map_name == routemap) + break; + } + + list_delete_node(area->leanking_settings, node); + + lsp_regenerate_schedule(area, IS_LEVEL_1, 0); + lsp_regenerate_schedule(area, IS_LEVEL_2, 0); + + free(redist_tmp); +} + void isis_redist_unset(struct isis_area *area, int level, int family, int type, uint16_t table) { @@ -498,7 +603,6 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type, struct isis_ext_info *info; struct list *redist_list; int protocol = redist_protocol(family); - if (!redist || !redist->redist) return; @@ -520,6 +624,7 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type, info = rn->info; const struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); if (type == DEFAULT_ROUTE) { @@ -585,6 +690,85 @@ void isis_redist_area_finish(struct isis_area *area) } #ifdef FABRICD +DEFUN(isis_leanking, isis_leanking_cmd, + "route_leanking route-map RMAP_NAME}]", + ROUTE_LEANKING "Redistribute IPv4 routes\n" PROTO_IP_REDIST_HELP + "Redistribute IPv6 routes\n" PROTO_IP6_REDIST_HELP + "Route map reference\n" + "Pointer to route-map entries\n") +{ + int idx_afi = 1; + int idx_protocol = 2; + int idx_metric_rmap = 1; + int family; + int afi; + int type; + int level; + unsigned long metric = 0; + const char *routemap = NULL; + + VTY_DECLVAR_CONTEXT(isis_area, area); + family = str2family(argv[idx_afi]->text); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + afi = family2afi(family); + if (!afi) + return CMD_WARNING_CONFIG_FAILED; + + type = proto_redistnum(afi, argv[idx_protocol]->text); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; + + level = 2; + + if ((area->is_type & level) != level) { + vty_out(vty, "Node is not a level-%d IS\n", level); + return CMD_WARNING_CONFIG_FAILED; + } + idx_metric_rmap = 1; + if (argv_find(argv, argc, "route-map", &idx_metric_rmap)) + routemap = argv[idx_metric_rmap + 1]->arg; + + isis_redist_set(area, level, family, type, metric, routemap, 0, 0); + return 0; +} + +DEFUN(no_isis_leanking, no_isis_leanking_cmd, + "no route_leanking route-map RMAP_NAME}]", + ROUTE_LEANKING "Redistribute IPv4 routes\n" PROTO_IP_REDIST_HELP + "Redistribute IPv6 routes\n" PROTO_IP6_REDIST_HELP + "Route map reference\n" + "Pointer to route-map entries\n") +{ + int idx_afi = 2; + int idx_protocol = 3; + int type; + int level; + int family; + int afi; + + VTY_DECLVAR_CONTEXT(isis_area, area); + family = str2family(argv[idx_afi]->arg); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + afi = family2afi(family); + if (!afi) + return CMD_WARNING_CONFIG_FAILED; + + type = proto_redistnum(afi, argv[idx_protocol]->text); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; + + level = 2; + + isis_redist_unset(area, level, family, type, 0); + return 0; +} + DEFUN (isis_redistribute, isis_redistribute_cmd, "redistribute " @@ -811,6 +995,7 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, } } + for (level = 1; level <= ISIS_LEVELS; level++) { redist = isis_redist_lookup(area, family, DEFAULT_ROUTE, level, 0); @@ -832,6 +1017,53 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area, write++; } + + return write; +} + +int isis_leanking_config_write(struct vty *vty, struct isis_area *area, + int family) +{ + int type; + int level; + int write = 0; + struct isis_redist *redist; + struct list *redist_list; + const char *family_str; + struct listnode *node; + + if (family == AF_INET) + family_str = "ipv4"; + else if (family == AF_INET6) + family_str = "ipv6"; + else + return 0; + + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (type == PROTO_TYPE) + continue; + + for (level = 1; level <= ISIS_LEVELS; level++) { + redist_list = area->redist_settings[redist_protocol( + family)][type][level - 1]; + if (!redist_list) + continue; + for (ALL_LIST_ELEMENTS_RO(redist_list, node, redist)) { + if (!redist->redist) + continue; + vty_out(vty, " leanking %s %s", family_str, + zebra_route_string(type)); + if (!fabricd) + vty_out(vty, " level-%d", level); + if (redist->map_name) + vty_out(vty, " route-map %s", + redist->map_name); + vty_out(vty, "\n"); + write++; + } + } + } + return write; } @@ -841,6 +1073,8 @@ void isis_redist_init(void) install_element(ROUTER_NODE, &isis_redistribute_cmd); install_element(ROUTER_NODE, &no_isis_redistribute_cmd); + install_element(ROUTER_NODE, &isis_leanking_cmd); + install_element(ROUTER_NODE, &isis_default_originate_cmd); install_element(ROUTER_NODE, &no_isis_default_originate_cmd); #endif /* ifdef FABRICD */ diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 688f27e62db8..b3995cbccb83 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -13,22 +13,38 @@ #define DEFAULT_ROUTE ZEBRA_ROUTE_MAX #define DEFAULT_ORIGINATE 1 #define DEFAULT_ORIGINATE_ALWAYS 2 - -struct isis_ext_info { - int origin; +struct isis_redist { + int redist; uint32_t metric; - uint8_t distance; - route_tag_t tag; + char *map_name; + struct route_map *map; + uint16_t table; }; -struct isis_redist { +struct isis_leanking { int redist; + int protocol; + int type; + int level; + int level_tmp; uint32_t metric; char *map_name; struct route_map *map; uint16_t table; }; +struct prefix_leanking { + struct prefix *prefix; + uint32_t metric; +}; + +struct isis_ext_info { + int origin; + uint32_t metric; + uint8_t distance; + route_tag_t tag; +}; + struct isis_redist_table_present_args { /* from filter.h, struct acl_dup_args */ const char *rtda_ip; @@ -44,9 +60,11 @@ struct prefix_ipv6; struct vty; afi_t afi_for_redist_protocol(int protocol); - +struct isis_redist *isis_redist_lookup(struct isis_area *area, int family, + int type, int level, uint16_t table); struct route_table *get_ext_reach(struct isis_area *area, int family, int level); +void isis_leanking_add(struct isis *isis, struct prefix *p); void isis_redist_add(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint8_t distance, uint32_t metric, route_tag_t tag, uint16_t instance); @@ -54,15 +72,26 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p, struct prefix_ipv6 *src_p, uint16_t tableid); int isis_redist_config_write(struct vty *vty, struct isis_area *area, int family); +int isis_leanking_config_write(struct vty *vty, struct isis_area *area, + int family); +int compare_prefix(struct list *leanking_list, struct prefix *prefix); +void isis_redist_update_route_leanking(struct isis_area *aria, + struct isis_leanking *redist, + struct prefix *prefix); void isis_redist_init(void); void isis_redist_area_finish(struct isis_area *area); - +void iteration_in_spftree(struct isis_area *area, struct isis_leanking *redist); +void isis_redist_set_route_leanking(struct isis_area *area, int level, + int family, int type, uint32_t metric, + const char *routemap, int originate_type, + uint16_t table); +void iterate_in_lspdb(struct isis_area *area, struct isis_leanking *redist); void isis_redist_set(struct isis_area *area, int level, int family, int type, uint32_t metric, const char *routemap, int originate_type, uint16_t table); void isis_redist_unset(struct isis_area *area, int level, int family, int type, uint16_t table); - +void isis_leanking_unset(struct isis_area *area, const char *routemap); void isis_redist_free(struct isis *isis); bool isis_redist_table_is_present(const struct vty *vty, diff --git a/isisd/isisd.c b/isisd/isisd.c index 772eb9708dfc..16e0391a08f7 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -332,6 +332,11 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name) area->area_addrs = list_new(); area->area_addrs->del = delete_area_addr; + for (int level = 0; level < 2; level++) + area->leanking_list[level] = list_new(); + + area->leanking_settings = list_new(); + if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST)) event_add_timer(master, lsp_tick, area, 1, &area->t_tick); flags_initialize(&area->flags); @@ -547,6 +552,11 @@ void isis_area_destroy(struct isis_area *area) list_delete(&area->area_addrs); + for (int level = 0; level < 2; level++) + list_delete(&area->leanking_list[level]); + + list_delete(&area->leanking_settings); + for (int i = SPF_PREFIX_PRIO_CRITICAL; i <= SPF_PREFIX_PRIO_MEDIUM; i++) { struct spf_prefix_priority_acl *ppa; @@ -3561,6 +3571,8 @@ static int isis_config_write(struct vty *vty) } write += isis_redist_config_write(vty, area, AF_INET); write += isis_redist_config_write(vty, area, AF_INET6); + write += isis_leanking_config_write(vty, area, AF_INET); + write += isis_leanking_config_write(vty, area, AF_INET6); /* ISIS - Lsp generation interval */ if (area->lsp_gen_interval[0] == area->lsp_gen_interval[1]) { diff --git a/isisd/isisd.h b/isisd/isisd.h index f5042e4ad5c2..e7a80040acf9 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -256,6 +256,9 @@ struct isis_area { uint64_t id_len_mismatches[2]; uint64_t lsp_error_counter[2]; + struct list *leanking_settings; + struct list *leanking_list[2]; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(isis_area); diff --git a/lib/command.h b/lib/command.h index ef1815c0bd51..499baf01ab0a 100644 --- a/lib/command.h +++ b/lib/command.h @@ -393,6 +393,8 @@ struct cmd_node { #define SRTE_COLOR_STR "SR-TE Color information\n" #define NO_STR "Negate a command or set its defaults\n" #define IGNORED_IN_NO_STR "Ignored value in no form\n" +#define ROUTE_LEANKING "route_leanking\n" +#define LEANKING_STR "Leanking between level's in IS-IS routing protocol\n" #define REDIST_STR "Redistribute information from another routing protocol\n" #define CLEAR_STR "Reset functions\n" #define RIP_STR "RIP information\n" diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 5d7c739c05d2..c3cae157571a 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -104,6 +104,16 @@ module frr-isisd { description "This enum indicates capability for both levels."; } + enum "level2_to_level1" { + value 4; + description + "This enum indicates capability for both levels."; + } + enum "level1_to_level2" { + value 5; + description + "This enum indicates capability for both levels."; + } } description "This type defines IS-IS level of an object."; @@ -312,6 +322,27 @@ module frr-isisd { uses redistribute-attributes; } + grouping leanking-attributes { + description + "Common optional attributes of any leanking entry."; + leaf route-map { + type frr-route-map:route-map-ref; + description + "Applies the conditions of the specified route-map to routes that + are redistributed into this routing instance."; + } + + leaf metric { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Metric used for the redistributed route. If 0, + the default-metric attribute is used instead."; + } + } + grouping isis-password { description "Authentication attributes or an IS-IS area or domain."; @@ -2078,6 +2109,45 @@ module frr-isisd { } } + container route_leanking { + description + "Redistributes routes learned from other routing protocols."; + list ipv4 { + key "protocol level"; + description + "IPv4 route redistribution."; + leaf protocol { + type frr-route-types:frr-route-types-v4; + description + "Originating routing protocol for the IPv4 routes."; + } + + leaf level { + type level; + description + "IS-IS level into which the routes should be redistributed."; + } + + uses leanking-attributes; + } + list ipv6 { + key "protocol level"; + description + "IPv6 route redistribution."; + leaf protocol { + type frr-route-types:frr-route-types-v6; + description + "Originating routing protocol for the IPv6 routes."; + } + + leaf level { + type level; + description + "IS-IS level into which the routes should be redistributed."; + } + uses redistribute-attributes; + } + } } }