diff options
author | Russ White <russ@riw.us> | 2023-02-21 14:01:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-21 14:01:03 +0100 |
commit | ba755d35e508c2452e5459bdd7c0dd67a70a88a4 (patch) | |
tree | adc08f46788b8012240faec23ae7e7271bb0d40d /bgpd | |
parent | Merge pull request #12849 from opensourcerouting/fix/tests_enum (diff) | |
parent | bgpd: handle case where passed RD is null (diff) | |
download | frr-ba755d35e508c2452e5459bdd7c0dd67a70a88a4.tar.xz frr-ba755d35e508c2452e5459bdd7c0dd67a70a88a4.zip |
Merge pull request #12248 from pguibert6WIND/bgpasdot
lib, bgp: add initial support for asdot format
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_aspath.c | 81 | ||||
-rw-r--r-- | bgpd/bgp_aspath.h | 12 | ||||
-rw-r--r-- | bgpd/bgp_attr.c | 24 | ||||
-rw-r--r-- | bgpd/bgp_btoa.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_debug.c | 11 | ||||
-rw-r--r-- | bgpd/bgp_evpn.c | 16 | ||||
-rw-r--r-- | bgpd/bgp_evpn_mh.c | 28 | ||||
-rw-r--r-- | bgpd/bgp_evpn_private.h | 1 | ||||
-rw-r--r-- | bgpd/bgp_evpn_vty.c | 78 | ||||
-rw-r--r-- | bgpd/bgp_mplsvpn.c | 21 | ||||
-rw-r--r-- | bgpd/bgp_mplsvpn_snmp.c | 6 | ||||
-rw-r--r-- | bgpd/bgp_network.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_nexthop.c | 17 | ||||
-rw-r--r-- | bgpd/bgp_nht.c | 16 | ||||
-rw-r--r-- | bgpd/bgp_rd.c | 100 | ||||
-rw-r--r-- | bgpd/bgp_rd.h | 17 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 84 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 1 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 58 | ||||
-rw-r--r-- | bgpd/bgp_rpki.c | 53 | ||||
-rw-r--r-- | bgpd/bgp_script.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 395 | ||||
-rw-r--r-- | bgpd/bgp_vty.h | 3 | ||||
-rw-r--r-- | bgpd/bgpd.c | 127 | ||||
-rw-r--r-- | bgpd/bgpd.h | 48 | ||||
-rw-r--r-- | bgpd/rfapi/bgp_rfapi_cfg.c | 9 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi.c | 6 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_import.c | 12 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_rib.c | 6 | ||||
-rw-r--r-- | bgpd/rfapi/rfapi_vty.c | 3 |
30 files changed, 833 insertions, 408 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 584f524f0..2cc7e4657 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -287,9 +287,13 @@ static struct assegment *assegment_normalise(struct assegment *head) return head; } -static struct aspath *aspath_new(void) +static struct aspath *aspath_new(enum asnotation_mode asnotation) { - return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); + struct aspath *as; + + as = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); + as->asnotation = asnotation; + return as; } /* Free AS path structure. */ @@ -537,8 +541,10 @@ static void aspath_make_str_count(struct aspath *as, bool make_json) * * This was changed to 10 after the well-known BGP assertion, which * had hit some parts of the Internet in May of 2009. + * plain format : '4294967295 ' : 10 + 1 + * astod format : '65535.65535 ': 11 + 1 */ -#define ASN_STR_LEN (10 + 1) +#define ASN_STR_LEN (11 + 1) str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1, ASPATH_STR_DEFAULT_LEN); str_buf = XMALLOC(MTYPE_AS_STR, str_size); @@ -569,7 +575,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json) /* We might need to increase str_buf, particularly if path has * differing segments types, our initial guesstimate above will - * have been wrong. Need 10 chars for ASN, a separator each and + * have been wrong. Need 11 chars for ASN, a separator each and * potentially two segment delimiters, plus a space between each * segment and trailing zero. * @@ -595,12 +601,11 @@ static void aspath_make_str_count(struct aspath *as, bool make_json) /* write out the ASNs, with their separators, bar the last one*/ for (i = 0; i < seg->length; i++) { if (make_json) - json_object_array_add( - jseg_list, - json_object_new_int64(seg->as[i])); - - len += snprintf(str_buf + len, str_size - len, "%u", - seg->as[i]); + asn_asn2json_array(jseg_list, seg->as[i], + as->asnotation); + len += snprintfrr(str_buf + len, str_size - len, + ASN_FORMAT(as->asnotation), + &seg->as[i]); if (i < (seg->length - 1)) len += snprintf(str_buf + len, str_size - len, @@ -691,6 +696,7 @@ struct aspath *aspath_dup(struct aspath *aspath) new->str = XMALLOC(MTYPE_AS_STR, buflen); new->str_len = aspath->str_len; + new->asnotation = aspath->asnotation; /* copy the string data */ if (aspath->str_len > 0) @@ -718,6 +724,7 @@ static void *aspath_hash_alloc(void *arg) new->str = aspath->str; new->str_len = aspath->str_len; new->json = aspath->json; + new->asnotation = aspath->asnotation; return new; } @@ -825,7 +832,8 @@ static int assegments_parse(struct stream *s, size_t length, On error NULL is returned. */ -struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit) +struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit, + enum asnotation_mode asnotation) { struct aspath as; struct aspath *find; @@ -840,6 +848,7 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit) return NULL; memset(&as, 0, sizeof(as)); + as.asnotation = asnotation; if (assegments_parse(s, length, &as.segments, use32bit) < 0) return NULL; @@ -1057,7 +1066,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2) seg = assegment_append_asns(seg, seg1->as, match); if (!aspath) { - aspath = aspath_new(); + aspath = aspath_new(as1->asnotation); aspath->segments = seg; } else prevseg->next = seg; @@ -1077,7 +1086,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2) } if (!aspath) - aspath = aspath_new(); + aspath = aspath_new(as1->asnotation); /* Make as-set using rest of all information. */ from = match; @@ -1521,7 +1530,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source, struct assegment *srcseg, *exclseg, *lastseg; struct aspath *newpath; - newpath = aspath_new(); + newpath = aspath_new(source->asnotation); lastseg = NULL; for (srcseg = source->segments; srcseg; srcseg = srcseg->next) { @@ -1751,7 +1760,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath, newseg = assegment_append_asns(newseg, seg->as, cpasns); if (!newpath) { - newpath = aspath_new(); + newpath = aspath_new(aspath->asnotation); newpath->segments = newseg; } else prevseg->next = newseg; @@ -1880,16 +1889,16 @@ static void aspath_segment_add(struct aspath *as, int type) as->segments = new; } -struct aspath *aspath_empty(void) +struct aspath *aspath_empty(enum asnotation_mode asnotation) { - return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */ + return aspath_parse(NULL, 0, 1, asnotation); /* 32Bit ;-) */ } struct aspath *aspath_empty_get(void) { struct aspath *aspath; - aspath = aspath_new(); + aspath = aspath_new(bgp_get_asnotation(NULL)); aspath_make_str_count(aspath, false); return aspath; } @@ -1925,6 +1934,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token, unsigned long *asno) { const char *p = buf; + as_t asval; + bool found = false; /* Skip separators (space for sequences, ',' for sets). */ while (isspace((unsigned char)*p) || *p == ',') @@ -1961,30 +1972,18 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token, return p; } - /* Check actual AS value. */ - if (isdigit((unsigned char)*p)) { - as_t asval; - - *token = as_token_asval; - asval = (*p - '0'); - p++; - - while (isdigit((unsigned char)*p)) { - asval *= 10; - asval += (*p - '0'); - p++; - } + asval = 0; + p = asn_str2asn_parse(p, &asval, &found); + if (found) { *asno = asval; - return p; - } - - /* There is no match then return unknown token. */ - *token = as_token_unknown; - p++; + *token = as_token_asval; + } else + *token = as_token_unknown; return p; } -struct aspath *aspath_str2aspath(const char *str) +struct aspath *aspath_str2aspath(const char *str, + enum asnotation_mode asnotation) { enum as_token token = as_token_unknown; unsigned short as_type; @@ -1992,7 +1991,7 @@ struct aspath *aspath_str2aspath(const char *str) struct aspath *aspath; int needtype; - aspath = aspath_new(); + aspath = aspath_new(asnotation); /* We start default type as AS_SEQUENCE. */ as_type = AS_SEQUENCE; @@ -2066,6 +2065,10 @@ bool aspath_cmp(const void *arg1, const void *arg2) const struct assegment *seg1 = ((const struct aspath *)arg1)->segments; const struct assegment *seg2 = ((const struct aspath *)arg2)->segments; + if (((const struct aspath *)arg1)->asnotation != + ((const struct aspath *)arg2)->asnotation) + return false; + while (seg1 || seg2) { int i; if ((!seg1 && seg2) || (seg1 && !seg2)) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index dd65b423a..18af375c1 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -57,6 +57,9 @@ struct aspath { and AS path regular expression match. */ char *str; unsigned short str_len; + + /* AS notation used by string expression of AS path */ + enum asnotation_mode asnotation; }; #define ASPATH_STR_DEFAULT_LEN 32 @@ -65,7 +68,9 @@ struct aspath { extern void aspath_init(void); extern void aspath_finish(void); extern struct aspath *aspath_parse(struct stream *s, size_t length, - int use32bit); + int use32bit, + enum asnotation_mode asnotation); + extern struct aspath *aspath_dup(struct aspath *aspath); extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2); extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2); @@ -81,9 +86,10 @@ extern bool aspath_cmp_left(const struct aspath *aspath1, extern bool aspath_cmp_left_confed(const struct aspath *as1, const struct aspath *as2); extern struct aspath *aspath_delete_confed_seq(struct aspath *aspath); -extern struct aspath *aspath_empty(void); +extern struct aspath *aspath_empty(enum asnotation_mode asnotation); extern struct aspath *aspath_empty_get(void); -extern struct aspath *aspath_str2aspath(const char *str); +extern struct aspath *aspath_str2aspath(const char *str, + enum asnotation_mode asnotation); extern void aspath_str_update(struct aspath *as, bool make_json); extern void aspath_free(struct aspath *aspath); extern struct aspath *aspath_intern(struct aspath *aspath); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index fe918a3e0..19c65ce4d 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1054,7 +1054,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp, attr->origin = origin; attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); - attr->aspath = aspath_empty(); + attr->aspath = aspath_empty(bgp->asnotation); attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); attr->weight = BGP_ATTR_DEFAULT_WEIGHT; attr->tag = 0; @@ -1092,7 +1092,7 @@ struct attr *bgp_attr_aggregate_intern( if (aspath) attr.aspath = aspath_intern(aspath); else - attr.aspath = aspath_empty(); + attr.aspath = aspath_empty(bgp->asnotation); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); /* Next hop attribute. */ @@ -1590,15 +1590,19 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args) struct attr *const attr = args->attr; struct peer *const peer = args->peer; const bgp_size_t length = args->length; + enum asnotation_mode asnotation; + asnotation = bgp_get_asnotation( + args->peer && args->peer->bgp ? args->peer->bgp : NULL); /* * peer with AS4 => will get 4Byte ASnums * otherwise, will get 16 Bit */ - attr->aspath = aspath_parse( - peer->curr, length, - CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) - && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV)); + attr->aspath = + aspath_parse(peer->curr, length, + CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && + CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV), + asnotation); /* In case of IBGP, length will be zero. */ if (!attr->aspath) { @@ -1614,7 +1618,8 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args) * such messages, conformant BGP speakers SHOULD use the "Treat-as- * withdraw" error handling behavior as per [RFC7606]. */ - if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) { + if (peer->bgp && peer->bgp->reject_as_sets && + aspath_check_as_sets(attr->aspath)) { flog_err(EC_BGP_ATTR_MAL_AS_PATH, "AS_SET and AS_CONFED_SET are deprecated from %pBP", peer); @@ -1690,8 +1695,11 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args, struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; + enum asnotation_mode asnotation; + + asnotation = bgp_get_asnotation(peer->bgp); - *as4_path = aspath_parse(peer->curr, length, 1); + *as4_path = aspath_parse(peer->curr, length, 1, asnotation); /* In case of IBGP, length will be zero. */ if (!*as4_path) { diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index b410a4b89..fc3363b09 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -86,7 +86,8 @@ static void attr_parse(struct stream *s, uint16_t len) case BGP_ATTR_AS_PATH: { struct aspath *aspath; - aspath = aspath_parse(s, length, 1); + aspath = aspath_parse(s, length, 1, + bgp_get_asnotation(NULL)); printf("ASPATH: %s\n", aspath->str); aspath_free(aspath); } break; diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 2dec1ca46..782245e51 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -2635,6 +2635,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, char tag_buf[30]; char overlay_index_buf[INET6_ADDRSTRLEN + 14]; const struct prefix_evpn *evp; + int len = 0; /* ' with addpath ID ' 17 * max strlen of uint32 + 10 @@ -2688,11 +2689,15 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, } } - if (prd) - snprintfrr(str, size, "RD %pRD %pFX%s%s%s %s %s", prd, pu.p, + if (prd) { + len += snprintfrr(str + len, size - len, "RD "); + len += snprintfrr(str + len, size - len, + BGP_RD_AS_FORMAT(bgp_get_asnotation(NULL)), + prd); + snprintfrr(str + len, size - len, " %pFX%s%s%s %s %s", pu.p, overlay_index_buf, tag_buf, pathid_buf, afi2str(afi), safi2str(safi)); - else if (safi == SAFI_FLOWSPEC) { + } else if (safi == SAFI_FLOWSPEC) { char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX]; const struct prefix_fs *fs = pu.fs; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 4758cd98e..51b44a9e7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -5923,6 +5923,8 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn) vpn->prd.prefixlen = 64; snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, vpn->rd_id); (void)str2prefix_rd(buf, &vpn->prd); + if (vpn->prd_pretty) + XFREE(MTYPE_BGP, vpn->prd_pretty); UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD); } @@ -6027,6 +6029,8 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) bf_release_index(bm->rd_idspace, vpn->rd_id); hash_release(bgp->vni_svi_hash, vpn); hash_release(bgp->vnihash, vpn); + if (vpn->prd_pretty) + XFREE(MTYPE_BGP, vpn->prd_pretty); QOBJ_UNREG(vpn); XFREE(MTYPE_BGP_EVPN, vpn); } @@ -6238,13 +6242,14 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, ret = bgp_get_vty(&bgp_vrf, &as, vrf_id_to_name(vrf_id), vrf_id == VRF_DEFAULT - ? BGP_INSTANCE_TYPE_DEFAULT - : BGP_INSTANCE_TYPE_VRF); + ? BGP_INSTANCE_TYPE_DEFAULT + : BGP_INSTANCE_TYPE_VRF, + NULL, ASNOTATION_UNDEFINED); switch (ret) { case BGP_ERR_AS_MISMATCH: flog_err(EC_BGP_EVPN_AS_MISMATCH, - "BGP instance is already running; AS is %u", - as); + "BGP instance is already running; AS is %s", + bgp_vrf->as_pretty); return -1; case BGP_ERR_INSTANCE_MISMATCH: flog_err(EC_BGP_EVPN_INSTANCE_MISMATCH, @@ -6660,6 +6665,9 @@ void bgp_evpn_cleanup(struct bgp *bgp) list_delete(&bgp->vrf_import_rtl); list_delete(&bgp->vrf_export_rtl); list_delete(&bgp->l2vnis); + + if (bgp->vrf_prd_pretty) + XFREE(MTYPE_BGP, bgp->vrf_prd_pretty); } /* diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index fa913016f..391ca4cd1 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -2395,7 +2395,8 @@ static void bgp_evpn_es_json_frag_fill(json_object *json_frags, for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) { json_frag = json_object_new_object(); - json_object_string_addf(json_frag, "rd", "%pRD", &es_frag->prd); + json_object_string_addf(json_frag, "rd", "%pRDP", + &es_frag->prd); json_object_int_add(json_frag, "eviCount", listcount(es_frag->es_evi_frag_list)); @@ -2410,7 +2411,7 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty, struct bgp_evpn_es_frag *es_frag; for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) { - vty_out(vty, " %pRD EVIs: %d\n", &es_frag->prd, + vty_out(vty, " %pRDP EVIs: %d\n", &es_frag->prd, listcount(es_frag->es_evi_frag_list)); } } @@ -2524,7 +2525,7 @@ static void bgp_evpn_es_show_entry(struct vty *vty, json_object_string_add(json, "esi", es->esi_str); if (es->es_base_frag) - json_object_string_addf(json, "rd", "%pRD", + json_object_string_addf(json, "rd", "%pRDP", &es->es_base_frag->prd); if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) { @@ -2562,7 +2563,7 @@ static void bgp_evpn_es_show_entry(struct vty *vty, bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str)); - vty_out(vty, "%-30s %-5s %-21pRD %-8d %s\n", es->esi_str, + vty_out(vty, "%-30s %-5s %-21pRDP %-8d %s\n", es->esi_str, type_str, &es->es_base_frag->prd, listcount(es->es_evi_list), vtep_str); } @@ -2639,7 +2640,7 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty, vty_out(vty, "ESI: %s\n", es->esi_str); vty_out(vty, " Type: %s\n", type_str); - vty_out(vty, " RD: %pRD\n", &es->es_base_frag->prd); + vty_out(vty, " RD: %pRDP\n", &es->es_base_frag->prd); vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip); if (es->flags & BGP_EVPNES_LOCAL) vty_out(vty, " Local ES DF preference: %u\n", @@ -3958,7 +3959,8 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty, json_object *json_types; json_object_string_add(json, "esi", es_evi->es->esi_str); - json_object_int_add(json, "vni", es_evi->vpn->vni); + if (es_evi->vpn) + json_object_int_add(json, "vni", es_evi->vpn->vni); if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL | BGP_EVPNES_EVI_REMOTE)) { @@ -4002,13 +4004,18 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty, static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty, struct bgp_evpn_es_evi *es_evi, json_object *json) { + enum asnotation_mode mode; + + mode = bgp_get_asnotation(es_evi->vpn->bgp_vrf); + if (json) { json_object *json_flags; /* Add the "brief" info first */ bgp_evpn_es_evi_show_entry(vty, es_evi, json); if (es_evi->es_frag) - json_object_string_addf(json, "esFragmentRd", "%pRD", + json_object_string_addf(json, "esFragmentRd", + BGP_RD_AS_FORMAT(mode), &es_evi->es_frag->prd); if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) { json_flags = json_object_new_array(); @@ -4032,9 +4039,12 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty, vty_out(vty, "VNI: %d ESI: %s\n", es_evi->vpn->vni, es_evi->es->esi_str); vty_out(vty, " Type: %s\n", type_str); - if (es_evi->es_frag) - vty_out(vty, " ES fragment RD: %pRD\n", + if (es_evi->es_frag) { + vty_out(vty, " ES fragment RD: "); + vty_out(vty, BGP_RD_AS_FORMAT(mode), &es_evi->es_frag->prd); + vty_out(vty, "\n"); + } vty_out(vty, " Inconsistencies: %s\n", (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ? "es-vtep-mismatch":"-"); diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index d63e7a1a1..fbf3b19c3 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -76,6 +76,7 @@ struct bgpevpn { /* RD for this VNI. */ struct prefix_rd prd; + char *prd_pretty; /* Route type 3 field */ struct in_addr originator_ip; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 33c202c3d..59986102a 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -374,7 +374,9 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf, json_object_int_add(json, "vni", bgp_vrf->l3vni); json_object_string_add(json, "type", "L3"); json_object_string_add(json, "inKernel", "True"); - json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd); + json_object_string_addf(json, "rd", + BGP_RD_AS_FORMAT(bgp_vrf->asnotation), + &bgp_vrf->vrf_prd); json_object_string_addf(json, "originatorIp", "%pI4", &bgp_vrf->originator_ip); json_object_string_add(json, "advertiseGatewayMacip", "n/a"); @@ -398,7 +400,10 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf, vty_out(vty, " Type: %s\n", "L3"); vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(bgp_vrf->vrf_id)); - vty_out(vty, " RD: %pRD\n", &bgp_vrf->vrf_prd); + vty_out(vty, " RD: "); + vty_out(vty, BGP_RD_AS_FORMAT(bgp_vrf->asnotation), + &bgp_vrf->vrf_prd); + vty_out(vty, "\n"); vty_out(vty, " Originator IP: %pI4\n", &bgp_vrf->originator_ip); vty_out(vty, " Advertise-gw-macip : %s\n", "n/a"); @@ -461,8 +466,10 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json) json_object *json_import_rtl = NULL; json_object *json_export_rtl = NULL; struct bgp *bgp_evpn; + enum asnotation_mode asnotation; bgp_evpn = bgp_get_evpn(); + asnotation = bgp_get_asnotation(bgp_evpn); if (json) { json_import_rtl = json_object_new_array(); @@ -471,7 +478,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json) json_object_string_add(json, "type", "L2"); json_object_string_add(json, "inKernel", is_vni_live(vpn) ? "True" : "False"); - json_object_string_addf(json, "rd", "%pRD", &vpn->prd); + json_object_string_addf( + json, "rd", BGP_RD_AS_FORMAT(asnotation), &vpn->prd); json_object_string_addf(json, "originatorIp", "%pI4", &vpn->originator_ip); json_object_string_addf(json, "mcastGroup", "%pI4", @@ -512,7 +520,9 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json) vty_out(vty, " Type: %s\n", "L2"); vty_out(vty, " Tenant-Vrf: %s\n", vrf_id_to_name(vpn->tenant_vrf_id)); - vty_out(vty, " RD: %pRD\n", &vpn->prd); + vty_out(vty, " RD: "); + vty_out(vty, BGP_RD_AS_FORMAT(asnotation), &vpn->prd); + vty_out(vty, "\n"); vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip); vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp); if (!vpn->advertise_gw_macip && @@ -991,7 +1001,9 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, json_object_string_add(json_vni, "inKernel", "True"); json_object_string_addf(json_vni, "originatorIp", "%pI4", &bgp->originator_ip); - json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd); + json_object_string_addf(json_vni, "rd", + BGP_RD_AS_FORMAT(bgp->asnotation), + &bgp->vrf_prd); json_object_string_add(json_vni, "advertiseGatewayMacip", "n/a"); json_object_string_add(json_vni, "advertiseSviMacIp", "n/a"); @@ -1007,7 +1019,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, json_vni, "rmac", prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2))); } else { - vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3", + vty_out(vty, "%-1s %-10u %-4s ", buf1, bgp->l3vni, "L3"); + vty_out(vty, BGP_RD_AS_FORMAT_SPACE(bgp->asnotation), &bgp->vrf_prd); } @@ -1091,11 +1104,13 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[]) struct listnode *node, *nnode; struct ecommunity *ecom; struct bgp *bgp_evpn; + enum asnotation_mode asnotation; vty = args[0]; json = args[1]; bgp_evpn = bgp_get_evpn(); + asnotation = bgp_get_asnotation(bgp_evpn); if (json) { json_vni = json_object_new_object(); @@ -1112,7 +1127,9 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[]) json_object_string_add(json_vni, "type", "L2"); json_object_string_add(json_vni, "inKernel", is_vni_live(vpn) ? "True" : "False"); - json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd); + json_object_string_addf(json_vni, "rd", + BGP_RD_AS_FORMAT(asnotation), + &vpn->prd); json_object_string_addf(json_vni, "originatorIp", "%pI4", &vpn->originator_ip); json_object_string_addf(json_vni, "mcastGroup", "%pI4", @@ -1142,8 +1159,8 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[]) json_object_string_add(json_vni, "advertiseSviMacIp", "Disabled"); } else { - vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2", - &vpn->prd); + vty_out(vty, "%-1s %-10u %-4s ", buf1, vpn->vni, "L2"); + vty_out(vty, BGP_RD_AS_FORMAT_SPACE(asnotation), &vpn->prd); } for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { @@ -1332,9 +1349,9 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, json, "defaultLocPrf", bgp->default_local_pref); - json_object_int_add( - json, "localAS", - bgp->as); + asn_asn2json(json, "localAS", + bgp->as, + bgp->asnotation); } else { if (option == SHOW_DISPLAY_TAGS) vty_out(vty, @@ -2203,7 +2220,8 @@ static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn, /* * Configure RD for VRF */ -static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd) +static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd, + const char *rd_pretty) { /* If we have already advertise type-5 routes with a diffrent RD, we * have to delete and withdraw them firs @@ -2212,6 +2230,7 @@ static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd) /* update RD */ memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd)); + bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty); SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD); /* We have a new RD for VRF. @@ -2233,7 +2252,8 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf) /* fall back to default RD */ bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf); UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD); - + if (bgp_vrf->vrf_prd_pretty) + XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty); /* We have a new RD for VRF. * Advertise all type-5 routes again with the new RD */ @@ -2244,7 +2264,7 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf) * Configure RD for a VNI (vty handler) */ static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_rd *rd) + struct prefix_rd *rd, const char *rd_pretty) { /* If the VNI is "live", we need to delete and withdraw this VNI's * local routes with the prior RD first. Then, after updating RD, @@ -2255,6 +2275,7 @@ static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn, /* update RD */ memcpy(&vpn->prd, rd, sizeof(struct prefix_rd)); + vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty); SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD); if (is_vni_live(vpn)) @@ -2778,7 +2799,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, if (json) { json_rd = json_object_new_object(); - json_object_string_addf(json_rd, "rd", "%pRD", prd); + json_object_string_addf(json_rd, "rd", + BGP_RD_AS_FORMAT(bgp->asnotation), prd); } bgp_dest_unlock_node(rd_dest); @@ -2861,7 +2883,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, if (json) { if (add_rd_to_json) - json_object_object_addf(json, json_rd, "%pRD", prd); + json_object_object_addf( + json, json_rd, + BGP_RD_AS_FORMAT(bgp->asnotation), prd); else { json_object_free(json_rd); json_rd = NULL; @@ -2916,7 +2940,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp, continue; prefix_rd2str((struct prefix_rd *)rd_destp, rd_str, - sizeof(rd_str)); + sizeof(rd_str), bgp->asnotation); /* Construct an RT-2 from the user-supplied mac(ip), * then search the l2vpn evpn table for it. @@ -3043,7 +3067,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, tbl_ver = table->version; prefix_rd2str((struct prefix_rd *)rd_destp, rd_str, - sizeof(rd_str)); + sizeof(rd_str), bgp->asnotation); if (json) json_rd = json_object_new_object(); @@ -3460,7 +3484,7 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn) if (is_vni_configured(vpn)) { vty_out(vty, " vni %u\n", vpn->vni); if (is_rd_configured(vpn)) - vty_out(vty, " rd %pRD\n", &vpn->prd); + vty_out(vty, " rd %s\n", vpn->prd_pretty); if (is_import_rt_configured(vpn)) { for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, @@ -6111,7 +6135,7 @@ DEFUN (bgp_evpn_vrf_rd, return CMD_SUCCESS; /* Configure or update the RD. */ - evpn_configure_vrf_rd(bgp_vrf, &prd); + evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg); return CMD_SUCCESS; } @@ -6203,7 +6227,7 @@ DEFUN (bgp_evpn_vni_rd, return CMD_SUCCESS; /* Configure or update the RD. */ - evpn_configure_rd(bgp, vpn, &prd); + evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg); return CMD_SUCCESS; } @@ -6388,7 +6412,9 @@ DEFUN (show_bgp_vrf_l3vni_info, for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt)) vty_out(vty, "%s ", ecommunity_str(l3rt->ecom)); vty_out(vty, "\n"); - vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd); + vty_out(vty, " RD: "); + vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd); + vty_out(vty, "\n"); } else { json_object_string_add(json, "vrf", name); json_object_string_addf(json, "local-ip", "%pI4", @@ -6424,7 +6450,9 @@ DEFUN (show_bgp_vrf_l3vni_info, json_object_new_string( ecommunity_str(l3rt->ecom))); json_object_object_add(json, "import-rts", json_import_rts); - json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd); + json_object_string_addf(json, "rd", + BGP_RD_AS_FORMAT(bgp->asnotation), + &bgp->vrf_prd); } if (uj) @@ -7251,7 +7279,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, } } if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD)) - vty_out(vty, " rd %pRD\n", &bgp->vrf_prd); + vty_out(vty, " rd %s\n", bgp->vrf_prd_pretty); /* import route-target */ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index bd8ce5477..ab0217018 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1853,7 +1853,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ int origin_local = 0; struct bgp *src_vrf; struct interface *ifp; - + char rd_buf[RD_ADDRSTRLEN]; int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) { @@ -1892,6 +1892,10 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ return false; } + rd_buf[0] = '\0'; + if (debug && prd) + prefix_rd2str(prd, rd_buf, sizeof(rd_buf), to_bgp->asnotation); + /* A route MUST NOT ever be accepted back into its source VRF, even if * it carries one or more RTs that match that VRF. */ @@ -1900,15 +1904,14 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ ECOMMUNITY_SIZE) == 0) { if (debug) zlog_debug( - "%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)", - __func__, prd, to_bgp->name_pretty, p); - + "%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)", + __func__, rd_buf, to_bgp->name_pretty, p); return false; } if (debug) - zlog_debug("%s: updating RD %pRD, %pFX to %s", __func__, prd, p, - to_bgp->name_pretty); + zlog_debug("%s: updating RD %s, %pFX to %s", __func__, rd_buf, + p, to_bgp->name_pretty); /* shallow copy */ static_attr = *path_vpn->attr; @@ -2403,7 +2406,7 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw, &bgp->vrf_prd_auto); bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto; prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf, - sizeof(buf)); + sizeof(buf), bgp->asnotation); /* free up pre-existing memory if any and allocate * the ecommunity attribute with new RD/RT @@ -2538,8 +2541,8 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp, from_bgp->vpn_policy[afi].tovpn_rd = from_bgp->vrf_prd_auto; SET_FLAG(from_bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET); - prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd, - buf, sizeof(buf)); + prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd, buf, + sizeof(buf), from_bgp->asnotation); from_bgp->vpn_policy[afi].rtlist[edir] = ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0); SET_FLAG(from_bgp->af_flags[afi][safi], diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c index 95a7bb811..9b2ab6680 100644 --- a/bgpd/bgp_mplsvpn_snmp.c +++ b/bgpd/bgp_mplsvpn_snmp.c @@ -942,11 +942,13 @@ static uint8_t *mplsL3vpnVrfTable(struct variable *v, oid name[], if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP].tovpn_rd, - rd_buf, sizeof(rd_buf)); + rd_buf, sizeof(rd_buf), + bgp_get_asnotation(l3vpn_bgp)); else if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP6].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP6].tovpn_rd, - rd_buf, sizeof(rd_buf)); + rd_buf, sizeof(rd_buf), + bgp_get_asnotation(l3vpn_bgp)); *var_len = strnlen(rd_buf, RD_ADDRSTRLEN); return (uint8_t *)rd_buf; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index da89c594c..df67e2a72 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -538,7 +538,7 @@ static void bgp_accept(struct thread *thread) peer1->host); peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, - peer1->as, peer1->as_type, NULL, false); + peer1->as, peer1->as_type, NULL, false, NULL); peer_xfer_config(peer, peer1); bgp_peer_gr_flags_update(peer); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index a3014c0c6..00a0bc840 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -802,6 +802,7 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp, safi = table->safi; bgp_path = table->bgp; + if (json) { json_path = json_object_new_object(); json_object_string_add(json_path, "afi", afi2str(afi)); @@ -811,7 +812,8 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp, dest); if (dest->pdest) json_object_string_addf( - json_path, "rd", "%pRD", + json_path, "rd", + BGP_RD_AS_FORMAT(bgp->asnotation), (struct prefix_rd *)bgp_dest_get_prefix( dest->pdest)); json_object_string_add( @@ -821,13 +823,14 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp, json_object_array_add(paths, json_path); continue; } - if (dest->pdest) - vty_out(vty, " %d/%d %pBD RD %pRD %s flags 0x%x\n", - afi, safi, dest, + if (dest->pdest) { + vty_out(vty, " %d/%d %pBD RD ", afi, safi, dest); + vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), (struct prefix_rd *)bgp_dest_get_prefix( - dest->pdest), - bgp_path->name_pretty, path->flags); - else + dest->pdest)); + vty_out(vty, " %s flags 0x%x\n", bgp_path->name_pretty, + path->flags); + } else vty_out(vty, " %d/%d %pBD %s flags 0x%x\n", afi, safi, dest, bgp_path->name_pretty, path->flags); } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 4f42766b9..25b458a8e 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -1190,14 +1190,20 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc) } if (BGP_DEBUG(nht, NHT)) { - if (dest->pdest) - zlog_debug( - "... eval path %d/%d %pBD RD %pRD %s flags 0x%x", - afi, safi, dest, + + if (dest->pdest) { + char rd_buf[RD_ADDRSTRLEN]; + + prefix_rd2str( (struct prefix_rd *)bgp_dest_get_prefix( dest->pdest), + rd_buf, sizeof(rd_buf), + bgp_get_asnotation(bnc->bgp)); + zlog_debug( + "... eval path %d/%d %pBD RD %s %s flags 0x%x", + afi, safi, dest, rd_buf, bgp_path->name_pretty, path->flags); - else + } else zlog_debug( "... eval path %d/%d %pBD %s flags 0x%x", afi, safi, dest, bgp_path->name_pretty, diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index 6e73ab8d1..bb9f76b8a 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -83,12 +83,12 @@ void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth) int str2prefix_rd(const char *str, struct prefix_rd *prd) { - int ret = 0; - char *p; - char *p2; + int ret = 0, type = RD_TYPE_UNDEFINED; + char *p, *p2; struct stream *s = NULL; char *half = NULL; struct in_addr addr; + as_t as_val; prd->family = AF_UNSPEC; prd->prefixlen = 64; @@ -97,41 +97,55 @@ int str2prefix_rd(const char *str, struct prefix_rd *prd) if (!p) goto out; + /* a second ':' is accepted */ + p2 = strchr(p + 1, ':'); + if (p2) { + /* type is in first part */ + half = XMALLOC(MTYPE_TMP, (p - str) + 1); + memcpy(half, str, (p - str)); + half[p - str] = '\0'; + type = atoi(half); + if (type != RD_TYPE_AS && type != RD_TYPE_IP && + type != RD_TYPE_AS4) + goto out; + XFREE(MTYPE_TMP, half); + half = XMALLOC(MTYPE_TMP, (p2 - p)); + memcpy(half, p + 1, (p2 - p - 1)); + half[p2 - p - 1] = '\0'; + p = p2 + 1; + } else { + half = XMALLOC(MTYPE_TMP, (p - str) + 1); + memcpy(half, str, (p - str)); + half[p - str] = '\0'; + } if (!all_digit(p + 1)) goto out; s = stream_new(RD_BYTES); - half = XMALLOC(MTYPE_TMP, (p - str) + 1); - memcpy(half, str, (p - str)); - half[p - str] = '\0'; - - p2 = strchr(str, '.'); - - if (!p2) { - unsigned long as_val; - - if (!all_digit(half)) - goto out; - - as_val = atol(half); - if (as_val > 0xffff) { + /* if it is an AS format or an IP */ + if (asn_str2asn(half, &as_val)) { + if (as_val > UINT16_MAX) { stream_putw(s, RD_TYPE_AS4); stream_putl(s, as_val); stream_putw(s, atol(p + 1)); + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS4) + goto out; } else { stream_putw(s, RD_TYPE_AS); stream_putw(s, as_val); stream_putl(s, atol(p + 1)); + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS) + goto out; } - } else { - if (!inet_aton(half, &addr)) - goto out; - + } else if (inet_aton(half, &addr)) { stream_putw(s, RD_TYPE_IP); stream_put_in_addr(s, &addr); stream_putw(s, atol(p + 1)); - } + if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_IP) + goto out; + } else + goto out; memcpy(prd->val, s->data, 8); ret = 1; @@ -142,12 +156,14 @@ out: return ret; } -char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size) +char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size, + enum asnotation_mode asnotation) { const uint8_t *pnt; uint16_t type; struct rd_as rd_as; struct rd_ip rd_ip; + int len = 0; assert(size >= RD_ADDRSTRLEN); @@ -157,11 +173,15 @@ char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size) if (type == RD_TYPE_AS) { decode_rd_as(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); + len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), + &rd_as.as); + snprintfrr(buf + len, size - len, ":%u", rd_as.val); return buf; } else if (type == RD_TYPE_AS4) { decode_rd_as4(pnt + 2, &rd_as); - snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); + len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), + &rd_as.as); + snprintfrr(buf + len, size - len, ":%u", rd_as.val); return buf; } else if (type == RD_TYPE_IP) { decode_rd_ip(pnt + 2, &rd_ip); @@ -196,16 +216,38 @@ void form_auto_rd(struct in_addr router_id, (void)str2prefix_rd(buf, prd); } -printfrr_ext_autoreg_p("RD", printfrr_prd); -static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, - const void *ptr) +static ssize_t printfrr_prd_asnotation(struct fbuf *buf, + struct printfrr_eargs *ea, + const void *ptr, + enum asnotation_mode asnotation) { char rd_buf[RD_ADDRSTRLEN]; if (!ptr) return bputs(buf, "(null)"); - prefix_rd2str(ptr, rd_buf, sizeof(rd_buf)); + prefix_rd2str(ptr, rd_buf, sizeof(rd_buf), asnotation); return bputs(buf, rd_buf); } + +printfrr_ext_autoreg_p("RDP", printfrr_prd); +static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, + const void *ptr) +{ + return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_PLAIN); +} + +printfrr_ext_autoreg_p("RDD", printfrr_prd_dot); +static ssize_t printfrr_prd_dot(struct fbuf *buf, struct printfrr_eargs *ea, + const void *ptr) +{ + return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOT); +} + +printfrr_ext_autoreg_p("RDE", printfrr_prd_dotplus); +static ssize_t printfrr_prd_dotplus(struct fbuf *buf, struct printfrr_eargs *ea, + const void *ptr) +{ + return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS); +} diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h index 44173b7a2..e38c2fad3 100644 --- a/bgpd/bgp_rd.h +++ b/bgpd/bgp_rd.h @@ -7,7 +7,11 @@ #ifndef _QUAGGA_BGP_RD_H #define _QUAGGA_BGP_RD_H +#include "asn.h" +#include "prefix.h" + /* RD types */ +#define RD_TYPE_UNDEFINED (-1) #define RD_TYPE_AS 0 #define RD_TYPE_IP 1 #define RD_TYPE_AS4 2 @@ -19,6 +23,16 @@ #define RD_ADDRSTRLEN 28 #define RD_BYTES 8 +#define BGP_RD_AS_FORMAT(mode) \ + ((mode == ASNOTATION_DOT) \ + ? "%pRDD" \ + : ((mode == ASNOTATION_DOTPLUS) ? "%pRDE" : "%pRDP")) + +#define BGP_RD_AS_FORMAT_SPACE(mode) \ + ((mode == ASNOTATION_DOT) \ + ? "%-21pRDD" \ + : ((mode == ASNOTATION_DOTPLUS) ? "%-21pRDE" : "%-21pRDP")) + struct rd_as { uint16_t type; as_t as; @@ -51,7 +65,8 @@ extern void decode_rd_vnc_eth(const uint8_t *pnt, #endif extern int str2prefix_rd(const char *, struct prefix_rd *); -extern char *prefix_rd2str(const struct prefix_rd *, char *, size_t); +extern char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size, + enum asnotation_mode asnotation); extern void form_auto_rd(struct in_addr router_id, uint16_t rd_id, struct prefix_rd *prd); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0d93abc12..977dca13d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6078,6 +6078,8 @@ static void bgp_static_free(struct bgp_static *bgp_static) XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); route_map_counter_decrement(bgp_static->rmap.map); + if (bgp_static->prd_pretty) + XFREE(MTYPE_BGP, bgp_static->prd_pretty); XFREE(MTYPE_ATTR, bgp_static->eth_s_id); XFREE(MTYPE_BGP_STATIC, bgp_static); } @@ -6981,6 +6983,8 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, bgp_static->label = label; bgp_static->prd = prd; + if (rd_str) + bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str); if (rmap_str) { XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); route_map_counter_decrement(bgp_static->rmap.map); @@ -7243,7 +7247,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp, return false; /* Call route map matching and return result. */ - attr.aspath = aspath_empty(); + attr.aspath = aspath_empty(bgp->asnotation); rmap_path.peer = bgp->peer_self; rmap_path.attr = &attr; @@ -7337,9 +7341,12 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, struct lcommunity *lcomm) { static struct aspath *ae = NULL; + enum asnotation_mode asnotation; + + asnotation = bgp_get_asnotation(NULL); if (!ae) - ae = aspath_empty(); + ae = aspath_empty(asnotation); if (!pi) return false; @@ -10254,10 +10261,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, if (dest && dest->pdest) { pdest = dest->pdest; if (is_pi_family_evpn(parent_ri)) { - vty_out(vty, - " Imported from %pRD:%pFX, VNI %s", + vty_out(vty, " Imported from "); + vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), (struct prefix_rd *)bgp_dest_get_prefix( - pdest), + pdest)); + vty_out(vty, ":%pFX, VNI %s", (struct prefix_evpn *) bgp_dest_get_prefix(dest), tag_buf); @@ -10270,12 +10278,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, : "inactive"); vty_out(vty, "\n"); - } else - vty_out(vty, " Imported from %pRD:%pFX\n", + } else { + vty_out(vty, " Imported from "); + vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), (struct prefix_rd *)bgp_dest_get_prefix( - pdest), + pdest)); + vty_out(vty, ":%pFX\n", (struct prefix_evpn *) bgp_dest_get_prefix(dest)); + } } } @@ -11184,17 +11195,26 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, "{\n"); *json_header_depth = 2; } - vty_out(vty, " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n" - " \"localAS\": %u,\n \"routes\": { ", + " \"localAS\": ", bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id, bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? VRF_DEFAULT_NAME : bgp->name, table->version, &bgp->router_id, - bgp->default_local_pref, bgp->as); + bgp->default_local_pref); + if ((bgp->asnotation == ASNOTATION_PLAIN) || + ((bgp->asnotation == ASNOTATION_DOT) && + (bgp->as < UINT16_MAX))) + vty_out(vty, "%u", bgp->as); + else { + vty_out(vty, "\""); + vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as); + vty_out(vty, "\""); + } + vty_out(vty, ",\n \"routes\": { "); if (rd) { vty_out(vty, " \"routeDistinguishers\" : {"); ++*json_header_depth; @@ -11468,7 +11488,10 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, "\n"); vty_out(vty, "Default local pref %u, ", bgp->default_local_pref); - vty_out(vty, "local AS %u\n", bgp->as); + vty_out(vty, "local AS "); + vty_out(vty, ASN_FORMAT(bgp->asnotation), + &bgp->as); + vty_out(vty, "\n"); if (!detail_routes) { vty_out(vty, BGP_SHOW_SCODE_HEADER); vty_out(vty, BGP_SHOW_NCODE_HEADER); @@ -11665,7 +11688,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, char rd[RD_ADDRSTRLEN]; memcpy(&prd, dest_p, sizeof(struct prefix_rd)); - prefix_rd2str(&prd, rd, sizeof(rd)); + prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation); bgp_show_table(vty, bgp, safi, itable, type, output_arg, rd, next == NULL, &output_cum, &total_cum, &json_header_depth, @@ -11816,13 +11839,16 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, if (safi == SAFI_EVPN) { if (!json) { vty_out(vty, "BGP routing table entry for %s%s%pFX\n", - prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) + prd ? prefix_rd2str(prd, buf1, sizeof(buf1), + bgp->asnotation) : "", prd ? ":" : "", (struct prefix_evpn *)p); } else { - json_object_string_add(json, "rd", - prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) : - ""); + json_object_string_add( + json, "rd", + prd ? prefix_rd2str(prd, buf1, sizeof(buf1), + bgp->asnotation) + : ""); bgp_evpn_route2json((struct prefix_evpn *)p, json); } } else { @@ -11832,7 +11858,8 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, "\n", ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) ? prefix_rd2str(prd, buf1, - sizeof(buf1)) + sizeof(buf1), + bgp->asnotation) : ""), safi == SAFI_MPLS_VPN ? ":" : "", p, dest->version); @@ -12055,8 +12082,9 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd, json_object_object_add(json_header, "paths", json_paths); if (pfx_rd) - json_object_object_addf(json, json_header, "%pRD", - pfx_rd); + json_object_object_addf( + json, json_header, + BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd); } } @@ -14465,7 +14493,8 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs") prd = (const struct prefix_rd *)bgp_dest_get_prefix( dest); - prefix_rd2str(prd, rd_str, sizeof(rd_str)); + prefix_rd2str(prd, rd_str, sizeof(rd_str), + bgp->asnotation); show_adj_route( vty, peer, table, afi, safi, type, rmap_name, @@ -15594,7 +15623,6 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest; struct bgp_table *table; const struct prefix *p; - const struct prefix_rd *prd; struct bgp_static *bgp_static; mpls_label_t label; @@ -15612,13 +15640,12 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, continue; p = bgp_dest_get_prefix(dest); - prd = (const struct prefix_rd *)bgp_dest_get_prefix( - pdest); /* "network" configuration display. */ label = decode_label(&bgp_static->label); - vty_out(vty, " network %pFX rd %pRD", p, prd); + vty_out(vty, " network %pFX rd %s", p, + bgp_static->prd_pretty); if (safi == SAFI_MPLS_VPN) vty_out(vty, " label %u", label); @@ -15641,7 +15668,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest; struct bgp_table *table; const struct prefix *p; - const struct prefix_rd *prd; struct bgp_static *bgp_static; char buf[PREFIX_STRLEN * 2]; char buf2[SU_ADDRSTRLEN]; @@ -15669,7 +15695,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, esi_to_str(bgp_static->eth_s_id, esi_buf, sizeof(esi_buf)); p = bgp_dest_get_prefix(dest); - prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest); /* "network" configuration display. */ if (p->u.prefix_evpn.route_type == 5) { @@ -15696,8 +15721,9 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, &bgp_static->gatewayIp.u.prefix, buf2, sizeof(buf2)); vty_out(vty, - " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n", - buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag, + " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n", + buf, bgp_static->prd_pretty, + p->u.prefix_evpn.prefix_addr.eth_tag, decode_label(&bgp_static->label), esi_buf, buf2, macrouter); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index d449152c2..bd4191bfd 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -355,6 +355,7 @@ struct bgp_static { /* Route Distinguisher */ struct prefix_rd prd; + char *prd_pretty; /* MPLS label. */ mpls_label_t label; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index dbffecee3..4b6f290c7 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -213,7 +213,7 @@ static void *route_aspath_compile(const char *arg) { struct aspath *aspath; - aspath = aspath_str2aspath(arg); + aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL)); if (!aspath) return NULL; return aspath; @@ -5663,15 +5663,16 @@ DEFUN_YANG (no_set_label_index, DEFUN_YANG (set_aspath_prepend_asn, set_aspath_prepend_asn_cmd, - "set as-path prepend (1-4294967295)...", + "set as-path prepend ASNUM...", SET_STR "Transform BGP AS_PATH attribute\n" "Prepend to the as-path\n" - "AS number\n") + AS_STR) { int idx_asn = 3; int ret; char *str; + struct aspath *aspath; str = argv_concat(argv, argc, idx_asn); @@ -5679,6 +5680,12 @@ DEFUN_YANG (set_aspath_prepend_asn, "./set-action[action='frr-bgp-route-map:as-path-prepend']"; char xpath_value[XPATH_MAXLEN]; + aspath = route_aspath_compile(str); + if (!aspath) { + vty_out(vty, "%% Invalid AS path value %s\n", str); + return CMD_WARNING_CONFIG_FAILED; + } + route_aspath_free(aspath); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath); @@ -5713,16 +5720,22 @@ DEFUN_YANG (set_aspath_prepend_lastas, DEFPY_YANG (set_aspath_replace_asn, set_aspath_replace_asn_cmd, - "set as-path replace <any|(1-4294967295)>$replace", + "set as-path replace <any|ASNUM>$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") + "Replace a specific AS number in plain or dotted format to local AS number\n") { const char *xpath = "./set-action[action='frr-bgp-route-map:as-path-replace']"; char xpath_value[XPATH_MAXLEN]; + as_t as_value; + + if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) { + vty_out(vty, "%% Invalid AS value %s\n", replace); + return CMD_WARNING_CONFIG_FAILED; + } nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); snprintf(xpath_value, sizeof(xpath_value), @@ -5733,13 +5746,13 @@ DEFPY_YANG (set_aspath_replace_asn, DEFPY_YANG (no_set_aspath_replace_asn, no_set_aspath_replace_asn_cmd, - "no set as-path replace [<any|(1-4294967295)>]", + "no set as-path replace [<any|ASNUM>]", 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") + "Replace a specific AS number in plain or dotted format to local AS number\n") { const char *xpath = "./set-action[action='frr-bgp-route-map:as-path-replace']"; @@ -5750,12 +5763,12 @@ DEFPY_YANG (no_set_aspath_replace_asn, DEFUN_YANG (no_set_aspath_prepend, no_set_aspath_prepend_cmd, - "no set as-path prepend [(1-4294967295)]", + "no set as-path prepend [ASNUM]", NO_STR SET_STR "Transform BGP AS_PATH attribute\n" "Prepend to the as-path\n" - "AS number\n") + AS_STR) { const char *xpath = "./set-action[action='frr-bgp-route-map:as-path-prepend']"; @@ -5783,15 +5796,16 @@ DEFUN_YANG (no_set_aspath_prepend_lastas, DEFUN_YANG (set_aspath_exclude, set_aspath_exclude_cmd, - "set as-path exclude (1-4294967295)...", + "set as-path exclude ASNUM...", SET_STR "Transform BGP AS-path attribute\n" "Exclude from the as-path\n" - "AS number\n") + AS_STR) { int idx_asn = 3; int ret; char *str; + struct aspath *aspath; str = argv_concat(argv, argc, idx_asn); @@ -5799,6 +5813,12 @@ DEFUN_YANG (set_aspath_exclude, "./set-action[action='frr-bgp-route-map:as-path-exclude']"; char xpath_value[XPATH_MAXLEN]; + aspath = route_aspath_compile(str); + if (!aspath) { + vty_out(vty, "%% Invalid AS path value %s\n", str); + return CMD_WARNING_CONFIG_FAILED; + } + route_aspath_free(aspath); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath); @@ -5810,7 +5830,7 @@ DEFUN_YANG (set_aspath_exclude, DEFUN_YANG (no_set_aspath_exclude, no_set_aspath_exclude_cmd, - "no set as-path exclude (1-4294967295)...", + "no set as-path exclude ASNUM...", NO_STR SET_STR "Transform BGP AS_PATH attribute\n" @@ -6496,11 +6516,11 @@ DEFPY_YANG (no_set_aigp_metric, DEFUN_YANG (set_aggregator_as, set_aggregator_as_cmd, - "set aggregator as (1-4294967295) A.B.C.D", + "set aggregator as ASNUM A.B.C.D", SET_STR "BGP aggregator attribute\n" "AS number of aggregator\n" - "AS number\n" + AS_STR "IP address of aggregator\n") { int idx_number = 3; @@ -6509,6 +6529,12 @@ DEFUN_YANG (set_aggregator_as, char xpath_addr[XPATH_MAXLEN]; const char *xpath = "./set-action[action='frr-bgp-route-map:aggregator']"; + as_t as_value; + + if (!asn_str2asn(argv[idx_number]->arg, &as_value)) { + vty_out(vty, "%% Invalid AS value %s\n", argv[idx_number]->arg); + return CMD_WARNING_CONFIG_FAILED; + } nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); @@ -6531,12 +6557,12 @@ DEFUN_YANG (set_aggregator_as, DEFUN_YANG (no_set_aggregator_as, no_set_aggregator_as_cmd, - "no set aggregator as [(1-4294967295) A.B.C.D]", + "no set aggregator as [ASNUM A.B.C.D]", NO_STR SET_STR "BGP aggregator attribute\n" "AS number of aggregator\n" - "AS number\n" + AS_STR "IP address of aggregator\n") { const char *xpath = diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 61b8b4edc..d7e1a6341 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -81,6 +81,7 @@ struct rpki_for_each_record_arg { unsigned int *prefix_amount; as_t as; json_object *json; + enum asnotation_mode asnotation; }; static int start(void); @@ -105,7 +106,7 @@ static void rpki_delete_all_cache_nodes(void); static int add_tcp_cache(const char *host, const char *port, const uint8_t preference, const char *bindaddr); static void print_record(const struct pfx_record *record, struct vty *vty, - json_object *json); + json_object *json, enum asnotation_mode asnotation); static bool is_synchronized(void); static bool is_running(void); static bool is_stopping(void); @@ -270,7 +271,7 @@ static void rpki_delete_all_cache_nodes(void) } static void print_record(const struct pfx_record *record, struct vty *vty, - json_object *json) + json_object *json, enum asnotation_mode asnotation) { char ip[INET6_ADDRSTRLEN]; json_object *json_record = NULL; @@ -278,8 +279,10 @@ static void print_record(const struct pfx_record *record, struct vty *vty, lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip)); if (!json) { - vty_out(vty, "%-40s %3u - %3u %10u\n", ip, record->min_len, - record->max_len, record->asn); + vty_out(vty, "%-40s %3u - %3u ", ip, record->min_len, + record->max_len); + vty_out(vty, ASN_FORMAT(asnotation), &record->asn); + vty_out(vty, "\n"); } else { json_record = json_object_new_object(); json_object_string_add(json_record, "prefix", ip); @@ -287,7 +290,7 @@ static void print_record(const struct pfx_record *record, struct vty *vty, record->min_len); json_object_int_add(json_record, "prefixLenMax", record->max_len); - json_object_int_add(json_record, "asn", record->asn); + asn_asn2json(json_record, "asn", record->asn, asnotation); json_object_array_add(json, json_record); } } @@ -299,7 +302,7 @@ static void print_record_by_asn(const struct pfx_record *record, void *data) if (record->asn == arg->as) { (*arg->prefix_amount)++; - print_record(record, vty, arg->json); + print_record(record, vty, arg->json, arg->asnotation); } } @@ -310,7 +313,7 @@ static void print_record_cb(const struct pfx_record *record, void *data) (*arg->prefix_amount)++; - print_record(record, vty, arg->json); + print_record(record, vty, arg->json, arg->asnotation); } static struct rtr_mgr_group *get_groups(void) @@ -728,6 +731,7 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as, arg.vty = vty; arg.as = as; arg.json = NULL; + arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT)); if (!group) { if (!json) @@ -780,6 +784,7 @@ static void print_prefix_table(struct vty *vty, json_object *json) arg.vty = vty; arg.json = NULL; + arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT)); if (!group) { if (!json) @@ -1337,7 +1342,7 @@ DEFPY (show_rpki_prefix_table, DEFPY (show_rpki_as_number, show_rpki_as_number_cmd, - "show rpki as-number (1-4294967295)$by_asn [json$uj]", + "show rpki as-number ASNUM$by_asn [json$uj]", SHOW_STR RPKI_OUTPUT_STRING "Lookup by ASN in prefix table\n" @@ -1345,23 +1350,28 @@ DEFPY (show_rpki_as_number, JSON_STR) { struct json_object *json = NULL; + as_t as; if (!is_synchronized()) { if (!uj) vty_out(vty, "No Connection to RPKI cache server.\n"); return CMD_WARNING; } - + if (!asn_str2asn(by_asn, &as)) { + if (!uj) + vty_out(vty, "Invalid AS value: %s.\n", by_asn); + return CMD_WARNING; + } if (uj) json = json_object_new_object(); - print_prefix_table_by_asn(vty, by_asn, json); + print_prefix_table_by_asn(vty, as, json); return CMD_SUCCESS; } DEFPY (show_rpki_prefix, show_rpki_prefix_cmd, - "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]", + "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [json$uj]", SHOW_STR RPKI_OUTPUT_STRING "Lookup IP prefix and optionally ASN in prefix table\n" @@ -1372,6 +1382,8 @@ DEFPY (show_rpki_prefix, { json_object *json = NULL; json_object *json_records = NULL; + as_t as; + enum asnotation_mode asnotation; if (!is_synchronized()) { if (!uj) @@ -1392,13 +1404,19 @@ DEFPY (show_rpki_prefix, return CMD_WARNING; } + if (asn && !asn_str2asn(asn, &as)) { + if (!uj) + vty_out(vty, "Invalid AS value: %s.\n", asn); + return CMD_WARNING; + } + struct pfx_record *matches = NULL; unsigned int match_count = 0; enum pfxv_state result; if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count, - asn, &addr, prefix->prefixlen, &result) - != PFX_SUCCESS) { + as, &addr, prefix->prefixlen, + &result) != PFX_SUCCESS) { if (!json) vty_out(vty, "Prefix lookup failed\n"); return CMD_WARNING; @@ -1415,13 +1433,14 @@ DEFPY (show_rpki_prefix, json_object_object_add(json, "prefixes", json_records); } + asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT)); for (size_t i = 0; i < match_count; ++i) { const struct pfx_record *record = &matches[i]; - if (record->max_len >= prefix->prefixlen - && ((asn != 0 && (uint32_t)asn == record->asn) - || asn == 0)) { - print_record(&matches[i], vty, json_records); + if (record->max_len >= prefix->prefixlen && + ((as != 0 && (uint32_t)as == record->asn) || as == 0)) { + print_record(&matches[i], vty, json_records, + asnotation); } } diff --git a/bgpd/bgp_script.c b/bgpd/bgp_script.c index 6cc75494e..f4ab23352 100644 --- a/bgpd/bgp_script.c +++ b/bgpd/bgp_script.c @@ -149,7 +149,8 @@ void lua_decode_attr(lua_State *L, int idx, struct attr *attr) attr->nh_ifindex = lua_tointeger(L, -1); lua_pop(L, 1); lua_getfield(L, idx, "aspath"); - attr->aspath = aspath_str2aspath(lua_tostring(L, -1)); + attr->aspath = aspath_str2aspath(lua_tostring(L, -1), + bgp_get_asnotation(NULL)); lua_pop(L, 1); lua_getfield(L, idx, "localpref"); attr->local_pref = lua_tointeger(L, -1); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b858d9c4b..8ef18a34d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -24,6 +24,7 @@ #include "queue.h" #include "filter.h" #include "frrstr.h" +#include "asn.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr_evpn.h" @@ -579,9 +580,10 @@ static const char *get_bgp_default_af_flag(afi_t afi, safi_t safi) } int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, - enum bgp_instance_type inst_type) + enum bgp_instance_type inst_type, const char *as_pretty, + enum asnotation_mode asnotation) { - int ret = bgp_get(bgp, as, name, inst_type); + int ret = bgp_get(bgp, as, name, inst_type, as_pretty, asnotation); if (ret == BGP_CREATED) { bgp_timers_set(*bgp, DFLT_BGP_KEEPALIVE, DFLT_BGP_HOLDTIME, @@ -1222,7 +1224,12 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, /* Clear all neighbors belonging to a specific AS. */ if (sort == clear_as) { - as_t as = strtoul(arg, NULL, 10); + as_t as; + + if (!asn_str2asn(arg, &as)) { + vty_out(vty, "%% BGP: No such AS %s\n", arg); + return CMD_WARNING; + } for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->as != as) @@ -1460,16 +1467,23 @@ DEFUN (no_auto_summary, /* "router bgp" commands. */ DEFUN_NOSH (router_bgp, router_bgp_cmd, - "router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", + "router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]", ROUTER_STR BGP_STR AS_STR - BGP_INSTANCE_HELP_STR) + BGP_INSTANCE_HELP_STR + "Force the AS notation output\n" + "use 'AA.BB' format for AS 4 byte values\n" + "use 'AA.BB' format for all AS values\n" + "use plain format for all AS values\n") { int idx_asn = 2; int idx_view_vrf = 3; int idx_vrf = 4; int is_new_bgp = 0; + int idx_asnotation = 3; + int idx_asnotation_kind = 4; + enum asnotation_mode asnotation = ASNOTATION_UNDEFINED; int ret; as_t as; struct bgp *bgp; @@ -1494,39 +1508,62 @@ DEFUN_NOSH (router_bgp, // "router bgp X" else { - as = strtoul(argv[idx_asn]->arg, NULL, 10); + if (!asn_str2asn(argv[idx_asn]->arg, &as)) { + vty_out(vty, "%% BGP: No such AS %s\n", + argv[idx_asn]->arg); + return CMD_WARNING_CONFIG_FAILED; + } if (as == BGP_PRIVATE_AS_MAX || as == BGP_AS4_MAX) vty_out(vty, "Reserved AS used (%u|%u); AS is %u\n", BGP_PRIVATE_AS_MAX, BGP_AS4_MAX, as); inst_type = BGP_INSTANCE_TYPE_DEFAULT; - if (argc > 3) { - name = argv[idx_vrf]->arg; - if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { - if (strmatch(name, VRF_DEFAULT_NAME)) - name = NULL; - else - inst_type = BGP_INSTANCE_TYPE_VRF; - } else if (!strcmp(argv[idx_view_vrf]->text, "view")) - inst_type = BGP_INSTANCE_TYPE_VIEW; + if (argv_find(argv, argc, "VIEWVRFNAME", &idx_vrf)) { + idx_view_vrf = idx_vrf - 1; + if (argv[idx_view_vrf]->text) { + name = argv[idx_vrf]->arg; + + if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { + if (strmatch(name, VRF_DEFAULT_NAME)) + name = NULL; + else + inst_type = + BGP_INSTANCE_TYPE_VRF; + } else if (!strcmp(argv[idx_view_vrf]->text, + "view")) + inst_type = BGP_INSTANCE_TYPE_VIEW; + } + } + if (argv_find(argv, argc, "as-notation", &idx_asnotation)) { + idx_asnotation_kind = idx_asnotation + 1; + if (strmatch(argv[idx_asnotation_kind]->text, "dot+")) + asnotation = ASNOTATION_DOTPLUS; + else if (strmatch(argv[idx_asnotation_kind]->text, + "dot")) + asnotation = ASNOTATION_DOT; + else if (strmatch(argv[idx_asnotation_kind]->text, + "plain")) + asnotation = ASNOTATION_PLAIN; } if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) is_new_bgp = (bgp_lookup(as, name) == NULL); - ret = bgp_get_vty(&bgp, &as, name, inst_type); + ret = bgp_get_vty(&bgp, &as, name, inst_type, + argv[idx_asn]->arg, asnotation); switch (ret) { case BGP_ERR_AS_MISMATCH: - vty_out(vty, "BGP is already running; AS is %u\n", as); + vty_out(vty, "BGP is already running; AS is %s\n", + bgp->as_pretty); return CMD_WARNING_CONFIG_FAILED; case BGP_ERR_INSTANCE_MISMATCH: vty_out(vty, "BGP instance name and AS number mismatch\n"); vty_out(vty, - "BGP instance is already running; AS is %u\n", - as); + "BGP instance is already running; AS is %s\n", + bgp->as_pretty); return CMD_WARNING_CONFIG_FAILED; } @@ -1542,6 +1579,19 @@ DEFUN_NOSH (router_bgp, bgp_vpn_leak_export(bgp); /* Pending: handle when user tries to change a view to vrf n vv. */ + /* for pre-existing bgp instance, + * - update as_pretty + * - update asnotation if explicitly mentioned + */ + if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) { + XFREE(MTYPE_BGP, bgp->as_pretty); + bgp->as_pretty = XSTRDUP(MTYPE_BGP, argv[idx_asn]->arg); + if (!CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION) && + asnotation != ASNOTATION_UNDEFINED) { + SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION); + bgp->asnotation = asnotation; + } + } } /* unset the auto created flag as the user config is now present */ @@ -1554,12 +1604,16 @@ DEFUN_NOSH (router_bgp, /* "no router bgp" commands. */ DEFUN (no_router_bgp, no_router_bgp_cmd, - "no router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", + "no router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]", NO_STR ROUTER_STR BGP_STR AS_STR - BGP_INSTANCE_HELP_STR) + BGP_INSTANCE_HELP_STR + "Force the AS notation output\n" + "use 'AA.BB' format for AS 4 byte values\n" + "use 'AA.BB' format for all AS values\n" + "use plain format for all AS values\n") { int idx_asn = 3; int idx_vrf = 5; @@ -1588,8 +1642,11 @@ DEFUN (no_router_bgp, return CMD_WARNING_CONFIG_FAILED; } } else { - as = strtoul(argv[idx_asn]->arg, NULL, 10); - + if (!asn_str2asn(argv[idx_asn]->arg, &as)) { + vty_out(vty, "%% BGP: No such AS %s\n", + argv[idx_asn]->arg); + return CMD_WARNING_CONFIG_FAILED; + } if (argc > 4) { name = argv[idx_vrf]->arg; if (strmatch(argv[idx_vrf - 1]->text, "vrf") @@ -1821,7 +1878,6 @@ DEFPY (bgp_suppress_fib_pending, return CMD_SUCCESS; } - /* BGP Cluster ID. */ DEFUN (bgp_cluster_id, bgp_cluster_id_cmd, @@ -1917,30 +1973,33 @@ DEFPY (no_bgp_send_extra_data, DEFUN (bgp_confederation_identifier, bgp_confederation_identifier_cmd, - "bgp confederation identifier (1-4294967295)", + "bgp confederation identifier ASNUM", BGP_STR "AS confederation parameters\n" - "AS number\n" + AS_STR "Set routing domain confederation AS\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); int idx_number = 3; as_t as; - as = strtoul(argv[idx_number]->arg, NULL, 10); + if (!asn_str2asn(argv[idx_number]->arg, &as)) { + vty_out(vty, "%% BGP: No such AS %s\n", argv[idx_number]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - bgp_confederation_id_set(bgp, as); + bgp_confederation_id_set(bgp, as, argv[idx_number]->arg); return CMD_SUCCESS; } DEFUN (no_bgp_confederation_identifier, no_bgp_confederation_identifier_cmd, - "no bgp confederation identifier [(1-4294967295)]", + "no bgp confederation identifier [ASNUM]", NO_STR BGP_STR "AS confederation parameters\n" - "AS number\n" + AS_STR "Set routing domain confederation AS\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -1951,7 +2010,7 @@ DEFUN (no_bgp_confederation_identifier, DEFUN (bgp_confederation_peers, bgp_confederation_peers_cmd, - "bgp confederation peers (1-4294967295)...", + "bgp confederation peers ASNUM...", BGP_STR "AS confederation parameters\n" "Peer ASs in BGP confederation\n" @@ -1963,15 +2022,20 @@ DEFUN (bgp_confederation_peers, int i; for (i = idx_asn; i < argc; i++) { - as = strtoul(argv[i]->arg, NULL, 10); - bgp_confederation_peers_add(bgp, as); + if (!asn_str2asn(argv[i]->arg, &as)) { + vty_out(vty, "%% Invalid confed peer AS value: %s\n", + argv[i]->arg); + continue; + } + + bgp_confederation_peers_add(bgp, as, argv[i]->arg); } return CMD_SUCCESS; } DEFUN (no_bgp_confederation_peers, no_bgp_confederation_peers_cmd, - "no bgp confederation peers (1-4294967295)...", + "no bgp confederation peers ASNUM...", NO_STR BGP_STR "AS confederation parameters\n" @@ -1984,8 +2048,11 @@ DEFUN (no_bgp_confederation_peers, int i; for (i = idx_asn; i < argc; i++) { - as = strtoul(argv[i]->arg, NULL, 10); - + if (!asn_str2asn(argv[i]->arg, &as)) { + vty_out(vty, "%% Invalid confed peer AS value: %s\n", + argv[i]->arg); + continue; + } bgp_confederation_peers_remove(bgp, as); } return CMD_SUCCESS; @@ -4489,11 +4556,13 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str, } else if (as_str[0] == 'e') { as = 0; as_type = AS_EXTERNAL; - } else { - /* Get AS number. */ - as = strtoul(as_str, NULL, 10); - } + } else if (!asn_str2asn(as_str, &as)) + as_type = AS_UNSPECIFIED; + if (as_type == AS_UNSPECIFIED) { + vty_out(vty, "%% Invalid peer AS: %s\n", as_str); + return CMD_WARNING_CONFIG_FAILED; + } /* If peer is peer group or interface peer, call proper function. */ ret = str2sockunion(peer_str, &su); if (ret < 0) { @@ -4502,11 +4571,12 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str, /* Check if existing interface peer */ peer = peer_lookup_by_conf_if(bgp, peer_str); - ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type); + ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, as_str); /* if not interface peer, check peer-group settings */ if (ret < 0 && !peer) { - ret = peer_group_remote_as(bgp, peer_str, &as, as_type); + ret = peer_group_remote_as(bgp, peer_str, &as, as_type, + as_str); if (ret < 0) { vty_out(vty, "%% Create the peer-group or interface first\n"); @@ -4520,7 +4590,7 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str, "%% Can not configure the local system as neighbor\n"); return CMD_WARNING_CONFIG_FAILED; } - ret = peer_remote_as(bgp, &su, NULL, &as, as_type); + ret = peer_remote_as(bgp, &su, NULL, &as, as_type, as_str); } return bgp_vty_return(vty, ret); @@ -4591,7 +4661,7 @@ ALIAS(no_bgp_shutdown, no_bgp_shutdown_msg_cmd, DEFUN (neighbor_remote_as, neighbor_remote_as_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <(1-4294967295)|internal|external>", + "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external>", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a BGP neighbor\n" @@ -4671,18 +4741,19 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if, as_type = AS_EXTERNAL; } else { /* Get AS number. */ - as = strtoul(as_str, NULL, 10); - as_type = AS_SPECIFIED; + if (asn_str2asn(as_str, &as)) + as_type = AS_SPECIFIED; } } peer = peer_lookup_by_conf_if(bgp, conf_if); if (peer) { if (as_str) - ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type); + ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type, + as_str); } else { peer = peer_create(NULL, conf_if, bgp, bgp->as, as, as_type, - NULL, true); + NULL, true, as_str); if (!peer) { vty_out(vty, "%% BGP failed to create peer\n"); @@ -4784,7 +4855,7 @@ DEFUN (neighbor_interface_config_v6only, DEFUN (neighbor_interface_config_remote_as, neighbor_interface_config_remote_as_cmd, - "neighbor WORD interface remote-as <(1-4294967295)|internal|external>", + "neighbor WORD interface remote-as <ASNUM|internal|external>", NEIGHBOR_STR "Interface name or neighbor tag\n" "Enable BGP on interface\n" @@ -4801,7 +4872,7 @@ DEFUN (neighbor_interface_config_remote_as, DEFUN (neighbor_interface_v6only_config_remote_as, neighbor_interface_v6only_config_remote_as_cmd, - "neighbor WORD interface v6only remote-as <(1-4294967295)|internal|external>", + "neighbor WORD interface v6only remote-as <ASNUM|internal|external>", NEIGHBOR_STR "Interface name or neighbor tag\n" "Enable BGP with v6 link-local only\n" @@ -4970,7 +5041,7 @@ DEFUN (no_neighbor_peer_group, DEFUN (no_neighbor_interface_peer_group_remote_as, no_neighbor_interface_peer_group_remote_as_cmd, - "no neighbor WORD remote-as <(1-4294967295)|internal|external>", + "no neighbor WORD remote-as <ASNUM|internal|external>", NO_STR NEIGHBOR_STR "Interface name or neighbor tag\n" @@ -4987,7 +5058,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as, /* look up for neighbor by interface name config. */ peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg); if (peer) { - peer_as_change(peer, 0, AS_UNSPECIFIED); + peer_as_change(peer, 0, AS_UNSPECIFIED, NULL); return CMD_SUCCESS; } @@ -5003,11 +5074,11 @@ DEFUN (no_neighbor_interface_peer_group_remote_as, DEFUN (neighbor_local_as, neighbor_local_as_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295)", + "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a local-as number\n" - "AS number used as local AS\n") + "AS number expressed in dotted or plain format used as local AS\n") { int idx_peer = 1; int idx_number = 3; @@ -5019,18 +5090,23 @@ DEFUN (neighbor_local_as, if (!peer) return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set(peer, as, 0, 0); + if (!asn_str2asn(argv[idx_number]->arg, &as)) { + vty_out(vty, "%% Invalid neighbor local-as value: %s\n", + argv[idx_number]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_local_as_set(peer, as, 0, 0, argv[idx_number]->arg); return bgp_vty_return(vty, ret); } DEFUN (neighbor_local_as_no_prepend, neighbor_local_as_no_prepend_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295) no-prepend", + "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a local-as number\n" - "AS number used as local AS\n" + "AS number expressed in dotted or plain format used as local AS\n" "Do not prepend local-as to updates from ebgp peers\n") { int idx_peer = 1; @@ -5043,18 +5119,23 @@ DEFUN (neighbor_local_as_no_prepend, if (!peer) return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set(peer, as, 1, 0); + if (!asn_str2asn(argv[idx_number]->arg, &as)) { + vty_out(vty, "%% Invalid neighbor local-as value: %s\n", + argv[idx_number]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_local_as_set(peer, as, 1, 0, argv[idx_number]->arg); return bgp_vty_return(vty, ret); } DEFUN (neighbor_local_as_no_prepend_replace_as, neighbor_local_as_no_prepend_replace_as_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295) no-prepend replace-as", + "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a local-as number\n" - "AS number used as local AS\n" + "AS number expressed in dotted or plain format used as local AS\n" "Do not prepend local-as to updates from ebgp peers\n" "Do not prepend local-as to updates from ibgp peers\n") { @@ -5068,19 +5149,24 @@ DEFUN (neighbor_local_as_no_prepend_replace_as, if (!peer) return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set(peer, as, 1, 1); + if (!asn_str2asn(argv[idx_number]->arg, &as)) { + vty_out(vty, "%% Invalid neighbor local-as value: %s\n", + argv[idx_number]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_local_as_set(peer, as, 1, 1, argv[idx_number]->arg); return bgp_vty_return(vty, ret); } DEFUN (no_neighbor_local_as, no_neighbor_local_as_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [(1-4294967295) [no-prepend [replace-as]]]", + "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as]]]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a local-as number\n" - "AS number used as local AS\n" + "AS number expressed in dotted or plain format used as local AS\n" "Do not prepend local-as to updates from ebgp peers\n" "Do not prepend local-as to updates from ibgp peers\n") { @@ -9020,10 +9106,13 @@ DEFPY (af_rd_vpn_export, bgp_get_default(), bgp); if (yes) { + bgp->vpn_policy[afi].tovpn_rd_pretty = + XSTRDUP(MTYPE_BGP, rd_str); bgp->vpn_policy[afi].tovpn_rd = prd; SET_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET); } else { + XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty); UNSET_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET); } @@ -9548,7 +9637,8 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd, /* Auto-create assuming the same AS */ ret = bgp_get_vty(&bgp_default, &as, NULL, - BGP_INSTANCE_TYPE_DEFAULT); + BGP_INSTANCE_TYPE_DEFAULT, NULL, + ASNOTATION_UNDEFINED); if (ret) { vty_out(vty, @@ -9660,7 +9750,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd, if (!bgp_default) { /* Auto-create assuming the same AS */ ret = bgp_get_vty(&bgp_default, &as, NULL, - BGP_INSTANCE_TYPE_DEFAULT); + BGP_INSTANCE_TYPE_DEFAULT, NULL, + ASNOTATION_UNDEFINED); if (ret) { vty_out(vty, @@ -9675,8 +9766,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd, vrf_bgp = bgp_default; else /* Auto-create assuming the same AS */ - ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type); - + ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type, + NULL, ASNOTATION_UNDEFINED); if (ret) { vty_out(vty, "VRF %s is not configured as a bgp instance\n", @@ -10144,7 +10235,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name, /* one clear bgp command to rule them all */ DEFUN (clear_ip_bgp_all, clear_ip_bgp_all_cmd, - "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]", + "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]", CLEAR_STR IP_STR BGP_STR @@ -10157,7 +10248,7 @@ DEFUN (clear_ip_bgp_all, "BGP IPv4 neighbor to clear\n" "BGP IPv6 neighbor to clear\n" "BGP neighbor on interface to clear\n" - "Clear peers with the AS number\n" + "Clear peers with the AS number in plain or dotted format\n" "Clear all external peers\n" "Clear all members of peer-group\n" "BGP peer-group name\n" @@ -10198,7 +10289,7 @@ DEFUN (clear_ip_bgp_all, if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) argv_find_and_parse_safi(argv, argc, &idx, &safi); - /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group PGNAME> */ + /* <*|A.B.C.D|X:X::X:X|WORD|ASNUM|external|peer-group PGNAME> */ if (argv_find(argv, argc, "*", &idx)) { clr_sort = clear_all; } else if (argv_find(argv, argc, "A.B.C.D", &idx)) { @@ -10217,7 +10308,7 @@ DEFUN (clear_ip_bgp_all, } else if (argv_find(argv, argc, "WORD", &idx)) { clr_sort = clear_peer; clr_arg = argv[idx]->arg; - } else if (argv_find(argv, argc, "(1-4294967295)", &idx)) { + } else if (argv_find(argv, argc, "ASNUM", &idx)) { clr_sort = clear_as; clr_arg = argv[idx]->arg; } else if (argv_find(argv, argc, "external", &idx)) { @@ -10355,8 +10446,8 @@ DEFUN (show_bgp_views, /* Skip VRFs. */ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) continue; - vty_out(vty, "\t%s (AS%u)\n", bgp->name ? bgp->name : "(null)", - bgp->as); + vty_out(vty, "\t%s (AS%s)\n", bgp->name ? bgp->name : "(null)", + bgp->as_pretty); } return CMD_SUCCESS; @@ -11142,7 +11233,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_string_addf(json, "routerId", "%pI4", &bgp->router_id); - json_object_int_add(json, "as", bgp->as); + asn_asn2json(json, "as", bgp->as, + bgp->asnotation); json_object_int_add(json, "vrfId", vrf_id_ui); json_object_string_add( json, "vrfName", @@ -11152,8 +11244,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, : bgp->name); } else { vty_out(vty, - "BGP router identifier %pI4, local AS number %u vrf-id %d", - &bgp->router_id, bgp->as, + "BGP router identifier %pI4, local AS number %s vrf-id %d", + &bgp->router_id, bgp->as_pretty, bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id); @@ -11387,12 +11479,13 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_string_add(json_peer, "domainname", peer->domainname); - json_object_int_add(json_peer, "remoteAs", peer->as); - json_object_int_add( - json_peer, "localAs", - peer->change_local_as - ? peer->change_local_as - : peer->local_as); + asn_asn2json(json_peer, "remoteAs", peer->as, + bgp->asnotation); + asn_asn2json(json_peer, "localAs", + peer->change_local_as + ? peer->change_local_as + : peer->local_as, + bgp->asnotation); json_object_int_add(json_peer, "version", 4); json_object_int_add(json_peer, "msgRcvd", PEER_TOTAL_RX(peer)); @@ -11572,14 +11665,19 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, &peer->ibuf->count, memory_order_relaxed); - if (show_wide) + vty_out(vty, "4 "); + vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation), + &peer->as); + if (show_wide) { vty_out(vty, - "4 %10u %10u %9u %9u %8" PRIu64 - " %4zu %4zu %8s", - peer->as, + ASN_FORMAT_SPACE( + bgp->asnotation), peer->change_local_as - ? peer->change_local_as - : peer->local_as, + ? &peer->change_local_as + : &peer->local_as); + vty_out(vty, + " %9u %9u %8" PRIu64 + " %4zu %4zu %8s", PEER_TOTAL_RX(peer), PEER_TOTAL_TX(peer), peer->version[afi][safi], @@ -11588,10 +11686,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, timebuf, BGP_UPTIME_LEN, 0, NULL)); - else - vty_out(vty, "4 %10u %9u %9u %8" PRIu64 - " %4zu %4zu %8s", - peer->as, PEER_TOTAL_RX(peer), + } else { + vty_out(vty, + " %9u %9u %8" PRIu64 + " %4zu %4zu %8s", + PEER_TOTAL_RX(peer), PEER_TOTAL_TX(peer), peer->version[afi][safi], inq_count, outq_count, @@ -11599,7 +11698,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, timebuf, BGP_UPTIME_LEN, 0, NULL)); - + } if (peer_established(peer)) { if (peer->afc_recv[afi][safi]) { if (CHECK_FLAG( @@ -11892,7 +11991,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR - "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json$uj]", + "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <ASNUM|internal|external>>] [terse] [wide] [json$uj]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR "Display the entries for all address families\n" @@ -11903,8 +12002,7 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, "Neighbor to display information about\n" "Neighbor to display information about\n" "Neighbor on BGP configured interface\n" - "Show only the specified remote AS sessions\n" - "AS number\n" + "Show only the specified remote AS sessions\n" AS_STR "Internal (iBGP) AS sessions\n" "External (eBGP) AS sessions\n" "Shorten the information on BGP instances\n" @@ -11946,8 +12044,12 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, as_type = AS_INTERNAL; else if (argv[idx + 1]->arg[0] == 'e') as_type = AS_EXTERNAL; - else - as = (as_t)atoi(argv[idx + 1]->arg); + else if (!asn_str2asn(argv[idx + 1]->arg, &as)) { + vty_out(vty, + "%% Invalid neighbor remote-as value: %s\n", + argv[idx + 1]->arg); + return CMD_SUCCESS; + } } if (argv_find(argv, argc, "terse", &idx)) @@ -13082,13 +13184,14 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_string_addf(json_neigh, "bgpNeighborAddr", "%pSU", &p->su); - json_object_int_add(json_neigh, "remoteAs", p->as); + asn_asn2json(json_neigh, "remoteAs", p->as, bgp->asnotation); if (p->change_local_as) - json_object_int_add(json_neigh, "localAs", - p->change_local_as); + asn_asn2json(json_neigh, "localAs", p->change_local_as, + bgp->asnotation); else - json_object_int_add(json_neigh, "localAs", p->local_as); + asn_asn2json(json_neigh, "localAs", p->local_as, + bgp->asnotation); if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) json_object_boolean_true_add(json_neigh, @@ -13098,13 +13201,19 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_boolean_true_add(json_neigh, "localAsReplaceAs"); } else { - if ((p->as_type == AS_SPECIFIED) || (p->as_type == AS_EXTERNAL) - || (p->as_type == AS_INTERNAL)) - vty_out(vty, "remote AS %u, ", p->as); - else + if ((p->as_type == AS_SPECIFIED) || + (p->as_type == AS_EXTERNAL) || + (p->as_type == AS_INTERNAL)) { + vty_out(vty, "remote AS "); + vty_out(vty, ASN_FORMAT(bgp->asnotation), &p->as); + vty_out(vty, ", "); + } else vty_out(vty, "remote AS Unspecified, "); - vty_out(vty, "local AS %u%s%s, ", - p->change_local_as ? p->change_local_as : p->local_as, + vty_out(vty, "local AS "); + vty_out(vty, ASN_FORMAT(bgp->asnotation), + p->change_local_as ? &p->change_local_as + : &p->local_as); + vty_out(vty, "%s%s, ", CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? " no-prepend" : "", @@ -15577,10 +15686,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, json_object_new_string(vname)); json_object_object_add(json, "exportToVrfs", json_export_vrfs); - json_object_string_addf(json, "routeDistinguisher", - "%pRD", - &bgp->vpn_policy[afi].tovpn_rd); - + json_object_string_addf( + json, "routeDistinguisher", "%s", + bgp->vpn_policy[afi].tovpn_rd_pretty); dir = BGP_VPN_POLICY_DIR_TOVPN; if (bgp->vpn_policy[afi].rtlist[dir]) { ecom_str = ecommunity_ecom2str( @@ -15648,8 +15756,10 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, node, vname)) vty_out(vty, " %s\n", vname); - vty_out(vty, "RD: %pRD\n", + vty_out(vty, "RD: "); + vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vpn_policy[afi].tovpn_rd); + vty_out(vty, "\n"); dir = BGP_VPN_POLICY_DIR_TOVPN; if (bgp->vpn_policy[afi].rtlist[dir]) { @@ -16014,18 +16124,22 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group, if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) { if (json) - json_object_int_add(json_peer_group, "remoteAs", - conf->as); - else - vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", - group->name, conf->as); + asn_asn2json(json_peer_group, "remoteAs", conf->as, + bgp_get_asnotation(conf->bgp)); + else { + vty_out(vty, "\nBGP peer-group %s, remote AS ", + group->name); + vty_out(vty, ASN_FORMAT(bgp_get_asnotation(conf->bgp)), + &conf->as); + vty_out(vty, "\n"); + } } else if (conf->as_type == AS_INTERNAL) { if (json) - json_object_int_add(json_peer_group, "remoteAs", - group->bgp->as); + asn_asn2json(json, "remoteAs", group->bgp->as, + group->bgp->asnotation); else - vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", - group->name, group->bgp->as); + vty_out(vty, "\nBGP peer-group %s, remote AS %s\n", + group->name, group->bgp->as_pretty); } else { if (!json) vty_out(vty, "\nBGP peer-group %s\n", group->name); @@ -17148,8 +17262,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, } if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) - vty_out(vty, "%*srd vpn export %pRD\n", indent, "", - &bgp->vpn_policy[afi].tovpn_rd); + vty_out(vty, "%*srd vpn export %s\n", indent, "", + bgp->vpn_policy[afi].tovpn_rd_pretty); if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) { @@ -17319,7 +17433,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, vty_out(vty, " peer-group %s", peer->group->name); if_pg_printed = true; } else if (peer->as_type == AS_SPECIFIED) { - vty_out(vty, " remote-as %u", peer->as); + vty_out(vty, " remote-as %s", peer->as_pretty); if_ras_printed = true; } else if (peer->as_type == AS_INTERNAL) { vty_out(vty, " remote-as internal"); @@ -17339,8 +17453,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) { if (peer->as_type == AS_SPECIFIED) { - vty_out(vty, " neighbor %s remote-as %u\n", - addr, peer->as); + vty_out(vty, " neighbor %s remote-as %s\n", + addr, peer->as_pretty); } else if (peer->as_type == AS_INTERNAL) { vty_out(vty, " neighbor %s remote-as internal\n", @@ -17368,8 +17482,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, if (!if_ras_printed) { if (peer->as_type == AS_SPECIFIED) { - vty_out(vty, " neighbor %s remote-as %u\n", - addr, peer->as); + vty_out(vty, " neighbor %s remote-as %s\n", + addr, peer->as_pretty); } else if (peer->as_type == AS_INTERNAL) { vty_out(vty, " neighbor %s remote-as internal\n", @@ -17384,8 +17498,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, /* local-as */ if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS)) { - vty_out(vty, " neighbor %s local-as %u", addr, - peer->change_local_as); + vty_out(vty, " neighbor %s local-as %s", addr, + peer->change_local_as_pretty); if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND)) vty_out(vty, " no-prepend"); if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS)) @@ -18066,12 +18180,16 @@ int bgp_config_write(struct vty *vty) continue; /* Router bgp ASN */ - vty_out(vty, "router bgp %u", bgp->as); + vty_out(vty, "router bgp %s", bgp->as_pretty); if (bgp->name) vty_out(vty, " %s %s", (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ? "view" : "vrf", bgp->name); + if (CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION)) + vty_out(vty, " as-notation %s", + asn_mode2str(bgp->asnotation)); + vty_out(vty, "\n"); /* BGP fast-external-failover. */ @@ -18189,8 +18307,8 @@ int bgp_config_write(struct vty *vty) /* Confederation identifier*/ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - vty_out(vty, " bgp confederation identifier %u\n", - bgp->confed_id); + vty_out(vty, " bgp confederation identifier %s\n", + bgp->confed_id_pretty); /* Confederation peer */ if (bgp->confed_peers_cnt > 0) { @@ -18199,7 +18317,8 @@ int bgp_config_write(struct vty *vty) vty_out(vty, " bgp confederation peers"); for (i = 0; i < bgp->confed_peers_cnt; i++) - vty_out(vty, " %u", bgp->confed_peers[i]); + vty_out(vty, " %s", + bgp->confed_peers[i].as_pretty); vty_out(vty, "\n"); } diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 56485035e..1c5adff68 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -135,7 +135,8 @@ extern void bgp_vty_init(void); extern void community_alias_vty(void); extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json); extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, - enum bgp_instance_type inst_type); + enum bgp_instance_type inst_type, const char *as_pretty, + enum asnotation_mode asnotation); extern void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp); extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); extern void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9ea5a92ad..09d7944ae 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -553,7 +553,7 @@ void bgp_tcp_keepalive_unset(struct bgp *bgp) } /* BGP confederation configuration. */ -void bgp_confederation_id_set(struct bgp *bgp, as_t as) +void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str) { struct peer *peer; struct listnode *node, *nnode; @@ -565,6 +565,9 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as) /* Remember - were we doing confederation before? */ already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION); bgp->confed_id = as; + if (bgp->confed_id_pretty) + XFREE(MTYPE_BGP, bgp->confed_id_pretty); + bgp->confed_id_pretty = XSTRDUP(MTYPE_BGP, as_str); bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION); /* If we were doing confederation already, this is just an external @@ -617,6 +620,7 @@ void bgp_confederation_id_unset(struct bgp *bgp) struct listnode *node, *nnode; bgp->confed_id = 0; + XFREE(MTYPE_BGP, bgp->confed_id_pretty); bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { @@ -644,14 +648,14 @@ bool bgp_confederation_peers_check(struct bgp *bgp, as_t as) return false; for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) + if (bgp->confed_peers[i].as == as) return true; return false; } /* Add an AS to the confederation set. */ -void bgp_confederation_peers_add(struct bgp *bgp, as_t as) +void bgp_confederation_peers_add(struct bgp *bgp, as_t as, const char *as_str) { struct peer *peer; struct listnode *node, *nnode; @@ -662,11 +666,13 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as) if (bgp_confederation_peers_check(bgp, as)) return; - bgp->confed_peers = - XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, - (bgp->confed_peers_cnt + 1) * sizeof(as_t)); + bgp->confed_peers = XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + (bgp->confed_peers_cnt + 1) * + sizeof(struct as_confed)); - bgp->confed_peers[bgp->confed_peers_cnt] = as; + bgp->confed_peers[bgp->confed_peers_cnt].as = as; + bgp->confed_peers[bgp->confed_peers_cnt].as_pretty = + XSTRDUP(MTYPE_BGP, as_str); bgp->confed_peers_cnt++; if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { @@ -703,9 +709,15 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as) return; for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) - for (j = i + 1; j < bgp->confed_peers_cnt; j++) - bgp->confed_peers[j - 1] = bgp->confed_peers[j]; + if (bgp->confed_peers[i].as == as) { + XFREE(MTYPE_BGP, bgp->confed_peers[i].as_pretty); + for (j = i + 1; j < bgp->confed_peers_cnt; j++) { + bgp->confed_peers[j - 1].as = + bgp->confed_peers[j].as; + bgp->confed_peers[j - 1].as_pretty = + bgp->confed_peers[j].as_pretty; + } + } bgp->confed_peers_cnt--; @@ -714,9 +726,9 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as) XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers); bgp->confed_peers = NULL; } else - bgp->confed_peers = - XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, - bgp->confed_peers_cnt * sizeof(as_t)); + bgp->confed_peers = XREALLOC( + MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + bgp->confed_peers_cnt * sizeof(struct as_confed)); /* Now reset any peer who's remote AS has just been removed from the CONFED */ @@ -1172,6 +1184,11 @@ static void peer_free(struct peer *peer) FOREACH_AFI_SAFI (afi, safi) bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE); + if (peer->change_local_as_pretty) + XFREE(MTYPE_BGP, peer->change_local_as_pretty); + if (peer->as_pretty) + XFREE(MTYPE_BGP, peer->as_pretty); + bgp_unlock(peer->bgp); memset(peer, 0, sizeof(struct peer)); @@ -1753,7 +1770,7 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) struct peer *peer_create(union sockunion *su, const char *conf_if, struct bgp *bgp, as_t local_as, as_t remote_as, int as_type, struct peer_group *group, - bool config_node) + bool config_node, const char *as_str) { int active; struct peer *peer; @@ -1778,6 +1795,9 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, } peer->local_as = local_as; peer->as = remote_as; + /* internal and external values do not use as_pretty */ + if (as_str && asn_str2asn(as_str, NULL)) + peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str); peer->as_type = as_type; peer->local_id = bgp->router_id; peer->v_holdtime = bgp->default_holdtime; @@ -1881,7 +1901,8 @@ bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi) } /* Change peer's AS number. */ -void peer_as_change(struct peer *peer, as_t as, int as_specified) +void peer_as_change(struct peer *peer, as_t as, int as_specified, + const char *as_str) { enum bgp_peer_sort origtype, newtype; @@ -1896,6 +1917,12 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified) } origtype = peer_sort_lookup(peer); peer->as = as; + if (as_specified == AS_SPECIFIED && as_str) { + if (peer->as_pretty) + XFREE(MTYPE_BGP, peer->as_pretty); + peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str); + } else if (peer->as_type == AS_UNSPECIFIED && peer->as_pretty) + XFREE(MTYPE_BGP, peer->as_pretty); peer->as_type = as_specified; if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION) @@ -1953,7 +1980,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified) /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, - as_t *as, int as_type) + as_t *as, int as_type, const char *as_str) { struct peer *peer; as_t local_as; @@ -2007,7 +2034,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, /* Existing peer's AS number change. */ if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || (peer->as_type != as_type)) - peer_as_change(peer, *as, as_type); + peer_as_change(peer, *as, as_type, as_str); } else { if (conf_if) return BGP_ERR_NO_INTERFACE_CONFIG; @@ -2022,7 +2049,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, local_as = bgp->as; peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL, - true); + true, as_str); } return 0; @@ -2047,6 +2074,13 @@ const char *bgp_get_name_by_role(uint8_t role) return "unknown"; } +enum asnotation_mode bgp_get_asnotation(struct bgp *bgp) +{ + if (!bgp) + return ASNOTATION_PLAIN; + return bgp->asnotation; +} + static void peer_group2peer_config_copy_af(struct peer_group *group, struct peer *peer, afi_t afi, safi_t safi) @@ -2804,7 +2838,7 @@ static void peer_group2peer_config_copy(struct peer_group *group, /* Peer group's remote AS configuration. */ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, - int as_type) + int as_type, const char *as_str) { struct peer_group *group; struct peer *peer; @@ -2820,12 +2854,12 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, /* When we setup peer-group AS number all peer group member's AS number must be updated to same number. */ - peer_as_change(group->conf, *as, as_type); + peer_as_change(group->conf, *as, as_type, as_str); for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || (peer->as_type != as_type)) - peer_as_change(peer, *as, as_type); + peer_as_change(peer, *as, as_type, as_str); } return 0; @@ -3132,7 +3166,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, } peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, - group->conf->as_type, group, true); + group->conf->as_type, group, true, NULL); peer = peer_lock(peer); /* group->peer list reference */ listnode_add(group->peer, peer); @@ -3184,23 +3218,37 @@ static void bgp_vrf_string_name_delete(void *data) /* BGP instance creation by `router bgp' commands. */ static struct bgp *bgp_create(as_t *as, const char *name, - enum bgp_instance_type inst_type) + enum bgp_instance_type inst_type, + const char *as_pretty, + enum asnotation_mode asnotation) { struct bgp *bgp; afi_t afi; safi_t safi; bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp)); + bgp->as = *as; + if (as_pretty) + bgp->as_pretty = XSTRDUP(MTYPE_BGP, as_pretty); + else + bgp->as_pretty = XSTRDUP(MTYPE_BGP, asn_asn2asplain(*as)); + + if (asnotation != ASNOTATION_UNDEFINED) { + bgp->asnotation = asnotation; + SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION); + } else + asn_str2asn_notation(bgp->as_pretty, NULL, &bgp->asnotation); if (BGP_DEBUG(zebra, ZEBRA)) { if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) - zlog_debug("Creating Default VRF, AS %u", *as); + zlog_debug("Creating Default VRF, AS %s", + bgp->as_pretty); else - zlog_debug("Creating %s %s, AS %u", + zlog_debug("Creating %s %s, AS %s", (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", - name, *as); + name, bgp->as_pretty); } /* Default the EVPN VRF to the default one */ @@ -3277,7 +3325,6 @@ static struct bgp *bgp_create(as_t *as, const char *name, bgp->condition_check_period = DEFAULT_CONDITIONAL_ROUTES_POLL_TIME; bgp_addpath_init_bgp_data(&bgp->tx_addpath); bgp->fast_convergence = false; - bgp->as = *as; bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME; #ifdef ENABLE_BGP_VNC @@ -3514,7 +3561,8 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name, /* Called from VTY commands. */ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, - enum bgp_instance_type inst_type) + enum bgp_instance_type inst_type, const char *as_pretty, + enum asnotation_mode asnotation) { struct bgp *bgp; struct vrf *vrf = NULL; @@ -3524,7 +3572,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, if (ret || *bgp_val) return ret; - bgp = bgp_create(as, name, inst_type); + bgp = bgp_create(as, name, inst_type, as_pretty, asnotation); /* * view instances will never work inside of a vrf @@ -3918,8 +3966,13 @@ void bgp_free(struct bgp *bgp) dir = BGP_VPN_POLICY_DIR_TOVPN; if (bgp->vpn_policy[afi].rtlist[dir]) ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]); + if (bgp->vpn_policy[afi].tovpn_rd_pretty) + XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty); } + bgp_confederation_id_unset(bgp); + + XFREE(MTYPE_BGP, bgp->as_pretty); XFREE(MTYPE_BGP, bgp->name); XFREE(MTYPE_BGP, bgp->name_pretty); XFREE(MTYPE_BGP, bgp->snmp_stats); @@ -4024,7 +4077,7 @@ struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp, /* Create peer first; we've already checked group config is valid. */ peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, - group->conf->as_type, group, true); + group->conf->as_type, group, true, NULL); if (!peer) return NULL; @@ -6228,7 +6281,7 @@ int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi) } int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, - bool replace_as) + bool replace_as, const char *as_str) { bool old_no_prepend, old_replace_as; struct bgp *bgp = peer->bgp; @@ -6253,6 +6306,9 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, && old_replace_as == replace_as) return 0; peer->change_local_as = as; + if (as_str) + peer->change_local_as_pretty = XSTRDUP(MTYPE_BGP, as_str); + (void)peer_sort(peer); /* Check if handling a regular peer. */ @@ -6286,6 +6342,9 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as); member->change_local_as = as; + if (as_str) + member->change_local_as_pretty = + XSTRDUP(MTYPE_BGP, as_str); } return 0; @@ -6311,6 +6370,7 @@ int peer_local_as_unset(struct peer *peer) peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND); peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS); peer->change_local_as = 0; + XFREE(MTYPE_BGP, peer->change_local_as_pretty); } /* Check if handling a regular peer. */ @@ -6341,6 +6401,7 @@ int peer_local_as_unset(struct peer *peer) UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); member->change_local_as = 0; + XFREE(MTYPE_BGP, member->change_local_as_pretty); /* Send notification or stop peer depending on state. */ if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) { @@ -8024,7 +8085,7 @@ static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token) { struct listnode *next, *next2; struct bgp *bgp, *bgp2; - char buf[11]; + char buf[ASN_STRING_MAX_SIZE]; for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { /* deduplicate */ @@ -8037,7 +8098,7 @@ static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token) if (bgp2 != bgp) continue; - snprintf(buf, sizeof(buf), "%u", bgp->as); + snprintf(buf, sizeof(buf), "%s", bgp->as_pretty); vector_set(comps, XSTRDUP(MTYPE_COMPLETION, buf)); } } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 91f0de0ce..2a7c7a314 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -16,6 +16,7 @@ #include "vty.h" #include "srv6.h" #include "iana_afi.h" +#include "asn.h" /* For union sockunion. */ #include "queue.h" @@ -62,7 +63,6 @@ enum zebra_gr_mode { }; /* Typedef BGP specific types. */ -typedef uint32_t as_t; typedef uint16_t as16_t; /* we may still encounter 16 Bit asnums */ typedef uint16_t bgp_size_t; @@ -203,6 +203,7 @@ struct vpn_policy { /* should be mpls_label_t? */ uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */ uint32_t tovpn_zebra_vrf_label_last_sent; + char *tovpn_rd_pretty; struct prefix_rd tovpn_rd; struct prefix tovpn_nexthop; /* unset => set to 0 */ uint32_t flags; @@ -324,10 +325,16 @@ struct bgp_srv6_function { char locator_name[SRV6_LOCNAME_SIZE]; }; +struct as_confed { + as_t as; + char *as_pretty; +}; + /* BGP instance structure. */ struct bgp { /* AS number of this BGP instance. */ as_t as; + char *as_pretty; /* Name of this BGP instance. */ char *name; @@ -383,6 +390,7 @@ struct bgp { uint16_t config; #define BGP_CONFIG_CLUSTER_ID (1 << 0) #define BGP_CONFIG_CONFEDERATION (1 << 1) +#define BGP_CONFIG_ASNOTATION (1 << 2) /* BGP router identifier. */ struct in_addr router_id; @@ -394,7 +402,8 @@ struct bgp { /* BGP confederation information. */ as_t confed_id; - as_t *confed_peers; + char *confed_id_pretty; + struct as_confed *confed_peers; int confed_peers_cnt; struct thread @@ -728,6 +737,7 @@ struct bgp { /* RD for this VRF */ struct prefix_rd vrf_prd; + char *vrf_prd_pretty; /* import rt list for the vrf instance */ struct list *vrf_import_rtl; @@ -782,6 +792,8 @@ struct bgp { bool allow_martian; + enum asnotation_mode asnotation; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(bgp); @@ -1105,6 +1117,8 @@ struct peer { /* Peer's remote AS number. */ int as_type; as_t as; + /* for vty as format */ + char *as_pretty; /* Peer's local AS number. */ as_t local_as; @@ -1113,6 +1127,8 @@ struct peer { /* Peer's Change local AS number. */ as_t change_local_as; + /* for vty as format */ + char *change_local_as_pretty; /* Remote router ID. */ struct in_addr remote_id; @@ -2131,7 +2147,7 @@ extern void bgp_recalculate_all_bestpaths(struct bgp *bgp); extern struct peer *peer_create(union sockunion *su, const char *conf_if, struct bgp *bgp, as_t local_as, as_t remote_as, int as_type, struct peer_group *group, - bool config_node); + bool config_node, const char *as_str); extern struct peer *peer_create_accept(struct bgp *); extern void peer_xfer_config(struct peer *dst, struct peer *src); extern char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json, @@ -2158,7 +2174,9 @@ extern void bgp_option_norib_set_runtime(void); /* unset the bgp no-rib option during runtime and reset all peers */ extern void bgp_option_norib_unset_runtime(void); -extern int bgp_get(struct bgp **, as_t *, const char *, enum bgp_instance_type); +extern int bgp_get(struct bgp **bgp, as_t *as, const char *name, + enum bgp_instance_type kind, const char *as_pretty, + enum asnotation_mode asnotation); extern void bgp_instance_up(struct bgp *); extern void bgp_instance_down(struct bgp *); extern int bgp_delete(struct bgp *); @@ -2174,11 +2192,13 @@ extern void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set); extern void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id); extern void bgp_cluster_id_unset(struct bgp *bgp); -extern void bgp_confederation_id_set(struct bgp *bgp, as_t as); +extern void bgp_confederation_id_set(struct bgp *bgp, as_t as, + const char *as_str); extern void bgp_confederation_id_unset(struct bgp *bgp); extern bool bgp_confederation_peers_check(struct bgp *, as_t); -extern void bgp_confederation_peers_add(struct bgp *bgp, as_t as); +extern void bgp_confederation_peers_add(struct bgp *bgp, as_t as, + const char *as_str); extern void bgp_confederation_peers_remove(struct bgp *bgp, as_t as); extern void bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime, @@ -2199,10 +2219,13 @@ extern void bgp_listen_limit_unset(struct bgp *bgp); extern bool bgp_update_delay_active(struct bgp *); extern bool bgp_update_delay_configured(struct bgp *); extern bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); -extern void peer_as_change(struct peer *, as_t, int); -extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, - int); -extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int); +extern void peer_as_change(struct peer *peer, as_t as, int as_type, + const char *as_str); +extern int peer_remote_as(struct bgp *bgp, union sockunion *su, + const char *conf_if, as_t *as, int as_type, + const char *as_str); +extern int peer_group_remote_as(struct bgp *bgp, const char *peer_str, as_t *as, + int as_type, const char *as_str); extern int peer_delete(struct peer *peer); extern void peer_notify_unconfig(struct peer *peer); extern int peer_group_delete(struct peer_group *); @@ -2281,8 +2304,8 @@ extern int peer_distribute_unset(struct peer *, afi_t, safi_t, int); extern int peer_allowas_in_set(struct peer *, afi_t, safi_t, int, int); extern int peer_allowas_in_unset(struct peer *, afi_t, safi_t); -extern int peer_local_as_set(struct peer *, as_t, bool no_prepend, - bool replace_as); +extern int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, + bool replace_as, const char *as_str); extern int peer_local_as_unset(struct peer *); extern int peer_prefix_list_set(struct peer *, afi_t, safi_t, int, @@ -2341,6 +2364,7 @@ extern void peer_tx_shutdown_message_unset(struct peer *); extern void bgp_route_map_update_timer(struct thread *thread); extern const char *bgp_get_name_by_role(uint8_t role); +extern enum asnotation_mode bgp_get_asnotation(struct bgp *bgp); extern void bgp_route_map_terminate(void); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 40cb8f8d5..5b6961d18 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -410,6 +410,7 @@ DEFUN (vnc_defaults_rd, } else { + /* TODO: save RD format */ ret = str2prefix_rd(argv[1]->arg, &prd); if (!ret) { vty_out(vty, "%% Malformed rd\n"); @@ -2874,6 +2875,7 @@ DEFUN (vnc_nve_group_rd, } else { + /* TODO: save RD format */ ret = str2prefix_rd(argv[1]->arg, &prd); if (!ret) { vty_out(vty, "%% Malformed rd\n"); @@ -3346,6 +3348,7 @@ DEFUN (vnc_vrf_policy_rd, } else { + /* TODO: save RD format */ ret = str2prefix_rd(argv[1]->arg, &prd); if (!ret) { vty_out(vty, "%% Malformed rd\n"); @@ -3924,7 +3927,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) value); } else - vty_out(vty, " rd %pRD\n", &rfg->rd); + vty_out(vty, " rd %pRDP\n", &rfg->rd); } if (rfg->rt_import_list && rfg->rt_export_list @@ -4144,7 +4147,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) value); } else - vty_out(vty, " rd %pRD\n", + vty_out(vty, " rd %pRDP\n", &hc->default_rd); } if (hc->default_response_lifetime @@ -4224,7 +4227,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) value); } else - vty_out(vty, " rd %pRD\n", + vty_out(vty, " rd %pRDP\n", &rfg->rd); } if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) { diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 0c8fdc72e..8d6db9d77 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -363,7 +363,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); vnc_zlog_debug_verbose( - "%s: peer=%p, prefix=%pFX, prd=%pRD afi=%d, safi=%d bn=%p, bn->info=%p", + "%s: peer=%p, prefix=%pFX, prd=%pRDP afi=%d, safi=%d bn=%p, bn->info=%p", __func__, peer, p, prd, afi, safi, bn, (bn ? bgp_dest_get_bgp_path_info(bn) : NULL)); @@ -1053,7 +1053,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ bgp_process(bgp, bn, afi, safi); vnc_zlog_debug_any( - "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRD)", + "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)", __func__, safi2str(safi), buf, bn, prd); done: @@ -3712,7 +3712,7 @@ int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn) memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3], 4); /* low order 4 bytes */ } - vnc_zlog_debug_verbose("%s: auto-RD is set to %pRD", __func__, rd); + vnc_zlog_debug_verbose("%s: auto-RD is set to %pRDP", __func__, rd); return 0; } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 6d4fc53f8..a50440536 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -2082,7 +2082,7 @@ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */ assert(bpi); assert(bpi->extra); - vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi, + vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi, bpi->peer, &bpi->extra->vnc.import.rd); sl = RFAPI_RDINDEX_W_ALLOC(rn); @@ -2120,7 +2120,9 @@ static void rfapiItBiIndexDump(struct agg_node *rn) char buf[RD_ADDRSTRLEN]; char buf_aux_pfx[PREFIX_STRLEN]; - prefix_rd2str(&k->extra->vnc.import.rd, buf, sizeof(buf)); + prefix_rd2str( + &k->extra->vnc.import.rd, buf, sizeof(buf), + bgp_get_asnotation(k->peer ? k->peer->bgp : NULL)); if (k->extra->vnc.import.aux_prefix.family) { prefix2str(&k->extra->vnc.import.aux_prefix, buf_aux_pfx, sizeof(buf_aux_pfx)); @@ -2158,7 +2160,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch( strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx)); vnc_zlog_debug_verbose( - "%s want prd=%pRD, peer=%p, aux_prefix=%s", __func__, + "%s want prd=%pRDP, peer=%p, aux_prefix=%s", __func__, prd, peer, buf_aux_pfx); rfapiItBiIndexDump(rn); } @@ -2174,7 +2176,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch( bpi_result = bpi_result->next) { #ifdef DEBUG_BI_SEARCH vnc_zlog_debug_verbose( - "%s: bpi has prd=%pRD, peer=%p", __func__, + "%s: bpi has prd=%pRDP, peer=%p", __func__, &bpi_result->extra->vnc.import.rd, bpi_result->peer); #endif @@ -2238,7 +2240,7 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */ struct skiplist *sl; int rc; - vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi, + vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi, bpi->peer, &bpi->extra->vnc.import.rd); sl = RFAPI_RDINDEX(rn); diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index b15620741..f727f24f1 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -1114,7 +1114,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, skiplist_insert(slRibPt, &ori->rk, ori); vnc_zlog_debug_verbose( - "%s: nomatch lPendCost item %p in slRibPt, added (rd=%pRD)", + "%s: nomatch lPendCost item %p in slRibPt, added (rd=%pRDP)", __func__, ri, &ori->rk.rd); } @@ -1356,7 +1356,7 @@ callback: ri->last_sent_time = monotime(NULL); #if DEBUG_RIB_SL_RD vnc_zlog_debug_verbose( - "%s: move route to recently deleted list, rd=%pRD", + "%s: move route to recently deleted list, rd=%pRDP", __func__, &ri->rk.rd); #endif @@ -2252,7 +2252,7 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty, } #endif - fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRD\n", + fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRDP\n", deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn, str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd); diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 0144c28d5..2b768b8f8 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1589,7 +1589,7 @@ void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd) vty_out(vty, " "); rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr); vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie); - vty_out(vty, "%pRD", &rfd->rd); + vty_out(vty, "%pRDP", &rfd->rd); vty_out(vty, " %d", rfd->response_lifetime); vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>")); vty_out(vty, "%s", HVTYNL); @@ -4709,6 +4709,7 @@ static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf, if (arg_rd) { opt = &optary[cur_opt++]; opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + /* TODO: save RD format */ if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) { vty_out(vty, "Malformed RD \"%s\"\n", arg_rd); return CMD_WARNING_CONFIG_FAILED; |