diff options
46 files changed, 781 insertions, 360 deletions
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 0e5f701fc2..f6259b9c3b 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -678,7 +678,8 @@ static void bfdd_sessions_enable_interface(struct interface *ifp) /* If Interface matches vrfname, then bypass iface check */ if (vrf_is_backend_netns() || strcmp(ifp->name, vrf->name)) { /* Interface name mismatch. */ - if (strcmp(ifp->name, bs->key.ifname)) + if (bs->key.ifname[0] && + strcmp(ifp->name, bs->key.ifname)) continue; } diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index fd644ebf0a..880e15fadb 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1258,6 +1258,28 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath, return new; } +/* Replace all ASNs with our own ASN */ +struct aspath *aspath_replace_all_asn(struct aspath *aspath, as_t our_asn) +{ + struct aspath *new; + struct assegment *seg; + + new = aspath_dup(aspath); + seg = new->segments; + + while (seg) { + int i; + + for (i = 0; i < seg->length; i++) + seg->as[i] = our_asn; + + seg = seg->next; + } + + aspath_str_update(new, false); + return new; +} + /* Replace all private ASNs with our own ASN */ struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn, as_t peer_asn) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 4b16818167..912db7b254 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -112,6 +112,8 @@ extern bool aspath_single_asn_check(struct aspath *, as_t asn); extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath, as_t target_asn, as_t our_asn); +extern struct aspath *aspath_replace_all_asn(struct aspath *aspath, + as_t our_asn); extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn, as_t peer_asn); extern struct aspath *aspath_remove_private_asns(struct aspath *aspath, diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index fbb0d2272a..78d7bf20eb 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -520,8 +520,10 @@ static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl) ecomadd = ecommunity_new(); ecommunity_add_val(ecomadd, &eval, false, false); for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) - if (ecommunity_cmp(ecomadd, ecom)) + if (ecommunity_cmp(ecomadd, ecom)) { ecom_found = true; + break; + } if (!ecom_found) listnode_add_sort(rtl, ecomadd); @@ -4556,6 +4558,7 @@ void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl) if (ecommunity_match(ecom, ecom_auto)) { ecommunity_free(&ecom); node_to_del = node; + break; } } @@ -5104,7 +5107,6 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, /* * Map the RTs (configured or automatically derived) of a VRF to the VRF. * The mapping will be used during route processing. - * bgp_def: default bgp instance * bgp_vrf: specific bgp vrf instance on which RT is configured */ void bgp_evpn_map_vrf_to_its_rts(struct bgp *bgp_vrf) diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 6db4cba44d..39b31c0c1a 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -196,9 +196,8 @@ static int bgp_evpn_es_route_install(struct bgp *bgp, /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra - && (struct bgp_path_info *)pi->extra->parent == - parent_pi) + if (pi->extra && + (struct bgp_path_info *)pi->extra->parent == parent_pi) break; if (!pi) { @@ -3841,13 +3840,13 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, es = bgp_evpn_es_find(&p->prefix.ead_addr.esi); if (!es) { if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) - zlog_debug("del remote %s es %s evi %u vtep %pI4, NO es", - p->prefix.ead_addr.eth_tag ? "ead-es" - : "ead-evi", - esi_to_str(&p->prefix.ead_addr.esi, buf, - sizeof(buf)), - vpn->vni, - &p->prefix.ead_addr.ip.ipaddr_v4); + zlog_debug( + "del remote %s es %s evi %u vtep %pI4, NO es", + p->prefix.ead_addr.eth_tag ? "ead-es" + : "ead-evi", + esi_to_str(&p->prefix.ead_addr.esi, buf, + sizeof(buf)), + vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4); return 0; } es_evi = bgp_evpn_es_evi_find(es, vpn); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index b3d8d1b82d..4d8c4ac2ac 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -532,6 +532,7 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index, bool alloced = false; int label = 0; uint8_t offset = 0; + uint8_t len = 0; if (!bgp || !sid_locator || !sid) return false; @@ -540,10 +541,11 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index, *sid_locator = chunk->prefix.prefix; *sid = chunk->prefix.prefix; offset = chunk->block_bits_length + chunk->node_bits_length; + len = chunk->function_bits_length ?: 16; if (index != 0) { label = index << 12; - transpose_sid(sid, label, offset, 16); + transpose_sid(sid, label, offset, len); if (sid_exist(bgp, sid)) return false; alloced = true; @@ -552,7 +554,7 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index, for (size_t i = 1; i < 255; i++) { label = i << 12; - transpose_sid(sid, label, offset, 16); + transpose_sid(sid, label, offset, len); if (sid_exist(bgp, sid)) continue; alloced = true; @@ -633,13 +635,29 @@ void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi) tovpn_sid_transpose_label; } +/* + * This function shifts "label" 4 bits to the right and + * embeds it by length "len", starting at offset "offset" + * as seen from the MSB (Most Significant Bit) of "sid". + * + * e.g. if "label" is 0x1000 and "len" is 16, "label" is + * embedded in "sid" as follows: + * + * <---- len -----> + * label: 0000 0001 0000 0000 0000 + * sid: .... 0000 0001 0000 0000 + * <---- len -----> + * ^ + * | + * offset from MSB + */ void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset, uint8_t len) { for (uint8_t idx = 0; idx < len; idx++) { uint8_t tidx = offset + idx; sid->s6_addr[tidx / 8] &= ~(0x1 << (7 - tidx % 8)); - if (label >> (19 - idx) & 0x1) + if (label >> (len + 3 - idx) & 0x1) sid->s6_addr[tidx / 8] |= 0x1 << (7 - tidx % 8); } } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index dc4f30a906..3433e1471c 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -390,7 +390,8 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) } static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc, - struct zapi_route *nhr) + struct zapi_route *nhr, + bool import_check) { struct nexthop *nexthop; struct nexthop *oldnh; @@ -421,7 +422,21 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc, if (nhr->nexthop_num != bnc->nexthop_num) bnc->change_flags |= BGP_NEXTHOP_CHANGED; - if (nhr->nexthop_num) { + if (import_check && (nhr->type == ZEBRA_ROUTE_BGP || + !prefix_same(&bnc->prefix, &nhr->prefix))) { + SET_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE); + + bnc_nexthop_free(bnc); + bnc->nexthop = NULL; + + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "%s: Import Check does not resolve to the same prefix for %pFX received %pFX or matching route is BGP", + __func__, &bnc->prefix, &nhr->prefix); + } else if (nhr->nexthop_num) { struct peer *peer = bnc->nht_info; /* notify bgp fsm if nbr ip goes from invalid->valid */ @@ -695,7 +710,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache", &nhr.prefix, nhr.srte_color, bgp->name_pretty); } else - bgp_process_nexthop_update(bnc_nhc, &nhr); + bgp_process_nexthop_update(bnc_nhc, &nhr, false); tree = &bgp->import_check_table[afi]; @@ -706,17 +721,8 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check", &nhr.prefix, nhr.srte_color, bgp->name_pretty); return; - } else { - if (nhr.type == ZEBRA_ROUTE_BGP - || !prefix_same(&bnc_import->prefix, &nhr.prefix)) { - if (BGP_DEBUG(nht, NHT)) - zlog_debug( - "%s: Import Check does not resolve to the same prefix for %pFX received %pFX", - __func__, &bnc_import->prefix, &nhr.prefix); - return; - } - bgp_process_nexthop_update(bnc_import, &nhr); } + bgp_process_nexthop_update(bnc_import, &nhr, true); /* * HACK: if any BGP route is dependant on an SR-policy that doesn't @@ -739,7 +745,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) || CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID)) continue; - bgp_process_nexthop_update(bnc_iter, &nhr); + bgp_process_nexthop_update(bnc_iter, &nhr, false); } } } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7e2cb5c70c..30615c5a43 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9463,7 +9463,6 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, json_object *json_paths) { struct attr *attr; - char buf[BUFSIZ] = {0}; json_object *json_path = NULL; json_object *json_nexthop = NULL; json_object *json_overlay = NULL; @@ -9488,16 +9487,15 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, /* Print attribute */ attr = path->attr; - char buf1[BUFSIZ]; int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); switch (af) { case AF_INET: - inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ); if (!json_path) { - vty_out(vty, "%-16s", buf); + vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in); } else { - json_object_string_add(json_nexthop, "ip", buf); + json_object_string_addf(json_nexthop, "ip", "%pI4", + &attr->mp_nexthop_global_in); json_object_string_add(json_nexthop, "afi", "ipv4"); @@ -9506,15 +9504,17 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, } break; case AF_INET6: - inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ); - inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ); if (!json_path) { - vty_out(vty, "%s(%s)", buf, buf1); + vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global, + &attr->mp_nexthop_local); } else { - json_object_string_add(json_nexthop, "ipv6Global", buf); + json_object_string_addf(json_nexthop, "ipv6Global", + "%pI6", + &attr->mp_nexthop_global); - json_object_string_add(json_nexthop, "ipv6LinkLocal", - buf1); + json_object_string_addf(json_nexthop, "ipv6LinkLocal", + "%pI6", + &attr->mp_nexthop_local); json_object_string_add(json_nexthop, "afi", "ipv6"); @@ -9535,12 +9535,10 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr); - ipaddr2str(&eo->gw_ip, buf, BUFSIZ); - if (!json_path) - vty_out(vty, "/%s", buf); + vty_out(vty, "/%pIA", &eo->gw_ip); else - json_object_string_add(json_overlay, "gw", buf); + json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip); if (bgp_attr_get_ecommunity(attr)) { char *mac = NULL; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 6c303a9e5f..20ee2e4d49 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2174,6 +2174,57 @@ static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = { route_aspath_free, }; +/* `set as-path replace AS-PATH` */ +static void *route_aspath_replace_compile(const char *arg) +{ + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); +} + +static void route_aspath_replace_free(void *rule) +{ + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); +} + +static enum route_map_cmd_result_t +route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object) +{ + struct aspath *aspath_new; + const char *replace = rule; + struct bgp_path_info *path = object; + as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as + : path->peer->local_as; + + if (path->peer->sort != BGP_PEER_EBGP) { + zlog_warn( + "`set as-path replace` is supported only for EBGP peers"); + return RMAP_NOOP; + } + + if (path->attr->aspath->refcnt) + aspath_new = aspath_dup(path->attr->aspath); + else + aspath_new = path->attr->aspath; + + if (strmatch(replace, "any")) { + path->attr->aspath = + aspath_replace_all_asn(aspath_new, own_asn); + } else { + as_t replace_asn = strtoul(replace, NULL, 10); + + path->attr->aspath = aspath_replace_specific_asn( + aspath_new, replace_asn, own_asn); + } + + return RMAP_OKAY; +} + +static const struct route_map_rule_cmd route_set_aspath_replace_cmd = { + "as-path replace", + route_set_aspath_replace, + route_aspath_replace_compile, + route_aspath_replace_free, +}; + /* `set community COMMUNITY' */ struct rmap_com_set { struct community *com; @@ -5389,6 +5440,43 @@ DEFUN_YANG (set_aspath_prepend_lastas, return nb_cli_apply_changes(vty, NULL); } +DEFPY_YANG (set_aspath_replace_asn, + set_aspath_replace_asn_cmd, + "set as-path replace <any|(1-4294967295)>$replace", + SET_STR + "Transform BGP AS_PATH attribute\n" + "Replace AS number to local AS number\n" + "Replace any AS number to local AS number\n" + "Replace a specific AS number to local AS number\n") +{ + const char *xpath = + "./set-action[action='frr-bgp-route-map:as-path-replace']"; + char xpath_value[XPATH_MAXLEN]; + + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + snprintf(xpath_value, sizeof(xpath_value), + "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_set_aspath_replace_asn, + no_set_aspath_replace_asn_cmd, + "no set as-path replace [<any|(1-4294967295)>]", + NO_STR + SET_STR + "Transform BGP AS_PATH attribute\n" + "Replace AS number to local AS number\n" + "Replace any AS number to local AS number\n" + "Replace a specific AS number to local AS number\n") +{ + const char *xpath = + "./set-action[action='frr-bgp-route-map:as-path-replace']"; + + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); +} + DEFUN_YANG (no_set_aspath_prepend, no_set_aspath_prepend_cmd, "no set as-path prepend [(1-4294967295)]", @@ -6727,6 +6815,7 @@ void bgp_route_map_init(void) route_map_install_set(&route_set_distance_cmd); route_map_install_set(&route_set_aspath_prepend_cmd); route_map_install_set(&route_set_aspath_exclude_cmd); + route_map_install_set(&route_set_aspath_replace_cmd); route_map_install_set(&route_set_origin_cmd); route_map_install_set(&route_set_atomic_aggregate_cmd); route_map_install_set(&route_set_aggregator_as_cmd); @@ -6800,10 +6889,12 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd); install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd); install_element(RMAP_NODE, &set_aspath_exclude_cmd); + install_element(RMAP_NODE, &set_aspath_replace_asn_cmd); install_element(RMAP_NODE, &no_set_aspath_prepend_cmd); install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_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_replace_asn_cmd); install_element(RMAP_NODE, &set_origin_cmd); install_element(RMAP_NODE, &no_set_origin_cmd); install_element(RMAP_NODE, &set_atomic_aggregate_cmd); diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c index caf1553ec1..585596e1aa 100644 --- a/bgpd/bgp_routemap_nb.c +++ b/bgpd/bgp_routemap_nb.c @@ -297,6 +297,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = { } }, { + .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path", + .cbs = { + .modify = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify, + .destroy = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy, + } + }, + { .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none", .cbs = { .modify = lib_route_map_entry_set_action_rmap_set_action_community_none_modify, diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h index e0b3a6926f..a01adf7d5d 100644 --- a/bgpd/bgp_routemap_nb.h +++ b/bgpd/bgp_routemap_nb.h @@ -108,6 +108,10 @@ int lib_route_map_entry_set_action_rmap_set_action_last_as_modify(struct nb_cb_m int lib_route_map_entry_set_action_rmap_set_action_last_as_destroy(struct nb_cb_destroy_args *args); int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_modify(struct nb_cb_modify_args *args); int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy(struct nb_cb_destroy_args *args); +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify( + struct nb_cb_modify_args *args); +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy( + struct nb_cb_destroy_args *args); int lib_route_map_entry_set_action_rmap_set_action_community_none_modify(struct nb_cb_modify_args *args); int lib_route_map_entry_set_action_rmap_set_action_community_none_destroy(struct nb_cb_destroy_args *args); int lib_route_map_entry_set_action_rmap_set_action_community_string_modify(struct nb_cb_modify_args *args); diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index 773538ee41..b87877b1e0 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -2209,6 +2209,58 @@ lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy( /* * XPath: + * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path + */ +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify( + struct nb_cb_modify_args *args) +{ + struct routemap_hook_context *rhc; + const char *type; + int rv; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + /* Add configuration. */ + rhc = nb_running_get_entry(args->dnode, NULL, true); + type = yang_dnode_get_string(args->dnode, NULL); + + /* Set destroy information. */ + rhc->rhc_shook = generic_set_delete; + rhc->rhc_rule = "as-path replace"; + rhc->rhc_event = RMAP_EVENT_SET_DELETED; + + rv = generic_set_add(rhc->rhc_rmi, "as-path replace", type, + args->errmsg, args->errmsg_len); + if (rv != CMD_SUCCESS) { + rhc->rhc_shook = NULL; + return NB_ERR_INCONSISTENCY; + } + } + + return NB_OK; +} + +int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy( + struct nb_cb_destroy_args *args) +{ + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + return lib_route_map_entry_set_destroy(args); + } + + return NB_OK; +} + +/* + * XPath: * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none */ int lib_route_map_entry_set_action_rmap_set_action_community_none_modify( diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index e7adad91b7..6f99b41140 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1983,6 +1983,11 @@ Using AS Path in Route Map Prepend the existing last AS number (the leftmost ASN) to the AS_PATH. The no form of this command removes this set operation from the route-map. +.. clicmd:: set as-path replace <any|ASN> + + Replace a specific AS number to local AS number. ``any`` replaces each + AS number in the AS-PATH with the local AS number. + .. _bgp-communities-attribute: Communities Attribute diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c index d515873ec1..348381ee74 100644 --- a/isisd/isis_lfa.c +++ b/isisd/isis_lfa.c @@ -1646,6 +1646,11 @@ void isis_ldp_rlfa_handle_client_close(struct zapi_client_close_info *info) level++) { struct isis_spftree *spftree; + if (!(area->is_type & level)) + continue; + if (!area->spftree[tree][level - 1]) + continue; + spftree = area->spftree[tree][level - 1]; isis_rlfa_list_clear(spftree); } diff --git a/lib/command.c b/lib/command.c index 1989668bf0..a429510059 100644 --- a/lib/command.c +++ b/lib/command.c @@ -445,11 +445,15 @@ static bool full_cli; /* This function write configuration of this host. */ static int config_write_host(struct vty *vty) { - if (cmd_hostname_get()) - vty_out(vty, "hostname %s\n", cmd_hostname_get()); + const char *name; - if (cmd_domainname_get()) - vty_out(vty, "domainname %s\n", cmd_domainname_get()); + name = cmd_hostname_get(); + if (name && name[0] != '\0') + vty_out(vty, "hostname %s\n", name); + + name = cmd_domainname_get(); + if (name && name[0] != '\0') + vty_out(vty, "domainname %s\n", name); /* The following are all configuration commands that are not sent to * watchfrr. For instance watchfrr is hardcoded to log to syslog so diff --git a/lib/prefix.h b/lib/prefix.h index 5e03a7b4f5..f1d6b2dc02 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -420,6 +420,11 @@ extern const char *family2str(int family); extern const char *safi2str(safi_t safi); extern const char *afi2str(afi_t afi); +static inline afi_t prefix_afi(union prefixconstptr pu) +{ + return family2afi(pu.p->family); +} + /* * Check bit of the prefix. * diff --git a/lib/routemap.h b/lib/routemap.h index 3ef60222bf..13dafe6849 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -370,6 +370,7 @@ DECLARE_QOBJ_TYPE(route_map); (strmatch(A, "frr-bgp-route-map:as-path-prepend")) #define IS_SET_AS_EXCLUDE(A) \ (strmatch(A, "frr-bgp-route-map:as-path-exclude")) +#define IS_SET_AS_REPLACE(A) (strmatch(A, "frr-bgp-route-map:as-path-replace")) #define IS_SET_IPV6_NH_GLOBAL(A) \ (strmatch(A, "frr-bgp-route-map:ipv6-nexthop-global")) #define IS_SET_IPV6_VPN_NH(A) \ diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 315007be1c..ff98a14c41 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -1197,6 +1197,11 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode, yang_dnode_get_string( dnode, "./rmap-set-action/frr-bgp-route-map:exclude-as-path")); + } else if (IS_SET_AS_REPLACE(action)) { + vty_out(vty, " set as-path replace %s\n", + yang_dnode_get_string( + dnode, + "./rmap-set-action/frr-bgp-route-map:replace-as-path")); } else if (IS_SET_AS_PREPEND(action)) { if (yang_dnode_exists( dnode, diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index ce26f912f4..f0ea4a03a1 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -652,8 +652,8 @@ DEFPY (interface_no_ipv6_mld_query_interval, "frr-routing:ipv6"); } -DEFPY (mld_group_watermark, - mld_group_watermark_cmd, +DEFPY (ipv6_mld_group_watermark, + ipv6_mld_group_watermark_cmd, "ipv6 mld watermark-warn (1-65535)$limit", IPV6_STR MLD_STR @@ -665,8 +665,8 @@ DEFPY (mld_group_watermark, return CMD_SUCCESS; } -DEFPY (no_mld_group_watermark, - no_mld_group_watermark_cmd, +DEFPY (no_ipv6_mld_group_watermark, + no_ipv6_mld_group_watermark_cmd, "no ipv6 mld watermark-warn [(1-65535)$limit]", NO_STR IPV6_STR @@ -1541,7 +1541,6 @@ DEFPY (show_ipv6_pim_nexthop_lookup, pim_addr vif_source; struct prefix grp; struct pim_nexthop nexthop; - char nexthop_addr_str[PIM_ADDRSTRLEN]; struct vrf *v; v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); @@ -1564,10 +1563,8 @@ DEFPY (show_ipv6_pim_nexthop_lookup, return CMD_SUCCESS; } - pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); - vty_out(vty, "Group %s --- Nexthop %s Interface %s\n", group_str, - nexthop_addr_str, nexthop.interface->name); + vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s\n", group_str, + &nexthop.mrib_nexthop_addr, nexthop.interface->name); return CMD_SUCCESS; } @@ -1628,10 +1625,10 @@ void pim_cmd_init(void) install_element(INTERFACE_NODE, &interface_ipv6_mld_query_interval_cmd); install_element(INTERFACE_NODE, &interface_no_ipv6_mld_query_interval_cmd); - install_element(CONFIG_NODE, &mld_group_watermark_cmd); - install_element(VRF_NODE, &mld_group_watermark_cmd); - install_element(CONFIG_NODE, &no_mld_group_watermark_cmd); - install_element(VRF_NODE, &no_mld_group_watermark_cmd); + install_element(CONFIG_NODE, &ipv6_mld_group_watermark_cmd); + install_element(VRF_NODE, &ipv6_mld_group_watermark_cmd); + install_element(CONFIG_NODE, &no_ipv6_mld_group_watermark_cmd); + install_element(VRF_NODE, &no_ipv6_mld_group_watermark_cmd); install_element(INTERFACE_NODE, &interface_ipv6_mld_query_max_response_time_cmd); install_element(INTERFACE_NODE, diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 9d95408cbe..6b17c8d0e5 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3525,7 +3525,6 @@ DEFPY (show_ip_pim_nexthop_lookup, pim_addr vif_source; struct prefix grp; struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; struct vrf *v; v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); @@ -3560,10 +3559,8 @@ DEFPY (show_ip_pim_nexthop_lookup, return CMD_SUCCESS; } - pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); - vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", group_str, - nexthop_addr_str, nexthop.interface->name); + vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s \n", group_str, + &nexthop.mrib_nexthop_addr, nexthop.interface->name); return CMD_SUCCESS; } @@ -4680,7 +4677,6 @@ DEFUN (show_ip_rib, struct in_addr addr; const char *addr_str; struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; int result; if (!vrf) @@ -4706,10 +4702,8 @@ DEFUN (show_ip_rib, vty_out(vty, "Address NextHop Interface Metric Preference\n"); - pim_addr_dump("<nexthop?>", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); - - vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str, + vty_out(vty, "%-15s %-15pPAs %-9s %6d %10d\n", addr_str, + &nexthop.mrib_nexthop_addr, nexthop.interface ? nexthop.interface->name : "<ifname?>", nexthop.mrib_route_metric, nexthop.mrib_metric_preference); @@ -4975,8 +4969,8 @@ DEFUN (no_ip_pim_packets, return pim_process_no_pim_packet_cmd(vty); } -DEFPY (igmp_group_watermark, - igmp_group_watermark_cmd, +DEFPY (ip_igmp_group_watermark, + ip_igmp_group_watermark_cmd, "ip igmp watermark-warn (1-65535)$limit", IP_STR IGMP_STR @@ -4989,8 +4983,8 @@ DEFPY (igmp_group_watermark, return CMD_SUCCESS; } -DEFPY (no_igmp_group_watermark, - no_igmp_group_watermark_cmd, +DEFPY (no_ip_igmp_group_watermark, + no_ip_igmp_group_watermark_cmd, "no ip igmp watermark-warn [(1-65535)$limit]", NO_STR IP_STR @@ -6139,6 +6133,32 @@ DEFUN (no_debug_igmp_trace, } +DEFUN (debug_igmp_trace_detail, + debug_igmp_trace_detail_cmd, + "debug igmp trace detail", + DEBUG_STR + DEBUG_IGMP_STR + DEBUG_IGMP_TRACE_STR + "detailed\n") +{ + PIM_DO_DEBUG_IGMP_TRACE_DETAIL; + return CMD_SUCCESS; +} + +DEFUN (no_debug_igmp_trace_detail, + no_debug_igmp_trace_detail_cmd, + "no debug igmp trace detail", + NO_STR + DEBUG_STR + DEBUG_IGMP_STR + DEBUG_IGMP_TRACE_STR + "detailed\n") +{ + PIM_DONT_DEBUG_IGMP_TRACE_DETAIL; + return CMD_SUCCESS; +} + + DEFUN (debug_mroute, debug_mroute_cmd, "debug mroute", @@ -8422,10 +8442,10 @@ void pim_cmd_init(void) install_element(VRF_NODE, &no_ip_pim_ecmp_rebalance_cmd); install_element(CONFIG_NODE, &ip_pim_mlag_cmd); install_element(CONFIG_NODE, &no_ip_pim_mlag_cmd); - install_element(CONFIG_NODE, &igmp_group_watermark_cmd); - install_element(VRF_NODE, &igmp_group_watermark_cmd); - install_element(CONFIG_NODE, &no_igmp_group_watermark_cmd); - install_element(VRF_NODE, &no_igmp_group_watermark_cmd); + install_element(CONFIG_NODE, &ip_igmp_group_watermark_cmd); + install_element(VRF_NODE, &ip_igmp_group_watermark_cmd); + install_element(CONFIG_NODE, &no_ip_igmp_group_watermark_cmd); + install_element(VRF_NODE, &no_ip_igmp_group_watermark_cmd); install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); @@ -8548,6 +8568,8 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd); install_element(ENABLE_NODE, &debug_igmp_trace_cmd); install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd); + install_element(ENABLE_NODE, &debug_igmp_trace_detail_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_trace_detail_cmd); install_element(ENABLE_NODE, &debug_mroute_cmd); install_element(ENABLE_NODE, &debug_mroute_detail_cmd); install_element(ENABLE_NODE, &no_debug_mroute_cmd); @@ -8601,6 +8623,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd); install_element(CONFIG_NODE, &debug_igmp_trace_cmd); install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd); + install_element(CONFIG_NODE, &debug_igmp_trace_detail_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_trace_detail_cmd); install_element(CONFIG_NODE, &debug_mroute_cmd); install_element(CONFIG_NODE, &debug_mroute_detail_cmd); install_element(CONFIG_NODE, &no_debug_mroute_cmd); diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index f7cd0dceab..dfba369e5b 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -882,15 +882,11 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json) frr_each (rb_pim_upstream, &pim->upstream_head, up) { char rpf_addr_str[PREFIX_STRLEN]; - char rib_nexthop_str[PREFIX_STRLEN]; const char *rpf_ifname; struct pim_rpf *rpf = &up->rpf; pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - pim_addr_dump("<nexthop?>", - &rpf->source_nexthop.mrib_nexthop_addr, - rib_nexthop_str, sizeof(rib_nexthop_str)); rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop @@ -921,8 +917,9 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json) rpf_ifname); json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - json_object_string_add(json_row, "ribNexthop", - rib_nexthop_str); + json_object_string_addf( + json_row, "ribNexthop", "%pPAs", + &rpf->source_nexthop.mrib_nexthop_addr); json_object_int_add( json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); @@ -933,9 +930,10 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json) } else { vty_out(vty, - "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", + "%-15pPAs %-15pPAs %-16s %-15s %-15pPAs %6d %4d\n", &up->sg.src, &up->sg.grp, rpf_ifname, - rpf_addr_str, rib_nexthop_str, + rpf_addr_str, + &rpf->source_nexthop.mrib_nexthop_addr, rpf->source_nexthop.mrib_route_metric, rpf->source_nexthop.mrib_metric_preference); } @@ -1519,16 +1517,12 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) "Source Group RpfIface RibNextHop RpfAddress \n"); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char rpf_nexthop_str[PREFIX_STRLEN]; char rpf_addr_str[PREFIX_STRLEN]; struct pim_rpf *rpf; const char *rpf_ifname; rpf = &up->rpf; - pim_addr_dump("<nexthop?>", - &rpf->source_nexthop.mrib_nexthop_addr, - rpf_nexthop_str, sizeof(rpf_nexthop_str)); pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); @@ -1559,15 +1553,17 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) json_object_string_add(json_row, "group", grp_str); json_object_string_add(json_row, "rpfInterface", rpf_ifname); - json_object_string_add(json_row, "ribNexthop", - rpf_nexthop_str); + json_object_string_addf( + json_row, "ribNexthop", "%pPAs", + &rpf->source_nexthop.mrib_nexthop_addr); json_object_string_add(json_row, "rpfAddress", rpf_addr_str); json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s\n", + vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15pPA %-15s\n", &up->sg.src, &up->sg.grp, rpf_ifname, - rpf_nexthop_str, rpf_addr_str); + &rpf->source_nexthop.mrib_nexthop_addr, + rpf_addr_str); } } diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index f5e0ef5878..c766d134b1 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -104,14 +104,6 @@ int gm_process_last_member_query_interval_cmd(struct vty *vty, int gm_process_no_last_member_query_interval_cmd(struct vty *vty); int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation, const char *src_str); -/* - * Special Macro to allow us to get the correct pim_instance - */ -#define PIM_DECLVAR_CONTEXT(A, B) \ - struct vrf *A = VTY_GET_CONTEXT(vrf); \ - struct pim_instance *B = \ - (vrf) ? vrf->info : pim_get_pim_instance(VRF_DEFAULT); \ - vrf = (vrf) ? vrf : pim->vrf /* * Special Macro to allow us to get the correct pim_instance; diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index 11bb2db7eb..9148d1050a 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -81,11 +81,9 @@ static bool mtrace_fwd_info_weak(struct pim_instance *pim, zlog_debug("mtrace pim_nexthop_lookup OK"); if (PIM_DEBUG_MTRACE) - zlog_debug("mtrace next_hop=%pI4", - &nexthop.mrib_nexthop_addr.u.prefix4); + zlog_debug("mtrace next_hop=%pPAs", &nexthop.mrib_nexthop_addr); - if (nexthop.mrib_nexthop_addr.family == AF_INET) - nh_addr = nexthop.mrib_nexthop_addr.u.prefix4; + nh_addr = nexthop.mrib_nexthop_addr; ifp_in = nexthop.interface; @@ -134,7 +132,7 @@ static bool mtrace_fwd_info(struct pim_instance *pim, } ifp_in = up->rpf.source_nexthop.interface; - nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4; + nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr; total = htonl(MTRACE_UNKNOWN_COUNT); if (PIM_DEBUG_MTRACE) diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 7c1c80f71a..10e515cb56 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -709,8 +709,8 @@ bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) } /* check if the MSDP peer is the nexthop for the RP */ - if (pim_nexthop_lookup(mp->pim, &nexthop, rp, 0) - && nexthop.mrib_nexthop_addr.u.prefix4.s_addr == mp->peer.s_addr) { + if (pim_nexthop_lookup(mp->pim, &nexthop, rp, 0) && + nexthop.mrib_nexthop_addr.s_addr == mp->peer.s_addr) { return true; } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 106bce61db..eec763a4ff 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -331,13 +331,12 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr_addr, if (if_is_loopback(ifp) && if_is_loopback(src_ifp)) return true; - nbr = pim_neighbor_find_prefix(ifp, &znh->nexthop_addr); + nbr = pim_neighbor_find(ifp, znh->nexthop_addr); if (!nbr) continue; - return znh->ifindex == src_ifp->ifindex - && znh->nexthop_addr.u.prefix4.s_addr - == src_ip.s_addr; + return znh->ifindex == src_ifp->ifindex && + (!pim_addr_cmp(znh->nexthop_addr, src_ip)); } return false; } @@ -406,8 +405,7 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr_addr, void pim_rp_nexthop_del(struct rp_info *rp_info) { rp_info->rp.source_nexthop.interface = NULL; - pim_addr_to_prefix(&rp_info->rp.source_nexthop.mrib_nexthop_addr, - PIMADDR_ANY); + rp_info->rp.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY; rp_info->rp.source_nexthop.mrib_metric_preference = router->infinite_assert_metric.metric_preference; rp_info->rp.source_nexthop.mrib_route_metric = @@ -510,7 +508,7 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim, uint32_t hash_val = 0, mod_val = 0; uint8_t nh_iter = 0, found = 0; uint32_t i, num_nbrs = 0; - pim_addr nh_addr = pim_addr_from_prefix(&(nexthop->mrib_nexthop_addr)); + pim_addr nh_addr = nexthop->mrib_nexthop_addr; pim_addr src_addr = pim_addr_from_prefix(src); pim_addr grp_addr = pim_addr_from_prefix(grp); @@ -546,9 +544,9 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim, if (curr_route_valid && !pim_if_connected_to_source(nexthop->interface, src_addr)) { - nbr = pim_neighbor_find_prefix( + nbr = pim_neighbor_find( nexthop->interface, - &nexthop->mrib_nexthop_addr); + nexthop->mrib_nexthop_addr); if (!nbr && !if_is_loopback(nexthop->interface)) { if (PIM_DEBUG_PIM_NHT) @@ -655,14 +653,10 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim, if (nh_iter == mod_val) { nexthop->interface = ifp; - nexthop->mrib_nexthop_addr.family = PIM_AF; - nexthop->mrib_nexthop_addr.prefixlen = PIM_MAX_BITLEN; #if PIM_IPV == 4 - nexthop->mrib_nexthop_addr.u.prefix4 = - nh_node->gate.ipv4; + nexthop->mrib_nexthop_addr = nh_node->gate.ipv4; #else - nexthop->mrib_nexthop_addr.u.prefix6 = - nh_node->gate.ipv6; + nexthop->mrib_nexthop_addr = nh_node->gate.ipv6; #endif nexthop->mrib_metric_preference = pnc->distance; nexthop->mrib_route_metric = pnc->metric; @@ -942,8 +936,8 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, ifps[i] = if_lookup_by_index(nexthop_tab[i].ifindex, pim->vrf->vrf_id); if (ifps[i]) { - nbrs[i] = pim_neighbor_find_prefix( - ifps[i], &nexthop_tab[i].nexthop_addr); + nbrs[i] = pim_neighbor_find( + ifps[i], nexthop_tab[i].nexthop_addr); if (nbrs[i] || pim_if_connected_to_source(ifps[i], src_addr)) num_nbrs++; @@ -1006,7 +1000,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, mod_val++; if (PIM_DEBUG_PIM_NHT) zlog_debug( - "%s: NBR (%pFXh) not found on input interface %s(%s) (RPF for source %pPA)", + "%s: NBR (%pPA) not found on input interface %s(%s) (RPF for source %pPA)", __func__, &nexthop_tab[i].nexthop_addr, ifp->name, pim->vrf->name, @@ -1017,19 +1011,13 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim, } if (i == mod_val) { - if (PIM_DEBUG_PIM_NHT) { - char nexthop_str[PREFIX_STRLEN]; - - pim_addr_dump("<nexthop?>", - &nexthop_tab[i].nexthop_addr, - nexthop_str, sizeof(nexthop_str)); + if (PIM_DEBUG_PIM_NHT) zlog_debug( - "%s: found nhop %s for addr %pPA interface %s(%s) metric %d dist %d", - __func__, nexthop_str, &src_addr, - ifp->name, pim->vrf->name, + "%s: found nhop %pPA for addr %pPA interface %s(%s) metric %d dist %d", + __func__, &nexthop_tab[i].nexthop_addr, + &src_addr, ifp->name, pim->vrf->name, nexthop_tab[i].route_metric, nexthop_tab[i].protocol_distance); - } /* update nexthop data */ nexthop->interface = ifp; nexthop->mrib_nexthop_addr = diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index cee542aa13..4e812ae3f0 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -76,7 +76,7 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, if (PIM_DEBUG_PIM_NHT) zlog_debug( "%s: Using last lookup for %pPAs at %lld, %" PRId64 - " addr %pFX", + " addr %pPAs", __func__, &addr, nexthop->last_lookup_time, pim->last_route_change_time, &nexthop->mrib_nexthop_addr); @@ -124,8 +124,8 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, i++; } else if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) { - nbr = pim_neighbor_find_prefix( - ifp, &nexthop_tab[i].nexthop_addr); + nbr = pim_neighbor_find(ifp, + nexthop_tab[i].nexthop_addr); if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug("ifp name: %s, pim nbr: %p", ifp->name, nbr); @@ -140,11 +140,12 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, if (found) { if (PIM_DEBUG_ZEBRA) zlog_debug( - "%s %s: found nexthop %pFX for address %pPAs: interface %s ifindex=%d metric=%d pref=%d", + "%s %s: found nexthop %pPAs for address %pPAs: interface %s ifindex=%d metric=%d pref=%d", __FILE__, __func__, &nexthop_tab[i].nexthop_addr, &addr, ifp->name, first_ifindex, nexthop_tab[i].route_metric, nexthop_tab[i].protocol_distance); + /* update nexthop data */ nexthop->interface = ifp; nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; @@ -162,11 +163,8 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, static int nexthop_mismatch(const struct pim_nexthop *nh1, const struct pim_nexthop *nh2) { - pim_addr nh_addr1 = pim_addr_from_prefix(&nh1->mrib_nexthop_addr); - pim_addr nh_addr2 = pim_addr_from_prefix(&nh2->mrib_nexthop_addr); - return (nh1->interface != nh2->interface) || - (pim_addr_cmp(nh_addr1, nh_addr2)) || + (pim_addr_cmp(nh1->mrib_nexthop_addr, nh2->mrib_nexthop_addr)) || (nh1->mrib_metric_preference != nh2->mrib_metric_preference) || (nh1->mrib_route_metric != nh2->mrib_route_metric); } @@ -257,7 +255,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { if (PIM_DEBUG_ZEBRA) - zlog_debug("%s(%s): (S,G)=%s source nexthop now is: interface=%s address=%pFX pref=%d metric=%d", + zlog_debug("%s(%s): (S,G)=%s source nexthop now is: interface=%s address=%pPAs pref=%d metric=%d", __func__, caller, up->sg_str, rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>", @@ -316,8 +314,7 @@ void pim_upstream_rpf_clear(struct pim_instance *pim, if (up->rpf.source_nexthop.interface) { pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED); up->rpf.source_nexthop.interface = NULL; - pim_addr_to_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr, - PIMADDR_ANY); + up->rpf.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY; up->rpf.source_nexthop.mrib_metric_preference = router->infinite_assert_metric.metric_preference; up->rpf.source_nexthop.mrib_route_metric = @@ -364,11 +361,8 @@ static pim_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ - pim_addr nhaddr; - - nhaddr = - pim_addr_from_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr); - neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, nhaddr); + neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, + up->rpf.source_nexthop.mrib_nexthop_addr); if (neigh) rpf_addr = neigh->source_addr; else diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 74aca43d54..40cd066bd1 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -39,7 +39,7 @@ struct pim_nexthop { pim_addr last_lookup; long long last_lookup_time; struct interface *interface; /* RPF_interface(S) */ - struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ + pim_addr mrib_nexthop_addr; /* MRIB.next_hop(S) */ uint32_t mrib_metric_preference; /* MRIB.pref(S) */ uint32_t mrib_route_metric; /* MRIB.metric(S) */ struct pim_neighbor *nbr; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 2b5b4bcf53..3817d5d9e1 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -838,8 +838,7 @@ void pim_upstream_fill_static_iif(struct pim_upstream *up, up->rpf.source_nexthop.interface = incoming; /* reset other parameters to matched a connected incoming interface */ - pim_addr_to_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr, - PIMADDR_ANY); + up->rpf.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY; up->rpf.source_nexthop.mrib_metric_preference = ZEBRA_CONNECT_DISTANCE_DEFAULT; up->rpf.source_nexthop.mrib_route_metric = 0; @@ -899,8 +898,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; up->rpf.source_nexthop.interface = NULL; - pim_addr_to_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr, - PIMADDR_ANY); + up->rpf.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY; up->rpf.source_nexthop.mrib_metric_preference = router->infinite_assert_metric.metric_preference; up->rpf.source_nexthop.mrib_route_metric = diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index b0db6b4d96..d044aec510 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -65,23 +65,28 @@ int pim_debug_config_write(struct vty *vty) vty_out(vty, "debug igmp packets\n"); ++writes; } - if (PIM_DEBUG_IGMP_TRACE) { + /* PIM_DEBUG_IGMP_TRACE catches _DETAIL too */ + if (router->debugs & PIM_MASK_IGMP_TRACE) { vty_out(vty, "debug igmp trace\n"); ++writes; } + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + vty_out(vty, "debug igmp trace detail\n"); + ++writes; + } - if (PIM_DEBUG_MROUTE) { + /* PIM_DEBUG_MROUTE catches _DETAIL too */ + if (router->debugs & PIM_MASK_MROUTE) { vty_out(vty, "debug mroute\n"); ++writes; } - - if (PIM_DEBUG_MTRACE) { - vty_out(vty, "debug mtrace\n"); + if (PIM_DEBUG_MROUTE_DETAIL) { + vty_out(vty, "debug mroute detail\n"); ++writes; } - if (PIM_DEBUG_MROUTE_DETAIL_ONLY) { - vty_out(vty, "debug mroute detail\n"); + if (PIM_DEBUG_MTRACE) { + vty_out(vty, "debug mtrace\n"); ++writes; } @@ -102,11 +107,12 @@ int pim_debug_config_write(struct vty *vty) ++writes; } - if (PIM_DEBUG_PIM_TRACE) { + /* PIM_DEBUG_PIM_TRACE catches _DETAIL too */ + if (router->debugs & PIM_MASK_PIM_TRACE) { vty_out(vty, "debug pim trace\n"); ++writes; } - if (PIM_DEBUG_PIM_TRACE_DETAIL_ONLY) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) { vty_out(vty, "debug pim trace detail\n"); ++writes; } diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 5d99f131a8..c3f0b44431 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -156,7 +156,7 @@ void zclient_lookup_new(void) static int zclient_read_nexthop(struct pim_instance *pim, struct zclient *zlookup, struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, struct in_addr addr) + const int tab_size, pim_addr addr) { int num_ifindex = 0; struct stream *s; @@ -165,19 +165,15 @@ static int zclient_read_nexthop(struct pim_instance *pim, uint8_t version; vrf_id_t vrf_id; uint16_t command = 0; - struct in_addr raddr; + pim_addr raddr; uint8_t distance; uint32_t metric; int nexthop_num; int i, err; - if (PIM_DEBUG_PIM_NHT_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s(%s)", __func__, addr_str, + if (PIM_DEBUG_PIM_NHT_DETAIL) + zlog_debug("%s: addr=%pPAs(%s)", __func__, &addr, pim->vrf->name); - } s = zlookup->ibuf; @@ -201,17 +197,15 @@ static int zclient_read_nexthop(struct pim_instance *pim, } } +#if PIM_IPV == 4 raddr.s_addr = stream_get_ipv4(s); - - if (raddr.s_addr != addr.s_addr) { - char addr_str[INET_ADDRSTRLEN]; - char raddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - pim_inet4_dump("<raddr?>", raddr, raddr_str, sizeof(raddr_str)); - zlog_warn("%s: address mismatch: addr=%s(%s) raddr=%s", - __func__, addr_str, pim->vrf->name, raddr_str); - /* warning only */ - } +#else + stream_get(&raddr, s, sizeof(struct in6_addr)); +#endif + if (pim_addr_cmp(raddr, addr)) + zlog_warn("%s: address mismatch: addr=%pPAs(%s) raddr=%pPAs", + __func__, &addr, pim->vrf->name, &raddr); + /* warning only */ distance = stream_getc(s); metric = stream_getl(s); @@ -233,12 +227,9 @@ static int zclient_read_nexthop(struct pim_instance *pim, nexthop_vrf_id = stream_getl(s); nexthop_type = stream_getc(s); if (num_ifindex >= tab_size) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); zlog_warn( - "%s: found too many nexthop ifindexes (%d > %d) for address %s(%s)", - __func__, (num_ifindex + 1), tab_size, addr_str, + "%s: found too many nexthop ifindexes (%d > %d) for address %pPAs(%s)", + __func__, (num_ifindex + 1), tab_size, &addr, pim->vrf->name); return num_ifindex; } @@ -254,32 +245,25 @@ static int zclient_read_nexthop(struct pim_instance *pim, * allow us to work in cases where we are * trying to find a route for this box. */ - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - nexthop_tab[num_ifindex].nexthop_addr.prefixlen = - IPV4_MAX_BITLEN; - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4 = - addr; + nexthop_tab[num_ifindex].nexthop_addr = addr; ++num_ifindex; break; case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = + nexthop_tab[num_ifindex].nexthop_addr.s_addr = stream_get_ipv4(s); nexthop_tab[num_ifindex].ifindex = stream_getl(s); ++num_ifindex; break; case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; - stream_get(&nexthop_tab[num_ifindex] - .nexthop_addr.u.prefix6, - s, sizeof(struct in6_addr)); + stream_get(&nexthop_tab[num_ifindex].nexthop_addr, s, + sizeof(struct in6_addr)); nexthop_tab[num_ifindex].ifindex = stream_getl(s); p.family = AF_INET6; p.prefixlen = IPV6_MAX_BITLEN; memcpy(&p.u.prefix6, - &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + &nexthop_tab[num_ifindex].nexthop_addr, sizeof(struct in6_addr)); /* @@ -298,23 +282,17 @@ static int zclient_read_nexthop(struct pim_instance *pim, nbr = pim_neighbor_find_if(ifp); if (nbr) { - nexthop_tab[num_ifindex].nexthop_addr.family = - AF_INET; - pim_addr_to_prefix( - &nexthop_tab[num_ifindex].nexthop_addr, - nbr->source_addr); + nexthop_tab[num_ifindex].nexthop_addr = + nbr->source_addr; } ++num_ifindex; break; default: /* do nothing */ { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); zlog_warn( - "%s: found non-ifindex nexthop type=%d for address %s(%s)", - __func__, nexthop_type, addr_str, + "%s: found non-ifindex nexthop type=%d for address %pPAs(%s)", + __func__, nexthop_type, &addr, pim->vrf->name); } break; @@ -326,17 +304,14 @@ static int zclient_read_nexthop(struct pim_instance *pim, static int zclient_lookup_nexthop_once(struct pim_instance *pim, struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, struct in_addr addr) + const int tab_size, pim_addr addr) { struct stream *s; int ret; - if (PIM_DEBUG_PIM_NHT_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s(%s)", __func__, addr_str, + if (PIM_DEBUG_PIM_NHT_DETAIL) + zlog_debug("%s: addr=%pPAs(%s)", __func__, &addr, pim->vrf->name); - } /* Check socket. */ if (zlookup->sock < 0) { @@ -358,7 +333,11 @@ static int zclient_lookup_nexthop_once(struct pim_instance *pim, stream_reset(s); zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, pim->vrf->vrf_id); +#if PIM_IPV == 4 stream_put_in_addr(s, &addr); +#else + stream_write(s, (uint8_t *)&addr, 16); +#endif stream_putw_at(s, 0, stream_get_endp(s)); ret = writen(zlookup->sock, s->data, stream_get_endp(s)); @@ -386,7 +365,7 @@ void zclient_lookup_read_pipe(struct thread *thread) struct zclient *zlookup = THREAD_ARG(thread); struct pim_instance *pim = pim_get_pim_instance(VRF_DEFAULT); struct pim_zlookup_nexthop nexthop_tab[10]; - struct in_addr l = {.s_addr = INADDR_ANY}; + pim_addr l = PIMADDR_ANY; if (!pim) { if (PIM_DEBUG_PIM_NHT_DETAIL) @@ -413,7 +392,7 @@ int zclient_lookup_nexthop(struct pim_instance *pim, for (lookup = 0; lookup < max_lookup; ++lookup) { int num_ifindex; int first_ifindex; - struct prefix nexthop_addr; + pim_addr nexthop_addr; num_ifindex = zclient_lookup_nexthop_once(pim, nexthop_tab, tab_size, addr); @@ -462,8 +441,7 @@ int zclient_lookup_nexthop(struct pim_instance *pim, nexthop_tab[0].route_metric); /* use last address as nexthop address */ - pim_addr_to_prefix( - &(nexthop_tab[0].nexthop_addr), addr); + nexthop_tab[0].nexthop_addr = addr; /* report original route metric/distance */ nexthop_tab[0].route_metric = route_metric; @@ -474,23 +452,16 @@ int zclient_lookup_nexthop(struct pim_instance *pim, return num_ifindex; } - if (PIM_DEBUG_PIM_NHT) { - char addr_str[INET_ADDRSTRLEN]; - char nexthop_str[PREFIX_STRLEN]; - pim_inet4_dump("<addr?>", addr, addr_str, - sizeof(addr_str)); - pim_addr_dump("<nexthop?>", &nexthop_addr, nexthop_str, - sizeof(nexthop_str)); + if (PIM_DEBUG_PIM_NHT) zlog_debug( - "%s: lookup=%d/%d: zebra returned recursive nexthop %s for address %pPA(%s) dist=%d met=%d", - __func__, lookup, max_lookup, nexthop_str, + "%s: lookup=%d/%d: zebra returned recursive nexthop %pPAs for address %pPA(%s) dist=%d met=%d", + __func__, lookup, max_lookup, &nexthop_addr, &addr, pim->vrf->name, nexthop_tab[0].protocol_distance, nexthop_tab[0].route_metric); - } - addr = pim_addr_from_prefix(&(nexthop_addr)); /* use nexthop - addr for recursive lookup */ + addr = nexthop_addr; /* use nexthop + addr for recursive lookup */ } /* for (max_lookup) */ diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index c3818dbdbc..4ea865a7e7 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -28,7 +28,7 @@ struct pim_zlookup_nexthop { vrf_id_t vrf_id; - struct prefix nexthop_addr; + pim_addr nexthop_addr; ifindex_t ifindex; uint32_t route_metric; uint8_t protocol_distance; diff --git a/pimd/pimd.h b/pimd/pimd.h index 1f7919ac6c..aeb4859952 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -157,23 +157,22 @@ extern uint8_t qpim_ecmp_rebalance_enable; (router->debugs & PIM_MASK_PIM_PACKETDUMP_SEND) #define PIM_DEBUG_PIM_PACKETDUMP_RECV \ (router->debugs & PIM_MASK_PIM_PACKETDUMP_RECV) -#define PIM_DEBUG_PIM_TRACE (router->debugs & PIM_MASK_PIM_TRACE) +#define PIM_DEBUG_PIM_TRACE \ + (router->debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_PIM_TRACE_DETAIL)) #define PIM_DEBUG_PIM_TRACE_DETAIL \ - (router->debugs & (PIM_MASK_PIM_TRACE_DETAIL | PIM_MASK_PIM_TRACE)) -#define PIM_DEBUG_PIM_TRACE_DETAIL_ONLY \ (router->debugs & PIM_MASK_PIM_TRACE_DETAIL) #define PIM_DEBUG_IGMP_EVENTS (router->debugs & PIM_MASK_IGMP_EVENTS) #define PIM_DEBUG_IGMP_PACKETS (router->debugs & PIM_MASK_IGMP_PACKETS) -#define PIM_DEBUG_IGMP_TRACE (router->debugs & PIM_MASK_IGMP_TRACE) +#define PIM_DEBUG_IGMP_TRACE \ + (router->debugs & (PIM_MASK_IGMP_TRACE | PIM_MASK_IGMP_TRACE_DETAIL)) #define PIM_DEBUG_IGMP_TRACE_DETAIL \ - (router->debugs & (PIM_MASK_IGMP_TRACE_DETAIL | PIM_MASK_IGMP_TRACE)) + (router->debugs & PIM_MASK_IGMP_TRACE_DETAIL) #define PIM_DEBUG_ZEBRA (router->debugs & PIM_MASK_ZEBRA) #define PIM_DEBUG_MLAG (router->debugs & PIM_MASK_MLAG) #define PIM_DEBUG_SSMPINGD (router->debugs & PIM_MASK_SSMPINGD) -#define PIM_DEBUG_MROUTE (router->debugs & PIM_MASK_MROUTE) -#define PIM_DEBUG_MROUTE_DETAIL \ - (router->debugs & (PIM_MASK_MROUTE_DETAIL | PIM_MASK_MROUTE)) -#define PIM_DEBUG_MROUTE_DETAIL_ONLY (router->debugs & PIM_MASK_MROUTE_DETAIL) +#define PIM_DEBUG_MROUTE \ + (router->debugs & (PIM_MASK_MROUTE | PIM_MASK_MROUTE_DETAIL)) +#define PIM_DEBUG_MROUTE_DETAIL (router->debugs & PIM_MASK_MROUTE_DETAIL) #define PIM_DEBUG_PIM_HELLO (router->debugs & PIM_MASK_PIM_HELLO) #define PIM_DEBUG_PIM_J_P (router->debugs & PIM_MASK_PIM_J_P) #define PIM_DEBUG_PIM_REG (router->debugs & PIM_MASK_PIM_REG) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 889643f65e..2281b3ce26 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -104,7 +104,7 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, p.family = AF_INET6; } else { type_import = true; - p = *(const struct prefix *)inhop; + prefix_copy(&p, inhop); } sharp_nh_tracker_get(&p); @@ -149,7 +149,7 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, } else { type_import = true; - p = *(const struct prefix *)inhop; + prefix_copy(&p, inhop); } sharp_nh_tracker_get(&p); diff --git a/staticd/static_routes.c b/staticd/static_routes.c index 589d509a59..ed4cdc51ce 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -369,13 +369,11 @@ void static_install_nexthop(struct static_nexthop *nh) switch (nh->type) { case STATIC_IPV4_GATEWAY: case STATIC_IPV6_GATEWAY: - if (!static_zebra_nh_update(nh)) - static_zebra_nht_register(nh, true); + static_zebra_nht_register(nh, true); break; case STATIC_IPV4_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME: - if (!static_zebra_nh_update(nh)) - static_zebra_nht_register(nh, true); + static_zebra_nht_register(nh, true); break; case STATIC_BLACKHOLE: static_install_path(pn); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index bf0e4e8ab9..de07ad8ef3 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -57,6 +57,7 @@ struct static_nht_data { uint32_t refcount; uint8_t nh_num; + bool registered; }; static int static_nht_data_cmp(const struct static_nht_data *nhtd1, @@ -175,9 +176,12 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) return 0; } + static void zebra_connected(struct zclient *zclient) { zclient_send_reg_requests(zclient, VRF_DEFAULT); + + static_fixup_vrf_ids(vrf_info_lookup(VRF_DEFAULT)); } /* API to check whether the configured nexthop address is @@ -262,8 +266,12 @@ static_nht_hash_getref(const struct static_nht_data *ref) return nhtd; } -static bool static_nht_hash_decref(struct static_nht_data *nhtd) +static bool static_nht_hash_decref(struct static_nht_data **nhtd_p) { + struct static_nht_data *nhtd = *nhtd_p; + + *nhtd_p = NULL; + if (--nhtd->refcount > 0) return true; @@ -280,133 +288,110 @@ static void static_nht_hash_clear(void) XFREE(MTYPE_STATIC_NHT_DATA, nhtd); } -void static_zebra_nht_register(struct static_nexthop *nh, bool reg) +static bool static_zebra_nht_get_prefix(const struct static_nexthop *nh, + struct prefix *p) { - struct static_path *pn = nh->pn; - struct route_node *rn = pn->rn; - struct static_route_info *si = static_route_info_from_rnode(rn); - struct static_nht_data lookup; - uint32_t cmd; - struct prefix p; - afi_t afi = AFI_IP; - - cmd = (reg) ? - ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER; - - if (nh->nh_registered && reg) - return; - - if (!nh->nh_registered && !reg) - return; - - memset(&p, 0, sizeof(p)); switch (nh->type) { case STATIC_IFNAME: case STATIC_BLACKHOLE: - return; + p->family = AF_UNSPEC; + return false; + case STATIC_IPV4_GATEWAY: case STATIC_IPV4_GATEWAY_IFNAME: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nh->addr.ipv4; - afi = AFI_IP; - break; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = nh->addr.ipv4; + return true; + case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY_IFNAME: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = nh->addr.ipv6; - afi = AFI_IP6; - break; + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_BITLEN; + p->u.prefix6 = nh->addr.ipv6; + return true; } - memset(&lookup, 0, sizeof(lookup)); - lookup.nh = p; + assertf(0, "BUG: someone forgot to add nexthop type %u", nh->type); +} + +void static_zebra_nht_register(struct static_nexthop *nh, bool reg) +{ + struct static_path *pn = nh->pn; + struct route_node *rn = pn->rn; + struct static_route_info *si = static_route_info_from_rnode(rn); + struct static_nht_data *nhtd, lookup = {}; + uint32_t cmd; + + if (!static_zebra_nht_get_prefix(nh, &lookup.nh)) + return; lookup.nh_vrf_id = nh->nh_vrf_id; lookup.safi = si->safi; - nh->nh_registered = reg; - - if (reg) { - struct static_nht_data *nhtd; + if (nh->nh_registered) { + /* nh->nh_registered means we own a reference on the nhtd */ + nhtd = static_nht_hash_find(static_nht_hash, &lookup); + assertf(nhtd, "BUG: NH %pFX registered but not in hashtable", + &lookup.nh); + } else if (reg) { nhtd = static_nht_hash_getref(&lookup); - if (nhtd->refcount > 1) { + if (nhtd->refcount > 1) DEBUGD(&static_dbg_route, - "Already registered nexthop(%pFX) for %pRN %d", - &p, rn, nhtd->nh_num); - if (nhtd->nh_num) - static_nht_update(&rn->p, &nhtd->nh, - nhtd->nh_num, afi, si->safi, - nh->nh_vrf_id); - return; - } + "Reusing registered nexthop(%pFX) for %pRN %d", + &lookup.nh, rn, nhtd->nh_num); } else { - struct static_nht_data *nhtd; + /* !reg && !nh->nh_registered */ + zlog_warn("trying to unregister nexthop %pFX twice", + &lookup.nh); + return; + } - nhtd = static_nht_hash_find(static_nht_hash, &lookup); - if (!nhtd) + nh->nh_registered = reg; + + if (reg) { + if (nhtd->nh_num) { + /* refresh with existing data */ + afi_t afi = prefix_afi(&lookup.nh); + + if (nh->state == STATIC_NOT_INSTALLED) + nh->state = STATIC_START; + static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi, + si->safi, nh->nh_vrf_id); return; - if (static_nht_hash_decref(nhtd)) + } + + if (nhtd->registered) + /* have no data, but did send register */ return; - } - DEBUGD(&static_dbg_route, "%s nexthop(%pFX) for %pRN", - reg ? "Registering" : "Unregistering", &p, rn); + cmd = ZEBRA_NEXTHOP_REGISTER; + DEBUGD(&static_dbg_route, "Registering nexthop(%pFX) for %pRN", + &lookup.nh, rn); + } else { + bool was_zebra_registered; - if (zclient_send_rnh(zclient, cmd, &p, si->safi, false, false, - nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) - zlog_warn("%s: Failure to send nexthop to zebra", __func__); -} -/* - * When nexthop gets updated via configuration then use the - * already registered NH and resend the route to zebra - */ -int static_zebra_nh_update(struct static_nexthop *nh) -{ - struct static_path *pn = nh->pn; - struct route_node *rn = pn->rn; - struct static_route_info *si = static_route_info_from_rnode(rn); - struct static_nht_data *nhtd, lookup = {}; - struct prefix p = {}; - afi_t afi = AFI_IP; + was_zebra_registered = nhtd->registered; + if (static_nht_hash_decref(&nhtd)) + /* still got references alive */ + return; - if (!nh->nh_registered) - return 0; + /* NB: nhtd is now NULL. */ + if (!was_zebra_registered) + return; - switch (nh->type) { - case STATIC_IFNAME: - case STATIC_BLACKHOLE: - return 0; - case STATIC_IPV4_GATEWAY: - case STATIC_IPV4_GATEWAY_IFNAME: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nh->addr.ipv4; - afi = AFI_IP; - break; - case STATIC_IPV6_GATEWAY: - case STATIC_IPV6_GATEWAY_IFNAME: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = nh->addr.ipv6; - afi = AFI_IP6; - break; + cmd = ZEBRA_NEXTHOP_UNREGISTER; + DEBUGD(&static_dbg_route, + "Unregistering nexthop(%pFX) for %pRN", &lookup.nh, rn); } - lookup.nh = p; - lookup.nh_vrf_id = nh->nh_vrf_id; - lookup.safi = si->safi; - - nhtd = static_nht_hash_find(static_nht_hash, &lookup); - if (nhtd && nhtd->nh_num) { - nh->state = STATIC_START; - static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi, - si->safi, nh->nh_vrf_id); - return 1; - } - return 0; + if (zclient_send_rnh(zclient, cmd, &lookup.nh, si->safi, false, false, + nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE) + zlog_warn("%s: Failure to send nexthop %pFX for %pRN to zebra", + __func__, &lookup.nh, rn); + else if (reg) + nhtd->registered = true; } extern void static_zebra_route_add(struct static_path *pn, bool install) diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h index e30fa3fd57..1cf13dcbbb 100644 --- a/staticd/static_zebra.h +++ b/staticd/static_zebra.h @@ -33,7 +33,6 @@ extern void static_zebra_init(void); extern void static_zebra_stop(void); extern void static_zebra_vrf_register(struct vrf *vrf); extern void static_zebra_vrf_unregister(struct vrf *vrf); -extern int static_zebra_nh_update(struct static_nexthop *nh); #ifdef __cplusplus } diff --git a/tests/topotests/bgp_set_aspath_replace/__init__.py b/tests/topotests/bgp_set_aspath_replace/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/__init__.py diff --git a/tests/topotests/bgp_set_aspath_replace/r1/bgpd.conf b/tests/topotests/bgp_set_aspath_replace/r1/bgpd.conf new file mode 100644 index 0000000000..1e98f4e491 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r1/bgpd.conf @@ -0,0 +1,17 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 3 10 + address-family ipv4 unicast + neighbor 192.168.1.2 route-map r2 in + exit-address-family +! +ip prefix-list p1 seq 5 permit 172.16.255.31/32 +! +route-map r2 permit 10 + match ip address prefix-list p1 + set as-path replace 65003 +route-map r2 permit 20 + set as-path replace any +! diff --git a/tests/topotests/bgp_set_aspath_replace/r1/zebra.conf b/tests/topotests/bgp_set_aspath_replace/r1/zebra.conf new file mode 100644 index 0000000000..acf120b200 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r1/zebra.conf @@ -0,0 +1,6 @@ +! +interface r1-eth0 + ip address 192.168.1.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_set_aspath_replace/r2/bgpd.conf b/tests/topotests/bgp_set_aspath_replace/r2/bgpd.conf new file mode 100644 index 0000000000..23367f94ff --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r2/bgpd.conf @@ -0,0 +1,8 @@ +! +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 3 10 + neighbor 192.168.2.1 remote-as external + neighbor 192.168.2.1 timers 3 10 +! diff --git a/tests/topotests/bgp_set_aspath_replace/r2/zebra.conf b/tests/topotests/bgp_set_aspath_replace/r2/zebra.conf new file mode 100644 index 0000000000..f229954341 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r2/zebra.conf @@ -0,0 +1,9 @@ +! +interface r2-eth0 + ip address 192.168.1.2/24 +! +interface r2-eth1 + ip address 192.168.2.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_set_aspath_replace/r3/bgpd.conf b/tests/topotests/bgp_set_aspath_replace/r3/bgpd.conf new file mode 100644 index 0000000000..b7a7ceda13 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r3/bgpd.conf @@ -0,0 +1,9 @@ +! +router bgp 65003 + no bgp ebgp-requires-policy + neighbor 192.168.2.2 remote-as external + neighbor 192.168.2.2 timers 3 10 + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_set_aspath_replace/r3/zebra.conf b/tests/topotests/bgp_set_aspath_replace/r3/zebra.conf new file mode 100644 index 0000000000..3fa6c64484 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/r3/zebra.conf @@ -0,0 +1,10 @@ +! +int lo + ip address 172.16.255.31/32 + ip address 172.16.255.32/32 +! +interface r3-eth0 + ip address 192.168.2.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py b/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py new file mode 100644 index 0000000000..d5549ae899 --- /dev/null +++ b/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# +# test_bgp_set_aspath_replace.py +# +# Copyright (c) 2022 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Test if `set as-path replace` is working correctly for route-maps. +""" + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + for routern in range(1, 5): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_maximum_prefix_out(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "172.16.255.31/32": [{"path": "65002 65001"}], + "172.16.255.32/32": [{"path": "65001 65001"}], + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, tgen.gears["r1"]) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) + + assert result is None, "Failed overriding incoming AS-PATH with route-map" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 4f30f7fbd8..f47f9a7eb0 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -763,6 +763,38 @@ def check_for_exit_vrf(lines_to_add, lines_to_del): return (lines_to_add, lines_to_del) +def bgp_delete_inst_move_line(lines_to_del): + # Deletion of bgp default inst followed by + # bgp vrf inst leads to issue of default + # instance can not be removed. + # Move the bgp default instance line to end. + bgp_defult_inst = False + bgp_vrf_inst = False + + for (ctx_keys, line) in lines_to_del: + # Find bgp default inst + if ( + ctx_keys[0].startswith("router bgp") + and not line + and "vrf" not in ctx_keys[0] + ): + bgp_defult_inst = True + # Find bgp vrf inst + if ctx_keys[0].startswith("router bgp") and not line and "vrf" in ctx_keys[0]: + bgp_vrf_inst = True + + if bgp_defult_inst and bgp_vrf_inst: + for (ctx_keys, line) in lines_to_del: + # move bgp default inst to end + if ( + ctx_keys[0].startswith("router bgp") + and not line + and "vrf" not in ctx_keys[0] + ): + lines_to_del.remove((ctx_keys, line)) + lines_to_del.append((ctx_keys, line)) + + def bgp_delete_nbr_remote_as_line(lines_to_add): # Handle deletion of neighbor <nbr> remote-as line from # lines_to_add if the nbr is configured with peer-group and @@ -841,19 +873,44 @@ def bgp_delete_nbr_remote_as_line(lines_to_add): lines_to_add.remove((ctx_keys, line)) -""" -This method handles deletion of bgp peer group config. -The objective is to delete config lines related to peers -associated with the peer-group and move the peer-group -config line to the end of the lines_to_del list. -""" +def bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict): + + # This method handles deletion of bgp neighbor configs, + # if there is neighbor to peer-group cmd is in delete list. + # As 'no neighbor .* peer-group' deletes the neighbor, + # subsequent neighbor speciic config line deletion results + # in error. + lines_to_del_to_del = [] + + for (ctx_keys, line) in lines_to_del: + if ( + ctx_keys[0].startswith("router bgp") + and line + and line.startswith("neighbor ") + ): + if ctx_keys[0] in del_nbr_dict: + for nbr in del_nbr_dict[ctx_keys[0]]: + re_nbr_pg = re.search('neighbor (\S+) .*peer-group (\S+)', line) + nb_exp = "neighbor %s .*" % nbr + if not re_nbr_pg: + re_nb = re.search(nb_exp, line) + if re_nb: + lines_to_del_to_del.append((ctx_keys, line)) + + for (ctx_keys, line) in lines_to_del_to_del: + lines_to_del.remove((ctx_keys, line)) def delete_move_lines(lines_to_add, lines_to_del): + # This method handles deletion of bgp peer group config. + # The objective is to delete config lines related to peers + # associated with the peer-group and move the peer-group + # config line to the end of the lines_to_del list. bgp_delete_nbr_remote_as_line(lines_to_add) del_dict = dict() + del_nbr_dict = dict() # Stores the lines to move to the end of the pending list. lines_to_del_to_del = [] # Stores the lines to move to end of the pending list. @@ -937,6 +994,16 @@ def delete_move_lines(lines_to_add, lines_to_del): if re_nb_remoteas: lines_to_del_to_app.append((ctx_keys, line)) + # 'no neighbor peer [interface] peer-group <>' is in lines_to_del + # copy the neighbor and look for all config removal lines associated + # to neighbor and delete them from the lines_to_del + re_nbr_pg = re.search('neighbor (\S+) .*peer-group (\S+)', line) + if re_nbr_pg: + if ctx_keys[0] not in del_nbr_dict: + del_nbr_dict[ctx_keys[0]] = list() + if re_nbr_pg.group(1) not in del_nbr_dict[ctx_keys[0]]: + del_nbr_dict[ctx_keys[0]].append(re_nbr_pg.group(1)) + # {'router bgp 65001': {'PG': [], 'PG1': []}, # 'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}} if ctx_keys[0] not in del_dict: @@ -948,6 +1015,9 @@ def delete_move_lines(lines_to_add, lines_to_del): found_pg_del_cmd = True if found_pg_del_cmd == False: + bgp_delete_inst_move_line(lines_to_del) + if del_nbr_dict: + bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict) return (lines_to_add, lines_to_del) for (ctx_keys, line) in lines_to_del_to_app: @@ -1001,6 +1071,8 @@ def delete_move_lines(lines_to_add, lines_to_del): lines_to_del.remove((ctx_keys, line)) lines_to_del.append((ctx_keys, line)) + bgp_delete_inst_move_line(lines_to_del) + return (lines_to_add, lines_to_del) diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index 74008bc078..eaa7891f0c 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -282,6 +282,12 @@ module frr-bgp-route-map { "Set the BGP AS-path attribute"; } + identity as-path-replace { + base frr-route-map:rmap-set-type; + description + "Replace ASNs to local AS number"; + } + identity set-community { base frr-route-map:rmap-set-type; description @@ -793,6 +799,15 @@ module frr-bgp-route-map { } } + case as-path-replace { + when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-replace')"; + leaf replace-as-path { + type string; + description + "Replace ASNs to local AS number"; + } + } + case community { when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-community')"; choice community { |
