From 4f40546c96c6aeaa4371161dca9db21071bcc5d2 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 5 Aug 2024 11:55:46 +0200 Subject: Adding upstream version 10.0.1. Signed-off-by: Daniel Baumann --- bgpd/bgp_attr.c | 9 + bgpd/bgp_fsm.c | 19 +- bgpd/bgp_mplsvpn.c | 5 +- bgpd/bgp_open.c | 4 +- bgpd/bgp_route.c | 81 ++- bgpd/bgp_route.h | 8 +- bgpd/bgp_routemap.c | 60 +- bgpd/bgp_snmp_bgp4.c | 4 +- bgpd/bgp_updgrp_adv.c | 13 +- bgpd/bgp_vpn.c | 2 +- bgpd/bgp_zebra.c | 9 +- bgpd/bgpd.c | 45 +- configure.ac | 2 +- doc/user/bgp.rst | 5 + doc/user/pim.rst | 2 +- doc/user/pimv6.rst | 2 +- isisd/isis_spf.c | 2 + isisd/isis_tlvs.c | 10 +- lib/command.c | 2 +- lib/libfrr.c | 2 - lib/nexthop.c | 8 +- lib/nexthop.h | 4 +- lib/resolver.c | 67 ++- lib/vrf.c | 2 +- nhrpd/nhrp_shortcut.c | 12 +- ospf6d/ospf6_abr.c | 7 +- ospf6d/ospf6_gr_helper.c | 1 + ospf6d/ospf6_interface.c | 617 +++++++++++++-------- ospf6d/ospf6_neighbor.c | 102 ++-- ospf6d/ospf6_route.h | 1 + ospfd/ospf_interface.c | 3 +- ospfd/ospf_interface.h | 1 + ospfd/ospf_snmp.c | 26 +- ospfd/ospf_te.c | 63 ++- ospfd/ospf_vty.c | 39 +- pimd/pim6_cmd.c | 4 +- pimd/pim_cmd.c | 4 +- pimd/pim_cmd_common.c | 11 +- pimd/pim_ifchannel.c | 8 +- pimd/pim_igmpv3.c | 2 - pimd/pim_register.c | 4 +- pimd/pim_upstream.c | 65 ++- pimd/pim_upstream.h | 3 +- redhat/frr.spec.in | 76 ++- snapcraft/snapcraft.yaml.in | 2 +- .../bgp_asdot_regex/r1/show_bgp_ipv4.json | 1 - .../bgp_asdot_regex/r2/show_bgp_ipv4.json | 1 - .../bgp_path_attribute_discard/peer1/exabgp.cfg | 29 +- .../bgp_path_attribute_discard/r1/bgpd.conf | 6 - .../bgp_path_attribute_discard/r1/frr.conf | 9 + .../bgp_path_attribute_discard/r1/zebra.conf | 4 - .../bgp_path_attribute_discard/r2/frr.conf | 10 + .../test_bgp_path_attribute_discard.py | 37 +- .../topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json | 1 - .../topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json | 1 - .../bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json | 1 - .../bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json | 1 - .../test_bgp-vrf-route-leak-basic.py | 145 +---- tests/topotests/evpn_pim_1/spine/bgp.summ.json | 1 - tests/topotests/nhrp_redundancy/r1/nhrp_cache.json | 40 ++ tests/topotests/nhrp_redundancy/r1/nhrp_route.json | 48 ++ tests/topotests/nhrp_redundancy/r1/nhrpd.conf | 9 + tests/topotests/nhrp_redundancy/r1/zebra.conf | 12 + tests/topotests/nhrp_redundancy/r2/nhrp_cache.json | 40 ++ tests/topotests/nhrp_redundancy/r2/nhrp_route.json | 48 ++ tests/topotests/nhrp_redundancy/r2/nhrpd.conf | 9 + tests/topotests/nhrp_redundancy/r2/zebra.conf | 12 + tests/topotests/nhrp_redundancy/r3/nhrp_cache.json | 40 ++ tests/topotests/nhrp_redundancy/r3/nhrp_route.json | 48 ++ tests/topotests/nhrp_redundancy/r3/nhrpd.conf | 9 + tests/topotests/nhrp_redundancy/r3/zebra.conf | 12 + tests/topotests/nhrp_redundancy/r4/nhrp_cache.json | 51 ++ tests/topotests/nhrp_redundancy/r4/nhrp_route.json | 71 +++ .../nhrp_redundancy/r4/nhrp_route_shortcut.json | 118 ++++ tests/topotests/nhrp_redundancy/r4/nhrpd.conf | 11 + tests/topotests/nhrp_redundancy/r4/zebra.conf | 16 + tests/topotests/nhrp_redundancy/r5/nhrp_cache.json | 51 ++ tests/topotests/nhrp_redundancy/r5/nhrp_route.json | 71 +++ tests/topotests/nhrp_redundancy/r5/nhrpd.conf | 11 + tests/topotests/nhrp_redundancy/r5/zebra.conf | 16 + tests/topotests/nhrp_redundancy/r6/zebra.conf | 7 + tests/topotests/nhrp_redundancy/r7/zebra.conf | 4 + .../nhrp_redundancy/test_nhrp_redundancy.dot | 103 ++++ .../nhrp_redundancy/test_nhrp_redundancy.py | 423 ++++++++++++++ .../r2/zebra-vrf-ray.txt | 4 +- tools/frr-reload.py | 50 ++ vtysh/vtysh.c | 4 +- yang/frr-pim.yang | 4 +- zebra/zebra_cli.c | 2 +- zebra/zebra_mpls.c | 12 +- zebra/zebra_mpls_vty.c | 5 +- zebra/zebra_nb_config.c | 1 + zebra/zebra_nhg.c | 3 +- zebra/zebra_routemap.c | 5 +- zebra/zebra_vxlan.c | 23 +- 95 files changed, 2414 insertions(+), 644 deletions(-) delete mode 100644 tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf create mode 100644 tests/topotests/bgp_path_attribute_discard/r1/frr.conf delete mode 100644 tests/topotests/bgp_path_attribute_discard/r1/zebra.conf create mode 100644 tests/topotests/bgp_path_attribute_discard/r2/frr.conf create mode 100644 tests/topotests/nhrp_redundancy/r1/nhrp_cache.json create mode 100644 tests/topotests/nhrp_redundancy/r1/nhrp_route.json create mode 100644 tests/topotests/nhrp_redundancy/r1/nhrpd.conf create mode 100644 tests/topotests/nhrp_redundancy/r1/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r2/nhrp_cache.json create mode 100644 tests/topotests/nhrp_redundancy/r2/nhrp_route.json create mode 100644 tests/topotests/nhrp_redundancy/r2/nhrpd.conf create mode 100644 tests/topotests/nhrp_redundancy/r2/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r3/nhrp_cache.json create mode 100644 tests/topotests/nhrp_redundancy/r3/nhrp_route.json create mode 100644 tests/topotests/nhrp_redundancy/r3/nhrpd.conf create mode 100644 tests/topotests/nhrp_redundancy/r3/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r4/nhrp_cache.json create mode 100644 tests/topotests/nhrp_redundancy/r4/nhrp_route.json create mode 100644 tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json create mode 100644 tests/topotests/nhrp_redundancy/r4/nhrpd.conf create mode 100644 tests/topotests/nhrp_redundancy/r4/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r5/nhrp_cache.json create mode 100644 tests/topotests/nhrp_redundancy/r5/nhrp_route.json create mode 100644 tests/topotests/nhrp_redundancy/r5/nhrpd.conf create mode 100644 tests/topotests/nhrp_redundancy/r5/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r6/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/r7/zebra.conf create mode 100644 tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot create mode 100644 tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 53420b4..40e074d 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1518,6 +1518,7 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) uint8_t mask = BGP_ATTR_FLAG_EXTLEN; const uint8_t flags = args->flags; const uint8_t attr_code = args->type; + struct peer *peer = args->peer; /* there may be attributes we don't know about */ if (attr_code > attr_flags_values_max) @@ -1525,6 +1526,14 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) if (attr_flags_values[attr_code] == 0) return false; + /* If `neighbor X path-attribute ` is + * configured, then ignore checking optional, trasitive flags. + * The attribute/route will be discarded/withdrawned later instead + * of dropping the session. + */ + if (peer->discard_attrs[attr_code] || peer->withdraw_attrs[attr_code]) + return false; + /* RFC4271, "For well-known attributes, the Transitive bit MUST be set * to * 1." diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 234dbb0..5043439 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1777,7 +1777,7 @@ bgp_connect_fail(struct peer_connection *connection) { struct peer *peer = connection->peer; - if (peer_dynamic_neighbor(peer)) { + if (peer_dynamic_neighbor_no_nsf(peer)) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s (dynamic neighbor) deleted (%s)", peer->host, __func__); @@ -2895,19 +2895,22 @@ int bgp_neighbor_graceful_restart(struct peer *peer, peer_old_state = bgp_peer_gr_mode_get(peer); - if (peer_old_state == PEER_INVALID) { - zlog_debug("[BGP_GR] peer_old_state == Invalid state !"); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s [BGP_GR] peer_old_state: %d", __func__, + peer_old_state); + + if (peer_old_state == PEER_INVALID) return BGP_ERR_GR_OPERATION_FAILED; - } peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd]; peer_new_state = peer_state.next_state; - if (peer_new_state == PEER_INVALID) { - zlog_debug( - "[BGP_GR] Invalid bgp graceful restart command used !"); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s [BGP_GR] peer_new_state: %d", __func__, + peer_new_state); + + if (peer_new_state == PEER_INVALID) return BGP_ERR_GR_INVALID_CMD; - } if (peer_new_state != peer_old_state) { result = peer_state.action_fun(peer, peer_old_state, diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index af8990a..58e3097 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -2230,8 +2230,9 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ * Let the kernel to decide with double lookup the real next-hop * interface when installing the route. */ - if (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC || - bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) { + if (src_vrf->vrf_id != VRF_DEFAULT && + (src_bgp || bpi_ultimate->sub_type == BGP_ROUTE_STATIC || + bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)) { ifp = if_get_vrf_loopback(src_vrf->vrf_id); if (ifp) static_attr.nh_ifindex = ifp->ifindex; diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 6447586..6c96ffc 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -939,8 +939,8 @@ static int bgp_capability_software_version(struct peer *peer, peer->soft_version = XSTRDUP(MTYPE_BGP_SOFT_VERSION, str); if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s sent Software Version: %s", peer->host, - peer->soft_version); + zlog_debug("%s received Software Version: %s", + peer->host, peer->soft_version); } return 0; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 38983e2..a69d6ee 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -553,6 +553,15 @@ void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi, bgp_pcount_adjust(dest, pi); } +static bool use_bgp_med_value(struct attr *attr, struct bgp *bgp) +{ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) || + CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST)) + return true; + + return false; +} + /* Get MED value. If MED value is missing and "bgp bestpath missing-as-worst" is specified, treat it as the worst value. */ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp) @@ -6833,6 +6842,10 @@ int bgp_static_set(struct vty *vty, bool negate, const char *ip_str, bgp_static->label = label; bgp_static->prd = prd; + if (rd_str) + bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, + rd_str); + if (rmap) { XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); @@ -9400,14 +9413,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p, } /* MED/Metric */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + if (use_bgp_med_value(attr, path->peer->bgp)) { + uint32_t value = bgp_med_value(attr, path->peer->bgp); + if (json_paths) - json_object_int_add(json_path, "metric", attr->med); + json_object_int_add(json_path, "metric", value); else if (wide) - vty_out(vty, "%7u", attr->med); + vty_out(vty, "%7u", value); else - vty_out(vty, "%10u", attr->med); - else if (!json_paths) { + vty_out(vty, "%10u", value); + } else if (!json_paths) { if (wide) vty_out(vty, "%*s", 7, " "); else @@ -9528,7 +9543,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, } /* called from terminal list command */ -void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, +void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest, const struct prefix *p, struct attr *attr, safi_t safi, bool use_json, json_object *json_ar, bool wide) { @@ -9587,10 +9602,11 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, &attr->mp_nexthop_global_in); } - if (attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - json_object_int_add(json_net, "metric", - attr->med); + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + + json_object_int_add(json_net, "metric", value); + } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) json_object_int_add(json_net, "locPrf", @@ -9630,13 +9646,15 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, else vty_out(vty, "%*s", len, " "); } - if (attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + if (wide) - vty_out(vty, "%7u", attr->med); + vty_out(vty, "%7u", value); else - vty_out(vty, "%10u", attr->med); - else if (wide) + vty_out(vty, "%10u", value); + } else if (wide) vty_out(vty, " "); else vty_out(vty, " "); @@ -10631,11 +10649,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, vty_out(vty, " Origin %s", bgp_origin_long_str[attr->origin]); - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + if (json_paths) - json_object_int_add(json_path, "metric", attr->med); + json_object_int_add(json_path, "metric", value); else - vty_out(vty, ", metric %u", attr->med); + vty_out(vty, ", metric %u", value); } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { @@ -11875,7 +11895,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, } else { if (incremental_print) { vty_out(vty, "\"prefix\": \"%pFX\",\n", p); - vty_out(vty, "\"version\": \"%" PRIu64 "\",\n", + vty_out(vty, "\"version\": \"%" PRIu64 "\",", dest->version); } else { json_object_string_addf(json, "prefix", "%pFX", @@ -14279,7 +14299,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, json_ar, json_net, "%pFX", rn_p); } else - route_vty_out_tmp(vty, dest, rn_p, + route_vty_out_tmp(vty, bgp, dest, rn_p, &attr, safi, use_json, json_ar, wide); bgp_attr_flush(&attr); @@ -14342,11 +14362,15 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, "%pFX", rn_p); } else - route_vty_out_tmp( - vty, dest, rn_p, - &attr, safi, - use_json, - json_ar, wide); + route_vty_out_tmp(vty, + bgp, + dest, + rn_p, + &attr, + safi, + use_json, + json_ar, + wide); (*output_count)++; } else { (*filtered_count)++; @@ -14384,9 +14408,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, json_ar, json_net, "%pFX", rn_p); } else - route_vty_out_tmp( - vty, dest, rn_p, pi->attr, safi, - use_json, json_ar, wide); + route_vty_out_tmp(vty, bgp, dest, rn_p, + pi->attr, safi, + use_json, json_ar, + wide); (*output_count)++; } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 2d82f0f..2929c75 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -845,10 +845,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p, extern void route_vty_out_tag(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json); -extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, - const struct prefix *p, struct attr *attr, - safi_t safi, bool use_json, json_object *json_ar, - bool wide); +extern void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, + struct bgp_dest *dest, const struct prefix *p, + struct attr *attr, safi_t safi, bool use_json, + json_object *json_ar, bool wide); extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index d604a7a..dbc3d64 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -5219,27 +5219,23 @@ DEFPY_YANG (match_peer, nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - if (addrv4_str) { - snprintf( - xpath_value, sizeof(xpath_value), - "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address", - xpath); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - addrv4_str); - } else if (addrv6_str) { - snprintf( - xpath_value, sizeof(xpath_value), - "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address", - xpath); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, - addrv6_str); - } else { - snprintf( - xpath_value, sizeof(xpath_value), - "%s/rmap-match-condition/frr-bgp-route-map:peer-interface", - xpath); - nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf); - } + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address", + xpath); + nb_cli_enqueue_change(vty, xpath_value, + addrv4_str ? NB_OP_MODIFY : NB_OP_DESTROY, + addrv4_str); + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address", + xpath); + nb_cli_enqueue_change(vty, xpath_value, + addrv6_str ? NB_OP_MODIFY : NB_OP_DESTROY, + addrv6_str); + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-match-condition/frr-bgp-route-map:peer-interface", + xpath); + nb_cli_enqueue_change(vty, xpath_value, + intf ? NB_OP_MODIFY : NB_OP_DESTROY, intf); return nb_cli_apply_changes(vty, NULL); } @@ -5882,10 +5878,11 @@ DEFUN_YANG (set_table_id, DEFUN_YANG (no_set_table_id, no_set_table_id_cmd, - "no set table", + "no set table [(1-4294967295)]", NO_STR SET_STR - "export route to non-main kernel table\n") + "export route to non-main kernel table\n" + "Kernel routing table id\n") { const char *xpath = "./set-action[action='frr-bgp-route-map:table']"; nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); @@ -6273,13 +6270,12 @@ DEFPY_YANG( } DEFUN_YANG (no_set_aspath_prepend, - no_set_aspath_prepend_cmd, - "no set as-path prepend [ASNUM] [last-as [(1-10)]]", + no_set_aspath_prepend_last_as_cmd, + "no set as-path prepend [last-as [(1-10)]]", NO_STR SET_STR "Transform BGP AS_PATH attribute\n" "Prepend to the as-path\n" - AS_STR "Use the peers AS-number\n" "Number of times to insert\n") { @@ -6290,6 +6286,15 @@ DEFUN_YANG (no_set_aspath_prepend, return nb_cli_apply_changes(vty, NULL); } +ALIAS_YANG (no_set_aspath_prepend, + no_set_aspath_prepend_as_cmd, + "no set as-path prepend ASNUM...", + NO_STR + SET_STR + "Transform BGP AS_PATH attribute\n" + "Prepend to the as-path\n" + AS_STR) + DEFUN_YANG (set_aspath_exclude, set_aspath_exclude_cmd, "set as-path exclude ASNUM...", @@ -7966,7 +7971,8 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &set_aspath_exclude_access_list_cmd); install_element(RMAP_NODE, &set_aspath_replace_asn_cmd); install_element(RMAP_NODE, &set_aspath_replace_access_list_cmd); - install_element(RMAP_NODE, &no_set_aspath_prepend_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_last_as_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_as_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_access_list_cmd); diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c index 3d04dc2..755777c 100644 --- a/bgpd/bgp_snmp_bgp4.c +++ b/bgpd/bgp_snmp_bgp4.c @@ -401,7 +401,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], /* Set OID offset for prefix. */ offset = name + v->namelen; oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix); - offset++; + offset += IN_ADDR_SIZE; /* Prefix length. */ addr->prefixlen = *offset; @@ -497,7 +497,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], offset = name + v->namelen; oid_copy_in_addr(offset, &rn_p->u.prefix4); - offset++; + offset += IN_ADDR_SIZE; *offset = rn_p->prefixlen; offset++; oid_copy_in_addr(offset, diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 267a756..9d62265 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -304,15 +304,16 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp, } if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv && adj->adv->baa) { - route_vty_out_tmp( - vty, dest, dest_p, adj->adv->baa->attr, - SUBGRP_SAFI(subgrp), 0, NULL, false); + route_vty_out_tmp(vty, bgp, dest, dest_p, + adj->adv->baa->attr, + SUBGRP_SAFI(subgrp), 0, NULL, + false); output_count++; } if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) { - route_vty_out_tmp(vty, dest, dest_p, adj->attr, - SUBGRP_SAFI(subgrp), 0, NULL, - false); + route_vty_out_tmp(vty, bgp, dest, dest_p, + adj->attr, SUBGRP_SAFI(subgrp), + 0, NULL, false); output_count++; } } diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index 8fe24eb..2470fb8 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -191,7 +191,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, } rd_header = 0; } - route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm), + route_vty_out_tmp(vty, bgp, rm, bgp_dest_get_prefix(rm), attr, safi, use_json, json_routes, false); output_count++; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 87f2e55..fe29662 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -3187,12 +3187,12 @@ static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS) struct bgp *bgp = bgp_get_default(); const char *loc_name = bgp->srv6_locator_name; - if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) - return -1; - if (!bgp || !bgp->srv6_enabled) return 0; + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) + return -1; + if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0) return -1; @@ -3210,6 +3210,9 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) struct in6_addr *tovpn_sid; struct prefix_ipv6 tmp_prefi; + if (!bgp) + return 0; + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) return -1; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1a03a06..d6d874b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1446,11 +1446,11 @@ int bgp_peer_gr_init(struct peer *peer) { /* PEER_GLOBAL_INHERIT Mode */ /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ - { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, + { PEER_GR, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ - { PEER_DISABLE, bgp_peer_gr_action}, { PEER_INVALID, NULL }, + { PEER_DISABLE, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ - { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } + { PEER_HELPER, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL } } }; memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM, @@ -1473,6 +1473,29 @@ static void bgp_srv6_init(struct bgp *bgp) static void bgp_srv6_cleanup(struct bgp *bgp) { + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) { + if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) + srv6_locator_chunk_free( + &bgp->vpn_policy[afi].tovpn_sid_locator); + if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); + if (bgp->vpn_policy[afi].tovpn_sid != NULL) { + sid_unregister(bgp, bgp->vpn_policy[afi].tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_sid); + } + } + + if (bgp->tovpn_sid_locator != NULL) + srv6_locator_chunk_free(&bgp->tovpn_sid_locator); + if (bgp->tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); + if (bgp->tovpn_sid != NULL) { + sid_unregister(bgp, bgp->tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_sid); + } + if (bgp->srv6_locator_chunks) list_delete(&bgp->srv6_locator_chunks); if (bgp->srv6_functions) @@ -1537,10 +1560,10 @@ struct peer *peer_new(struct bgp *bgp) SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) - SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS); + peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS); if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY)) - SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_SOFT_VERSION); + peer_flag_set(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION); SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN); SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN); @@ -4097,18 +4120,6 @@ void bgp_free(struct bgp *bgp) if (bgp->vpn_policy[afi].tovpn_rd_pretty) XFREE(MTYPE_BGP_NAME, bgp->vpn_policy[afi].tovpn_rd_pretty); - if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) - srv6_locator_chunk_free( - &bgp->vpn_policy[afi].tovpn_sid_locator); - if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL) - XFREE(MTYPE_BGP_SRV6_SID, - bgp->vpn_policy[afi] - .tovpn_zebra_vrf_sid_last_sent); - if (bgp->vpn_policy[afi].tovpn_sid != NULL) { - sid_unregister(bgp, bgp->vpn_policy[afi].tovpn_sid); - XFREE(MTYPE_BGP_SRV6_SID, - bgp->vpn_policy[afi].tovpn_sid); - } } bgp_srv6_cleanup(bgp); bgp_confederation_id_unset(bgp); diff --git a/configure.ac b/configure.ac index 0a40661..4762306 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ([2.69]) -AC_INIT([frr], [10.0], [https://github.com/frrouting/frr/issues]) +AC_INIT([frr], [10.0.1], [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST([PACKAGE_URL]) PACKAGE_FULLNAME="FRRouting" diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 53dc551..99d2a8c 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -425,6 +425,11 @@ Route Selection Disabled by default. +.. clicmd:: bgp bestpath med missing-as-worst + + If the paths MED value is missing and this command is configured + then treat it as the worse possible value that it can be. + .. clicmd:: maximum-paths (1-128) Sets the maximum-paths value used for ecmp calculations for this diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 80a6a27..b19bb9d 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -211,7 +211,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end. messages. This is enabled by default. 'no' form of this command is used to restrict processing of unicast bsm messages on this interface. -.. clicmd:: ip pim drpriority (1-4294967295) +.. clicmd:: ip pim drpriority (0-4294967295) Set the DR Priority for the interface. This command is useful to allow the user to influence what node becomes the DR for a lan segment. diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst index d550c8e..b8567e4 100644 --- a/doc/user/pimv6.rst +++ b/doc/user/pimv6.rst @@ -135,7 +135,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end. command will not do anything if you do not have the underlying ability of a mlag implementation. -.. clicmd:: ipv6 pim drpriority (1-4294967295) +.. clicmd:: ipv6 pim drpriority (0-4294967295) Set the DR Priority for the interface. This command is useful to allow the user to influence what node becomes the DR for a lan segment. diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 7a4b45a..3b3e1fd 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -703,6 +703,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree, } else { /* vertex->d_N > cost */ /* f) */ isis_vertex_queue_delete(&spftree->tents, vertex); + hash_release(spftree->prefix_sids, vertex); isis_vertex_del(vertex); } } @@ -808,6 +809,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, /* 4) */ } else { isis_vertex_queue_delete(&spftree->tents, vertex); + hash_release(spftree->prefix_sids, vertex); isis_vertex_del(vertex); } } diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index 2b0a58b..93ae8c6 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -8016,7 +8016,6 @@ void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs, apply_mask_ipv4(&r->prefix); if (pcfgs) { - r->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH); for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { struct isis_prefix_sid *psid; struct sr_prefix_cfg *pcfg = pcfgs[i]; @@ -8026,6 +8025,10 @@ void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs, psid = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*psid)); isis_sr_prefix_cfg2subtlv(pcfg, external, psid); + + if (!r->subtlvs) + r->subtlvs = isis_alloc_subtlvs( + ISIS_CONTEXT_SUBTLV_IP_REACH); append_item(&r->subtlvs->prefix_sids, (struct isis_item *)psid); } @@ -8044,7 +8047,6 @@ void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid, memcpy(&r->prefix, dest, sizeof(*dest)); apply_mask_ipv6(&r->prefix); if (pcfgs) { - r->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH); for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { struct isis_prefix_sid *psid; struct sr_prefix_cfg *pcfg = pcfgs[i]; @@ -8054,6 +8056,10 @@ void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid, psid = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*psid)); isis_sr_prefix_cfg2subtlv(pcfg, external, psid); + + if (!r->subtlvs) + r->subtlvs = isis_alloc_subtlvs( + ISIS_CONTEXT_SUBTLV_IPV6_REACH); append_item(&r->subtlvs->prefix_sids, (struct isis_item *)psid); } diff --git a/lib/command.c b/lib/command.c index fa26072..8f780d0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1356,7 +1356,7 @@ DEFUN (disable, } /* Down vty node level. */ -DEFUN (config_exit, +DEFUN_YANG (config_exit, config_exit_cmd, "exit", "Exit current mode and down to previous mode\n") diff --git a/lib/libfrr.c b/lib/libfrr.c index 9e47205..2861ebe 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -957,8 +957,6 @@ static void frr_daemonize(void) } close(fds[1]); - nb_terminate(); - yang_terminate(); frr_daemon_wait(fds[0]); } diff --git a/lib/nexthop.c b/lib/nexthop.c index 4ddb53c..243b52d 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -1150,11 +1150,7 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea, return -1; } -bool nexthop_is_ifindex_type(const struct nexthop *nh) +bool nexthop_is_blackhole(const struct nexthop *nh) { - if (nh->type == NEXTHOP_TYPE_IFINDEX || - nh->type == NEXTHOP_TYPE_IPV4_IFINDEX || - nh->type == NEXTHOP_TYPE_IPV6_IFINDEX) - return true; - return false; + return nh->type == NEXTHOP_TYPE_BLACKHOLE; } diff --git a/lib/nexthop.h b/lib/nexthop.h index bed6447..958d06a 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -240,8 +240,8 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, struct nexthop *rparent); -/* Check nexthop of IFINDEX type */ -extern bool nexthop_is_ifindex_type(const struct nexthop *nh); +/* Is this nexthop a blackhole? */ +extern bool nexthop_is_blackhole(const struct nexthop *nh); /* * Parse one or more backup index values, as comma-separated numbers, diff --git a/lib/resolver.c b/lib/resolver.c index d8245e3..901ccf8 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -104,7 +104,7 @@ static void resolver_cb_timeout(struct event *t) { struct resolver_state *r = EVENT_ARG(t); - ares_process(r->channel, NULL, NULL); + ares_process_fd(r->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); resolver_update_timeouts(r); } @@ -179,7 +179,56 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, resolver_fd_drop_maybe(resfd); } +#if (ARES_VERSION >= 0x011c00) +static void ares_address_cb(void *arg, int status, int timeouts, + struct ares_addrinfo *result) +{ + struct resolver_query *query = (struct resolver_query *)arg; + union sockunion addr[16]; + void (*callback)(struct resolver_query *q, const char *err, int ret, + union sockunion *s); + size_t i; + struct ares_addrinfo_node *node; + callback = query->callback; + query->callback = NULL; + + if (status != ARES_SUCCESS) { + if (resolver_debug) + zlog_debug("[%p] Resolving failed (%s)", + query, ares_strerror(status)); + + callback(query, ares_strerror(status), -1, NULL); + if (result) + ares_freeaddrinfo(result); + return; + } + + + node = result->nodes; + for (i = 0; i < array_size(addr) && node; i++) { + memset(&addr[i], 0, sizeof(addr[i])); + addr[i].sa.sa_family = node->ai_family; + switch (node->ai_family) { + case AF_INET: + memcpy(&addr[i].sin.sin_addr, node->ai_addr, + node->ai_addrlen); + break; + case AF_INET6: + memcpy(&addr[i].sin6.sin6_addr, node->ai_addr, + node->ai_addrlen); + break; + } + node = node->ai_next; + } + + if (resolver_debug) + zlog_debug("[%p] Resolved with %d results", query, (int)i); + + callback(query, NULL, i, &addr[0]); + ares_freeaddrinfo(result); +} +#else static void ares_address_cb(void *arg, int status, int timeouts, struct hostent *he) { @@ -222,6 +271,8 @@ static void ares_address_cb(void *arg, int status, int timeouts, callback(query, NULL, i, &addr[0]); } +#endif + static void resolver_cb_literal(struct event *t) { struct resolver_query *query = EVENT_ARG(t); @@ -240,6 +291,14 @@ void resolver_resolve(struct resolver_query *query, int af, vrf_id_t vrf_id, int, union sockunion *)) { int ret; +#if (ARES_VERSION >= 0x011c00) + struct ares_addrinfo_hints hints = { + .ai_flags = 0, + .ai_family = af, + .ai_socktype = 0, /* any of SOCK_STREAM or SOCK_DGRAM */ + .ai_protocol = 0 /* any protocol */ + }; +#endif if (hostname == NULL) return; @@ -278,7 +337,13 @@ void resolver_resolve(struct resolver_query *query, int af, vrf_id_t vrf_id, __func__, vrf_id, safe_strerror(errno)); return; } + +#if (ARES_VERSION >= 0x011c00) + ares_getaddrinfo(state.channel, hostname, NULL, &hints, ares_address_cb, + query); +#else ares_gethostbyname(state.channel, hostname, af, ares_address_cb, query); +#endif ret = vrf_switchback_to_initial(); if (ret < 0) flog_err_sys(EC_LIB_SOCKET, diff --git a/lib/vrf.c b/lib/vrf.c index e907626..31632a8 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -636,7 +636,7 @@ int vrf_configure_backend(enum vrf_backend_type backend) } /* vrf CLI commands */ -DEFUN_NOSH(vrf_exit, +DEFUN_YANG_NOSH (vrf_exit, vrf_exit_cmd, "exit-vrf", "Exit current mode and down to previous mode\n") diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 04dad2a..e83ce7f 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -19,7 +19,8 @@ DEFINE_MTYPE_STATIC(NHRPD, NHRP_SHORTCUT, "NHRP shortcut"); static struct route_table *shortcut_rib[AFI_MAX]; static void nhrp_shortcut_do_purge(struct event *t); -static void nhrp_shortcut_delete(struct nhrp_shortcut *s); +static void nhrp_shortcut_delete(struct nhrp_shortcut *s, + void *arg __attribute__((__unused__))); static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s); static void nhrp_shortcut_check_use(struct nhrp_shortcut *s) @@ -72,7 +73,7 @@ static void nhrp_shortcut_cache_notify(struct notifier_block *n, s->route_installed = 0; } if (cmd == NOTIFY_CACHE_DELETE) - nhrp_shortcut_delete(s); + nhrp_shortcut_delete(s, NULL); break; } } @@ -132,7 +133,8 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s, } } -static void nhrp_shortcut_delete(struct nhrp_shortcut *s) +static void nhrp_shortcut_delete(struct nhrp_shortcut *s, + void *arg __attribute__((__unused__))) { struct route_node *rn; afi_t afi = family2afi(PREFIX_FAMILY(s->p)); @@ -158,7 +160,7 @@ static void nhrp_shortcut_do_purge(struct event *t) { struct nhrp_shortcut *s = EVENT_ARG(t); s->t_timer = NULL; - nhrp_shortcut_delete(s); + nhrp_shortcut_delete(s, NULL); } static struct nhrp_shortcut *nhrp_shortcut_get(struct prefix *p) @@ -469,6 +471,8 @@ void nhrp_shortcut_init(void) void nhrp_shortcut_terminate(void) { + nhrp_shortcut_foreach(AFI_IP, nhrp_shortcut_delete, NULL); + nhrp_shortcut_foreach(AFI_IP6, nhrp_shortcut_delete, NULL); route_table_finish(shortcut_rib[AFI_IP]); route_table_finish(shortcut_rib[AFI_IP6]); } diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f4202a4..ef780af 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -1350,9 +1350,10 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) * does not match with the new entry then add the new route */ if (old_entry_updated == false) { - if ((old == NULL) || (old->type != route->type) - || (old->path.type != route->path.type) - || (old->path.cost != route->path.cost)) + if ((old == NULL) || (old->type != route->type) || + (old->path.type != route->path.type) || + (old->path.cost != route->path.cost) || + (old->path.router_bits != route->path.router_bits)) add_route = true; } diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index be1042f..42ea048 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -176,6 +176,7 @@ static int ospf6_extract_grace_lsa_fields(struct ospf6_lsa *lsa, return OSPF6_FAILURE; break; default: + sum += TLV_SIZE(tlvh); if (IS_DEBUG_OSPF6_GR) zlog_debug("%s, Ignoring unknown TLV type:%d", __func__, ntohs(tlvh->type)); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index b9dace2..7f813ce 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -455,9 +455,9 @@ void ospf6_interface_connected_route_update(struct interface *ifp) } } - if (oi->state == OSPF6_INTERFACE_LOOPBACK || - oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT || - oi->state == OSPF6_INTERFACE_POINTTOPOINT) { + if (oi->type == OSPF_IFTYPE_LOOPBACK || + oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF_IFTYPE_POINTOPOINT) { struct ospf6_route *la_route; la_route = ospf6_route_create(oi->area->ospf6); @@ -475,10 +475,10 @@ void ospf6_interface_connected_route_update(struct interface *ifp) ospf6_route_add(la_route, oi->route_connected); } - if (oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT && + if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT && !oi->p2xp_connected_pfx_include) continue; - if (oi->state == OSPF6_INTERFACE_POINTTOPOINT && + if (oi->type == OSPF_IFTYPE_POINTOPOINT && oi->p2xp_connected_pfx_exclude) continue; @@ -792,8 +792,8 @@ void interface_up(struct event *thread) return; } - /* Recompute cost */ - ospf6_interface_recalculate_cost(oi); + /* Recompute cost & update connected LSAs */ + ospf6_interface_force_recalculate_cost(oi); /* if already enabled, do nothing */ if (oi->state > OSPF6_INTERFACE_DOWN) { @@ -1395,10 +1395,17 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id, } /* show interface */ -DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd, +DEFUN(show_ipv6_ospf6_interface, + show_ipv6_ospf6_interface_ifname_cmd, "show ipv6 ospf6 [vrf ] interface [IFNAME] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR) + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + IFNAME_STR + JSON_STR) { int idx_ifname = 4; int intf_idx = 5; @@ -1598,11 +1605,18 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc, } /* show interface */ -DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, +DEFUN(show_ipv6_ospf6_interface_traffic, + show_ipv6_ospf6_interface_traffic_cmd, "show ipv6 ospf6 [vrf ] interface traffic [IFNAME] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR - "Protocol Packet counters\n" IFNAME_STR JSON_STR) + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + "Protocol Packet counters\n" + IFNAME_STR + JSON_STR) { struct ospf6 *ospf6; struct listnode *node; @@ -1631,17 +1645,21 @@ DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, DEFUN(show_ipv6_ospf6_interface_ifname_prefix, show_ipv6_ospf6_interface_ifname_prefix_cmd, - "show ipv6 ospf6 [vrf ] interface IFNAME prefix\ - [<\ - detail\ - | []\ - >] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR IFNAME_STR + "show ipv6 ospf6 [vrf ] interface IFNAME prefix " + "[ []>] [json]", + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR IFNAME_STR "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" JSON_STR) + "Display details of the prefixes\n" + OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR + OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" + JSON_STR) { int idx_ifname = 4; int idx_prefix = 6; @@ -1693,17 +1711,23 @@ DEFUN(show_ipv6_ospf6_interface_ifname_prefix, return CMD_SUCCESS; } -DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, - "show ipv6 ospf6 [vrf ] interface prefix\ - [<\ - detail\ - | []\ - >] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" JSON_STR) +DEFUN(show_ipv6_ospf6_interface_prefix, + show_ipv6_ospf6_interface_prefix_cmd, + "show ipv6 ospf6 [vrf ] interface prefix " + "[ []>] [json]", + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" + OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR + OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" + JSON_STR) { struct vrf *vrf = NULL; int idx_prefix = 5; @@ -1802,11 +1826,14 @@ void ospf6_interface_stop(struct ospf6_interface *oi) } /* interface variable set command */ -DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd, - "ipv6 ospf6 area ", - IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN (ipv6_ospf6_area, + ipv6_ospf6_area_cmd, + "ipv6 ospf6 area ", + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1840,11 +1867,15 @@ DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd, return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd, - "no ipv6 ospf6 area []", - NO_STR IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN (no_ipv6_ospf6_area, + no_ipv6_ospf6_area_cmd, + "no ipv6 ospf6 area []", + NO_STR + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1864,9 +1895,14 @@ DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", - IP6_STR OSPF6_STR "Interface MTU\n" - "OSPFv3 Interface MTU\n") +DEFUN (ipv6_ospf6_ifmtu, + ipv6_ospf6_ifmtu_cmd, + "ipv6 ospf6 ifmtu (1-65535)", + IP6_STR + OSPF6_STR + "Interface MTU\n" + "OSPFv3 Interface MTU\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1915,10 +1951,15 @@ DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd, - "no ipv6 ospf6 ifmtu [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Interface MTU\n" - "OSPFv3 Interface MTU\n") +DEFUN (no_ipv6_ospf6_ifmtu, + no_ipv6_ospf6_ifmtu_cmd, + "no ipv6 ospf6 ifmtu [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interface MTU\n" + "OSPFv3 Interface MTU\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1956,9 +1997,13 @@ DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)", - IP6_STR OSPF6_STR "Interface cost\n" - "Outgoing metric of this interface\n") +DEFUN (ipv6_ospf6_cost, + ipv6_ospf6_cost_cmd, + "ipv6 ospf6 cost (1-65535)", + IP6_STR + OSPF6_STR + "Interface cost\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1989,10 +2034,14 @@ DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, - "no ipv6 ospf6 cost [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n" - "Outgoing metric of this interface\n") +DEFUN (no_ipv6_ospf6_cost, + no_ipv6_ospf6_cost_cmd, + "no ipv6 ospf6 cost [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Calculate interface cost from bandwidth\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2010,11 +2059,12 @@ DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, return CMD_SUCCESS; } -DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd, - "auto-cost reference-bandwidth (1-4294967)", - "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN (auto_cost_reference_bandwidth, + auto_cost_reference_bandwidth_cmd, + "auto-cost reference-bandwidth (1-4294967)", + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); int idx_number = 2; @@ -2041,11 +2091,13 @@ DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd, return CMD_SUCCESS; } -DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd, - "no auto-cost reference-bandwidth [(1-4294967)]", - NO_STR "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN (no_auto_cost_reference_bandwidth, + no_auto_cost_reference_bandwidth_cmd, + "no auto-cost reference-bandwidth [(1-4294967)]", + NO_STR + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); struct ospf6_area *oa; @@ -2064,10 +2116,11 @@ DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd, } -DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd, - "write-multiplier (1-100)", - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN (ospf6_write_multiplier, + ospf6_write_multiplier_cmd, + "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); uint32_t write_oi_count; @@ -2082,10 +2135,12 @@ DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd, return CMD_SUCCESS; } -DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd, - "no write-multiplier (1-100)", - NO_STR "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN (no_ospf6_write_multiplier, + no_ospf6_write_multiplier_cmd, + "no write-multiplier (1-100)", + NO_STR + "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); @@ -2093,9 +2148,13 @@ DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, - "ipv6 ospf6 hello-interval (1-65535)", - IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) +DEFUN (ipv6_ospf6_hellointerval, + ipv6_ospf6_hellointerval_cmd, + "ipv6 ospf6 hello-interval (1-65535)", + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2123,15 +2182,23 @@ DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_hellointerval, no_ipv6_ospf6_hellointerval_cmd, - "no ipv6 ospf6 hello-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) +ALIAS (ipv6_ospf6_hellointerval, + no_ipv6_ospf6_hellointerval_cmd, + "no ipv6 ospf6 hello-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, - "ipv6 ospf6 dead-interval (1-65535)", - IP6_STR OSPF6_STR - "Interval time after which a neighbor is declared down\n" SECONDS_STR) +DEFUN (ipv6_ospf6_deadinterval, + ipv6_ospf6_deadinterval_cmd, + "ipv6 ospf6 dead-interval (1-65535)", + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2149,16 +2216,23 @@ DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_deadinterval, no_ipv6_ospf6_deadinterval_cmd, - "no ipv6 ospf6 dead-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR - "Interval time after which a neighbor is declared down\n" SECONDS_STR) +ALIAS (ipv6_ospf6_deadinterval, + no_ipv6_ospf6_deadinterval_cmd, + "no ipv6 ospf6 dead-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) -DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, +DEFPY(ipv6_ospf6_gr_hdelay, + ipv6_ospf6_gr_hdelay_cmd, "ipv6 ospf6 graceful-restart hello-delay (1-1800)", - IP6_STR OSPF6_STR "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + IP6_STR + OSPF6_STR + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2173,11 +2247,15 @@ DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, return CMD_SUCCESS; } -DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, +DEFPY(no_ipv6_ospf6_gr_hdelay, + no_ipv6_ospf6_gr_hdelay_cmd, "no ipv6 ospf6 graceful-restart hello-delay [(1-1800)]", - NO_STR IP6_STR OSPF6_STR "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + NO_STR + IP6_STR + OSPF6_STR + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2194,9 +2272,13 @@ DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, } /* interface variable set command */ -DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, - "ipv6 ospf6 transmit-delay (1-3600)", - IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) +DEFUN (ipv6_ospf6_transmitdelay, + ipv6_ospf6_transmitdelay_cmd, + "ipv6 ospf6 transmit-delay (1-3600)", + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2214,15 +2296,23 @@ DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_transmitdelay, no_ipv6_ospf6_transmitdelay_cmd, - "no ipv6 ospf6 transmit-delay [(1-3600)]", - NO_STR IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) +ALIAS (ipv6_ospf6_transmitdelay, + no_ipv6_ospf6_transmitdelay_cmd, + "no ipv6 ospf6 transmit-delay [(1-3600)]", + NO_STR + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, - "ipv6 ospf6 retransmit-interval (1-65535)", - IP6_STR OSPF6_STR - "Time between retransmitting lost link state advertisements\n" SECONDS_STR) +DEFUN (ipv6_ospf6_retransmitinterval, + ipv6_ospf6_retransmitinterval_cmd, + "ipv6 ospf6 retransmit-interval (1-65535)", + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2240,16 +2330,23 @@ DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_retransmitinterval, no_ipv6_ospf6_retransmitinterval_cmd, - "no ipv6 ospf6 retransmit-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR - "Time between retransmitting lost link state advertisements\n" SECONDS_STR) +ALIAS (ipv6_ospf6_retransmitinterval, + no_ipv6_ospf6_retransmitinterval_cmd, + "no ipv6 ospf6 retransmit-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, - "ipv6 ospf6 priority (0-255)", - IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n") +DEFUN (ipv6_ospf6_priority, + ipv6_ospf6_priority_cmd, + "ipv6 ospf6 priority (0-255)", + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2275,15 +2372,22 @@ DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_priority, no_ipv6_ospf6_priority_cmd, - "no ipv6 ospf6 priority [(0-255)]", - NO_STR IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n") +ALIAS (ipv6_ospf6_priority, + no_ipv6_ospf6_priority_cmd, + "no ipv6 ospf6 priority [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") -DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, - "ipv6 ospf6 instance-id (0-255)", - IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n") +DEFUN (ipv6_ospf6_instance, + ipv6_ospf6_instance_cmd, + "ipv6 ospf6 instance-id (0-255)", + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2301,14 +2405,22 @@ DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_instance, no_ipv6_ospf6_instance_cmd, - "no ipv6 ospf6 instance-id [(0-255)]", - NO_STR IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n") +ALIAS (ipv6_ospf6_instance, + no_ipv6_ospf6_instance_cmd, + "no ipv6 ospf6 instance-id [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") -DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", - IP6_STR OSPF6_STR - "Passive interface; no adjacency will be formed on this interface\n") +DEFUN (ipv6_ospf6_passive, + ipv6_ospf6_passive_cmd, + "ipv6 ospf6 passive", + IP6_STR + OSPF6_STR + "Passive interface; no adjacency will be formed on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2334,9 +2446,14 @@ DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive", - NO_STR IP6_STR OSPF6_STR - "passive interface: No Adjacency will be formed on this I/F\n") +DEFUN (no_ipv6_ospf6_passive, + no_ipv6_ospf6_passive_cmd, + "no ipv6 ospf6 passive", + NO_STR + IP6_STR + OSPF6_STR + "passive interface: No Adjacency will be formed on this I/F\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2359,8 +2476,13 @@ DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive", return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore", - IP6_STR OSPF6_STR "Disable MTU mismatch detection on this interface\n") +DEFUN (ipv6_ospf6_mtu_ignore, + ipv6_ospf6_mtu_ignore_cmd, + "ipv6 ospf6 mtu-ignore", + IP6_STR + OSPF6_STR + "Disable MTU mismatch detection on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2376,10 +2498,14 @@ DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd, - "no ipv6 ospf6 mtu-ignore", - NO_STR IP6_STR OSPF6_STR - "Disable MTU mismatch detection on this interface\n") +DEFUN (no_ipv6_ospf6_mtu_ignore, + no_ipv6_ospf6_mtu_ignore_cmd, + "no ipv6 ospf6 mtu-ignore", + NO_STR + IP6_STR + OSPF6_STR + "Disable MTU mismatch detection on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2395,11 +2521,14 @@ DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd, +DEFUN(ipv6_ospf6_advertise_prefix_list, + ipv6_ospf6_advertise_prefix_list_cmd, "ipv6 ospf6 advertise prefix-list PREFIXLIST6_NAME", - IP6_STR OSPF6_STR "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n") + IP6_STR + OSPF6_STR + "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_word = 4; @@ -2432,9 +2561,12 @@ DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd, DEFUN(no_ipv6_ospf6_advertise_prefix_list, no_ipv6_ospf6_advertise_prefix_list_cmd, "no ipv6 ospf6 advertise prefix-list [PREFIXLIST6_NAME]", - NO_STR IP6_STR OSPF6_STR "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n") + NO_STR + IP6_STR + OSPF6_STR + "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2462,12 +2594,16 @@ DEFUN(no_ipv6_ospf6_advertise_prefix_list, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd, - "ipv6 ospf6 network ", - IP6_STR OSPF6_STR "Network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n" - "Specify OSPF6 point-to-multipoint network\n") +DEFUN (ipv6_ospf6_network, + ipv6_ospf6_network_cmd, + "ipv6 ospf6 network ", + IP6_STR + OSPF6_STR + "Network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 point-to-multipoint network\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_network = 3; @@ -2506,11 +2642,16 @@ DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd, return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, - "no ipv6 ospf6 network []", - NO_STR IP6_STR OSPF6_STR "Set default network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n") +DEFUN (no_ipv6_ospf6_network, + no_ipv6_ospf6_network_cmd, + "no ipv6 ospf6 network []", + NO_STR + IP6_STR + OSPF6_STR + "Set default network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 point-to-multipoint network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2537,11 +2678,14 @@ DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd, - "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Only form adjacencies with explicitly configured neighbors\n") +DEFPY (ipv6_ospf6_p2xp_only_cfg_neigh, + ipv6_ospf6_p2xp_only_cfg_neigh_cmd, + "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Only form adjacencies with explicitly configured neighbors\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2561,11 +2705,14 @@ DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd, - "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Do not send multicast hellos\n") +DEFPY (ipv6_ospf6_p2xp_no_multicast_hello, + ipv6_ospf6_p2xp_no_multicast_hello_cmd, + "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Do not send multicast hellos\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2585,13 +2732,16 @@ DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd, - "[no] ipv6 ospf6 p2p-p2mp connected-prefixes ", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Adjust handling of directly connected prefixes\n" - "Advertise prefixes and own /128 (default for PtP)\n" - "Ignore, only advertise own /128 (default for PtMP)\n") +DEFPY (ipv6_ospf6_p2xp_connected_pfx, + ipv6_ospf6_p2xp_connected_pfx_cmd, + "[no] ipv6 ospf6 p2p-p2mp connected-prefixes ", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n" + "Advertise prefixes and own /128 (default for PtP)\n" + "Ignore, only advertise own /128 (default for PtMP)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2619,11 +2769,14 @@ DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_p2xp_connected_pfx, no_ipv6_ospf6_p2xp_connected_pfx_cmd, - "no ipv6 ospf6 p2p-p2mp connected-prefixes", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Adjust handling of directly connected prefixes\n") +ALIAS (ipv6_ospf6_p2xp_connected_pfx, + no_ipv6_ospf6_p2xp_connected_pfx_cmd, + "no ipv6 ospf6 p2p-p2mp connected-prefixes", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n") static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) @@ -2873,9 +3026,16 @@ void ospf6_interface_clear(struct interface *ifp) } /* Clear interface */ -DEFUN(clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd, - "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", - CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR) +DEFUN (clear_ipv6_ospf6_interface, + clear_ipv6_ospf6_interface_cmd, + "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", + CLEAR_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + INTERFACE_STR + IFNAME_STR + ) { struct vrf *vrf; int idx_vrf = 3; @@ -2916,16 +3076,26 @@ void install_element_ospf6_clear_interface(void) install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); } -DEFUN(debug_ospf6_interface, debug_ospf6_interface_cmd, "debug ospf6 interface", - DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") +DEFUN (debug_ospf6_interface, + debug_ospf6_interface_cmd, + "debug ospf6 interface", + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Interface\n" + ) { OSPF6_DEBUG_INTERFACE_ON(); return CMD_SUCCESS; } -DEFUN(no_debug_ospf6_interface, no_debug_ospf6_interface_cmd, - "no debug ospf6 interface", - NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") +DEFUN (no_debug_ospf6_interface, + no_debug_ospf6_interface_cmd, + "no debug ospf6 interface", + NO_STR + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Interface\n" + ) { OSPF6_DEBUG_INTERFACE_OFF(); return CMD_SUCCESS; @@ -2962,9 +3132,11 @@ void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data) DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, ipv6_ospf6_intf_auth_trailer_keychain_cmd, "ipv6 ospf6 authentication keychain KEYCHAIN_NAME", - IP6_STR OSPF6_STR "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + IP6_STR + OSPF6_STR + "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int keychain_idx = 4; @@ -2994,9 +3166,12 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain, no_ipv6_ospf6_intf_auth_trailer_keychain_cmd, "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]", - NO_STR IP6_STR OSPF6_STR "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + NO_STR + IP6_STR + OSPF6_STR + "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -3018,21 +3193,24 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd, +DEFUN(ipv6_ospf6_intf_auth_trailer_key, + ipv6_ospf6_intf_auth_trailer_key_cmd, "ipv6 ospf6 authentication key-id (1-65535) hash-algo " " " "key WORD", - IP6_STR OSPF6_STR "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + IP6_STR + OSPF6_STR + "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int key_id_idx = 4; @@ -3077,17 +3255,20 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_key, "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo " " " "key WORD]", - NO_STR IP6_STR OSPF6_STR "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + NO_STR + IP6_STR + OSPF6_STR + "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index a6089b2..cb65ed2 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -704,10 +704,14 @@ static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost) #include "ospf6d/ospf6_neighbor_clippy.c" #endif -DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n") +DEFPY (ipv6_ospf6_p2xp_neigh, + ipv6_ospf6_p2xp_neigh_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -745,12 +749,16 @@ DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_neigh_cost, ipv6_ospf6_p2xp_neigh_cost_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n" - "Outgoing metric for this neighbor\n" - "Outgoing metric for this neighbor\n") +DEFPY (ipv6_ospf6_p2xp_neigh_cost, + ipv6_ospf6_p2xp_neigh_cost_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n" + "Outgoing metric for this neighbor\n" + "Outgoing metric for this neighbor\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -821,13 +829,16 @@ static void p2xp_unicast_hello_send(struct event *event) ospf6_hello_send_addr(oi, &p2xp_cfg->addr); } -DEFPY(ipv6_ospf6_p2xp_neigh_poll_interval, - ipv6_ospf6_p2xp_neigh_poll_interval_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n" - "Send unicast hellos to neighbor when down\n" - "Unicast hello interval when down (seconds)\n") +DEFPY (ipv6_ospf6_p2xp_neigh_poll_interval, + ipv6_ospf6_p2xp_neigh_poll_interval_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n" + "Send unicast hellos to neighbor when down\n" + "Unicast hello interval when down (seconds)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -1338,13 +1349,18 @@ static void ospf6_neighbor_show_detail_common(struct vty *vty, } } -DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd, +DEFUN(show_ipv6_ospf6_neighbor, + show_ipv6_ospf6_neighbor_cmd, "show ipv6 ospf6 [vrf ] neighbor [] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR "All VRFs\n" "Neighbor list\n" "Display details\n" - "Display DR choices\n" JSON_STR) + "Display DR choices\n" + JSON_STR) { struct ospf6 *ospf6; struct listnode *node; @@ -1413,12 +1429,17 @@ static int ospf6_neighbor_show_common(struct vty *vty, int argc, return CMD_SUCCESS; } -DEFUN(show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd, +DEFUN(show_ipv6_ospf6_neighbor_one, + show_ipv6_ospf6_neighbor_one_cmd, "show ipv6 ospf6 [vrf ] neighbor A.B.C.D [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR "All VRFs\n" "Neighbor list\n" - "Specify Router-ID as IPv4 address notation\n" JSON_STR) + "Specify Router-ID as IPv4 address notation\n" + JSON_STR) { int idx_ipv4 = 4; struct ospf6 *ospf6; @@ -1458,11 +1479,14 @@ void ospf6_neighbor_init(void) &ipv6_ospf6_p2xp_neigh_poll_interval_cmd); } -DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd, - "debug ospf6 neighbor []", - DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN (debug_ospf6_neighbor, + debug_ospf6_neighbor_cmd, + "debug ospf6 neighbor []", + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 3; unsigned char level = 0; @@ -1480,11 +1504,15 @@ DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd, } -DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd, - "no debug ospf6 neighbor []", - NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN (no_debug_ospf6_neighbor, + no_debug_ospf6_neighbor_cmd, + "no debug ospf6 neighbor []", + NO_STR + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 4; unsigned char level = 0; @@ -1502,8 +1530,12 @@ DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd, } -DEFUN(no_debug_ospf6, no_debug_ospf6_cmd, "no debug ospf6", - NO_STR DEBUG_STR OSPF6_STR) +DEFUN (no_debug_ospf6, + no_debug_ospf6_cmd, + "no debug ospf6", + NO_STR + DEBUG_STR + OSPF6_STR) { unsigned int i; diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 2c1d17e..c9486bc 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -287,6 +287,7 @@ extern const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX]; prefix_same(&(ra)->prefix, &(rb)->prefix) && \ (ra)->path.type == (rb)->path.type && \ (ra)->path.cost == (rb)->path.cost && \ + (ra)->path.router_bits == (rb)->path.router_bits && \ (ra)->path.u.cost_e2 == (rb)->path.u.cost_e2 && \ listcount(ra->paths) == listcount(rb->paths) && \ ospf6_route_cmp_nexthops(ra, rb)) diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 0969ae1..173dafb 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -1373,7 +1373,8 @@ static int ospf_ifp_create(struct interface *ifp) (!OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type) || if_is_loopback(ifp))) { SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); - IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + if (!IF_DEF_PARAMS(ifp)->type_cfg) + IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); } ospf = ifp->vrf->info; diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 08a2b11..39dc951 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -57,6 +57,7 @@ struct ospf_if_params { DECLARE_IF_PARAM(struct in_addr, if_area); uint32_t if_area_id_fmt; + bool type_cfg; DECLARE_IF_PARAM(uint8_t, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index fc0c143..4e1f153 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -906,7 +906,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, area = ospf_area_lookup_by_area_id(ospf, *area_id); if (!area) return NULL; - offset++; + offset += IN_ADDR_SIZE; /* Type. */ *type = *offset; @@ -914,7 +914,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, /* LS ID. */ oid2in_addr(offset, IN_ADDR_SIZE, ls_id); - offset++; + offset += IN_ADDR_SIZE; /* Router ID. */ oid2in_addr(offset, IN_ADDR_SIZE, router_id); @@ -971,7 +971,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, } /* Router ID. */ - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; len = offsetlen; @@ -996,11 +996,11 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, /* Fill in value. */ offset = name + v->namelen; oid_copy_in_addr(offset, area_id); - offset++; + offset += IN_ADDR_SIZE; *offset = lsa->data->type; offset++; oid_copy_in_addr(offset, &lsa->data->id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, &lsa->data->adv_router); @@ -1106,7 +1106,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, if (!area) return NULL; - offset++; + offset += IN_ADDR_SIZE; /* Lookup area range. */ oid2in_addr(offset, IN_ADDR_SIZE, range_net); @@ -1135,7 +1135,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, return NULL; do { - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; len = offsetlen; @@ -1157,7 +1157,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, /* Fill in value. */ offset = name + v->namelen; oid_copy_in_addr(offset, area_id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, range_net); return range; @@ -1559,7 +1559,7 @@ static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name, *length = v->namelen + IN_ADDR_SIZE + 1; offset = name + v->namelen; oid_copy_in_addr(offset, ifaddr); - offset++; + offset += IN_ADDR_SIZE; *offset = *ifindex; return oi; } @@ -1703,7 +1703,7 @@ static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name, *length = v->namelen + IN_ADDR_SIZE + 1 + 1; offset = name + v->namelen; oid_copy_in_addr(offset, ifaddr); - offset++; + offset += IN_ADDR_SIZE; *offset = *ifindex; offset++; *offset = OSPF_SNMP_METRIC_VALUE; @@ -2241,7 +2241,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, /* LS ID. */ oid2in_addr(offset, IN_ADDR_SIZE, ls_id); - offset++; + offset += IN_ADDR_SIZE; /* Router ID. */ oid2in_addr(offset, IN_ADDR_SIZE, router_id); @@ -2269,7 +2269,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, oid2in_addr(offset, len, ls_id); - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; /* Router ID. */ @@ -2292,7 +2292,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, *offset = OSPF_AS_EXTERNAL_LSA; offset++; oid_copy_in_addr(offset, &lsa->data->id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, &lsa->data->adv_router); return lsa; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 80ebab3..b1563b5 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1670,6 +1670,11 @@ static struct ls_edge *get_edge(struct ls_ted *ted, struct ls_node_id adv, struct ls_edge *edge; struct ls_attributes *attr; + /* Check that Link ID and Node ID are valid */ + if (IPV4_NET0(link_id.s_addr) || IPV4_NET0(adv.id.ip.addr.s_addr) || + adv.origin != OSPFv2) + return NULL; + /* Search Edge that corresponds to the Link ID */ key.family = AF_INET; IPV4_ADDR_COPY(&key.k.addr, &link_id); @@ -1743,6 +1748,10 @@ static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex, /* Get Corresponding Edge from Link State Data Base */ edge = get_edge(ted, vertex->node->adv, link_data); + if (!edge) { + ote_debug(" |- Found no edge from Link Data. Abort!"); + return; + } attr = edge->attributes; /* re-attached edge to vertex if needed */ @@ -2246,11 +2255,11 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa) } /* Get corresponding Edge from Link State Data Base */ - if (IPV4_NET0(attr.standard.local.s_addr) && !attr.standard.local_id) { - ote_debug(" |- Found no TE Link local address/ID. Abort!"); + edge = get_edge(ted, attr.adv, attr.standard.local); + if (!edge) { + ote_debug(" |- Found no edge from Link local add./ID. Abort!"); return -1; } - edge = get_edge(ted, attr.adv, attr.standard.local); old = edge->attributes; ote_debug(" |- Process Traffic Engineering LSA %pI4 for Edge %pI4", @@ -2456,6 +2465,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa) switch (ntohs(tlvh->type)) { case RI_SR_TLV_SR_ALGORITHM: + if (TLV_BODY_SIZE(tlvh) < 1 || + TLV_BODY_SIZE(tlvh) > ALGORITHM_COUNT) + break; algo = (struct ri_sr_tlv_sr_algorithm *)tlvh; for (int i = 0; i < ntohs(algo->header.length); i++) { @@ -2480,6 +2492,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa) break; case RI_SR_TLV_SRGB_LABEL_RANGE: + if (TLV_BODY_SIZE(tlvh) != RI_SR_TLV_LABEL_RANGE_SIZE) + break; range = (struct ri_sr_tlv_sid_label_range *)tlvh; size = GET_RANGE_SIZE(ntohl(range->size)); lower = GET_LABEL(ntohl(range->lower.value)); @@ -2497,6 +2511,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa) break; case RI_SR_TLV_SRLB_LABEL_RANGE: + if (TLV_BODY_SIZE(tlvh) != RI_SR_TLV_LABEL_RANGE_SIZE) + break; range = (struct ri_sr_tlv_sid_label_range *)tlvh; size = GET_RANGE_SIZE(ntohl(range->size)); lower = GET_LABEL(ntohl(range->lower.value)); @@ -2514,6 +2530,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa) break; case RI_SR_TLV_NODE_MSD: + if (TLV_BODY_SIZE(tlvh) < RI_SR_TLV_NODE_MSD_SIZE) + break; msd = (struct ri_sr_tlv_node_msd *)tlvh; if ((CHECK_FLAG(node->flags, LS_NODE_MSD)) && (node->msd == msd->value)) @@ -2611,6 +2629,7 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa) struct ext_tlv_prefix *ext; struct ext_subtlv_prefix_sid *pref_sid; uint32_t label; + uint16_t len, size; /* Get corresponding Subnet from Link State Data Base */ ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data); @@ -2632,6 +2651,18 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa) ote_debug(" |- Process Extended Prefix LSA %pI4 for subnet %pFX", &lsa->data->id, &pref); + /* + * Check Extended Prefix TLV size against LSA size + * as only one TLV is allowed per LSA + */ + len = TLV_BODY_SIZE(&ext->header); + size = lsa->size - (OSPF_LSA_HEADER_SIZE + TLV_HDR_SIZE); + if (len != size || len <= 0) { + ote_debug(" |- Wrong TLV size: %u instead of %u", + (uint32_t)len, (uint32_t)size); + return -1; + } + /* Initialize TLV browsing */ ls_pref = subnet->ls_pref; pref_sid = (struct ext_subtlv_prefix_sid *)((char *)(ext) + TLV_HDR_SIZE @@ -2737,13 +2768,29 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) lnid.id.ip.area_id = lsa->area->area_id; ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data); edge = get_edge(ted, lnid, ext->link_data); + if (!edge) { + ote_debug(" |- Found no edge from Extended Link Data. Abort!"); + return -1; + } atr = edge->attributes; ote_debug(" |- Process Extended Link LSA %pI4 for edge %pI4", &lsa->data->id, &edge->attributes->standard.local); - /* Initialize TLV browsing */ - len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE; + /* + * Check Extended Link TLV size against LSA size + * as only one TLV is allowed per LSA + */ + len = TLV_BODY_SIZE(&ext->header); + i = lsa->size - (OSPF_LSA_HEADER_SIZE + TLV_HDR_SIZE); + if (len != i || len <= 0) { + ote_debug(" |- Wrong TLV size: %u instead of %u", + (uint32_t)len, (uint32_t)i); + return -1; + } + + /* Initialize subTLVs browsing */ + len -= EXT_TLV_LINK_SIZE; tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE + EXT_TLV_LINK_SIZE); for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) { @@ -2753,6 +2800,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) switch (ntohs(tlvh->type)) { case EXT_SUBTLV_ADJ_SID: + if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_ADJ_SID_SIZE) + break; adj = (struct ext_subtlv_adj_sid *)tlvh; label = CHECK_FLAG(adj->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) @@ -2779,6 +2828,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) break; case EXT_SUBTLV_LAN_ADJ_SID: + if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_LAN_ADJ_SID_SIZE) + break; ladj = (struct ext_subtlv_lan_adj_sid *)tlvh; label = CHECK_FLAG(ladj->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) @@ -2808,6 +2859,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) break; case EXT_SUBTLV_RMT_ITF_ADDR: + if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_RMT_ITF_ADDR_SIZE) + break; rmt = (struct ext_subtlv_rmt_itf_addr *)tlvh; if (CHECK_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR) && IPV4_ADDR_SAME(&atr->standard.remote, diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 93dd12c..4f30d52 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -8267,6 +8267,8 @@ static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str, ospf_nbr_timer_update(oi); } + if (params->fast_hello != OSPF_FAST_HELLO_DEFAULT) + ospf_reset_hello_timer(ifp, addr, false); return CMD_SUCCESS; } @@ -8591,6 +8593,8 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd, IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1; } + IF_DEF_PARAMS(ifp)->type_cfg = true; + if (IF_DEF_PARAMS(ifp)->type == old_type && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn && IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood) @@ -8654,6 +8658,7 @@ DEFUN (no_ip_ospf_network, struct route_node *rn; IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + IF_DEF_PARAMS(ifp)->type_cfg = false; IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0; IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = OSPF_P2MP_DELAY_REFLOOD_DEFAULT; @@ -12211,25 +12216,21 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) do { /* Interface Network print. */ - if (OSPF_IF_PARAM_CONFIGURED(params, type) - && params->type != OSPF_IFTYPE_LOOPBACK) { - if (params->type != ospf_default_iftype(ifp)) { - vty_out(vty, " ip ospf network %s", - ospf_int_type_str - [params->type]); - if (params->type - == OSPF_IFTYPE_POINTOPOINT - && params->ptp_dmvpn) - vty_out(vty, " dmvpn"); - if (params->type == - OSPF_IFTYPE_POINTOMULTIPOINT && - params->p2mp_delay_reflood) - vty_out(vty, " delay-reflood"); - if (params != IF_DEF_PARAMS(ifp) && rn) - vty_out(vty, " %pI4", - &rn->p.u.prefix4); - vty_out(vty, "\n"); - } + if (OSPF_IF_PARAM_CONFIGURED(params, type) && + params->type != OSPF_IFTYPE_LOOPBACK && + params->type_cfg) { + vty_out(vty, " ip ospf network %s", + ospf_int_type_str[params->type]); + if (params->type == OSPF_IFTYPE_POINTOPOINT && + params->ptp_dmvpn) + vty_out(vty, " dmvpn"); + if (params->type == + OSPF_IFTYPE_POINTOMULTIPOINT && + params->p2mp_delay_reflood) + vty_out(vty, " delay-reflood"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); } /* OSPF interface authentication print */ diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 4db1157..ec91270 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -244,7 +244,7 @@ DEFPY (interface_no_ipv6_pim, DEFPY (interface_ipv6_pim_drprio, interface_ipv6_pim_drprio_cmd, - "ipv6 pim drpriority (1-4294967295)", + "ipv6 pim drpriority (0-4294967295)", IPV6_STR PIM_STR "Set the Designated Router Election Priority\n" @@ -255,7 +255,7 @@ DEFPY (interface_ipv6_pim_drprio, DEFPY (interface_no_ipv6_pim_drprio, interface_no_ipv6_pim_drprio_cmd, - "no ipv6 pim drpriority [(1-4294967295)]", + "no ipv6 pim drpriority [(0-4294967295)]", NO_STR IPV6_STR PIM_STR diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index be36a07..c3528e2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3953,7 +3953,7 @@ DEFUN (interface_no_ip_igmp_last_member_query_interval, DEFUN (interface_ip_pim_drprio, interface_ip_pim_drprio_cmd, - "ip pim drpriority (1-4294967295)", + "ip pim drpriority (0-4294967295)", IP_STR PIM_STR "Set the Designated Router Election Priority\n" @@ -3966,7 +3966,7 @@ DEFUN (interface_ip_pim_drprio, DEFUN (interface_no_ip_pim_drprio, interface_no_ip_pim_drprio_cmd, - "no ip pim drpriority [(1-4294967295)]", + "no ip pim drpriority [(0-4294967295)]", NO_STR IP_STR PIM_STR diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index ee318d4..5e50a09 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -287,8 +287,15 @@ int pim_process_no_rp_kat_cmd(struct vty *vty) sizeof(rs_timer_xpath)); /* RFC4601 */ - v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s", - rs_timer_xpath); + /* Check if register suppress time is configured or assigned + * the default register suppress time. + */ + if (yang_dnode_exists(vty->candidate_config->dnode, rs_timer_xpath)) + v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s", + rs_timer_xpath); + else + v = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; + v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT; if (v > UINT16_MAX) v = UINT16_MAX; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index da55189..8f9e410 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -342,6 +342,13 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, ch->sg_str, ch->interface->name); } + /* pim_upstream_update_join_desired looks at up->channel_oil, + * but that's updated from pim_forward_stop(). Need this here + * so we correctly determine join_desired right below. + */ + if (new_state == PIM_IFJOIN_NOINFO) + pim_forward_stop(ch); + /* Record uptime of state transition to/from NOINFO */ @@ -619,7 +626,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg, static void ifjoin_to_noinfo(struct pim_ifchannel *ch) { pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO); - pim_forward_stop(ch); PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags); diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 18a9fb7..2c5ad4d 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -457,8 +457,6 @@ struct gm_source *igmp_get_source_by_addr(struct gm_group *group, listnode_add(group->group_source_list, src); - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); return src; } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 01da699..b149b5a 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -109,12 +109,12 @@ static void pim_reg_stop_upstream(struct pim_instance *pim, up->reg_state = PIM_REG_PRUNE; pim_channel_del_oif(up->channel_oil, pim->regiface, PIM_OIF_FLAG_PROTO_PIM, __func__); - pim_upstream_start_register_stop_timer(up, 0); + pim_upstream_start_register_probe_timer(up); pim_vxlan_update_sg_reg_state(pim, up, false); break; case PIM_REG_JOIN_PENDING: up->reg_state = PIM_REG_PRUNE; - pim_upstream_start_register_stop_timer(up, 0); + pim_upstream_start_register_probe_timer(up); return; } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 556d25b..7417f31 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1687,6 +1687,8 @@ const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str, return state_str; } +static void pim_upstream_start_register_stop_timer(struct pim_upstream *up); + static void pim_upstream_register_stop_timer(struct event *t) { struct pim_interface *pim_ifp; @@ -1734,7 +1736,7 @@ static void pim_upstream_register_stop_timer(struct event *t) return; } up->reg_state = PIM_REG_JOIN_PENDING; - pim_upstream_start_register_stop_timer(up, 1); + pim_upstream_start_register_stop_timer(up); if (((up->channel_oil->cc.lastused / 100) > pim->keep_alive_time) @@ -1752,34 +1754,59 @@ static void pim_upstream_register_stop_timer(struct event *t) } } -void pim_upstream_start_register_stop_timer(struct pim_upstream *up, - int null_register) +static void pim_upstream_start_register_stop_timer(struct pim_upstream *up) { uint32_t time; EVENT_OFF(up->t_rs_timer); - if (!null_register) { - uint32_t lower = (0.5 * router->register_suppress_time); - uint32_t upper = (1.5 * router->register_suppress_time); - time = lower + (frr_weak_random() % (upper - lower + 1)); - /* Make sure we don't wrap around */ - if (time >= router->register_probe_time) - time -= router->register_probe_time; - else - time = 0; - } else - time = router->register_probe_time; + time = router->register_probe_time; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug( - "%s: (S,G)=%s Starting upstream register stop timer %d", - __func__, up->sg_str, time); - } + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%s Starting upstream register stop timer %d", + __func__, up->sg_str, time); event_add_timer(router->master, pim_upstream_register_stop_timer, up, time, &up->t_rs_timer); } +static void pim_upstream_register_probe_timer(struct event *t) +{ + struct pim_upstream *up = EVENT_ARG(t); + + if (!up->rpf.source_nexthop.interface || + !up->rpf.source_nexthop.interface->info) { + if (PIM_DEBUG_PIM_REG) + zlog_debug("cannot send Null register for %pSG, no path to RP", + &up->sg); + } else + pim_null_register_send(up); + + pim_upstream_start_register_stop_timer(up); +} + +void pim_upstream_start_register_probe_timer(struct pim_upstream *up) +{ + uint32_t time; + + EVENT_OFF(up->t_rs_timer); + + uint32_t lower = (0.5 * router->register_suppress_time); + uint32_t upper = (1.5 * router->register_suppress_time); + time = lower + (frr_weak_random() % (upper - lower + 1)); + /* Make sure we don't wrap around */ + if (time >= router->register_probe_time) + time -= router->register_probe_time; + else + time = 0; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%s Starting upstream register stop null probe timer %d", + __func__, up->sg_str, time); + + event_add_timer(router->master, pim_upstream_register_probe_timer, up, + time, &up->t_rs_timer); +} + int pim_upstream_inherited_olist_decide(struct pim_instance *pim, struct pim_upstream *up) { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 62649cd..8b4a35b 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -331,8 +331,7 @@ int pim_upstream_is_sg_rpt(struct pim_upstream *up); void pim_upstream_set_sptbit(struct pim_upstream *up, struct interface *incoming); -void pim_upstream_start_register_stop_timer(struct pim_upstream *up, - int null_register); +void pim_upstream_start_register_probe_timer(struct pim_upstream *up); void pim_upstream_send_join(struct pim_upstream *up); diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index bd9edd1..13d5b86 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -187,7 +187,7 @@ BuildRequires: make BuildRequires: ncurses-devel BuildRequires: readline-devel BuildRequires: texinfo -BuildRequires: libyang-devel >= 2.1.80 +BuildRequires: libyang-devel >= 2.1.128 %if 0%{?rhel} && 0%{?rhel} < 7 #python27-devel is available from ius community repo for RedHat/CentOS 6 BuildRequires: python27-devel @@ -804,7 +804,79 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons %changelog -* Mon Apr 08 2024 Jafar Al-Gharaibeh - %{version} +* Thu Jun 06 2024 Jafar Al-Gharaibeh - %{version} + +* Thu Jun 06 2024 Jafar Al-Gharaibeh - 10.0.1 +- bgpd +- Fix route leaking from the default l3vrf +- Allow using optional table id for negative `no set table x` command +- Apply noop when doing negative commands for gr operations +- Drop newline in json output for `show bgp afi safi json detail` +- Fix `match peer` when switching between ipv4/ipv6/interface +- Fix `no set as-path prepend asnum...` +- Fix crash when deleting the srv6 locator +- Fix display when using `missing-as-worst` +- Fix dynamic peer graceful restart race condition +- Fix logging message when receiving a software version capability +- Fix show run of network route-distinguisher +- Fix srv6 memory leaks spotted by asan +- Fix the order of null check and zapi decode +- Ignore validating the attribute flags if path-attribute is configured +- Inherit `capability software-version` flag from the peer-group +- Inherit `enforce-first-as` flag from the peer-group +- Move srv6 cleanup functions +- Print old/new states of graceful restart fsm +- Revert "Fix pointer arithmetic in bgp snmp module" +- debian, redhat, snapcraft +- Libyang min version is 2.1.128 +- isisd +- Fix heap-after-free with prefix sid +- Fix ip/ipv6 reachability tlvs +- lib +- Check for not being a blackhole route +- Fix exit commands +- Remove nb/yang memory cleanup when daemonizing +- Replace deprecated ares_gethostbyname +- Replace deprecated ares_process() +- nhrpd +- Fix race condition +- Fix core dump on shutdown +- Clean up shortcut cache entries on termination +- ospf6d +- Accept cli `no` for point-to-multipoint +- Fix defun formatting wrecked by clang +- Fix loopback/ptp/ptmp conn. route checks +- Force recalculate on interface_up +- Prevent heap-buffer-overflow with unknown +- Ospfv3 route change comparision fixed for asbr-only change +- ospfd +- Correct opaque lsa extended parser +- Fix the bug where ip_ospf_dead-interval_minimal_hello-multiplier did not reset hello timer +- Protect call to get_edge() in ospf_te.c +- Solved crash in ri parsing with ospf te +- Revert "Fix some dicey pointer arith in snmp module" +- pimd +- Fix crash unconfiguring rp keepalive timer +- Fix dr-priority range +- Fix null register before aging out reg-stop +- Fix order of operations for evaluating join +- Fix crash when mixing ssm/any-source joins +- tests +- Check if ibgp session can drop invalid aigp attribute +- tools +- Frr-reload strip interface vrf ctx line +- Handle seq num for bgp as-path in frr-reload.py +- topotests +- Do not check table version +- vtysh +- Check if bgpd is enabled before installing vtysh commands for rpki +- Fix `show route-map` command when calling via `do` +- Show `ip ospf network ...` even if it's not the same as the interface type +- zebra +- Deny the routes if ip protocol cli refers to an undefined rmap +- Fix encoded dnssl length +- Fix evpn svd based remote nh neigh del +- Fix mpls command * Mon Apr 08 2024 Jafar Al-Gharaibeh - 10.0 - Major highlights: diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index cef02c3..d90236f 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -302,7 +302,7 @@ parts: - libpcre2-8-0 source: https://github.com/CESNET/libyang.git source-type: git - source-tag: v2.1.80 + source-tag: v2.1.128 plugin: cmake configflags: - -DCMAKE_INSTALL_PREFIX:PATH=/usr diff --git a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json index e3703bf..39ed61f 100644 --- a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json +++ b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 3, "routerId": "192.168.255.1", "defaultLocPrf": 100, "localAS": "1.1", diff --git a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json index 1af4ff7..3013317 100644 --- a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json +++ b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 3, "routerId": "192.168.255.2", "defaultLocPrf": 100, "localAS": 65538, diff --git a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg index 7fb9210..dccec7d 100644 --- a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg +++ b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg @@ -1,8 +1,8 @@ neighbor 10.0.0.1 { - router-id 10.0.0.2; - local-address 10.0.0.2; - local-as 65001; - peer-as 65002; + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65001; capability { route-refresh; @@ -12,13 +12,28 @@ neighbor 10.0.0.1 { route 192.168.100.101/32 { atomic-aggregate; community 65001:101; - next-hop 10.0.0.2; + next-hop 10.0.0.254; } route 192.168.100.102/32 { - originator-id 10.0.0.2; + originator-id 10.0.0.254; community 65001:102; - next-hop 10.0.0.2; + next-hop 10.0.0.254; + } + } +} + +neighbor 10.0.0.2 { + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65254; + + static { + route 192.168.100.101/32 { + # AIGP invalid attribute: flagged as transitive + optional. + attribute [0x1a 0xc0 0x00000064]; + next-hop 10.0.0.254; } } } diff --git a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf b/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf deleted file mode 100644 index c96f354..0000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf +++ /dev/null @@ -1,6 +0,0 @@ -! -router bgp 65002 - no bgp ebgp-requires-policy - neighbor 10.0.0.2 remote-as external - neighbor 10.0.0.2 timers 3 10 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/frr.conf b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf new file mode 100644 index 0000000..ae7fbdd --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf @@ -0,0 +1,9 @@ +! +interface r1-eth0 + ip address 10.0.0.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as external + neighbor 10.0.0.254 timers 3 10 +! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf b/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf deleted file mode 100644 index 51a1b26..0000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf +++ /dev/null @@ -1,4 +0,0 @@ -! -interface r1-eth0 - ip address 10.0.0.1/24 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r2/frr.conf b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf new file mode 100644 index 0000000..1dafbdd --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf @@ -0,0 +1,10 @@ +! +interface r2-eth0 + ip address 10.0.0.2/24 +! +router bgp 65254 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as internal + neighbor 10.0.0.254 timers 3 10 + neighbor 10.0.0.254 path-attribute discard 26 +! diff --git a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py index c97cd0b..bd8cd8e 100644 --- a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py +++ b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py @@ -31,10 +31,12 @@ pytestmark = [pytest.mark.bgpd] def build_topo(tgen): r1 = tgen.add_router("r1") - peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1") + r2 = tgen.add_router("r2") + peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.254", defaultRoute="via 10.0.0.1") switch = tgen.add_switch("s1") switch.add_link(r1) + switch.add_link(r2) switch.add_link(peer1) @@ -42,10 +44,10 @@ def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) tgen.start_topology() - router = tgen.gears["r1"] - router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")) - router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf")) - router.start() + for _, (rname, router) in enumerate(tgen.routers().items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() peer = tgen.gears["peer1"] peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env")) @@ -63,6 +65,7 @@ def test_bgp_path_attribute_discard(): pytest.skip(tgen.errors) r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] def _bgp_converge(): output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json detail")) @@ -103,7 +106,7 @@ def test_bgp_path_attribute_discard(): """ configure terminal router bgp - neighbor 10.0.0.2 path-attribute discard 6 8 + neighbor 10.0.0.254 path-attribute discard 6 8 """ ) @@ -139,6 +142,28 @@ def test_bgp_path_attribute_discard(): result is None ), "Failed to discard path attributes (atomic-aggregate, community)" + def _bgp_check_if_aigp_invalid_attribute_discarded(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail")) + expected = { + "routes": { + "192.168.100.101/32": { + "paths": [ + { + "valid": True, + "aigpMetric": None, + } + ], + }, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_check_if_aigp_invalid_attribute_discarded) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) + assert ( + result is None + ), "Failed to discard AIGP invalid path attribute (iBGP session)" + def test_memory_leak(): "Run the memory leak test and report results." diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json index 6fc43e1..f054fab 100644 --- a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json @@ -1,6 +1,5 @@ { "vrfName": "default", - "tableVersion": 2, "routerId": "192.0.2.1", "defaultLocPrf": 100, "localAS": 1, diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json index 538e895..60bcb75 100644 --- a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json @@ -1,6 +1,5 @@ { "vrfName": "default", - "tableVersion": 2, "routerId": "192.0.2.2", "defaultLocPrf": 100, "localAS": 2, diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json index 25b7a86..0fdd3d6 100644 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 2, "routerId": "1.1.1.1", "defaultLocPrf": 100, "localAS": 1, diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json index 2cd47b9..03bbcc0 100644 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json @@ -1,7 +1,6 @@ { "vrfId": 0, "vrfName": "default", - "tableVersion": 2, "routerId": "2.2.2.2", "defaultLocPrf": 100, "localAS": 2, diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py index ef813e9..13c38a9 100644 --- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py +++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py @@ -116,7 +116,7 @@ def test_vrf_route_leak_donna(): "nexthops": [ { "fib": True, - "interfaceName": "lo", + "interfaceName": "dummy0", "vrf": "default", "active": True, }, @@ -214,149 +214,6 @@ def test_vrf_route_leak_eva(): assert result, "BGP VRF EVA check failed:\n{}".format(diff) -def test_vrf_route_leak_donna(): - logger.info("Ensure that routes are leaked back and forth") - tgen = get_topogen() - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - r1 = tgen.gears["r1"] - - # Test DONNA VRF. - expect = { - "10.0.0.0/24": [ - { - "protocol": "connected", - } - ], - "10.0.1.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "EVA", - "vrf": "EVA", - "active": True, - }, - ], - }, - ], - "10.0.2.0/24": [{"protocol": "connected"}], - "10.0.3.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "EVA", - "vrf": "EVA", - "active": True, - }, - ], - }, - ], - "10.0.4.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "lo", - "vrf": "default", - "active": True, - }, - ], - }, - ], - "172.16.101.0/24": [ - { - "protocol": "bgp", - "nexthops": [ - { - "interfaceIndex": 0, - "interfaceName": "unknown", - "vrf": "Unknown", - }, - ], - }, - ], - } - - test_func = partial( - topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect - ) - result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5) - assert result, "BGP VRF DONNA check failed:\n{}".format(diff) - - -def test_vrf_route_leak_eva(): - logger.info("Ensure that routes are leaked back and forth") - tgen = get_topogen() - # Don't run this test if we have any failure. - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - r1 = tgen.gears["r1"] - - # Test EVA VRF. - expect = { - "10.0.0.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "DONNA", - "vrf": "DONNA", - "active": True, - }, - ], - }, - ], - "10.0.1.0/24": [ - { - "protocol": "connected", - } - ], - "10.0.2.0/24": [ - { - "protocol": "bgp", - "selected": True, - "nexthops": [ - { - "fib": True, - "interfaceName": "DONNA", - "vrf": "DONNA", - "active": True, - }, - ], - }, - ], - "10.0.3.0/24": [ - { - "protocol": "connected", - } - ], - "172.16.101.0/24": [ - { - "protocol": "bgp", - "nexthops": [ - { - "interfaceIndex": 0, - "interfaceName": "unknown", - "vrf": "Unknown", - }, - ], - }, - ], - } - def test_vrf_route_leak_default(): logger.info("Ensure that routes are leaked back and forth") diff --git a/tests/topotests/evpn_pim_1/spine/bgp.summ.json b/tests/topotests/evpn_pim_1/spine/bgp.summ.json index 7f37ced..b5b03e8 100644 --- a/tests/topotests/evpn_pim_1/spine/bgp.summ.json +++ b/tests/topotests/evpn_pim_1/spine/bgp.summ.json @@ -2,7 +2,6 @@ "routerId":"192.168.100.1", "as":65001, "vrfName":"default", - "tableVersion":7, "peerCount":2, "peers":{ "192.168.1.2":{ diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json new file mode 100644 index 0000000..a94dd9f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r1-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r1-gre0", + "type": "local", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r1-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r1/nhrp_route.json b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json new file mode 100644 index 0000000..b5f3e29 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r1-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r1-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r1/nhrpd.conf b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf new file mode 100644 index 0000000..ad48ce3 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r1-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r1-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r1/zebra.conf b/tests/topotests/nhrp_redundancy/r1/zebra.conf new file mode 100644 index 0000000..0f11563 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r1/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r1-eth0 + ip address 192.168.1.1/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r1-gre0 + ip address 176.16.1.1/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5 diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json new file mode 100644 index 0000000..91557a1 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r2-gre0", + "type": "local", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r2-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r2-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r2/nhrp_route.json b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json new file mode 100644 index 0000000..f1fa6e5 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r2-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r2-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r2/nhrpd.conf b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf new file mode 100644 index 0000000..4d63f07 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r2-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r2-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r2/zebra.conf b/tests/topotests/nhrp_redundancy/r2/zebra.conf new file mode 100644 index 0000000..1a9c4ff --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r2/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r2-eth0 + ip address 192.168.1.2/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r2-gre0 + ip address 176.16.1.2/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5 diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json new file mode 100644 index 0000000..ef3ab69 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrp_cache.json @@ -0,0 +1,40 @@ +{ + "attr": { + "entriesCount": 3 + }, + "table": [ + { + "interface": "r3-gre0", + "type": "dynamic", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r3-gre0", + "type": "local", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r3-gre0", + "type": "dynamic", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r3/nhrp_route.json b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json new file mode 100644 index 0000000..3d548c0 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrp_route.json @@ -0,0 +1,48 @@ +{ + "176.16.1.4\/32": [ + { + "prefix": "176.16.1.4\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r3-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r3-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r3/nhrpd.conf b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf new file mode 100644 index 0000000..87cc216 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/nhrpd.conf @@ -0,0 +1,9 @@ +!debug nhrp all +nhrp nflog-group 1 +interface r3-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp redirect + tunnel source r3-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r3/zebra.conf b/tests/topotests/nhrp_redundancy/r3/zebra.conf new file mode 100644 index 0000000..980cfbc --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r3/zebra.conf @@ -0,0 +1,12 @@ +ip forwarding +interface r3-eth0 + ip address 192.168.1.3/24 +! +ip route 192.168.2.0/24 192.168.1.6 +interface r3-gre0 + ip address 176.16.1.3/32 + no link-detect + ipv6 nd suppress-ra +! +ip route 4.4.4.0/24 176.16.1.4 +ip route 5.5.5.0/24 176.16.1.5 \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json new file mode 100644 index 0000000..f87ebcf --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_cache.json @@ -0,0 +1,51 @@ +{ + "attr": { + "entriesCount": 4 + }, + "table": [ + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r4-gre0", + "type": "local", + "protocol": "176.16.1.4", + "nbma": "192.168.2.4", + "claimed_nbma": "192.168.2.4", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + }, + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r4-gre0", + "type": "nhs", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json new file mode 100644 index 0000000..4f1faee --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route.json @@ -0,0 +1,71 @@ +{ + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json new file mode 100644 index 0000000..f8efff2 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrp_route_shortcut.json @@ -0,0 +1,118 @@ +{ + "5.5.5.5\/32": [ + { + "prefix": "5.5.5.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "ip": "176.16.1.5", + "afi": "ipv4", + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ], + "176.16.1.5\/32": [ + { + "prefix": "176.16.1.5\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r4-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r4/nhrpd.conf b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf new file mode 100644 index 0000000..8a52f33 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/nhrpd.conf @@ -0,0 +1,11 @@ +!debug nhrp all +interface r4-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp registration no-unique + ip nhrp nhs dynamic nbma 192.168.1.1 + ip nhrp nhs dynamic nbma 192.168.1.2 + ip nhrp nhs dynamic nbma 192.168.1.3 + ip nhrp shortcut + tunnel source r4-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r4/zebra.conf b/tests/topotests/nhrp_redundancy/r4/zebra.conf new file mode 100644 index 0000000..e4a9a6f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r4/zebra.conf @@ -0,0 +1,16 @@ +ip forwarding +interface r4-eth0 + ip address 192.168.2.4/24 +! +ip route 192.168.1.0/24 192.168.2.6 +interface r4-gre0 + ip address 176.16.1.4/32 + no link-detect + ipv6 nd suppress-ra +! +interface r4-eth1 + ip address 4.4.4.4/24 +! +ip route 0.0.0.0/0 176.16.1.1 50 +ip route 0.0.0.0/0 176.16.1.2 60 +ip route 0.0.0.0/0 176.16.1.3 70 \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json new file mode 100644 index 0000000..bc041c6 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrp_cache.json @@ -0,0 +1,51 @@ +{ + "attr": { + "entriesCount": 4 + }, + "table": [ + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.2", + "nbma": "192.168.1.2", + "claimed_nbma": "192.168.1.2", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.3", + "nbma": "192.168.1.3", + "claimed_nbma": "192.168.1.3", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "nhs", + "protocol": "176.16.1.1", + "nbma": "192.168.1.1", + "claimed_nbma": "192.168.1.1", + "used": false, + "timeout": true, + "auth": false, + "identity": "" + }, + { + "interface": "r5-gre0", + "type": "local", + "protocol": "176.16.1.5", + "nbma": "192.168.2.5", + "claimed_nbma": "192.168.2.5", + "used": false, + "timeout": false, + "auth": false, + "identity": "-" + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrp_route.json b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json new file mode 100644 index 0000000..1d1c16f --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrp_route.json @@ -0,0 +1,71 @@ +{ + "176.16.1.1\/32": [ + { + "prefix": "176.16.1.1\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ], + "176.16.1.2\/32": [ + { + "prefix": "176.16.1.2\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ], + "176.16.1.3\/32": [ + { + "prefix": "176.16.1.3\/32", + "protocol": "nhrp", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 10, + "metric": 0, + "installed": true, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "directlyConnected": true, + "interfaceName": "r5-gre0", + "active": true + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/topotests/nhrp_redundancy/r5/nhrpd.conf b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf new file mode 100644 index 0000000..7241ed5 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/nhrpd.conf @@ -0,0 +1,11 @@ +!debug nhrp all +interface r5-gre0 + ip nhrp holdtime 10 + ip nhrp network-id 42 + ip nhrp nhs dynamic nbma 192.168.1.1 + ip nhrp nhs dynamic nbma 192.168.1.2 + ip nhrp nhs dynamic nbma 192.168.1.3 + ip nhrp registration no-unique + ip nhrp shortcut + tunnel source r5-eth0 +exit diff --git a/tests/topotests/nhrp_redundancy/r5/zebra.conf b/tests/topotests/nhrp_redundancy/r5/zebra.conf new file mode 100644 index 0000000..9b1e1c0 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r5/zebra.conf @@ -0,0 +1,16 @@ +ip forwarding +interface r5-eth0 + ip address 192.168.2.5/24 +! +ip route 192.168.1.0/24 192.168.2.6 +interface r5-gre0 + ip address 176.16.1.5/32 + no link-detect + ipv6 nd suppress-ra +! +interface r5-eth1 + ip address 5.5.5.5/24 +! +ip route 0.0.0.0/0 176.16.1.1 50 +ip route 0.0.0.0/0 176.16.1.2 60 +ip route 0.0.0.0/0 176.16.1.3 70 diff --git a/tests/topotests/nhrp_redundancy/r6/zebra.conf b/tests/topotests/nhrp_redundancy/r6/zebra.conf new file mode 100644 index 0000000..63a37cd --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r6/zebra.conf @@ -0,0 +1,7 @@ +ip forwarding +interface r6-eth0 + ip address 192.168.1.6/24 +! +interface r6-eth1 + ip address 192.168.2.6/24 +exit diff --git a/tests/topotests/nhrp_redundancy/r7/zebra.conf b/tests/topotests/nhrp_redundancy/r7/zebra.conf new file mode 100644 index 0000000..5747b40 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/r7/zebra.conf @@ -0,0 +1,4 @@ +interface r7-eth0 + ip address 4.4.4.7/24 +! +ip route 0.0.0.0/0 4.4.4.4 diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot new file mode 100644 index 0000000..c169436 --- /dev/null +++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.dot @@ -0,0 +1,103 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="nhrp-topo-redundant-nhs"; + + # Routers + r1 [ + shape=doubleoctagon, + label="NHS 1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon + label="NHS 2", + fillcolor="#f08080", + style=filled, + ]; + r3 [ + shape=doubleoctagon + label="NHS 3", + fillcolor="#f08080", + style=filled, + ]; + r4 [ + shape=doubleoctagon + label="NHC 1", + fillcolor="#f08080", + style=filled, + ]; + r5 [ + shape=doubleoctagon + label="NHC 2", + fillcolor="#f08080", + style=filled, + ]; + r6 [ + shape=doubleoctagon + label="router", + fillcolor="#f08080", + style=filled, + ]; + r7 [ + shape=doubleoctagon + label="host", + fillcolor="#f08080", + style=filled, + ]; + + # Switches + sw1 [ + shape=oval, + label="sw1\n192.168.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw2 [ + shape=oval, + label="sw2\n192.168.2.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw3 [ + shape=oval, + label="sw3\n4.4.4.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + sw4 [ + shape=oval, + label="sw4\n5.5.5.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + r1 -- sw1 [label="eth0"]; + r2 -- sw1 [label="eth0"]; + r3 -- sw1 [label="eth0"]; + r6 -- sw1 [label="eth0"]; + + r4 -- sw2 [label="eth0"]; + r5 -- sw2 [label="eth0"]; + r6 -- sw2 [label="eth1"]; + + r4 -- sw3 [label="eth1"]; + r7 -- sw3 [label="eth0"]; + + r5 -- sw4 [label="eth1"]; + +} diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py new file mode 100644 index 0000000..81a22eb --- /dev/null +++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py @@ -0,0 +1,423 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0-or-later +# +# test_nhrp_redundancy.py +# +# Copyright 2024, LabN Consulting, L.L.C. +# Dave LeRoy +# + +import os +import sys +import json +from time import sleep +from functools import partial +import pytest + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import ( + required_linux_kernel_version, + shutdown_bringup_interface, + retry, +) + +""" +test_nhrp_redundancy.py: Test NHS redundancy for NHRP +""" + +TOPOLOGY = """ ++------------+ +------------+ +------------+ +| | | | | | +| | | | | | +| NHS 1 | | NHS 2 | | NHS 3 | +| | | | | | ++-----+------+ +-----+------+ +-----+------+ + |.1 |.2 |.3 + | | | + | | 192.168.1.0/24 | +------+-------------------------------+------------------+-------------+------ + | + |.6 + GRE P2MP between all NHS and NHC +-----+------+ + 172.16.1.x/32 | | + | | + | Router | + | | + +-----+------+ + | + | + ---------+----------------+-------------+------ + | 192.168.2.0/24 | + | | + | |.4 |.5 ++------------+ | +-------+----+ +------+-----+ | +| | | | | | | | +| | +--------+ | | | | +| Host |.7 | | NHC 1 | | NHC 2 +-----+5.5.5.0/24 +| +---------+ | | | | | ++------------+ | +------------+ +------------+ | + | | + 4.4.4.0/24 +""" + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# Required to instantiate the topology builder class. + +pytestmark = [pytest.mark.nhrpd] + + +def build_topo(tgen): + "Build function" + + # Create 7 routers + for routern in range(1, 8): + tgen.add_router("r{}".format(routern)) + + # Interconnect routers 1, 2, 3, 6 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r6"]) + + # Interconnect routers 4, 5, 6 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r5"]) + switch.add_link(tgen.gears["r6"]) + + # Connect router 4, 7 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r7"]) + + # Connect router 5 + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r5"]) + + +def _populate_iface(): + tgen = get_topogen() + cmds_tot_hub = [ + "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.1.{1} remote 0.0.0.0", + "ip link set dev {0}-gre0 up", + "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6", + "iptables -A FORWARD -i {0}-gre0 -o {0}-gre0 -m hashlimit --hashlimit-upto 4/minute --hashlimit-burst 1 --hashlimit-mode srcip,dstip --hashlimit-srcmask 24 --hashlimit-dstmask 24 --hashlimit-name loglimit-0 -j NFLOG --nflog-group 1 --nflog-range 128", + ] + + cmds_tot = [ + "ip tunnel add {0}-gre0 mode gre ttl 64 key 42 dev {0}-eth0 local 192.168.2.{1} remote 0.0.0.0", + "ip link set dev {0}-gre0 up", + "echo 0 > /proc/sys/net/ipv4/ip_forward_use_pmtu", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-eth0/disable_ipv6", + "echo 1 > /proc/sys/net/ipv6/conf/{0}-gre0/disable_ipv6", + ] + + for cmd in cmds_tot_hub: + # Router 1 + input = cmd.format("r1", "1") + logger.info("input: " + input) + output = tgen.net["r1"].cmd(input) + logger.info("output: " + output) + + # Router 2 + input = cmd.format("r2", "2") + logger.info("input: " + input) + output = tgen.net["r2"].cmd(input) + logger.info("output: " + output) + + # Router 3 + input = cmd.format("r3", "3") + logger.info("input: " + input) + output = tgen.net["r3"].cmd(input) + logger.info("output: " + output) + + for cmd in cmds_tot: + input = cmd.format("r4", "4") + logger.info("input: " + input) + output = tgen.net["r4"].cmd(input) + logger.info("output: " + output) + + input = cmd.format("r5", "5") + logger.info("input: " + input) + output = tgen.net["r5"].cmd(input) + logger.info("output: " + output) + + +def _verify_iptables(): + tgen = get_topogen() + # Verify iptables is installed. Required for shortcuts + rc, _, _ = tgen.net["r1"].cmd_status("iptables") + return False if rc == 127 else True + + +def setup_module(mod): + logger.info("NHRP Redundant NHS:\n {}".format(TOPOLOGY)) + + result = required_linux_kernel_version("5.0") + if result is not True: + pytest.skip("Kernel requirements are not met") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + # Starting Routers + router_list = tgen.routers() + _populate_iface() + + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, "{}/zebra.conf".format(rname)), + ) + if rname in ("r1", "r2", "r3", "r4", "r5"): + router.load_config( + TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname)) + ) + + # Initialize all routers. + tgen.start_router() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + tgen.stop_topology() + + +def test_protocols_convergence(): + """ + Assert that all protocols have converged before checking for the NHRP + statuses as they depend on it. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Checking NHRP cache and IPv4 routes for convergence") + router_list = tgen.routers() + + # Check NHRP cache on servers and clients + for rname, router in router_list.items(): + + json_file = "{}/{}/nhrp_cache.json".format(CWD, router.name) + if not os.path.isfile(json_file): + logger.info("skipping file {}".format(json_file)) + continue + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip nhrp cache json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip nhrp cache") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Check NHRP IPV4 routes on servers and clients + for rname, router in router_list.items(): + + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + if not os.path.isfile(json_file): + logger.info("skipping file {}".format(json_file)) + continue + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Test connectivity from 1 NHRP server to all clients + pingrouter = tgen.gears["r1"] + logger.info("Check Ping IPv4 from R1 to R4 = 176.16.1.4)") + output = pingrouter.run("ping 176.16.1.4 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R1 to R4 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R1 to R4 OK") + + logger.info("Check Ping IPv4 from R1 to R5 = 176.16.1.5)") + output = pingrouter.run("ping 176.16.1.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R1 to R5 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R1 to R5 OK") + + # Test connectivity from 1 NHRP client to all servers + pingrouter = tgen.gears["r4"] + logger.info("Check Ping IPv4 from R4 to R1 = 176.16.1.1)") + output = pingrouter.run("ping 176.16.1.1 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R1 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R1 OK") + + logger.info("Check Ping IPv4 from R4 to R2 = 176.16.1.2)") + output = pingrouter.run("ping 176.16.1.2 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R2 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R2 OK") + + logger.info("Check Ping IPv4 from R4 to R3 = 176.16.1.3)") + output = pingrouter.run("ping 176.16.1.3 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R4 to R3 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R4 to R3 OK") + + +@retry(retry_timeout=30, initial_wait=5) +def verify_shortcut_path(): + """ + Verifying that traffic flows through shortcut path + """ + tgen = get_topogen() + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 OK") + + +def test_redundancy_shortcut(): + """ + Assert that if shortcut created and then NHS goes down, there is no traffic disruption + Stop traffic and verify next time traffic started, shortcut is initiated by backup NHS + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + if not _verify_iptables(): + pytest.skip("iptables not installed") + + logger.info("Testing NHRP shortcuts with redundant servers") + + # Verify R4 nhrp routes before shortcut creation + router = tgen.gears["r4"] + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Initiate shortcut by pinging between clients + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK") + + # Now check that NHRP shortcut route installed + json_file = "{}/{}/nhrp_route_shortcut.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Bring down primary GRE interface and verify shortcut is not disturbed + logger.info("Bringing down R1, primary NHRP server.") + shutdown_bringup_interface(tgen, "r1", "r1-gre0", False) + + # Verify shortcut is still active + pingrouter = tgen.gears["r7"] + logger.info("Check Ping IPv4 from R7 to R5 via shortcut = 5.5.5.5") + + output = pingrouter.run("ping 5.5.5.5 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = "expected ping IPv4 from R7 to R5 via shortcut should be ok" + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R7 to R5 via shortcut OK") + + # Now verify shortcut is purged with lack of traffic + json_file = "{}/{}/nhrp_route.json".format(CWD, router.name) + assertmsg = "No nhrp_route file found" + assert os.path.isfile(json_file), assertmsg + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, router, "show ip route nhrp json", expected + ) + _, result = topotest.run_and_expect(test_func, None, count=40, wait=0.5) + + output = router.vtysh_cmd("show ip route nhrp") + logger.info(output) + + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt index 6ab1bb8..1495c88 100644 --- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt +++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt @@ -1,9 +1,9 @@ VRF ray: B 10.0.1.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX -B 10.0.2.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX +B 10.0.2.0/24 [20/0] is directly connected, r2-eth0 (vrf default) inactive, weight 1, XX:XX:XX B>* 10.0.3.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX O>* 10.0.4.0/24 [110/20] via 10.0.40.4, r2-eth2, weight 1, XX:XX:XX -B 10.0.20.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX +B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 73479c6..b06f1df 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -220,6 +220,23 @@ def get_normalized_mac_ip_line(line): return line +def get_normalized_interface_vrf(line): + """ + If 'interface vrf ' is present in file, + we need to remove the explicit "vrf " + so that the context information is created + correctly and configurations are matched appropriately. + """ + + intf_vrf = re.search("interface (\S+) vrf (\S+)", line) + if intf_vrf: + old_line = "vrf %s" % intf_vrf.group(2) + new_line = line.replace(old_line, "").strip() + return new_line + + return line + + # This dictionary contains a tree of all commands that we know start a # new multi-line context. All other commands are treated either as # commands inside a multi-line context or as single-line contexts. This @@ -295,6 +312,10 @@ class Config(object): # Compress duplicate whitespaces line = " ".join(line.split()) + # Remove 'vrf ' from 'interface vrf ' + if line.startswith("interface ") and "vrf" in line: + line = get_normalized_interface_vrf(line) + if ":" in line: line = get_normalized_mac_ip_line(line) @@ -1438,6 +1459,35 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_add.append((add_cmd, None)) lines_to_del_to_del.append((ctx_keys, None)) + # bgp as-path access-list can be specified without a seq number. + # However, the running config always + # adds `seq X` (sequence number). So, ignore such lines as well. + # Examples: + # bgp as-path access-list important_internet_bgp_as_numbers seq 30 permit _40841_" + re_bgp_as_path = re.search( + "^(bgp )(as-path )(access-list )(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", + ctx_keys[0], + ) + if re_bgp_as_path: + found = False + tmpline = ( + re_bgp_as_path.group(1) + + re_bgp_as_path.group(2) + + re_bgp_as_path.group(3) + + re_bgp_as_path.group(4) + + re_bgp_as_path.group(6) + + re_bgp_as_path.group(7) + ) + for ctx in lines_to_add: + if ctx[0][0] == tmpline: + lines_to_del_to_del.append((ctx_keys, None)) + lines_to_add_to_del.append(((tmpline,), None)) + found = True + if found is False: + add_cmd = ("no " + ctx_keys[0],) + lines_to_add.append((add_cmd, None)) + lines_to_del_to_del.append((ctx_keys, None)) + if ( len(ctx_keys) == 3 and ctx_keys[0].startswith("router bgp") diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index f90f898..12d22b1 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -3423,7 +3423,7 @@ static void show_route_map_send(const char *route_map, bool json) bool first = true; char command_line[128]; - snprintf(command_line, sizeof(command_line), "show route-map "); + snprintf(command_line, sizeof(command_line), "do show route-map "); if (route_map) strlcat(command_line, route_map, sizeof(command_line)); if (json) @@ -5064,11 +5064,13 @@ void vtysh_init_vty(void) install_element(VRF_NODE, &vtysh_exit_vrf_cmd); install_element(VRF_NODE, &vtysh_quit_vrf_cmd); +#ifdef HAVE_BGPD install_node(&rpki_vrf_node); install_element(VRF_NODE, &rpki_cmd); install_element(RPKI_VRF_NODE, &rpki_exit_cmd); install_element(RPKI_VRF_NODE, &rpki_quit_cmd); install_element(RPKI_VRF_NODE, &vtysh_end_all_cmd); +#endif install_element(CONFIG_NODE, &vtysh_affinity_map_cmd); install_element(CONFIG_NODE, &vtysh_no_affinity_map_cmd); diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang index e9b3f67..732a38a 100644 --- a/yang/frr-pim.yang +++ b/yang/frr-pim.yang @@ -422,9 +422,7 @@ module frr-pim { } leaf dr-priority { - type uint32 { - range "1..max"; - } + type uint32; default 1; description "DR (Designated Router) priority"; diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c index 00e0a49..3e03d74 100644 --- a/zebra/zebra_cli.c +++ b/zebra/zebra_cli.c @@ -241,7 +241,7 @@ DEFUN_YANG_NOSH (link_params, return ret; } -DEFUN_NOSH (exit_link_params, +DEFUN_YANG_NOSH (exit_link_params, exit_link_params_cmd, "exit-link-params", "Exit from Link Params configuration mode\n") diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 15e36ac..39fc678 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2634,8 +2634,16 @@ int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf) continue; write = 1; - vty_out(vty, "mpls label bind %pFX %s\n", &rn->p, - label2str(fec->label, 0, lstr, BUFSIZ)); + + if (fec->label == MPLS_LABEL_IPV4_EXPLICIT_NULL || + fec->label == MPLS_LABEL_IPV6_EXPLICIT_NULL) + strlcpy(lstr, "explicit-null", sizeof(lstr)); + else if (fec->label == MPLS_LABEL_IMPLICIT_NULL) + strlcpy(lstr, "implicit-null", sizeof(lstr)); + else + snprintf(lstr, sizeof(lstr), "%d", fec->label); + + vty_out(vty, "mpls label bind %pFX %s\n", &rn->p, lstr); } } diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index fd09e6b..83a1aad 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -247,7 +247,7 @@ DEFUN (mpls_label_bind, DEFUN (no_mpls_label_bind, no_mpls_label_bind_cmd, - "no mpls label bind [<(16-1048575)|implicit-null>]", + "no mpls label bind [<(16-1048575)|implicit-null|explicit-null>]", NO_STR MPLS_STR "Label configuration\n" @@ -255,7 +255,8 @@ DEFUN (no_mpls_label_bind, "IPv4 prefix\n" "IPv6 prefix\n" "MPLS Label to bind\n" - "Use Implicit-Null Label\n") + "Use Implicit-Null Label\n" + "Use Explicit-Null Label\n") { return zebra_mpls_bind(vty, 0, argv[4]->arg, NULL); } diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index 5cb9985..ff2529f 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -3187,6 +3187,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create( strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"), sizeof(dnssl.name)); ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name); + dnssl.encoded_len = ret; if (args->event == NB_EV_VALIDATE) { if (ret < 0) { diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index dc403b8..ed949da 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -3657,8 +3657,9 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) "%s: Setting the valid flag for nhe %pNG, interface: %s", __func__, rb_node_dep->nhe, ifp->name); } + /* Check for singleton NHG associated to interface */ - if (nexthop_is_ifindex_type(nh) && + if (!nexthop_is_blackhole(nh) && zebra_nhg_depends_is_empty(rb_node_dep->nhe)) { struct nhg_connected *rb_node_dependent; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 95da789..c1ec506 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -299,8 +299,7 @@ int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype)); route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype)); - if (PROTO_RM_MAP(zvrf, afi, rtype)) { - + if (PROTO_RM_NAME(zvrf, afi, rtype)) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug( "%u: IPv4 Routemap config for protocol %d scheduling RIB processing", @@ -326,7 +325,7 @@ int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) { route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype)); - if (PROTO_RM_MAP(zvrf, afi, rtype)) { + if (PROTO_RM_NAME(zvrf, afi, rtype)) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug( "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing", diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 2ffaefd..0b75ec2 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1763,9 +1763,9 @@ static int svd_remote_nh_add(struct zebra_l3vni *zl3vni, } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "SVD RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX", - &nh->emac, rmac, vtep_ip, host_prefix); + zlog_debug("SVD RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX refcnt %u", + &nh->emac, rmac, vtep_ip, host_prefix, + nh->refcnt); memcpy(&nh->emac, rmac, ETH_ALEN); /* install (update) the nh neigh in kernel */ @@ -2473,11 +2473,26 @@ static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx) /* delete and uninstall nh hash entry */ static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx) { - struct zebra_neigh *n = NULL; + struct zebra_neigh *n = NULL, *svd_nh = NULL; struct zebra_l3vni *zl3vni = NULL; n = (struct zebra_neigh *)bucket->data; zl3vni = (struct zebra_l3vni *)ctx; + + /* remove SVD based remote nexthop neigh entry */ + svd_nh = svd_nh_lookup(&n->ip); + if (svd_nh) { + svd_nh->refcnt--; + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s L3VNI %u remove svd nh %pIA refcnt %u", + __func__, zl3vni->vni, &n->ip, + svd_nh->refcnt); + if (svd_nh->refcnt == 0) { + svd_nh_uninstall(zl3vni, svd_nh); + svd_nh_del(svd_nh); + } + } + zl3vni_nh_uninstall(zl3vni, n); zl3vni_nh_del(zl3vni, n); } -- cgit v1.2.3