summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/ptm_adapter.c3
-rw-r--r--bgpd/bgp_aspath.c22
-rw-r--r--bgpd/bgp_aspath.h2
-rw-r--r--bgpd/bgp_evpn.c6
-rw-r--r--bgpd/bgp_evpn_mh.c19
-rw-r--r--bgpd/bgp_mplsvpn.c24
-rw-r--r--bgpd/bgp_nht.c34
-rw-r--r--bgpd/bgp_route.c28
-rw-r--r--bgpd/bgp_routemap.c91
-rw-r--r--bgpd/bgp_routemap_nb.c7
-rw-r--r--bgpd/bgp_routemap_nb.h4
-rw-r--r--bgpd/bgp_routemap_nb_config.c52
-rw-r--r--doc/user/bgp.rst5
-rw-r--r--isisd/isis_lfa.c5
-rw-r--r--lib/command.c12
-rw-r--r--lib/prefix.h5
-rw-r--r--lib/routemap.h1
-rw-r--r--lib/routemap_cli.c5
-rw-r--r--pimd/pim6_cmd.c23
-rw-r--r--pimd/pim_cmd.c60
-rw-r--r--pimd/pim_cmd_common.c28
-rw-r--r--pimd/pim_cmd_common.h8
-rw-r--r--pimd/pim_igmp_mtrace.c8
-rw-r--r--pimd/pim_msdp.c4
-rw-r--r--pimd/pim_nht.c44
-rw-r--r--pimd/pim_rpf.c26
-rw-r--r--pimd/pim_rpf.h2
-rw-r--r--pimd/pim_upstream.c6
-rw-r--r--pimd/pim_vty.c24
-rw-r--r--pimd/pim_zlookup.c105
-rw-r--r--pimd/pim_zlookup.h2
-rw-r--r--pimd/pimd.h17
-rw-r--r--sharpd/sharp_vty.c4
-rw-r--r--staticd/static_routes.c6
-rw-r--r--staticd/static_zebra.c187
-rw-r--r--staticd/static_zebra.h1
-rw-r--r--tests/topotests/bgp_set_aspath_replace/__init__.py0
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r1/bgpd.conf17
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r3/bgpd.conf9
-rw-r--r--tests/topotests/bgp_set_aspath_replace/r3/zebra.conf10
-rw-r--r--tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py103
-rwxr-xr-xtools/frr-reload.py84
-rw-r--r--yang/frr-bgp-route-map.yang15
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 {