diff options
313 files changed, 10058 insertions, 4825 deletions
diff --git a/.clang-format b/.clang-format index 93ad18b98a..06769c9661 100644 --- a/.clang-format +++ b/.clang-format @@ -207,4 +207,21 @@ SpacesInSquareBrackets: false Standard: Cpp03 TabWidth: 8 UseTab: Always +WhitespaceSensitiveMacros: + - "DEFPY" + - "DEFPY_HIDDEN" + - "DEFPY_NOSH" + - "DEFPY_YANG" + - "DEFPY_YANG_HIDDEN" + - "DEFPY_YANG_NOSH" + - "DEFSH" + - "DEFSH_HIDDEN" + - "DEFUN" + - "DEFUN_HIDDEN" + - "DEFUN_NOSH" + - "DEFUN_YANG" + - "DEFUN_YANG_HIDDEN" + - "DEFUN_YANG_NOSH" + - "DEFUNSH" + - "DEFUNSH_HIDDEN" ... diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 1ecdfd2fb3..9b6932c285 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -20,3 +20,5 @@ c14777c6bfd0a446c85243d3a9835054a259c276 8451921b70044a2c1075e7ba391f095fabee2550 bf8d3d6aca3f20255a621ed1c148fd05b3a8ae5c 96941f80927ce31a41f7d1905717f099187be723 +# apply `black` python formatting for all tests/topotests +1a1c2a9f84d0ad1bdadc0cb47d6175d4ccc32544 diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index a81f288c7a..d519749f6b 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -182,12 +182,15 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr, adj->uptime = monotime(NULL); adj->addpath_rx_id = addpath_id; BGP_ADJ_IN_ADD(dest, adj); + peer->stat_pfx_adj_rib_in++; bgp_dest_lock_node(dest); } void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai) { bgp_attr_unintern(&bai->attr); + if (bai->peer) + bai->peer->stat_pfx_adj_rib_in--; BGP_ADJ_IN_DEL(*dest, bai); *dest = bgp_dest_unlock_node(*dest); peer_unlock(bai->peer); /* adj_in peer reference */ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e2321ad296..71f02a7f83 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -915,12 +915,13 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty) "\n", attr->flag, attr->distance, attr->med, attr->local_pref, attr->origin, attr->weight, attr->label, sid, attr->aigp_metric); - vty_out(vty, - "\taspath: %s Community: %s Extended Community: %s Large Community: %s\n", + vty_out(vty, "\taspath: %s Community: %s Large Community: %s\n", aspath_print(attr->aspath), community_str(attr->community, false, false), - ecommunity_str(attr->ecommunity), lcommunity_str(attr->lcommunity, false, false)); + vty_out(vty, "\tExtended Community: %s Extended IPv6 Community: %s\n", + ecommunity_str(attr->ecommunity), + ecommunity_str(attr->ipv6_ecommunity)); } void attr_show_all(struct vty *vty) @@ -1525,6 +1526,7 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) uint8_t mask = BGP_ATTR_FLAG_EXTLEN; const uint8_t flags = args->flags; const uint8_t attr_code = args->type; + struct peer *peer = args->peer; /* there may be attributes we don't know about */ if (attr_code > attr_flags_values_max) @@ -1532,6 +1534,14 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) if (attr_flags_values[attr_code] == 0) return false; + /* If `neighbor X path-attribute <discard|treat-as-withdraw>` is + * configured, then ignore checking optional, trasitive flags. + * The attribute/route will be discarded/withdrawned later instead + * of dropping the session. + */ + if (peer->discard_attrs[attr_code] || peer->withdraw_attrs[attr_code]) + return false; + /* RFC4271, "For well-known attributes, the Transitive bit MUST be set * to * 1." @@ -2650,10 +2660,7 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args) if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type]) goto ipv6_ext_community_ignore; - ipv6_ecomm = ecommunity_parse_ipv6( - stream_pnt(peer->curr), length, - CHECK_FLAG(peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length); bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm); /* XXX: fix ecommunity_parse to use stream API */ @@ -2663,6 +2670,10 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args) return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); + /* Extract link bandwidth, if any. */ + (void)ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(attr), + &attr->link_bw); + return BGP_ATTR_PARSE_PROCEED; ipv6_ext_community_ignore: @@ -4354,6 +4365,69 @@ static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi) return false; } +static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer, + struct ecommunity *ecomm, + bool transparent, int attribute) +{ + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || + peer->sub_sort == BGP_PEER_EBGP_OAD || transparent) { + if (ecomm->size * ecomm->unit_size > 255) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS | + BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, attribute); + stream_putw(s, ecomm->size * ecomm->unit_size); + } else { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS); + stream_putc(s, attribute); + stream_putc(s, ecomm->size * ecomm->unit_size); + } + stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size); + } else { + uint8_t *pnt; + int tbit; + int ecom_tr_size = 0; + uint32_t i; + + for (i = 0; i < ecomm->size; i++) { + pnt = ecomm->val + (i * ecomm->unit_size); + tbit = *pnt; + + if (CHECK_FLAG(tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) + continue; + + ecom_tr_size++; + } + + if (ecom_tr_size) { + if (ecom_tr_size * ecomm->unit_size > 255) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS | + BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, attribute); + stream_putw(s, ecom_tr_size * ecomm->unit_size); + } else { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | + BGP_ATTR_FLAG_TRANS); + stream_putc(s, attribute); + stream_putc(s, ecom_tr_size * ecomm->unit_size); + } + + for (i = 0; i < ecomm->size; i++) { + pnt = ecomm->val + (i * ecomm->unit_size); + tbit = *pnt; + + if (CHECK_FLAG(tbit, + ECOMMUNITY_FLAG_NON_TRANSITIVE)) + continue; + + stream_put(s, pnt, ecomm->unit_size); + } + } + } +} + /* Make attribute packet. */ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s, struct attr *attr, @@ -4656,82 +4730,31 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } } - /* Extended Communities attribute. */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { - struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr); + /* Extended IPv6/Communities attributes. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) { bool transparent = CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) && from && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT); - if (peer->sort == BGP_PEER_IBGP || - peer->sort == BGP_PEER_CONFED || transparent) { - if (ecomm->size * 8 > 255) { - stream_putc(s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS - | BGP_ATTR_FLAG_EXTLEN); - stream_putc(s, BGP_ATTR_EXT_COMMUNITIES); - stream_putw(s, ecomm->size * 8); - } else { - stream_putc(s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS); - stream_putc(s, BGP_ATTR_EXT_COMMUNITIES); - stream_putc(s, ecomm->size * 8); - } - stream_put(s, ecomm->val, ecomm->size * 8); - } else { - uint8_t *pnt; - int tbit; - int ecom_tr_size = 0; - uint32_t i; - - for (i = 0; i < ecomm->size; i++) { - pnt = ecomm->val + (i * 8); - tbit = *pnt; + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr); - if (CHECK_FLAG(tbit, - ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; + bgp_packet_ecommunity_attribute(s, peer, ecomm, + transparent, + BGP_ATTR_EXT_COMMUNITIES); + } - ecom_tr_size++; - } + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) { + struct ecommunity *ecomm = + bgp_attr_get_ipv6_ecommunity(attr); - if (ecom_tr_size) { - if (ecom_tr_size * 8 > 255) { - stream_putc( - s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS - | BGP_ATTR_FLAG_EXTLEN); - stream_putc(s, - BGP_ATTR_EXT_COMMUNITIES); - stream_putw(s, ecom_tr_size * 8); - } else { - stream_putc( - s, - BGP_ATTR_FLAG_OPTIONAL - | BGP_ATTR_FLAG_TRANS); - stream_putc(s, - BGP_ATTR_EXT_COMMUNITIES); - stream_putc(s, ecom_tr_size * 8); - } - - for (i = 0; i < ecomm->size; i++) { - pnt = ecomm->val + (i * 8); - tbit = *pnt; - - if (CHECK_FLAG( - tbit, - ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; - - stream_put(s, pnt, 8); - } - } + bgp_packet_ecommunity_attribute(s, peer, ecomm, + transparent, + BGP_ATTR_IPV6_EXT_COMMUNITIES); } } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 164aa5ae79..a8ba36d2d9 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -301,7 +301,7 @@ struct attr { uint32_t rmap_table_id; /* Link bandwidth value, if any. */ - uint32_t link_bw; + uint64_t link_bw; /* EVPN ES */ esi_t esi; @@ -517,11 +517,9 @@ static inline void bgp_attr_set_ecommunity(struct attr *attr, { attr->ecommunity = ecomm; - if (ecomm) { + if (ecomm) SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); - if (ecommunity_select_color(ecomm)) - SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)); - } else + else UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); } diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 5fcb8c5645..2f3be0bc9d 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -391,11 +391,11 @@ static int bmp_send_initiation(struct bmp *bmp) bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_INITIATION); -#define BMP_INFO_TYPE_SYSDESCR 1 -#define BMP_INFO_TYPE_SYSNAME 2 - bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSDESCR, - FRR_FULL_NAME " " FRR_VER_SHORT); - bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSNAME, cmd_hostname_get()); +#define BMP_INIT_INFO_TYPE_SYSDESCR 1 +#define BMP_INIT_INFO_TYPE_SYSNAME 2 + bmp_put_info_tlv(s, BMP_INIT_INFO_TYPE_SYSDESCR, + FRR_FULL_NAME " " FRR_VER_SHORT); + bmp_put_info_tlv(s, BMP_INIT_INFO_TYPE_SYSNAME, cmd_hostname_get()); len = stream_get_endp(s); stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */ @@ -438,6 +438,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) monotime_to_realtime(&uptime, &uptime_real); #define BGP_BMP_MAX_PACKET_SIZE 1024 +#define BMP_PEERUP_INFO_TYPE_STRING 0 s = stream_new(BGP_MAX_PACKET_SIZE); if (peer_established(peer->connection) && !down) { @@ -493,7 +494,8 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down) } if (peer->desc) - bmp_put_info_tlv(s, 0, peer->desc); + bmp_put_info_tlv(s, BMP_PEERUP_INFO_TYPE_STRING, + peer->desc); } else { uint8_t type; size_t type_pos; @@ -1592,6 +1594,15 @@ static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type, (*cnt)++; } +static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type, + uint64_t value) +{ + stream_putw(s, type); + stream_putw(s, 8); + stream_putq(s, value); + (*cnt)++; +} + static void bmp_stats(struct event *thread) { struct bmp_targets *bt = EVENT_ARG(thread); @@ -1633,8 +1644,13 @@ static void bmp_stats(struct event *thread) peer->stat_pfx_dup_withdraw); bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW, peer->stat_upd_7606); - bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID, - peer->stat_pfx_nh_invalid); + if (bt->stats_send_experimental) + bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID, + peer->stat_pfx_nh_invalid); + bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN, + peer->stat_pfx_adj_rib_in); + bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_LOC_RIB, + peer->stat_pfx_loc_rib); stream_putl_at(s, count_pos, count); @@ -1889,6 +1905,7 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name) bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name); bt->bgp = bgp; bt->bmpbgp = bmp_bgp_get(bgp); + bt->stats_send_experimental = true; bmp_session_init(&bt->sessions); bmp_qhash_init(&bt->updhash); bmp_qlist_init(&bt->updlist); @@ -2469,6 +2486,21 @@ DEFPY(bmp_stats_cfg, return CMD_SUCCESS; } +DEFPY(bmp_stats_send_experimental, + bmp_stats_send_experimental_cmd, + "[no] bmp stats send-experimental", + NO_STR + BMP_STR + "Send BMP statistics messages\n" + "Send experimental BMP stats [65531-65534]\n") +{ + VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt); + + bt->stats_send_experimental = !!no; + + return CMD_SUCCESS; +} + #define BMP_POLICY_IS_LOCRIB(str) ((str)[0] == 'l') /* __l__oc-rib */ #define BMP_POLICY_IS_PRE(str) ((str)[1] == 'r') /* p__r__e-policy */ @@ -2761,6 +2793,9 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) if (bt->acl_name) vty_out(vty, " ip access-list %s\n", bt->acl_name); + if (!bt->stats_send_experimental) + vty_out(vty, " no bmp stats send-experimental\n"); + if (bt->stat_msec) vty_out(vty, " bmp stats interval %d\n", bt->stat_msec); @@ -2816,6 +2851,7 @@ static int bgp_bmp_init(struct event_loop *tm) install_element(BMP_NODE, &no_bmp_listener_cmd); install_element(BMP_NODE, &bmp_connect_cmd); install_element(BMP_NODE, &bmp_acl_cmd); + install_element(BMP_NODE, &bmp_stats_send_experimental_cmd); install_element(BMP_NODE, &bmp_stats_cmd); install_element(BMP_NODE, &bmp_monitor_cmd); install_element(BMP_NODE, &bmp_mirror_cmd); diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h index dadd99eb6d..33247c4025 100644 --- a/bgpd/bgp_bmp.h +++ b/bgpd/bgp_bmp.h @@ -240,6 +240,8 @@ struct bmp_targets { uint64_t cnt_accept, cnt_aclrefused; + bool stats_send_experimental; + QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(bmp_targets); diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index ffe715a42f..673926f24c 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -153,8 +153,8 @@ struct bgp_debug_filter { TERM_DEBUG_OFF(a, b); \ } while (0) -#define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b) -#define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b) +#define BGP_DEBUG(a, b) (unlikely(term_bgp_debug_##a & BGP_DEBUG_##b)) +#define CONF_BGP_DEBUG(a, b) (unlikely(conf_bgp_debug_##a & BGP_DEBUG_##b)) extern const char *const bgp_type_str[]; diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index e1b462ae56..d392b6585c 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -237,11 +237,10 @@ struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length, disable_ieee_floating); } -struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length, - bool disable_ieee_floating) +struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length) { return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE, - disable_ieee_floating); + false); } /* Duplicate the Extended Communities Attribute structure. */ @@ -1026,10 +1025,6 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt, uint32_t bw_tmp, bw; char bps_buf[20] = {0}; -#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8) -#define ONE_MBPS_BYTES (1000 * 1000 / 8) -#define ONE_KBPS_BYTES (1000 / 8) - as = (*pnt++ << 8); as |= (*pnt++); (void)ptr_get_be32(pnt, &bw_tmp); @@ -1053,6 +1048,33 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt, return len; } +static int ipv6_ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt) +{ + int len = 0; + as_t as; + uint64_t bw; + char bps_buf[20] = { 0 }; + + pnt += 2; /* Reserved */ + pnt = ptr_get_be64(pnt, &bw); + (void)ptr_get_be32(pnt, &as); + + if (bw >= ONE_GBPS_BYTES) + snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps", + (float)(bw / ONE_GBPS_BYTES)); + else if (bw >= ONE_MBPS_BYTES) + snprintf(bps_buf, sizeof(bps_buf), "%.3f Mbps", + (float)(bw / ONE_MBPS_BYTES)); + else if (bw >= ONE_KBPS_BYTES) + snprintf(bps_buf, sizeof(bps_buf), "%.3f Kbps", + (float)(bw / ONE_KBPS_BYTES)); + else + snprintfrr(bps_buf, sizeof(bps_buf), "%" PRIu64 " bps", bw * 8); + + len = snprintfrr(buf, bufsz, "LB:%u:%" PRIu64 " (%s)", as, bw, bps_buf); + return len; +} + bool ecommunity_has_route_target(struct ecommunity *ecom) { uint32_t i; @@ -1153,6 +1175,12 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) ecommunity_lb_str( encbuf, sizeof(encbuf), pnt, ecom->disable_ieee_floating); + } else if (sub_type == + ECOMMUNITY_EXTENDED_LINK_BANDWIDTH && + type == ECOMMUNITY_ENCODE_AS4) { + ipv6_ecommunity_lb_str(encbuf, + sizeof(encbuf), + pnt); } else if (sub_type == ECOMMUNITY_NODE_TARGET && type == ECOMMUNITY_ENCODE_IP) { ecommunity_node_target_str( @@ -1368,6 +1396,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) if (sub_type == ECOMMUNITY_LINK_BANDWIDTH) ecommunity_lb_str(encbuf, sizeof(encbuf), pnt, ecom->disable_ieee_floating); + else if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) + ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf), + pnt); else unk_ecom = 1; } else if (type == ECOMMUNITY_ENCODE_IP_NON_TRANS) { @@ -1805,7 +1836,7 @@ ecommunity_add_origin_validation_state(enum rpki_states rpki_state, * return the BGP link bandwidth extended community, if present; * the actual bandwidth is returned via param */ -const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw) +const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw) { const uint8_t *eval; uint32_t i; @@ -1819,23 +1850,36 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw) for (i = 0; i < ecom->size; i++) { const uint8_t *pnt; uint8_t type, sub_type; - uint32_t bwval; - eval = pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + eval = pnt = (ecom->val + (i * ecom->unit_size)); type = *pnt++; sub_type = *pnt++; if ((type == ECOMMUNITY_ENCODE_AS || type == ECOMMUNITY_ENCODE_AS_NON_TRANS) && sub_type == ECOMMUNITY_LINK_BANDWIDTH) { + uint32_t bwval; + pnt += 2; /* bandwidth is encoded as AS:val */ pnt = ptr_get_be32(pnt, &bwval); (void)pnt; /* consume value */ if (bw) - *bw = ecom->disable_ieee_floating - ? bwval - : ieee_float_uint32_to_uint32( - bwval); + *bw = (uint64_t)(ecom->disable_ieee_floating + ? bwval + : ieee_float_uint32_to_uint32( + bwval)); + return eval; + } else if (type == ECOMMUNITY_ENCODE_AS4 && + sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) { + uint64_t bwval; + + pnt += 2; /* Reserved */ + pnt = ptr_get_be64(pnt, &bwval); + (void)pnt; + + if (bw) + *bw = bwval; + return eval; } } @@ -1846,13 +1890,13 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw) struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw, - bool disable_ieee_floating) + bool disable_ieee_floating, + bool extended) { struct ecommunity *new; - struct ecommunity_val lb_eval; const uint8_t *eval; uint8_t type; - uint32_t cur_bw; + uint64_t cur_bw; /* Nothing to replace if link-bandwidth doesn't exist or * is non-transitive - just return existing extcommunity. @@ -1876,10 +1920,21 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, */ if (cum_bw > 0xFFFFFFFF) cum_bw = 0xFFFFFFFF; - encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false, - &lb_eval, disable_ieee_floating); - new = ecommunity_dup(ecom); - ecommunity_add_val(new, &lb_eval, true, true); + + if (extended) { + struct ecommunity_val_ipv6 lb_eval; + + encode_lb_extended_extcomm(as, cum_bw, false, &lb_eval); + new = ecommunity_dup(ecom); + ecommunity_add_val_ipv6(new, &lb_eval, true, true); + } else { + struct ecommunity_val lb_eval; + + encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, + false, &lb_eval, disable_ieee_floating); + new = ecommunity_dup(ecom); + ecommunity_add_val(new, &lb_eval, true, true); + } return new; } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 794c5a3975..929e4e60be 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -10,6 +10,10 @@ #include "bgpd/bgp_rpki.h" #include "bgpd/bgpd.h" +#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8) +#define ONE_MBPS_BYTES (1000 * 1000 / 8) +#define ONE_KBPS_BYTES (1000 / 8) + /* Refer to rfc7153 for the IANA registry definitions. These are * updated by other standards like rfc7674. */ @@ -55,6 +59,12 @@ /* RFC 8956 */ #define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d +/* https://datatracker.ietf.org/doc/html/draft-li-idr-link-bandwidth-ext-01 + * Sub-type is allocated by IANA, just the draft is not yet updated with the + * new value. + */ +#define ECOMMUNITY_EXTENDED_LINK_BANDWIDTH 0x0006 + /* Low-order octet of the Extended Communities type field for EVPN types */ #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 #define ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL 0x01 @@ -224,12 +234,13 @@ static uint32_t uint32_to_ieee_float_uint32(uint32_t u) * Encode BGP Link Bandwidth extended community * bandwidth (bw) is in bytes-per-sec */ -static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans, +static inline void encode_lb_extcomm(as_t as, uint64_t bw, bool non_trans, struct ecommunity_val *eval, bool disable_ieee_floating) { - uint32_t bandwidth = - disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw); + uint64_t bandwidth = disable_ieee_floating + ? bw + : uint32_to_ieee_float_uint32(bw); memset(eval, 0, sizeof(*eval)); eval->val[0] = ECOMMUNITY_ENCODE_AS; @@ -244,6 +255,33 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans, eval->val[7] = bandwidth & 0xff; } +/* + * Encode BGP Link Bandwidth inside IPv6 Extended Community, + * bandwidth is in bytes per second. + */ +static inline void encode_lb_extended_extcomm(as_t as, uint64_t bandwidth, + bool non_trans, + struct ecommunity_val_ipv6 *eval) +{ + memset(eval, 0, sizeof(*eval)); + eval->val[0] = ECOMMUNITY_ENCODE_AS4; + if (non_trans) + eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE; + eval->val[1] = ECOMMUNITY_EXTENDED_LINK_BANDWIDTH; + eval->val[4] = (bandwidth >> 56) & 0xff; + eval->val[5] = (bandwidth >> 48) & 0xff; + eval->val[6] = (bandwidth >> 40) & 0xff; + eval->val[7] = (bandwidth >> 32) & 0xff; + eval->val[8] = (bandwidth >> 24) & 0xff; + eval->val[9] = (bandwidth >> 16) & 0xff; + eval->val[10] = (bandwidth >> 8) & 0xff; + eval->val[11] = bandwidth & 0xff; + eval->val[12] = (as >> 24) & 0xff; + eval->val[13] = (as >> 16) & 0xff; + eval->val[14] = (as >> 8) & 0xff; + eval->val[15] = as & 0xff; +} + static inline void encode_origin_validation_state(enum rpki_states state, struct ecommunity_val *eval) { @@ -325,8 +363,7 @@ extern void ecommunity_free(struct ecommunity **); extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short, bool disable_ieee_floating); extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, - unsigned short length, - bool disable_ieee_floating); + unsigned short length); extern struct ecommunity *ecommunity_dup(struct ecommunity *); extern struct ecommunity *ecommunity_merge(struct ecommunity *, struct ecommunity *); @@ -385,11 +422,10 @@ extern void bgp_remove_ecomm_from_aggregate_hash( struct ecommunity *ecommunity); extern void bgp_aggr_ecommunity_remove(void *arg); extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, - uint32_t *bw); -extern struct ecommunity *ecommunity_replace_linkbw(as_t as, - struct ecommunity *ecom, - uint64_t cum_bw, - bool disable_ieee_floating); + uint64_t *bw); +extern struct ecommunity * +ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw, + bool disable_ieee_floating, bool extended); extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo); diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 7866adbdcd..f10705ef21 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1801,14 +1801,18 @@ bgp_connect_fail(struct peer_connection *connection) */ static void bgp_connect_in_progress_update_connection(struct peer *peer) { - bgp_getsockname(peer); - if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) { - /* if connect initiated, then dest port and dest addresses are well known */ - peer->su_remote = sockunion_dup(&peer->connection->su); - if (sockunion_family(peer->su_remote) == AF_INET) - peer->su_remote->sin.sin_port = htons(peer->port); - else if (sockunion_family(peer->su_remote) == AF_INET6) - peer->su_remote->sin6.sin6_port = htons(peer->port); + if (bgp_getsockname(peer) < 0) { + if (!peer->su_remote && + !BGP_CONNECTION_SU_UNSPEC(peer->connection)) { + /* if connect initiated, then dest port and dest addresses are well known */ + peer->su_remote = sockunion_dup(&peer->connection->su); + if (sockunion_family(peer->su_remote) == AF_INET) + peer->su_remote->sin.sin_port = + htons(peer->port); + else if (sockunion_family(peer->su_remote) == AF_INET6) + peer->su_remote->sin6.sin6_port = + htons(peer->port); + } } } @@ -2915,19 +2919,22 @@ int bgp_neighbor_graceful_restart(struct peer *peer, peer_old_state = bgp_peer_gr_mode_get(peer); - if (peer_old_state == PEER_INVALID) { - zlog_debug("[BGP_GR] peer_old_state == Invalid state !"); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s [BGP_GR] peer_old_state: %d", __func__, + peer_old_state); + + if (peer_old_state == PEER_INVALID) return BGP_ERR_GR_OPERATION_FAILED; - } peer_state = peer->PEER_GR_FSM[peer_old_state][peer_gr_cmd]; peer_new_state = peer_state.next_state; - if (peer_new_state == PEER_INVALID) { - zlog_debug( - "[BGP_GR] Invalid bgp graceful restart command used !"); + if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) + zlog_debug("%s [BGP_GR] peer_new_state: %d", __func__, + peer_new_state); + + if (peer_new_state == PEER_INVALID) return BGP_ERR_GR_INVALID_CMD; - } if (peer_new_state != peer_old_state) { result = peer_state.action_fun(peer, peer_old_state, diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 296e64003d..e12d84b84c 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -521,7 +521,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, struct bgp_maxpaths_cfg *mpath_cfg) { uint16_t maxpaths, mpath_count, old_mpath_count; - uint32_t bwval; + uint64_t bwval; uint64_t cum_bw, old_cum_bw; struct listnode *mp_node, *mp_next_node; struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; @@ -613,8 +613,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, cur_mpath); prev_mpath = cur_mpath; mpath_count++; - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( + if (ecommunity_linkbw_present(bgp_attr_get_ecommunity( + cur_mpath->attr), + &bwval) || + ecommunity_linkbw_present( + bgp_attr_get_ipv6_ecommunity( cur_mpath->attr), &bwval)) cum_bw += bwval; @@ -700,8 +703,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, prev_mpath = new_mpath; mpath_changed = 1; mpath_count++; - if (ecommunity_linkbw_present( - bgp_attr_get_ecommunity( + if (ecommunity_linkbw_present(bgp_attr_get_ecommunity( + new_mpath->attr), + &bwval) || + ecommunity_linkbw_present( + bgp_attr_get_ipv6_ecommunity( new_mpath->attr), &bwval)) cum_bw += bwval; @@ -724,8 +730,12 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, if (new_best) { bgp_path_info_mpath_count_set(new_best, mpath_count - 1); if (mpath_count <= 1 || - !ecommunity_linkbw_present( - bgp_attr_get_ecommunity(new_best->attr), &bwval)) + (!ecommunity_linkbw_present(bgp_attr_get_ecommunity( + new_best->attr), + &bwval) && + !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity( + new_best->attr), + &bwval))) all_paths_lb = false; else cum_bw += bwval; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index fcaf2aebe3..66d6a55683 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -352,9 +352,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, return 0; } - if (CHECK_FLAG(pi->attr->flag, - ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) - srte_color = bgp_attr_get_color(pi->attr); + srte_color = bgp_attr_get_color(pi->attr); } else if (peer) { /* diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 78554893ff..9c194eac1c 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -3734,7 +3734,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, zlog_err("%pBP: Capability length error", peer); bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - pnt += length; + /* + * If we did not return then + * pnt += length; + */ return BGP_Stop; } action = *pnt; @@ -3759,7 +3762,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, zlog_err("%pBP: Capability length error", peer); bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - pnt += length; + /* + * If we did not return then + * pnt += length; + */ return BGP_Stop; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 185ad0e317..ae06f067df 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -487,6 +487,8 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest, bgp_dest_lock_node(dest); peer_lock(pi->peer); /* bgp_path_info peer reference */ bgp_dest_set_defer_flag(dest, false); + if (pi->peer) + pi->peer->stat_pfx_loc_rib++; hook_call(bgp_snmp_update_stats, dest, pi, true); } @@ -507,6 +509,8 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest, pi->next = NULL; pi->prev = NULL; + if (pi->peer) + pi->peer->stat_pfx_loc_rib--; hook_call(bgp_snmp_update_stats, dest, pi, false); bgp_path_info_unlock(pi); @@ -521,6 +525,8 @@ static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest, pi->next = NULL; pi->prev = NULL; + if (pi->peer) + pi->peer->stat_pfx_loc_rib--; hook_call(bgp_snmp_update_stats, dest, pi, false); bgp_path_info_unlock(pi); @@ -2771,17 +2777,26 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, * the most sense. However, don't modify if the link-bandwidth has * been explicitly set by user policy. */ - if (nh_reset && - bgp_path_info_mpath_chkwtd(bgp, pi) && + if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) && (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 && - !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) - bgp_attr_set_ecommunity( - attr, - ecommunity_replace_linkbw( - bgp->as, bgp_attr_get_ecommunity(attr), cum_bw, - CHECK_FLAG( - peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE))); + !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) + bgp_attr_set_ipv6_ecommunity( + attr, + ecommunity_replace_linkbw(bgp->as, + bgp_attr_get_ipv6_ecommunity( + attr), + cum_bw, false, true)); + else + bgp_attr_set_ecommunity( + attr, + ecommunity_replace_linkbw( + bgp->as, bgp_attr_get_ecommunity(attr), + cum_bw, + CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE), + false)); + } return true; } @@ -7138,6 +7153,10 @@ int bgp_static_set(struct vty *vty, bool negate, const char *ip_str, bgp_static->label = label; bgp_static->prd = prd; + if (rd_str) + bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, + rd_str); + if (rmap) { XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); @@ -10450,6 +10469,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, json_object *json_cluster_list = NULL; json_object *json_cluster_list_list = NULL; json_object *json_ext_community = NULL; + json_object *json_ext_ipv6_community = NULL; json_object *json_last_update = NULL; json_object *json_pmsi = NULL; json_object *json_nexthop_global = NULL; @@ -11158,6 +11178,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } } + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)) { + if (json_paths) { + json_ext_ipv6_community = json_object_new_object(); + json_object_string_add(json_ext_ipv6_community, "string", + bgp_attr_get_ipv6_ecommunity(attr) + ->str); + json_object_object_add(json_path, + "extendedIpv6Community", + json_ext_ipv6_community); + } else { + vty_out(vty, " Extended IPv6 Community: %s\n", + bgp_attr_get_ipv6_ecommunity(attr)->str); + } + } + /* Line 6 display Large community */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) { if (json_paths) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 15828b6594..df5c2557bd 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1944,7 +1944,6 @@ route_set_srte_color(void *rule, const struct prefix *prefix, void *object) path = object; path->attr->srte_color = *srte_color; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR); return RMAP_OKAY; } @@ -3196,7 +3195,7 @@ struct rmap_ecomm_lb_set { #define RMAP_ECOMM_LB_SET_CUMUL 2 #define RMAP_ECOMM_LB_SET_NUM_MPATH 3 bool non_trans; - uint32_t bw; + uint64_t bw; }; static enum route_map_cmd_result_t @@ -3206,8 +3205,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) struct bgp_path_info *path; struct peer *peer; struct ecommunity ecom_lb = {0}; - struct ecommunity_val lb_eval; - uint32_t bw_bytes = 0; + uint64_t bw_bytes = 0; uint16_t mpath_count = 0; struct ecommunity *new_ecom; struct ecommunity *old_ecom; @@ -3221,13 +3219,13 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) /* Build link bandwidth extended community */ as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as; if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) { - bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8; + bw_bytes = (rels->bw * 1000 * 1000) / 8; } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) { /* process this only for the best path. */ if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) return RMAP_OKAY; - bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path); + bw_bytes = bgp_path_info_mpath_cumbw(path); if (!bw_bytes) return RMAP_OKAY; @@ -3237,31 +3235,53 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) return RMAP_OKAY; - bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8; + bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8; mpath_count = bgp_path_info_mpath_count(path) + 1; bw_bytes *= mpath_count; } - encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval, - CHECK_FLAG(peer->flags, - PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) { + struct ecommunity_val_ipv6 lb_eval; - /* add to route or merge with existing */ - old_ecom = bgp_attr_get_ecommunity(path->attr); - if (old_ecom) { - new_ecom = ecommunity_dup(old_ecom); - ecommunity_add_val(new_ecom, &lb_eval, true, true); - if (!old_ecom->refcnt) - ecommunity_free(&old_ecom); + encode_lb_extended_extcomm(as, bw_bytes, rels->non_trans, + &lb_eval); + + old_ecom = bgp_attr_get_ipv6_ecommunity(path->attr); + if (old_ecom) { + new_ecom = ecommunity_dup(old_ecom); + ecommunity_add_val_ipv6(new_ecom, &lb_eval, true, true); + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } else { + ecom_lb.size = 1; + ecom_lb.unit_size = IPV6_ECOMMUNITY_SIZE; + ecom_lb.val = (uint8_t *)lb_eval.val; + new_ecom = ecommunity_dup(&ecom_lb); + } + + bgp_attr_set_ipv6_ecommunity(path->attr, new_ecom); } else { - ecom_lb.size = 1; - ecom_lb.unit_size = ECOMMUNITY_SIZE; - ecom_lb.val = (uint8_t *)lb_eval.val; - new_ecom = ecommunity_dup(&ecom_lb); - } + struct ecommunity_val lb_eval; + + encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval, + CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)); + + old_ecom = bgp_attr_get_ecommunity(path->attr); + if (old_ecom) { + new_ecom = ecommunity_dup(old_ecom); + ecommunity_add_val(new_ecom, &lb_eval, true, true); + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } else { + ecom_lb.size = 1; + ecom_lb.unit_size = ECOMMUNITY_SIZE; + ecom_lb.val = (uint8_t *)lb_eval.val; + new_ecom = ecommunity_dup(&ecom_lb); + } - /* new_ecom will be intern()'d or attr_flush()'d in call stack */ - bgp_attr_set_ecommunity(path->attr, new_ecom); + bgp_attr_set_ecommunity(path->attr, new_ecom); + } /* Mark that route-map has set link bandwidth; used in attribute * setting decisions. @@ -3275,7 +3295,7 @@ static void *route_set_ecommunity_lb_compile(const char *arg) { struct rmap_ecomm_lb_set *rels; uint8_t lb_type; - uint32_t bw = 0; + uint64_t bw = 0; char bw_str[40] = {0}; char *p, *str; bool non_trans = false; @@ -3317,13 +3337,8 @@ static enum route_map_cmd_result_t route_set_ecommunity_color(void *rule, const struct prefix *prefix, void *object) { - struct bgp_path_info *path; - - path = object; - route_set_ecommunity(rule, prefix, object); - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR); return RMAP_OKAY; } @@ -5882,10 +5897,11 @@ DEFUN_YANG (set_table_id, DEFUN_YANG (no_set_table_id, no_set_table_id_cmd, - "no set table", + "no set table [(1-4294967295)]", NO_STR SET_STR - "export route to non-main kernel table\n") + "export route to non-main kernel table\n" + "Kernel routing table id\n") { const char *xpath = "./set-action[action='frr-bgp-route-map:table']"; nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); @@ -6273,13 +6289,12 @@ DEFPY_YANG( } DEFUN_YANG (no_set_aspath_prepend, - no_set_aspath_prepend_cmd, - "no set as-path prepend [ASNUM] [last-as [(1-10)]]", + no_set_aspath_prepend_last_as_cmd, + "no set as-path prepend [last-as [(1-10)]]", NO_STR SET_STR "Transform BGP AS_PATH attribute\n" "Prepend to the as-path\n" - AS_STR "Use the peers AS-number\n" "Number of times to insert\n") { @@ -6290,6 +6305,15 @@ DEFUN_YANG (no_set_aspath_prepend, return nb_cli_apply_changes(vty, NULL); } +ALIAS_YANG (no_set_aspath_prepend, + no_set_aspath_prepend_as_cmd, + "no set as-path prepend ASNUM...", + NO_STR + SET_STR + "Transform BGP AS_PATH attribute\n" + "Prepend to the as-path\n" + AS_STR) + DEFUN_YANG (set_aspath_exclude, set_aspath_exclude_cmd, "set as-path exclude ASNUM...", @@ -6875,7 +6899,7 @@ DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd, DEFUN_YANG (set_ecommunity_lb, set_ecommunity_lb_cmd, - "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]", + "set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]", SET_STR "BGP extended community attribute\n" "Link bandwidth extended community\n" @@ -6929,7 +6953,7 @@ DEFUN_YANG (set_ecommunity_lb, DEFUN_YANG (no_set_ecommunity_lb, no_set_ecommunity_lb_cmd, - "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]", + "no set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]", NO_STR SET_STR "BGP extended community attribute\n" @@ -7966,7 +7990,8 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &set_aspath_exclude_access_list_cmd); install_element(RMAP_NODE, &set_aspath_replace_asn_cmd); install_element(RMAP_NODE, &set_aspath_replace_access_list_cmd); - install_element(RMAP_NODE, &no_set_aspath_prepend_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_last_as_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_as_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_access_list_cmd); diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c index c1d6ee12e1..15c32eaa28 100644 --- a/bgpd/bgp_routemap_nb_config.c +++ b/bgpd/bgp_routemap_nb_config.c @@ -2937,7 +2937,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( struct routemap_hook_context *rhc; enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; - uint16_t bandwidth; + uint32_t bandwidth; int ret; /* Add configuration. */ @@ -2951,8 +2951,8 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish( switch (lb_type) { case EXPLICIT_BANDWIDTH: - bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth"); - snprintf(str, sizeof(str), "%d", bandwidth); + bandwidth = yang_dnode_get_uint32(args->dnode, "bandwidth"); + snprintf(str, sizeof(str), "%u", bandwidth); break; case CUMULATIVE_BANDWIDTH: snprintf(str, sizeof(str), "%s", "cumulative"); diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c index 3d04dc2ece..755777c167 100644 --- a/bgpd/bgp_snmp_bgp4.c +++ b/bgpd/bgp_snmp_bgp4.c @@ -401,7 +401,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], /* Set OID offset for prefix. */ offset = name + v->namelen; oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix); - offset++; + offset += IN_ADDR_SIZE; /* Prefix length. */ addr->prefixlen = *offset; @@ -497,7 +497,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], offset = name + v->namelen; oid_copy_in_addr(offset, &rn_p->u.prefix4); - offset++; + offset += IN_ADDR_SIZE; *offset = rn_p->prefixlen; offset++; oid_copy_in_addr(offset, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f8d8e8ad3a..d5f12897ea 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -3347,7 +3347,7 @@ DEFUN (bgp_neighbor_graceful_restart_set, { int idx_peer = 1; struct peer *peer; - int ret = BGP_GR_FAILURE; + int result = BGP_GR_FAILURE, ret = BGP_GR_SUCCESS; VTY_BGP_GR_DEFINE_LOOP_VARIABLE; @@ -3359,8 +3359,8 @@ DEFUN (bgp_neighbor_graceful_restart_set, if (!peer) return CMD_WARNING_CONFIG_FAILED; - ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD); - if (ret == BGP_GR_SUCCESS) { + result = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD); + if (result == BGP_GR_SUCCESS) { VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); vty_out(vty, @@ -3371,7 +3371,11 @@ DEFUN (bgp_neighbor_graceful_restart_set, zlog_debug( "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END "); - return bgp_vty_return(vty, ret); + if (ret != BGP_GR_SUCCESS) + vty_out(vty, + "As part of configuring graceful-restart, capability send to zebra failed\n"); + + return bgp_vty_return(vty, result); } DEFUN (no_bgp_neighbor_graceful_restart, @@ -3384,7 +3388,7 @@ DEFUN (no_bgp_neighbor_graceful_restart, ) { int idx_peer = 2; - int ret = BGP_GR_FAILURE; + int result = BGP_GR_FAILURE, ret = BGP_GR_SUCCESS; struct peer *peer; VTY_BGP_GR_DEFINE_LOOP_VARIABLE; @@ -3397,7 +3401,7 @@ DEFUN (no_bgp_neighbor_graceful_restart, zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START "); - ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD); + result = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD); if (ret == BGP_GR_SUCCESS) { VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); @@ -3409,7 +3413,11 @@ DEFUN (no_bgp_neighbor_graceful_restart, zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END "); - return bgp_vty_return(vty, ret); + if (ret != BGP_GR_SUCCESS) + vty_out(vty, + "As part of configuring graceful-restart, capability send to zebra failed\n"); + + return bgp_vty_return(vty, result); } DEFUN (bgp_neighbor_graceful_restart_helper_set, @@ -5119,6 +5127,8 @@ DEFUN (no_neighbor, struct peer_group *group; struct peer *peer; struct peer *other; + afi_t afi; + int lr_count; ret = str2sockunion(argv[idx_peer]->arg, &su); if (ret < 0) { @@ -5136,6 +5146,15 @@ DEFUN (no_neighbor, group = peer_group_lookup(bgp, argv[idx_peer]->arg); if (group) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + lr_count = listcount(group->listen_range[afi]); + if (lr_count) { + vty_out(vty, + "%%Peer-group %s is attached to %d listen-range(s), delete them first\n", + group->name, lr_count); + return CMD_WARNING_CONFIG_FAILED; + } + } peer_group_notify_unconfig(group); peer_group_delete(group); } else { @@ -5213,9 +5232,20 @@ DEFUN (no_neighbor_peer_group, VTY_DECLVAR_CONTEXT(bgp, bgp); int idx_word = 2; struct peer_group *group; + afi_t afi; + int lr_count; group = peer_group_lookup(bgp, argv[idx_word]->arg); if (group) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + lr_count = listcount(group->listen_range[afi]); + if (lr_count) { + vty_out(vty, + "%%Peer-group %s is attached to %d listen-range(s), delete them first\n", + group->name, lr_count); + return CMD_WARNING_CONFIG_FAILED; + } + } peer_group_notify_unconfig(group); peer_group_delete(group); } else { @@ -7115,6 +7145,26 @@ DEFUN (no_neighbor_disable_connected_check, PEER_FLAG_DISABLE_CONNECTED_CHECK); } +DEFPY(neighbor_extended_link_bw, + neighbor_extended_link_bw_cmd, + "[no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor extended-link-bandwidth", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Send Extended (64-bit) version of encoding for Link-Bandwidth\n") +{ + int ret; + + if (no) + ret = peer_flag_unset_vty(vty, neighbor, + PEER_FLAG_EXTENDED_LINK_BANDWIDTH); + else + ret = peer_flag_set_vty(vty, neighbor, + PEER_FLAG_EXTENDED_LINK_BANDWIDTH); + + return ret; +} + /* disable-link-bw-encoding-ieee */ DEFUN(neighbor_disable_link_bw_encoding_ieee, neighbor_disable_link_bw_encoding_ieee_cmd, @@ -18439,6 +18489,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n", addr); + if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) + vty_out(vty, " neighbor %s extended-link-bandwidth\n", addr); + /* extended-optional-parameters */ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS)) vty_out(vty, " neighbor %s extended-optional-parameters\n", @@ -20951,6 +21004,9 @@ void bgp_vty_init(void) install_element(BGP_NODE, &no_neighbor_disable_link_bw_encoding_ieee_cmd); + + install_element(BGP_NODE, &neighbor_extended_link_bw_cmd); + /* "neighbor extended-optional-parameters" commands. */ install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd); install_element(BGP_NODE, diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 4955e4c3df..addd71757d 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -13,8 +13,6 @@ struct bgp; #define BGP_INSTANCE_HELP_STR "BGP view\nBGP VRF\nView/VRF name\n" #define BGP_INSTANCE_ALL_HELP_STR "BGP view\nBGP VRF\nAll Views/VRFs\n" -#define BGP_AF_STR "Address Family\n" -#define BGP_AF_MODIFIER_STR "Address Family modifier\n" #define BGP_AFI_CMD_STR "<ipv4|ipv6>" #define BGP_AFI_HELP_STR BGP_AF_STR BGP_AF_STR #define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>" diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 5deea3f32f..aaad7e8a2a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1241,7 +1241,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, } static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr, - uint32_t *nh_weight) + uint64_t *nh_weight) { /* zero link-bandwidth and link-bandwidth not present are treated * as the same situation. @@ -1303,7 +1303,7 @@ static void bgp_zebra_announce_parse_nexthop( for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { labels = NULL; num_labels = 0; - uint32_t nh_weight; + uint64_t nh_weight; bool is_evpn; bool is_parent_evpn; @@ -1338,9 +1338,7 @@ static void bgp_zebra_announce_parse_nexthop( else api_nh = &api->backup_nexthops[*valid_nh_count]; - if (CHECK_FLAG(info->attr->flag, - ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) - api_nh->srte_color = bgp_attr_get_color(info->attr); + api_nh->srte_color = bgp_attr_get_color(info->attr); if (bgp_debug_zebra(&api->prefix)) { if (mpinfo->extra) { @@ -1548,8 +1546,9 @@ static void bgp_debug_zebra_nh(struct zapi_route *api) snprintf(eth_buf, sizeof(eth_buf), " RMAC %s", prefix_mac2str(&api_nh->rmac, buf1, sizeof(buf1))); - zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1, - nh_buf, api_nh->ifindex, api_nh->vrf_id, + zlog_debug(" nhop [%d]: %s if %u VRF %u wt %" PRIu64 + " %s %s %s", + i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id, api_nh->weight, label_buf, segs_buf, eth_buf); } } @@ -1568,7 +1567,6 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info, route_tag_t tag; bool is_add; uint32_t nhg_id = 0; - uint32_t recursion_flag = 0; struct bgp_table *table = bgp_dest_table(dest); const struct prefix *p = bgp_dest_get_prefix(dest); @@ -1611,7 +1609,7 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info, api.tableid = info->attr->rmap_table_id; } - if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR))) + if (info->attr->srte_color) SET_FLAG(api.message, ZAPI_MESSAGE_SRTE); /* Metric is currently based on the best-path only */ @@ -1686,11 +1684,8 @@ bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info, api.metric, api.tag, api.nexthop_num, nhg_id); bgp_debug_zebra_nh(&api); - if (CHECK_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION)) - recursion_flag = 1; - zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)", - __func__, p, (recursion_flag ? "" : "NOT ")); + __func__, p, (allow_recursion ? "" : "NOT ")); } return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient, &api); @@ -3416,12 +3411,12 @@ static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS) struct bgp *bgp = bgp_get_default(); const char *loc_name = bgp->srv6_locator_name; - if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) - return -1; - if (!bgp || !bgp->srv6_enabled) return 0; + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) + return -1; + if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0) return -1; @@ -3439,6 +3434,9 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS) struct in6_addr *tovpn_sid; struct prefix_ipv6 tmp_prefi; + if (!bgp) + return 0; + if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0) return -1; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5fd4ebe8cc..76014d4eb9 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1446,11 +1446,11 @@ int bgp_peer_gr_init(struct peer *peer) { /* PEER_GLOBAL_INHERIT Mode */ /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ - { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, + { PEER_GR, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ - { PEER_DISABLE, bgp_peer_gr_action}, { PEER_INVALID, NULL }, + { PEER_DISABLE, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ - { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } + { PEER_HELPER, bgp_peer_gr_action }, { PEER_GLOBAL_INHERIT, NULL } } }; memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM, @@ -1473,6 +1473,29 @@ static void bgp_srv6_init(struct bgp *bgp) static void bgp_srv6_cleanup(struct bgp *bgp) { + for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) { + if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) + srv6_locator_chunk_free( + &bgp->vpn_policy[afi].tovpn_sid_locator); + if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent); + if (bgp->vpn_policy[afi].tovpn_sid != NULL) { + sid_unregister(bgp, bgp->vpn_policy[afi].tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, + bgp->vpn_policy[afi].tovpn_sid); + } + } + + if (bgp->tovpn_sid_locator != NULL) + srv6_locator_chunk_free(&bgp->tovpn_sid_locator); + if (bgp->tovpn_zebra_vrf_sid_last_sent != NULL) + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent); + if (bgp->tovpn_sid != NULL) { + sid_unregister(bgp, bgp->tovpn_sid); + XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_sid); + } + if (bgp->srv6_locator_chunks) list_delete(&bgp->srv6_locator_chunks); if (bgp->srv6_functions) @@ -1539,13 +1562,13 @@ struct peer *peer_new(struct bgp *bgp) SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) - SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS); + peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS); if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY)) - SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_SOFT_VERSION); + peer_flag_set(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION); if (CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY)) - SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY); + peer_flag_set(peer, PEER_FLAG_DYNAMIC_CAPABILITY); SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN); SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN); @@ -4136,18 +4159,6 @@ void bgp_free(struct bgp *bgp) if (bgp->vpn_policy[afi].tovpn_rd_pretty) XFREE(MTYPE_BGP_NAME, bgp->vpn_policy[afi].tovpn_rd_pretty); - if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) - srv6_locator_chunk_free( - &bgp->vpn_policy[afi].tovpn_sid_locator); - if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL) - XFREE(MTYPE_BGP_SRV6_SID, - bgp->vpn_policy[afi] - .tovpn_zebra_vrf_sid_last_sent); - if (bgp->vpn_policy[afi].tovpn_sid != NULL) { - sid_unregister(bgp, bgp->vpn_policy[afi].tovpn_sid); - XFREE(MTYPE_BGP_SRV6_SID, - bgp->vpn_policy[afi].tovpn_sid); - } } bgp_srv6_cleanup(bgp); bgp_confederation_id_unset(bgp); @@ -4413,6 +4424,11 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su) zlog_debug("%s Dynamic Neighbor added, group %s count %d", peer->host, group->name, dncount); + if (dncount == gbgp->dynamic_neighbors_limit) { + zlog_warn("Dynamic Neighbor %s added as last connection. Peer-group %s reached maximum listen limit %d", + peer->host, group->name, + gbgp->dynamic_neighbors_limit); + } return peer; } @@ -4599,7 +4615,7 @@ static const struct peer_flag_action peer_flag_action_list[] = { {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none}, {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none}, {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none}, - {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset}, + {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_none}, {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset}, {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset}, {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in}, @@ -4623,6 +4639,7 @@ static const struct peer_flag_action peer_flag_action_list[] = { {PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none}, {PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none}, {PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none}, + {PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none}, {0, 0, 0}}; static const struct peer_flag_action peer_af_flag_action_list[] = { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e882a181b5..f577a6e5f3 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -478,7 +478,7 @@ struct bgp { * factor (e.g., number of multipaths for the prefix) * Value is in Mbps */ - uint32_t lb_ref_bw; + uint64_t lb_ref_bw; #define BGP_LINK_BW_REF_BW 1 /* BGP flags. */ @@ -1480,6 +1480,7 @@ struct peer { #define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36) #define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */ #define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */ +#define PEER_FLAG_EXTENDED_LINK_BANDWIDTH (1ULL << 39) /* *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART @@ -1667,6 +1668,8 @@ struct peer { uint32_t stat_pfx_nh_invalid; uint32_t stat_pfx_dup_withdraw; uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */ + uint64_t stat_pfx_loc_rib; /* RFC7854 : Number of routes in Loc-RIB */ + uint64_t stat_pfx_adj_rib_in; /* RFC7854 : Number of routes in Adj-RIBs-In */ /* BGP state count */ uint32_t established; /* Established */ @@ -1971,7 +1974,6 @@ struct bgp_nlri { #define BGP_ATTR_LARGE_COMMUNITIES 32 #define BGP_ATTR_OTC 35 #define BGP_ATTR_PREFIX_SID 40 -#define BGP_ATTR_SRTE_COLOR 51 #ifdef ENABLE_BGP_VNC_ATTR #define BGP_ATTR_VNC 255 #endif diff --git a/configure.ac b/configure.ac index f11b345cf6..cad8ea12c0 100644 --- a/configure.ac +++ b/configure.ac @@ -275,7 +275,16 @@ AC_DEFUN([AC_C_FLAG], [{ AC_CACHE_CHECK([[whether $CC supports $1]], cachename, [ AC_LANG_PUSH([C]) ac_c_flag_save="$CFLAGS" - CFLAGS="$CFLAGS $1" + dnl GCC ignores unknown -Wno-whatever flags, but errors on -Wwhatever + dnl except when it ignores them it prints: + dnl cc1: note: unrecognized command-line option ‘-Wno-whatever’ may have been intended to silence earlier diagnostics + dnl which is annoying as hell. So check for the positive flag instead. + flag_add="$1" + if test "$flag_add" != "${flag_add#-Wno-}"; then + CFLAGS="$CFLAGS -W${flag_add#-Wno-}" + else + CFLAGS="$CFLAGS $flag_add" + fi AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[$4]])], [ @@ -453,6 +462,7 @@ fi AC_C_FLAG([-Wno-unused-parameter]) AC_C_FLAG([-Wno-missing-field-initializers]) AC_C_FLAG([-Wno-microsoft-anon-tag]) +AC_C_FLAG([-Wno-error=deprecated-declarations]) AC_C_FLAG([-Wc++-compat], [], [CXX_COMPAT_CFLAGS="-Wc++-compat"]) AC_SUBST([CXX_COMPAT_CFLAGS]) @@ -1095,6 +1105,8 @@ dnl ------------------------- AC_CHECK_HEADERS([stropts.h sys/ksym.h \ linux/version.h asm/types.h endian.h sys/endian.h]) +AC_CHECK_LIB([atomic], [main], [LIBS="$LIBS -latomic"], [], []) + ac_stdatomic_ok=false AC_DEFINE([FRR_AUTOCONF_ATOMIC], [1], [did autoconf checks for atomic funcs]) AC_CHECK_HEADER([stdatomic.h],[ diff --git a/debian/control b/debian/control index e6d65133d3..12b80a77f3 100644 --- a/debian/control +++ b/debian/control @@ -23,7 +23,7 @@ Build-Depends: bison, librtr-dev (>= 0.8.0~) <!pkg.frr.nortrlib>, libsnmp-dev, libssh-dev <!pkg.frr.nortrlib>, - libyang2-dev (>= 2.1.128), + libyang2-dev (>= 2.1.128) | libyang-dev ( >= 3.0.3), lsb-base, pkg-config, protobuf-c-compiler, diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst index a46c79376c..8d9876c21a 100644 --- a/doc/developer/building-libyang.rst +++ b/doc/developer/building-libyang.rst @@ -41,7 +41,7 @@ DEB packages are available as CI artifacts `here cd libyang git checkout v2.1.128 mkdir build; cd build - cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr \ + cmake --install-prefix /usr \ -D CMAKE_BUILD_TYPE:String="Release" .. make sudo make install diff --git a/doc/developer/cross-compiling.rst b/doc/developer/cross-compiling.rst index af99262c4f..c503487441 100644 --- a/doc/developer/cross-compiling.rst +++ b/doc/developer/cross-compiling.rst @@ -148,7 +148,7 @@ be built and installed generally like: CC=${HOST_ARCH}-gcc \ CXX=${HOST_ARCH}-g++ \ cmake \ - -DCMAKE_INSTALL_PREFIX=/usr/${HOST_ARCH} \ + --install-prefix /usr/${HOST_ARCH} \ .. make make install diff --git a/doc/developer/northbound/plugins-sysrepo.rst b/doc/developer/northbound/plugins-sysrepo.rst index 0cfdb825e5..f4df68ce3c 100644 --- a/doc/developer/northbound/plugins-sysrepo.rst +++ b/doc/developer/northbound/plugins-sysrepo.rst @@ -32,7 +32,7 @@ libyang cd libyang git checkout v2.1.148 mkdir build; cd build - cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + cmake --install-prefix /usr \ -DCMAKE_BUILD_TYPE:String="Release" .. make sudo make install @@ -51,7 +51,7 @@ Sysrepo cd sysrepo/ git checkout v2.2.150 mkdir build; cd build - cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + cmake --install-prefix /usr \ -DCMAKE_BUILD_TYPE:String="Release" .. make sudo make install diff --git a/doc/developer/static-linking.rst b/doc/developer/static-linking.rst index 5342fbfbf6..e9bb9281f8 100644 --- a/doc/developer/static-linking.rst +++ b/doc/developer/static-linking.rst @@ -44,7 +44,7 @@ when building libyang statically. The resultant cmake command is:: cmake -DENABLE_STATIC=ON -DENABLE_LYD_PRIV=ON \ - -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + --install-prefix /usr \ -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \ -DCMAKE_BUILD_TYPE:String="Release" .. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 68ae796bc9..1de6773922 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1334,7 +1334,14 @@ OSPFv3 into ``address-family ipv4 unicast`` as OSPFv3 supports IPv6. .. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static> [metric (0-4294967295)] [route-map WORD] -Redistribute routes from other protocols into BGP. + Redistribute routes from other protocols into BGP. + + Note - When redistributing a static route, or any better Admin Distance route, + into BGP for which the same path is learned dynamically from another BGP + speaker, if the redistribute path is more preferred from a BGP Best Path + standpoint than the dynamically learned path, then BGP will not export + the best path to Zebra(RIB) for installation into the routing table, + unless BGP receives the path before the static route is created. .. clicmd:: redistribute <table|table-direct> (1-65535)] [metric (0-4294967295)] [route-map WORD] @@ -1565,6 +1572,15 @@ Configuring Peers value is carried encoded as uint32. To enable backward compatibility we need to disable IEEE floating-point encoding option per-peer. +.. clicmd:: neighbor PEER extended-link-bandwidth + + By default bandwidth in extended communities is carried encoded as IEEE + floating-point format, and is limited to maximum of 25 Gbps. + + Enabling this parameter, you can use the bandwidth of to 4294967295 Mbps. + + This is disabled by default. + .. clicmd:: neighbor PEER enforce-first-as Discard updates received from the specified (eBGP) peer if the AS_PATH diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst index 0f46832059..14d0849b34 100644 --- a/doc/user/bmp.rst +++ b/doc/user/bmp.rst @@ -23,6 +23,8 @@ The `BMP` implementation in FRR has the following properties: - 3: count of **prefixes** with loop in cluster id - 4: count of **prefixes** with loop in AS-path - 5: count of **prefixes** with loop in originator + - 7: count of **routes** in adj-rib-in + - 8: count of **routes** in Loc-RIB - 11: count of updates subjected to :rfc:`7607` "treat as withdrawal" handling due to errors - 65531: *experimental* count of prefixes rejected due to invalid next-hop @@ -146,6 +148,11 @@ associated with a particular ``bmp targets``: Send BMP Statistics (counter) messages at the specified interval (in milliseconds.) +.. clicmd:: bmp stats send-experimental + + Send BMP Statistics (counter) messages whose code is defined as + experimental (in the [65531-65534] range). + .. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib> Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index 40669a3c02..7412611869 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -462,10 +462,14 @@ To do so, it defines a set of Flex-Algo Definitions (FAD) which have the following characteristics: - a numeric identifier (ID) between 128 and 255 inclusive + - a set of constraints (basically, include or exclude a certain given set of links, designated by a admin-group) + - the calculation type (only the `Shortest-Path-First` is currently supported) + - the metric type (only the IGP inherited metric type is currently supported) + - some additional flags (not supported for the moment). A subset of routers advertises the Flex-Algo Definitions (FAD) to the other @@ -475,13 +479,18 @@ rules: - If a locally configured FAD is not advertised to the area, the router does not participate in the particular flex algorithm. + - If a given flex algorithm is running, the participation in this particular flex algorithm stops when its advertisements are over. + - A router includes its own FAD in the election process if and only if it is advertised to the other routers. + - If only one router advertises the FAD, the FAD is elected. + - If several FADs are advertised with different priorities, the one with the highest priority value is selected. + - If there are multiple advertisements of the FAD with the same highest priority, the FAD of the router with the highest IS-IS system-ID is selected. @@ -497,15 +506,11 @@ which flex algorithm they must use for a given packet. The following commands configure Flex-Algo at the 'router isis' configuration level. Segment-Routing prefixes must be configured for the Flex-Algo. -.. clicmd:: flexible-algorithm (128-255) +.. clicmd:: flex-algo (128-255) Add a Flex-Algo Definition (FAD) and enter the FAD configuration level. The algorithm ID value is in the range of 128 to 255 inclusive. -.. clicmd:: no flexible-algorithm (128-255) - - Unconfigure a Flex-Algo Definition. - .. clicmd:: affinity-map NAME bit-position (0-255) Add the specified 'affinity-map'. Affinity-map definitions are used in @@ -517,7 +522,7 @@ level. Segment-Routing prefixes must be configured for the Flex-Algo. admin-group 'bit-position' is set 1, else it is set to 0. The following commands configure Flex-Algo at the 'router isis' and -'flexible-algorithm (128-255)' configuration level. +'flex-algo (128-255)' configuration level. .. clicmd:: advertise-definition @@ -634,26 +639,14 @@ Debugging ISIS IS-IS Adjacency related packets. -.. clicmd:: debug isis checksum-errors - - IS-IS LSP checksum errors. - .. clicmd:: debug isis events IS-IS Events. -.. clicmd:: debug isis local-updates - - IS-IS local update packets. - .. clicmd:: debug isis packet-dump IS-IS packet dump. -.. clicmd:: debug isis protocol-errors - - IS-IS LSP protocol errors. - .. clicmd:: debug isis route-events IS-IS Route related events. @@ -663,11 +656,8 @@ Debugging ISIS IS-IS CSNP/PSNP packets. .. clicmd:: debug isis spf-events -.. clicmd:: debug isis spf-statistics -.. clicmd:: debug isis spf-triggers - IS-IS Shortest Path First Events, Timing and Statistic Data and triggering - events. + IS-IS Shortest Path First Events. .. clicmd:: debug isis update-packets @@ -846,7 +836,7 @@ A simple vrf example: ! interface eth0 vrf RED - ip router isis FOO vrf RED + ip router isis FOO isis network point-to-point isis circuit-type level-2-only ! diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 47f8fad17b..ad0b25aec4 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -28,6 +28,12 @@ Configuring OSPF Enable the OSPF API server. This is required to use ``ospfclient``. +.. option:: -l, --apiserver_addr <address> + + Specify the local IPv4 address to which to bind the OSPF API server socket. + If unspecified, connections are accepted to any address. Specification of + 127.0.0.1 can be used to limit socket access to local applications. + *ospfd* must acquire interface information from *zebra* in order to function. Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is restarted then *ospfd* must be too. @@ -757,6 +763,32 @@ Interfaces optional IPv4 address is specified, the prefix suppression will apply to the OSPF interface associated with the specified interface address. +.. clicmd:: ip ospf neighbor-filter NAME [A.B.C.D] + + Configure an IP prefix-list to use to filter packets received from + OSPF neighbors on the OSPF interface. The prefix-list should include rules + to permit or deny OSPF neighbors by IP source address. This is useful for + multi-access interfaces where adjacencies with only a subset of the + reachable neighbors are desired. Applications include testing partially + meshed topologies, OSPF Denial of Sevice (DoS) mitigation, and avoidance + of adjacencies with OSPF neighbors not meeting traffic engineering criteria. + + Example: + +.. code-block:: frr + + ! + ! Prefix-list to block neighbor with source address 10.1.0.2 + ! + ip prefix-list nbr-filter seq 10 deny 10.1.0.2/32 + ip prefix-list nbr-filter seq 200 permit any + ! + ! Configure the neighbor filter prefix-list on interface eth0 + ! + interface eth0 + ip ospf neighbor-filter nbr-filter + ! + .. clicmd:: ip ospf area (A.B.C.D|(0-4294967295)) diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 80a6a2787c..b19bb9d1b3 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -211,7 +211,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end. messages. This is enabled by default. 'no' form of this command is used to restrict processing of unicast bsm messages on this interface. -.. clicmd:: ip pim drpriority (1-4294967295) +.. clicmd:: ip pim drpriority (0-4294967295) Set the DR Priority for the interface. This command is useful to allow the user to influence what node becomes the DR for a lan segment. diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst index d550c8e89c..b8567e4863 100644 --- a/doc/user/pimv6.rst +++ b/doc/user/pimv6.rst @@ -135,7 +135,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end. command will not do anything if you do not have the underlying ability of a mlag implementation. -.. clicmd:: ipv6 pim drpriority (1-4294967295) +.. clicmd:: ipv6 pim drpriority (0-4294967295) Set the DR Priority for the interface. This command is useful to allow the user to influence what node becomes the DR for a lan segment. diff --git a/fpm/fpm_pb.c b/fpm/fpm_pb.c index e4c9395a84..0e8f618c4d 100644 --- a/fpm/fpm_pb.c +++ b/fpm/fpm_pb.c @@ -10,3 +10,8 @@ /* * Main file for the fpm_pb library. */ + +#include "config.h" +#include "xref.h" + +XREF_SETUP(); diff --git a/grpc/frrgrpc_pb.c b/grpc/frrgrpc_pb.c new file mode 100644 index 0000000000..938d777534 --- /dev/null +++ b/grpc/frrgrpc_pb.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: ISC +/* + * libfrrgrpc_pb library stub source + */ + +#include "config.h" +#include "xref.h" + +XREF_SETUP(); diff --git a/grpc/subdir.am b/grpc/subdir.am index 06b37f91d6..a464edc930 100644 --- a/grpc/subdir.am +++ b/grpc/subdir.am @@ -10,6 +10,10 @@ nodist_grpc_libfrrgrpc_pb_la_SOURCES = \ grpc/frr-northbound.pb.cc \ grpc/frr-northbound.grpc.pb.cc \ # end + +grpc_libfrrgrpc_pb_la_SOURCES = \ + grpc/frrgrpc_pb.c \ + # end endif CLEANFILES += \ diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 7acd3a2b4e..430bee92bf 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -726,13 +726,13 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, now = time(NULL); if (adj->last_upd) { if (adj->last_upd + adj->hold_time < now) - vty_out(vty, " Expiring"); + vty_out(vty, " Expiring "); else vty_out(vty, " %-9llu", (unsigned long long)adj->last_upd + adj->hold_time - now); } else - vty_out(vty, "- "); + vty_out(vty, " - "); vty_out(vty, "%-10pSY", adj->snpa); vty_out(vty, "\n"); } diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 77573cdfac..9d671137e9 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -822,15 +822,24 @@ int lsp_print_all(struct vty *vty, struct json_object *json, { struct isis_lsp *lsp; int lsp_count = 0; + struct json_object *lsp_json = NULL; if (detail == ISIS_UI_LEVEL_BRIEF) { frr_each (lspdb, head, lsp) { - lsp_print_common(lsp, vty, json, dynhost, isis); + if (json) { + lsp_json = json_object_new_object(); + json_object_array_add(json, lsp_json); + } + lsp_print_common(lsp, vty, lsp_json, dynhost, isis); lsp_count++; } } else if (detail == ISIS_UI_LEVEL_DETAIL) { frr_each (lspdb, head, lsp) { - lsp_print_detail(lsp, vty, json, dynhost, isis); + if (json) { + lsp_json = json_object_new_object(); + json_object_array_add(json, lsp_json); + } + lsp_print_detail(lsp, vty, lsp_json, dynhost, isis); lsp_count++; } } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 294c03def1..418e0af16b 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -2343,9 +2343,6 @@ static void show_isis_topology_common(struct vty *vty, int levels, return; for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - vty_out(vty, - "Area %s:", area->area_tag ? area->area_tag : "null"); - #ifndef FABRICD /* * The shapes of the flex algo spftree 2-dimensional array @@ -2361,6 +2358,9 @@ static void show_isis_topology_common(struct vty *vty, int levels, } else fa_data = NULL; + vty_out(vty, + "Area %s:", area->area_tag ? area->area_tag : "null"); + if (algo != SR_ALGORITHM_SPF) vty_out(vty, " Algorithm %hhu\n", algo); else @@ -2469,37 +2469,33 @@ DEFUN(show_isis_topology, show_isis_topology_cmd, } ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { - if (all_algorithm) { - for (algorithm = SR_ALGORITHM_FLEX_MIN; - algorithm <= SR_ALGORITHM_FLEX_MAX; - algorithm++) - show_isis_topology_common( - vty, levels, isis, - (uint8_t)algorithm); - } else { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { + if (all_algorithm) { + for (algorithm = SR_ALGORITHM_FLEX_MIN; + algorithm <= SR_ALGORITHM_FLEX_MAX; + algorithm++) show_isis_topology_common( vty, levels, isis, (uint8_t)algorithm); - } - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis == NULL) - return CMD_SUCCESS; - if (all_algorithm) { - for (algorithm = SR_ALGORITHM_FLEX_MIN; - algorithm <= SR_ALGORITHM_FLEX_MAX; algorithm++) { + } else { show_isis_topology_common(vty, levels, isis, (uint8_t)algorithm); } - } else + } + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis == NULL) + return CMD_SUCCESS; + if (all_algorithm) { + for (algorithm = SR_ALGORITHM_FLEX_MIN; + algorithm <= SR_ALGORITHM_FLEX_MAX; algorithm++) { show_isis_topology_common(vty, levels, isis, (uint8_t)algorithm); - } + } + } else + show_isis_topology_common(vty, levels, isis, (uint8_t)algorithm); return CMD_SUCCESS; } @@ -2672,17 +2668,14 @@ DEFUN(show_isis_flex_algo, show_isis_flex_algo_cmd, ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - show_isis_flex_algo_common(vty, isis, - flex_algo); - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) show_isis_flex_algo_common(vty, isis, flex_algo); + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + show_isis_flex_algo_common(vty, isis, flex_algo); return CMD_SUCCESS; } @@ -3140,34 +3133,8 @@ DEFUN(show_isis_route, show_isis_route_cmd, if (uj) json = json_object_new_array(); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { - if (all_algorithm) - show_isis_route_all_algos(vty, levels, - isis, - prefix_sid, - backup, - uj ? &json_vrf - : NULL); - else - show_isis_route_common(vty, levels, - isis, prefix_sid, - backup, algorithm, - uj ? &json_vrf - : NULL); - if (uj) { - json_object_object_add( - json_vrf, "vrf_id", - json_object_new_int( - isis->vrf_id)); - json_object_array_add(json, json_vrf); - } - } - goto out; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { if (all_algorithm) show_isis_route_all_algos(vty, levels, isis, prefix_sid, backup, @@ -3178,12 +3145,28 @@ DEFUN(show_isis_route, show_isis_route_cmd, algorithm, uj ? &json_vrf : NULL); if (uj) { - json_object_object_add( - json_vrf, "vrf_id", - json_object_new_int(isis->vrf_id)); + json_object_object_add(json_vrf, "vrf_id", + json_object_new_int( + isis->vrf_id)); json_object_array_add(json, json_vrf); } } + goto out; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + if (all_algorithm) + show_isis_route_all_algos(vty, levels, isis, prefix_sid, + backup, uj ? &json_vrf : NULL); + else + show_isis_route_common(vty, levels, isis, prefix_sid, + backup, algorithm, + uj ? &json_vrf : NULL); + if (uj) { + json_object_object_add(json_vrf, "vrf_id", + json_object_new_int(isis->vrf_id)); + json_object_array_add(json, json_vrf); + } } out: @@ -3395,16 +3378,14 @@ DEFUN(show_isis_frr_summary, show_isis_frr_summary_cmd, } ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - show_isis_frr_summary_common(vty, levels, isis); - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) show_isis_frr_summary_common(vty, levels, isis); + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + show_isis_frr_summary_common(vty, levels, isis); return CMD_SUCCESS; } diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 90b53c540e..3683f74558 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -488,6 +488,10 @@ void isis_link_params_update(struct isis_circuit *circuit, ext->status = EXT_ADJ_SID; else if (IS_SUBTLV(ext, EXT_LAN_ADJ_SID)) ext->status = EXT_LAN_ADJ_SID; + else if (IS_SUBTLV(ext, EXT_SRV6_LAN_ENDX_SID)) + ext->status = EXT_SRV6_LAN_ENDX_SID; + else if (IS_SUBTLV(ext, EXT_SRV6_ENDX_SID)) + ext->status = EXT_SRV6_ENDX_SID; else ext->status = 0; } @@ -793,6 +797,12 @@ static struct ls_vertex *lsp_to_vertex(struct ls_ted *ted, struct isis_lsp *lsp) lnode.msd = cap->msd; SET_FLAG(lnode.flags, LS_NODE_MSD); } + if (cap->srv6_cap.is_srv6_capable) { + SET_FLAG(lnode.flags, LS_NODE_SRV6); + lnode.srv6_cap_flags = cap->srv6_cap.flags; + memcpy(&lnode.srv6_msd, &cap->srv6_msd, + sizeof(struct isis_srv6_msd)); + } } } @@ -1048,7 +1058,51 @@ static struct ls_attributes *get_attributes(struct ls_node_id adv, } } } + if (CHECK_FLAG(tlvs->status, EXT_SRV6_ENDX_SID)) { + struct isis_srv6_endx_sid_subtlv *endx = + (struct isis_srv6_endx_sid_subtlv *) + tlvs->srv6_endx_sid.head; + int i; + + for (; endx; endx = endx->next) { + if (endx->flags & EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG) { + i = 1; + SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID); + } else { + i = 0; + SET_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID); + } + attr->adj_srv6_sid[i].flags = endx->flags; + attr->adj_srv6_sid[i].weight = endx->weight; + memcpy(&attr->adj_srv6_sid[i].sid, &endx->sid, + sizeof(struct in6_addr)); + attr->adj_srv6_sid[i].endpoint_behavior = endx->behavior; + } + } + if (CHECK_FLAG(tlvs->status, EXT_SRV6_LAN_ENDX_SID)) { + struct isis_srv6_lan_endx_sid_subtlv *lendx = + (struct isis_srv6_lan_endx_sid_subtlv *) + tlvs->srv6_lan_endx_sid.head; + int i; + for (; lendx; lendx = lendx->next) { + if (lendx->flags & EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG) { + i = 1; + SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID); + } else { + i = 0; + SET_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID); + } + memcpy(&attr->adj_srv6_sid[i].neighbor.sysid, + &lendx->neighbor_id, ISIS_SYS_ID_LEN); + attr->adj_srv6_sid[i].flags = lendx->flags; + attr->adj_srv6_sid[i].weight = lendx->weight; + memcpy(&attr->adj_srv6_sid[i].sid, &lendx->sid, + sizeof(struct in6_addr)); + attr->adj_srv6_sid[i].endpoint_behavior = + lendx->behavior; + } + } return attr; } @@ -1636,30 +1690,26 @@ DEFUN(show_isis_mpls_te_router, return CMD_SUCCESS; } ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, - anode, area)) { - if (!IS_MPLS_TE(area->mta)) - continue; - - show_router_id(vty, area); - } - } - return 0; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, - area)) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { if (!IS_MPLS_TE(area->mta)) continue; show_router_id(vty, area); } } + return 0; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + if (!IS_MPLS_TE(area->mta)) + continue; + + show_router_id(vty, area); + } } return CMD_SUCCESS; @@ -2108,19 +2158,18 @@ DEFUN(show_isis_mpls_te_db, int rc = CMD_WARNING; ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { - rc = show_isis_ted(vty, argv, argc, isis); - if (rc != CMD_SUCCESS) - return rc; - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis) + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { rc = show_isis_ted(vty, argv, argc, isis); + if (rc != CMD_SUCCESS) + return rc; + } + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis) + rc = show_isis_ted(vty, argv, argc, isis); return rc; } diff --git a/isisd/isis_te.h b/isisd/isis_te.h index 5087cdac43..bf1dc2b9bb 100644 --- a/isisd/isis_te.h +++ b/isisd/isis_te.h @@ -69,9 +69,10 @@ typedef enum _status_t { disable, enable, learn } status_t; /* Mode for Inter-AS LSP */ /* TODO: Check how if LSP is flooded in RFC5316 */ typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t; -#define IS_EXT_TE(e) (e && e->status != 0 \ - && e->status != EXT_ADJ_SID \ - && e->status != EXT_LAN_ADJ_SID) +#define IS_EXT_TE(e) \ + (e && e->status != 0 && e->status != EXT_ADJ_SID && \ + e->status != EXT_LAN_ADJ_SID && e->status != EXT_SRV6_ENDX_SID && \ + e->status != EXT_SRV6_LAN_ENDX_SID) #define IS_MPLS_TE(a) (a && a->status == enable) #define IS_EXPORT_TE(a) (a->export) diff --git a/isisd/isisd.c b/isisd/isisd.c index 772eb9708d..382a6aa3be 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -988,63 +988,17 @@ int show_isis_interface_common_json(struct json_object *json, "no"); return CMD_SUCCESS; } - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { - areas_json = json_object_new_array(); - json_object_object_add(json, "areas", - areas_json); - for (ALL_LIST_ELEMENTS_RO(isis->area_list, - anode, area)) { - area_json = json_object_new_object(); - json_object_string_add( - area_json, "area", - area->area_tag ? area->area_tag - : "null"); - circuits_json = json_object_new_array(); - json_object_object_add(area_json, - "circuits", - circuits_json); - for (ALL_LIST_ELEMENTS_RO( - area->circuit_list, cnode, - circuit)) { - circuit_json = - json_object_new_object(); - json_object_int_add( - circuit_json, "circuit", - circuit->circuit_id); - if (!ifname) - isis_circuit_print_json( - circuit, - circuit_json, - detail); - else if (strcmp(circuit->interface->name, ifname) == 0) - isis_circuit_print_json( - circuit, - circuit_json, - detail); - json_object_array_add( - circuits_json, - circuit_json); - } - json_object_array_add(areas_json, - area_json); - } - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { areas_json = json_object_new_array(); json_object_object_add(json, "areas", areas_json); - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, - area)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { area_json = json_object_new_object(); json_object_string_add(area_json, "area", area->area_tag ? area->area_tag : "null"); - circuits_json = json_object_new_array(); json_object_object_add(area_json, "circuits", circuits_json); @@ -1055,22 +1009,56 @@ int show_isis_interface_common_json(struct json_object *json, circuit_json, "circuit", circuit->circuit_id); if (!ifname) - isis_circuit_print_json( - circuit, circuit_json, - detail); - else if ( - strcmp(circuit->interface->name, - ifname) == 0) - isis_circuit_print_json( - circuit, circuit_json, - detail); + isis_circuit_print_json(circuit, + circuit_json, + detail); + else if (strcmp(circuit->interface->name, + ifname) == 0) + isis_circuit_print_json(circuit, + circuit_json, + detail); json_object_array_add(circuits_json, circuit_json); } json_object_array_add(areas_json, area_json); } } + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + areas_json = json_object_new_array(); + json_object_object_add(json, "areas", areas_json); + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + area_json = json_object_new_object(); + json_object_string_add(area_json, "area", + area->area_tag ? area->area_tag + : "null"); + + circuits_json = json_object_new_array(); + json_object_object_add(area_json, "circuits", + circuits_json); + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, + circuit)) { + circuit_json = json_object_new_object(); + json_object_int_add(circuit_json, "circuit", + circuit->circuit_id); + if (!ifname) + isis_circuit_print_json(circuit, + circuit_json, + detail); + else if (strcmp(circuit->interface->name, + ifname) == 0) + isis_circuit_print_json(circuit, + circuit_json, + detail); + json_object_array_add(circuits_json, + circuit_json); + } + json_object_array_add(areas_json, area_json); + } } + return CMD_SUCCESS; } @@ -1087,37 +1075,10 @@ int show_isis_interface_common_vty(struct vty *vty, const char *ifname, vty_out(vty, "IS-IS Routing Process not enabled\n"); return CMD_SUCCESS; } - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, - anode, area)) { - vty_out(vty, "Area %s:\n", - area->area_tag); - if (detail == ISIS_UI_LEVEL_BRIEF) - vty_out(vty, - " Interface CircId State Type Level\n"); - - for (ALL_LIST_ELEMENTS_RO( - area->circuit_list, cnode, - circuit)) - if (!ifname) - isis_circuit_print_vty( - circuit, vty, - detail); - else if (strcmp(circuit->interface->name, ifname) == 0) - isis_circuit_print_vty( - circuit, vty, - detail); - } - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, - area)) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { vty_out(vty, "Area %s:\n", area->area_tag); if (detail == ISIS_UI_LEVEL_BRIEF) @@ -1127,15 +1088,37 @@ int show_isis_interface_common_vty(struct vty *vty, const char *ifname, for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) if (!ifname) - isis_circuit_print_vty( - circuit, vty, detail); - else if ( - strcmp(circuit->interface->name, - ifname) == 0) - isis_circuit_print_vty( - circuit, vty, detail); + isis_circuit_print_vty(circuit, + vty, + detail); + else if (strcmp(circuit->interface->name, + ifname) == 0) + isis_circuit_print_vty(circuit, + vty, + detail); } } + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + vty_out(vty, "Area %s:\n", area->area_tag); + + if (detail == ISIS_UI_LEVEL_BRIEF) + vty_out(vty, + " Interface CircId State Type Level\n"); + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, + circuit)) + if (!ifname) + isis_circuit_print_vty(circuit, vty, + detail); + else if (strcmp(circuit->interface->name, + ifname) == 0) + isis_circuit_print_vty(circuit, vty, + detail); + } } return CMD_SUCCESS; @@ -1318,7 +1301,7 @@ static void isis_neighbor_common_vty(struct vty *vty, const char *id, if (detail == ISIS_UI_LEVEL_BRIEF) vty_out(vty, - " System Id Interface L State Holdtime SNPA\n"); + " System Id Interface L State Holdtime SNPA\n"); for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { if (circuit->circ_type == CIRCUIT_T_BROADCAST) { @@ -1376,28 +1359,23 @@ int show_isis_neighbor_common(struct vty *vty, struct json_object *json, return CMD_SUCCESS; } - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { - if (id_to_sysid(isis, id, sysid)) { - vty_out(vty, "Invalid system id %s\n", - id); - return CMD_SUCCESS; - } - isis_neighbor_common(vty, json, id, detail, - isis, sysid); - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { if (id_to_sysid(isis, id, sysid)) { vty_out(vty, "Invalid system id %s\n", id); return CMD_SUCCESS; } - isis_neighbor_common(vty, json, id, detail, isis, - sysid); + isis_neighbor_common(vty, json, id, detail, isis, sysid); } + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + if (id_to_sysid(isis, id, sysid)) { + vty_out(vty, "Invalid system id %s\n", id); + return CMD_SUCCESS; + } + isis_neighbor_common(vty, json, id, detail, isis, sysid); } return CMD_SUCCESS; @@ -1461,27 +1439,23 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_ return CMD_SUCCESS; } - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { - if (id_to_sysid(isis, id, sysid)) { - vty_out(vty, "Invalid system id %s\n", - id); - return CMD_SUCCESS; - } - isis_neighbor_common_clear(vty, id, sysid, - isis); - } - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) { if (id_to_sysid(isis, id, sysid)) { vty_out(vty, "Invalid system id %s\n", id); return CMD_SUCCESS; } isis_neighbor_common_clear(vty, id, sysid, isis); } + return CMD_SUCCESS; + } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) { + if (id_to_sysid(isis, id, sysid)) { + vty_out(vty, "Invalid system id %s\n", id); + return CMD_SUCCESS; + } + isis_neighbor_common_clear(vty, id, sysid, isis); } return CMD_SUCCESS; @@ -2234,17 +2208,16 @@ DEFUN (show_hostname, struct isis *isis; ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - dynhn_print_all(vty, isis); - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) dynhn_print_all(vty, isis); + + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + dynhn_print_all(vty, isis); return CMD_SUCCESS; } @@ -2307,17 +2280,15 @@ DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd, return CMD_SUCCESS; } - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - isis_spf_ietf_common(vty, isis); - - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) isis_spf_ietf_common(vty, isis); + + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + isis_spf_ietf_common(vty, isis); return CMD_SUCCESS; } @@ -2596,17 +2567,16 @@ DEFUN(show_isis_summary, show_isis_summary_cmd, } if (uj) json = json_object_new_object(); - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - common_isis_summary(vty, json, isis); - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis != NULL) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) common_isis_summary(vty, json, isis); + + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis != NULL) + common_isis_summary(vty, json, isis); if (uj) vty_json(vty, json); @@ -2681,6 +2651,7 @@ void show_isis_database_lspdb_json(struct json_object *json, { struct isis_lsp *lsp; int lsp_count; + struct json_object *lsp_arr_json; if (lspdb_count(lspdb) > 0) { lsp = lsp_for_sysid(lspdb, sysid_str, area->isis); @@ -2697,9 +2668,12 @@ void show_isis_database_lspdb_json(struct json_object *json, lsp_print_json(lsp, json, area->dynhostname, area->isis); } else if (sysid_str == NULL) { - lsp_count = - lsp_print_all(NULL, json, lspdb, ui_level, - area->dynhostname, area->isis); + lsp_arr_json = json_object_new_array(); + json_object_object_add(json, "lsps", lsp_arr_json); + + lsp_count = lsp_print_all(NULL, lsp_arr_json, lspdb, + ui_level, area->dynhostname, + area->isis); json_object_int_add(json, "count", lsp_count); } @@ -2828,19 +2802,16 @@ static int show_isis_database(struct vty *vty, struct json_object *json, const c struct listnode *node; struct isis *isis; - if (vrf_name) { - if (all_vrf) { - for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) - show_isis_database_common(vty, json, sysid_str, - ui_level, isis); - - return CMD_SUCCESS; - } - isis = isis_lookup_by_vrfname(vrf_name); - if (isis) + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) show_isis_database_common(vty, json, sysid_str, ui_level, isis); + + return CMD_SUCCESS; } + isis = isis_lookup_by_vrfname(vrf_name); + if (isis) + show_isis_database_common(vty, json, sysid_str, ui_level, isis); return CMD_SUCCESS; } diff --git a/lib/command.h b/lib/command.h index ef1815c0bd..e4c575e8d7 100644 --- a/lib/command.h +++ b/lib/command.h @@ -462,6 +462,8 @@ struct cmd_node { #define MPLS_LDP_SYNC_HOLDDOWN_STR \ "Time to wait for LDP-SYNC to occur before restoring if cost\n" #define NO_MPLS_LDP_SYNC_HOLDDOWN_STR "holddown timer disable\n" +#define BGP_AF_STR "Address Family\n" +#define BGP_AF_MODIFIER_STR "Address Family modifier\n" /* Command warnings. */ #define NO_PASSWD_CMD_WARNING \ diff --git a/lib/compiler.h b/lib/compiler.h index 03261052a2..9d39026c66 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -455,6 +455,12 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, #define unlikely(_x) !!(_x) #endif +#ifdef __MACH__ +#define _DATA_SECTION(name) __attribute__((section("__DATA," name))) +#else +#define _DATA_SECTION(name) __attribute__((section(".data." name))) +#endif + #ifdef __cplusplus } #endif diff --git a/lib/elf_py.c b/lib/elf_py.c index 643495d8c7..2b4fea373f 100644 --- a/lib/elf_py.c +++ b/lib/elf_py.c @@ -1358,6 +1358,15 @@ bool elf_py_init(PyObject *pymod) (void)methods_elfpy; #endif +#if defined(HAVE_GELF_GETNOTE) && defined(HAVE_ELF_GETDATA_RAWCHUNK) + PyObject *elf_notes = Py_True; +#else + PyObject *elf_notes = Py_False; +#endif + Py_INCREF(elf_notes); + if (PyModule_AddObject(pymod, "elf_notes", elf_notes)) + Py_DECREF(elf_notes); + ELFFormatError = PyErr_NewException("_clippy.ELFFormatError", PyExc_ValueError, NULL); PyModule_AddObject(pymod, "ELFFormatError", ELFFormatError); diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index 1ffa5934aa..3a4bc712fc 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -92,9 +92,14 @@ struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr, MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t)); fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM, sizeof(pthread_cond_t)); + pthread_mutex_init(fpt->running_cond_mtx, NULL); pthread_cond_init(fpt->running_cond, NULL); + pthread_mutex_init(&fpt->startup_cond_mtx, NULL); + pthread_cond_init(&fpt->startup_cond, NULL); + fpt->started = false; + frr_with_mutex (&frr_pthread_list_mtx) { listnode_add(frr_pthread_list, fpt); } @@ -108,6 +113,8 @@ static void frr_pthread_destroy_nolock(struct frr_pthread *fpt) pthread_mutex_destroy(&fpt->mtx); pthread_mutex_destroy(fpt->running_cond_mtx); pthread_cond_destroy(fpt->running_cond); + pthread_mutex_destroy(&fpt->startup_cond_mtx); + pthread_cond_destroy(&fpt->startup_cond); XFREE(MTYPE_FRR_PTHREAD, fpt->name); XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx); XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond); @@ -140,11 +147,34 @@ int frr_pthread_set_name(struct frr_pthread *fpt) return ret; } +/* New pthread waits before running */ +static void frr_pthread_wait_startup(struct frr_pthread *fpt) +{ + frr_with_mutex (&fpt->startup_cond_mtx) { + while (!fpt->started) + pthread_cond_wait(&fpt->startup_cond, + &fpt->startup_cond_mtx); + } +} + +/* Parent pthread allows new pthread to start running */ +static void frr_pthread_notify_startup(struct frr_pthread *fpt) +{ + frr_with_mutex (&fpt->startup_cond_mtx) { + fpt->started = true; + pthread_cond_signal(&fpt->startup_cond); + } +} + static void *frr_pthread_inner(void *arg) { struct frr_pthread *fpt = arg; + /* The new pthead waits until the parent allows it to continue. */ + frr_pthread_wait_startup(fpt); + rcu_thread_start(fpt->rcu_thread); + return fpt->attr.start(fpt); } @@ -169,6 +199,9 @@ int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr) /* Restore caller's signals */ pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); + /* Allow new child pthread to start */ + frr_pthread_notify_startup(fpt); + /* * Per pthread_create(3), the contents of fpt->thread are undefined if * pthread_create() did not succeed. Reset this value to zero. @@ -250,6 +283,8 @@ int frr_pthread_non_controlled_startup(pthread_t thread, const char *name, fpt->thread = thread; fpt->rcu_thread = rcu_thread; + fpt->started = true; + frr_pthread_inner(fpt); return 0; diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 1e1b8d7fd3..bb751b7071 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -47,6 +47,17 @@ struct frr_pthread { struct frr_pthread_attr attr; /* + * Startup serialization: newly-started pthreads wait at a point + * very early in life so that there isn't a race with the + * starting pthread. The OS 'start' apis don't make any guarantees + * about which pthread runs first - the existing pthread that has + * called the 'start' api, or the new pthread that is just starting. + */ + pthread_cond_t startup_cond; + pthread_mutex_t startup_cond_mtx; + atomic_bool started; + + /* * Notification mechanism for allowing pthreads to notify their parents * when they are ready to do work. This mechanism has two associated * functions: diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c index b28dd7f1bb..5273d36974 100644 --- a/lib/frr_zmq.c +++ b/lib/frr_zmq.c @@ -21,6 +21,8 @@ #include "log.h" #include "lib_errors.h" +XREF_SETUP(); + DEFINE_MTYPE_STATIC(LIB, ZEROMQ_CB, "ZeroMQ callback"); /* libzmq's context */ @@ -885,21 +885,6 @@ nbr_connected_log(struct nbr_connected *connected, char *str) zlog_info("%s", logbuf); } -/* If two connected address has same prefix return 1. */ -static int connected_same_prefix(const struct prefix *p1, - const struct prefix *p2) -{ - if (p1->family == p2->family) { - if (p1->family == AF_INET - && IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4)) - return 1; - if (p1->family == AF_INET6 - && IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6)) - return 1; - } - return 0; -} - /* count the number of connected addresses that are in the given family */ unsigned int connected_count_by_family(struct interface *ifp, int family) { @@ -919,7 +904,7 @@ struct connected *connected_lookup_prefix_exact(struct interface *ifp, struct connected *ifc; frr_each (if_connected, ifp->connected, ifc) { - if (connected_same_prefix(ifc->address, p)) + if (prefix_same(ifc->address, p)) return ifc; } return NULL; @@ -932,7 +917,7 @@ struct connected *connected_delete_by_prefix(struct interface *ifp, /* In case of same prefix come, replace it with new one. */ frr_each_safe (if_connected, ifp->connected, ifc) { - if (connected_same_prefix(ifc->address, p)) { + if (prefix_same(ifc->address, p)) { if_connected_del(ifp->connected, ifc); return ifc; } diff --git a/lib/libfrr.c b/lib/libfrr.c index 03025328b7..876efe23a8 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -59,7 +59,7 @@ char config_default[512]; char frr_zclientpath[512]; static char pidfile_default[1024]; #ifdef HAVE_SQLITE3 -static char dbfile_default[512]; +static char dbfile_default[1024]; #endif static char vtypath_default[512]; diff --git a/lib/link_state.c b/lib/link_state.c index 25373bdb20..c758b7f575 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -140,6 +140,12 @@ int ls_node_same(struct ls_node *n1, struct ls_node *n2) if (CHECK_FLAG(n1->flags, LS_NODE_MSD) && (n1->msd != n2->msd)) return 0; } + if (CHECK_FLAG(n1->flags, LS_NODE_SRV6)) { + if (n1->srv6_cap_flags != n2->srv6_cap_flags) + return 0; + if (memcmp(&n1->srv6_msd, &n2->srv6_msd, sizeof(n1->srv6_msd))) + return 0; + } /* OK, n1 & n2 are equal */ return 1; @@ -320,6 +326,23 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2) &l2->adj_sid[i].neighbor.addr))) return 0; } + for (int i = 0; i < ADJ_SRV6_MAX; i++) { + if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SRV6SID << i))) + continue; + if (memcmp(&l1->adj_srv6_sid[i].sid, &l2->adj_srv6_sid[i].sid, + sizeof(struct in6_addr)) || + (l1->adj_srv6_sid[i].flags != l2->adj_srv6_sid[i].flags) || + (l1->adj_srv6_sid[i].weight != l2->adj_srv6_sid[i].weight) || + (l1->adj_srv6_sid[i].endpoint_behavior != + l2->adj_srv6_sid[i].endpoint_behavior)) + return 0; + if (((l1->adv.origin == ISIS_L1) || + (l1->adv.origin == ISIS_L2)) && + (memcmp(&l1->adj_srv6_sid[i].neighbor.sysid, + &l2->adj_srv6_sid[i].neighbor.sysid, + ISO_SYS_ID_LEN) != 0)) + return 0; + } if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG) && ((l1->srlg_len != l2->srlg_len) || memcmp(l1->srlgs, l2->srlgs, @@ -1298,6 +1321,26 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s) STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s, ISO_SYS_ID_LEN); } + if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) { + STREAM_GET(&attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid, s, + sizeof(struct in6_addr)); + STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags); + STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight); + STREAM_GETW(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6] + .endpoint_behavior); + STREAM_GET(attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].neighbor.sysid, + s, ISO_SYS_ID_LEN); + } + if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) { + STREAM_GET(&attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid, s, + sizeof(struct in6_addr)); + STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags); + STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight); + STREAM_GETW(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6] + .endpoint_behavior); + STREAM_GET(attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].neighbor.sysid, + s, ISO_SYS_ID_LEN); + } if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) { STREAM_GETC(s, len); attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t)); @@ -1532,6 +1575,28 @@ static int ls_format_attributes(struct stream *s, struct ls_attributes *attr) stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, ISO_SYS_ID_LEN); } + if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) { + stream_put(s, &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid, + sizeof(struct in6_addr)); + stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags); + stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight); + stream_putw(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6] + .endpoint_behavior); + stream_put(s, + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].neighbor.sysid, + ISO_SYS_ID_LEN); + } + if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) { + stream_put(s, &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid, + sizeof(struct in6_addr)); + stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags); + stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight); + stream_putw(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6] + .endpoint_behavior); + stream_put(s, + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].neighbor.sysid, + ISO_SYS_ID_LEN); + } if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) { stream_putc(s, attr->srlg_len); for (len = 0; len < attr->srlg_len; len++) @@ -2351,6 +2416,24 @@ static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty, attr->adj_sid[ADJ_BCK_IPV6].flags, attr->adj_sid[ADJ_BCK_IPV6].weight); } + if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) { + sbuf_push(&sbuf, 4, "IPv6 Adjacency-SRV6-SID: %pI6", + &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid); + sbuf_push(&sbuf, 0, + "\tFlags: 0x%x\tWeight: 0x%x\tbehavior: 0x%x\n", + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags, + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight, + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].endpoint_behavior); + } + if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) { + sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SRV6-SID: %pI6", + &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid); + sbuf_push(&sbuf, 0, + "\tFlags: 0x%x\tWeight: 0x%x\tbehavior: 0x%x\n", + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags, + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight, + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].endpoint_behavior); + } if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) { sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len); for (int i = 1; i < attr->srlg_len; i++) { @@ -2372,7 +2455,7 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json) struct ls_attributes *attr; struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg, *js_ext_ag, *js_ext_ag_arr_word, - *js_ext_ag_arr_bit; + *js_ext_ag_arr_bit, *jsrv6 = NULL; char buf[INET6_BUFSIZ]; char buf_ag[strlen("0xffffffff") + 1]; uint32_t bitmap; @@ -2557,6 +2640,45 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json) attr->adj_sid[ADJ_BCK_IPV6].weight); json_object_array_add(jsr, jobj); } + if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) { + jsrv6 = json_object_new_array(); + json_object_object_add(json, "segment-routing-ipv6", jsrv6); + jobj = json_object_new_object(); + snprintfrr(buf, INET6_BUFSIZ, "%pI6", + &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid); + json_object_string_add(jobj, "adj-sid", buf); + snprintfrr(buf, 6, "0x%x", + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags); + json_object_string_add(jobj, "flags", buf); + json_object_int_add(jobj, "weight", + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight); + snprintfrr(buf, 6, "0x%x", + attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6] + .endpoint_behavior); + json_object_string_add(jobj, "endpoint-behavior", buf); + json_object_array_add(jsr, jobj); + } + if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) { + if (!jsrv6) { + jsrv6 = json_object_new_array(); + json_object_object_add(json, "segment-routing-ipv6", + jsrv6); + } + jobj = json_object_new_object(); + snprintfrr(buf, INET6_BUFSIZ, "%pI6", + &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid); + json_object_string_add(jobj, "adj-sid", buf); + snprintfrr(buf, 6, "0x%x", + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags); + json_object_string_add(jobj, "flags", buf); + json_object_int_add(jobj, "weight", + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight); + snprintfrr(buf, 6, "0x%x", + attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6] + .endpoint_behavior); + json_object_string_add(jobj, "endpoint-behavior", buf); + json_object_array_add(jsr, jobj); + } } void ls_show_edge(struct ls_edge *edge, struct vty *vty, diff --git a/lib/link_state.h b/lib/link_state.h index d3a0ce39da..d819c20db7 100644 --- a/lib/link_state.h +++ b/lib/link_state.h @@ -106,6 +106,7 @@ extern int ls_node_id_same(struct ls_node_id i1, struct ls_node_id i2); #define LS_NODE_SR 0x0040 #define LS_NODE_SRLB 0x0080 #define LS_NODE_MSD 0x0100 +#define LS_NODE_SRV6 0x0200 /* Link State Node structure */ struct ls_node { @@ -128,6 +129,14 @@ struct ls_node { } srlb; uint8_t algo[LIB_LS_SR_ALGO_COUNT]; /* Segment Routing Algorithms */ uint8_t msd; /* Maximum Stack Depth */ + + uint16_t srv6_cap_flags; /* draft-ietf-idr-bgpls-srv6-ext, 3.1., flags field */ + struct ls_srv6_msd { /* draft-ietf-idr-bgpls-srv6-ext, 3.2. */ + uint8_t max_seg_left_msd; + uint8_t max_end_pop_msd; + uint8_t max_h_encaps_msd; + uint8_t max_end_d_msd; + } srv6_msd; }; /* Link State flags to indicate which Attribute parameters are valid */ @@ -161,6 +170,8 @@ struct ls_node { #define LS_ATTR_BCK_ADJ_SID6 0x08000000 #define LS_ATTR_SRLG 0x10000000 #define LS_ATTR_EXT_ADM_GRP 0x20000000 +#define LS_ATTR_ADJ_SRV6SID 0x40000000 +#define LS_ATTR_BCK_ADJ_SRV6SID 0x80000000 /* Link State Attributes */ struct ls_attributes { @@ -209,6 +220,18 @@ struct ls_attributes { uint8_t sysid[ISO_SYS_ID_LEN]; /* or Sys-ID for ISIS */ } neighbor; } adj_sid[4]; /* IPv4/IPv6 & Primary/Backup (LAN)-Adj. SID */ +#define ADJ_SRV6_PRI_IPV6 0 +#define ADJ_SRV6_BCK_IPV6 1 +#define ADJ_SRV6_MAX 2 + struct ls_srv6_adjacency { /* Adjacency SID for IS-IS */ + struct in6_addr sid; /* SID as IPv6 address */ + uint8_t flags; /* Flags */ + uint8_t weight; /* Administrative weight */ + uint16_t endpoint_behavior; /* Endpoint Behavior */ + union { + uint8_t sysid[ISO_SYS_ID_LEN]; /* Sys-ID for ISIS */ + } neighbor; + } adj_srv6_sid[2]; uint32_t *srlgs; /* List of Shared Risk Link Group */ uint8_t srlg_len; /* number of SRLG in the list */ }; diff --git a/lib/memory.h b/lib/memory.h index ba437ebd0e..65b99a5fc9 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -69,14 +69,12 @@ struct memgroup { #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name #define _DEFINE_MGROUP(mname, desc, ...) \ - struct memgroup _mg_##mname \ - __attribute__((section(".data.mgroups"))) = { \ - .name = desc, \ - .types = NULL, \ - .next = NULL, \ - .insert = NULL, \ - .ref = NULL, \ - __VA_ARGS__ \ + struct memgroup _mg_##mname _DATA_SECTION("mgroups") = { \ + .name = desc, \ + .types = NULL, \ + .next = NULL, \ + .insert = NULL, \ + .ref = NULL, \ }; \ static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \ static void _mginit_##mname(void) \ @@ -105,13 +103,12 @@ struct memgroup { /* end */ #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \ - attr struct memtype MTYPE_##mname[1] \ - __attribute__((section(".data.mtypes"))) = { { \ - .name = desc, \ - .next = NULL, \ - .n_alloc = 0, \ - .size = 0, \ - .ref = NULL, \ + attr struct memtype MTYPE_##mname[1] _DATA_SECTION("mtypes") = { { \ + .name = desc, \ + .next = NULL, \ + .n_alloc = 0, \ + .size = 0, \ + .ref = NULL, \ } }; \ static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \ static void _mtinit_##mname(void) \ diff --git a/lib/mgmt.proto b/lib/mgmt.proto index 01a99ab63b..c95301118b 100644 --- a/lib/mgmt.proto +++ b/lib/mgmt.proto @@ -79,6 +79,7 @@ message BeSubscribeReq { repeated string config_xpaths = 2; repeated string oper_xpaths = 3; repeated string notif_xpaths = 4; + repeated string rpc_xpaths = 5; } message BeSubscribeReply { diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index f483d48d8d..6e2fb05e84 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -915,6 +915,143 @@ static void be_client_handle_get_tree(struct mgmt_be_client *client, be_client_send_tree_data_batch, args); } +static void be_client_send_rpc_reply(struct mgmt_be_client *client, + uint64_t txn_id, uint64_t req_id, + uint8_t result_type, + struct lyd_node *output) +{ + struct mgmt_msg_rpc_reply *rpc_reply_msg; + uint8_t **darrp; + LY_ERR err; + int ret = NB_OK; + + rpc_reply_msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc_reply, 0, + MTYPE_MSG_NATIVE_RPC_REPLY); + rpc_reply_msg->refer_id = txn_id; + rpc_reply_msg->req_id = req_id; + rpc_reply_msg->code = MGMT_MSG_CODE_RPC_REPLY; + rpc_reply_msg->result_type = result_type; + + if (output) { + darrp = mgmt_msg_native_get_darrp(rpc_reply_msg); + err = yang_print_tree_append(darrp, output, result_type, + LYD_PRINT_SHRINK); + lyd_free_all(output); + if (err) { + ret = NB_ERR; + goto done; + } + } + + (void)be_client_send_native_msg(client, rpc_reply_msg, + mgmt_msg_native_get_msg_len( + rpc_reply_msg), + false); +done: + mgmt_msg_native_free_msg(rpc_reply_msg); + if (ret != NB_OK) + be_client_send_error(client, txn_id, req_id, false, -EINVAL, + "Can't format RPC reply"); +} + +/* + * Process the RPC request. + */ +static void be_client_handle_rpc(struct mgmt_be_client *client, uint64_t txn_id, + void *msgbuf, size_t msg_len) +{ + struct mgmt_msg_rpc *rpc_msg = msgbuf; + struct nb_node *nb_node; + struct lyd_node *input, *output; + const char *xpath; + const char *data; + char errmsg[BUFSIZ] = { 0 }; + LY_ERR err; + int ret; + + debug_be_client("Received RPC request for client %s txn-id %" PRIu64 + " req-id %" PRIu64, + client->name, txn_id, rpc_msg->req_id); + + xpath = mgmt_msg_native_xpath_data_decode(rpc_msg, msg_len, data); + if (!xpath) { + be_client_send_error(client, txn_id, rpc_msg->req_id, false, + -EINVAL, "Corrupt RPC message"); + return; + } + + nb_node = nb_node_find(xpath); + if (!nb_node) { + be_client_send_error(client, txn_id, rpc_msg->req_id, false, + -EINVAL, "No schema found for RPC: %s", + xpath); + return; + } + + if (!nb_node->cbs.rpc) { + be_client_send_error(client, txn_id, rpc_msg->req_id, false, + -EINVAL, "No RPC callback for: %s", xpath); + return; + } + + if (data) { + err = yang_parse_rpc(xpath, rpc_msg->request_type, data, false, + &input); + if (err) { + be_client_send_error(client, txn_id, rpc_msg->req_id, + false, -EINVAL, + "Can't parse RPC data for: %s", + xpath); + return; + } + } else { + /* + * If there's no input data, create an empty input container. + * It is especially needed for actions, because their parents + * may hold necessary information. + */ + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, + NULL, &input); + if (err) { + be_client_send_error(client, txn_id, rpc_msg->req_id, + false, -EINVAL, + "Can't create input node for RPC: %s", + xpath); + return; + } + } + + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL, + &output); + if (err) { + lyd_free_all(input); + be_client_send_error(client, txn_id, rpc_msg->req_id, false, + -EINVAL, + "Can't create output node for RPC: %s", + xpath); + return; + } + + ret = nb_callback_rpc(nb_node, xpath, input, output, errmsg, + sizeof(errmsg)); + if (ret != NB_OK) { + lyd_free_all(input); + lyd_free_all(output); + be_client_send_error(client, txn_id, rpc_msg->req_id, false, + -EINVAL, "%s", errmsg); + return; + } + + lyd_free_all(input); + if (!lyd_child(output)) { + lyd_free_all(output); + output = NULL; + } + + be_client_send_rpc_reply(client, txn_id, rpc_msg->req_id, + rpc_msg->request_type, output); +} + /* * Process the notification. */ @@ -975,6 +1112,9 @@ static void be_client_handle_native_msg(struct mgmt_be_client *client, case MGMT_MSG_CODE_GET_TREE: be_client_handle_get_tree(client, txn_id, msg, msg_len); break; + case MGMT_MSG_CODE_RPC: + be_client_handle_rpc(client, txn_id, msg, msg_len); + break; case MGMT_MSG_CODE_NOTIFY: be_client_handle_notify(client, msg, msg_len); break; @@ -1040,6 +1180,9 @@ int mgmt_be_send_subscr_req(struct mgmt_be_client *client_ctx, subscr_req.n_notif_xpaths = client_ctx->cbs.nnotif_xpaths; subscr_req.notif_xpaths = (char **)client_ctx->cbs.notif_xpaths; + subscr_req.n_rpc_xpaths = client_ctx->cbs.nrpc_xpaths; + subscr_req.rpc_xpaths = (char **)client_ctx->cbs.rpc_xpaths; + mgmtd__be_message__init(&be_msg); be_msg.message_case = MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ; be_msg.subscr_req = &subscr_req; diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h index cd8b237526..7ad0589bdb 100644 --- a/lib/mgmt_be_client.h +++ b/lib/mgmt_be_client.h @@ -75,6 +75,8 @@ struct mgmt_be_client_cbs { const char **notif_xpaths; uint nnotif_xpaths; + const char **rpc_xpaths; + uint nrpc_xpaths; }; /*************************************************************** diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index 3345505213..8cfb025f72 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -360,6 +360,33 @@ int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, uint64_t session_id, return ret; } +int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client, uint64_t session_id, + uint64_t req_id, LYD_FORMAT request_type, + const char *xpath, const char *data) +{ + struct mgmt_msg_rpc *msg; + int ret; + + msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0, + MTYPE_MSG_NATIVE_RPC); + msg->refer_id = session_id; + msg->req_id = req_id; + msg->code = MGMT_MSG_CODE_RPC; + msg->request_type = request_type; + + mgmt_msg_native_xpath_encode(msg, xpath); + if (data) + mgmt_msg_native_append(msg, data, strlen(data) + 1); + + debug_fe_client("Sending RPC_REQ session-id %" PRIu64 " req-id %" PRIu64 + " xpath: %s", + session_id, req_id, xpath); + + ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false); + mgmt_msg_native_free_msg(msg); + return ret; +} + static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client, Mgmtd__FeMessage *fe_msg) { @@ -534,6 +561,7 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client, struct mgmt_msg_notify_data *notify_msg; struct mgmt_msg_tree_data *tree_msg; struct mgmt_msg_edit_reply *edit_msg; + struct mgmt_msg_rpc_reply *rpc_msg; struct mgmt_msg_error *err_msg; const char *xpath = NULL; const char *data = NULL; @@ -608,6 +636,23 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client, session->user_ctx, msg->req_id, xpath); break; + case MGMT_MSG_CODE_RPC_REPLY: + if (!session->client->cbs.rpc_notify) + return; + + rpc_msg = (typeof(rpc_msg))msg; + if (msg_len < sizeof(*rpc_msg)) { + log_err_fe_client("Corrupt rpc-reply msg recv"); + return; + } + dlen = msg_len - sizeof(*rpc_msg); + + session->client->cbs.rpc_notify(client, client->user_data, + session->client_id, + msg->refer_id, + session->user_ctx, msg->req_id, + dlen ? rpc_msg->data : NULL); + break; case MGMT_MSG_CODE_NOTIFY: if (!session->client->cbs.async_notification) return; diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h index 9d569348ae..20c87044a5 100644 --- a/lib/mgmt_fe_client.h +++ b/lib/mgmt_fe_client.h @@ -120,6 +120,12 @@ struct mgmt_fe_client_cbs { uintptr_t session_ctx, uint64_t req_id, const char *xpath); + /* Called when RPC result is returned */ + int (*rpc_notify)(struct mgmt_fe_client *client, uintptr_t user_data, + uint64_t client_id, uint64_t session_id, + uintptr_t session_ctx, uint64_t req_id, + const char *result); + /* Called with asynchronous notifications from backends */ int (*async_notification)(struct mgmt_fe_client *client, uintptr_t user_data, uint64_t client_id, @@ -455,6 +461,35 @@ extern int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, const char *xpath, const char *data); /* + * Send RPC request to MGMTD daemon. + * + * client + * Client object. + * + * session_id + * Client session ID. + * + * req_id + * Client request ID. + * + * result_type + * The LYD_FORMAT of the result. + * + * xpath + * the xpath of the RPC. + * + * data + * the data tree. + * + * Returns: + * 0 on success, otherwise msg_conn_send_msg() return values. + */ +extern int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client, + uint64_t session_id, uint64_t req_id, + LYD_FORMAT request_type, const char *xpath, + const char *data); + +/* * Destroy library and cleanup everything. */ extern void mgmt_fe_client_destroy(struct mgmt_fe_client *client); diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c index 09ea43ece0..39ce9abae6 100644 --- a/lib/mgmt_msg_native.c +++ b/lib/mgmt_msg_native.c @@ -16,6 +16,8 @@ DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_DATA, "native get data msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_NOTIFY, "native get data msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT, "native edit msg"); DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT_REPLY, "native edit reply msg"); +DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC, "native RPC msg"); +DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC_REPLY, "native RPC reply msg"); int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id, uint64_t req_id, bool short_circuit_ok, diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h index b7c29862aa..cf528a6356 100644 --- a/lib/mgmt_msg_native.h +++ b/lib/mgmt_msg_native.h @@ -152,6 +152,8 @@ DECLARE_MTYPE(MSG_NATIVE_GET_DATA); DECLARE_MTYPE(MSG_NATIVE_NOTIFY); DECLARE_MTYPE(MSG_NATIVE_EDIT); DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY); +DECLARE_MTYPE(MSG_NATIVE_RPC); +DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY); /* * Native message codes @@ -163,6 +165,8 @@ DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY); #define MGMT_MSG_CODE_NOTIFY 4 #define MGMT_MSG_CODE_EDIT 5 #define MGMT_MSG_CODE_EDIT_REPLY 6 +#define MGMT_MSG_CODE_RPC 7 +#define MGMT_MSG_CODE_RPC_REPLY 8 /* * Datastores @@ -377,6 +381,42 @@ _Static_assert(sizeof(struct mgmt_msg_edit_reply) == offsetof(struct mgmt_msg_edit_reply, data), "Size mismatch"); +/** + * struct mgmt_msg_rpc - RPC/action request. + * + * @request_type: ``LYD_FORMAT`` for the @data. + * @data: the xpath followed by the tree data for the operation. + */ +struct mgmt_msg_rpc { + struct mgmt_msg_header; + uint8_t request_type; + uint8_t resv2[7]; + + alignas(8) char data[]; +}; + +_Static_assert(sizeof(struct mgmt_msg_rpc) == + offsetof(struct mgmt_msg_rpc, data), + "Size mismatch"); + +/** + * struct mgmt_msg_rpc_reply - RPC/action reply. + * + * @result_type: ``LYD_FORMAT`` for the @data. + * @data: the tree data for the reply. + */ +struct mgmt_msg_rpc_reply { + struct mgmt_msg_header; + uint8_t result_type; + uint8_t resv2[7]; + + alignas(8) char data[]; +}; + +_Static_assert(sizeof(struct mgmt_msg_rpc_reply) == + offsetof(struct mgmt_msg_rpc_reply, data), + "Size mismatch"); + /* * Validate that the message ends in a NUL terminating byte */ @@ -569,7 +609,10 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn, const char *__s = NULL; \ if (msg->vsplit && msg->vsplit <= __len && \ msg->data[msg->vsplit - 1] == 0) { \ - (__data) = msg->data + msg->vsplit; \ + if (msg->vsplit < __len) \ + (__data) = msg->data + msg->vsplit; \ + else \ + (__data) = NULL; \ __s = msg->data; \ } \ __s; \ diff --git a/lib/nexthop.c b/lib/nexthop.c index 4ddb53cd96..243b52d554 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -1150,11 +1150,7 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea, return -1; } -bool nexthop_is_ifindex_type(const struct nexthop *nh) +bool nexthop_is_blackhole(const struct nexthop *nh) { - if (nh->type == NEXTHOP_TYPE_IFINDEX || - nh->type == NEXTHOP_TYPE_IPV4_IFINDEX || - nh->type == NEXTHOP_TYPE_IPV6_IFINDEX) - return true; - return false; + return nh->type == NEXTHOP_TYPE_BLACKHOLE; } diff --git a/lib/nexthop.h b/lib/nexthop.h index bed6447d49..958d06aa51 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -240,8 +240,8 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, struct nexthop *rparent); -/* Check nexthop of IFINDEX type */ -extern bool nexthop_is_ifindex_type(const struct nexthop *nh); +/* Is this nexthop a blackhole? */ +extern bool nexthop_is_blackhole(const struct nexthop *nh); /* * Parse one or more backup index values, as comma-separated numbers, diff --git a/lib/northbound.c b/lib/northbound.c index 9a5d67cd1b..0bc79d0277 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -932,14 +932,22 @@ static int nb_candidate_edit_tree_add(struct nb_config *candidate, /* if replace failed, restore the original node */ if (existing) { if (root) { + /* Restoring the whole config. */ candidate->dnode = existing; + } else if (ex_parent) { + /* + * Restoring a nested node. Insert it as a + * child. + */ + lyd_insert_child(ex_parent, existing); } else { - if (ex_parent) - lyd_insert_child(ex_parent, existing); - else - lyd_insert_sibling(candidate->dnode, - existing, - &candidate->dnode); + /* + * Restoring a top-level node. Insert it as a + * sibling to candidate->dnode to make sure + * the linkage is correct. + */ + lyd_insert_sibling(candidate->dnode, existing, + &candidate->dnode); } } yang_print_errors(ly_native_ctx, errmsg, errmsg_len); @@ -1820,14 +1828,11 @@ const void *nb_callback_lookup_next(const struct nb_node *nb_node, } int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, - const struct list *input, struct list *output, char *errmsg, - size_t errmsg_len) + const struct lyd_node *input, struct lyd_node *output, + char *errmsg, size_t errmsg_len) { struct nb_cb_rpc_args args = {}; - if (CHECK_FLAG(nb_node->flags, F_NB_NODE_IGNORE_CFG_CBS)) - return 0; - DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath); args.xpath = xpath; diff --git a/lib/northbound.h b/lib/northbound.h index 3bf1eacd61..34d17a587c 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -274,11 +274,11 @@ struct nb_cb_rpc_args { /* XPath of the YANG RPC or action. */ const char *xpath; - /* Read-only list of input parameters. */ - const struct list *input; + /* Read-only "input" tree of the RPC/action. */ + const struct lyd_node *input; - /* List of output parameters to be populated by the callback. */ - struct list *output; + /* The "output" tree of the RPC/action to be populated by the callback. */ + struct lyd_node *output; /* Buffer to store human-readable error message in case of error. */ char *errmsg; @@ -833,7 +833,7 @@ extern const void *nb_callback_lookup_next(const struct nb_node *nb_node, const void *parent_list_entry, const struct yang_list_keys *keys); extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath, - const struct list *input, struct list *output, + const struct lyd_node *input, struct lyd_node *output, char *errmsg, size_t errmsg_len); extern void nb_callback_notify(const struct nb_node *nb_node, const char *xpath, struct lyd_node *dnode); diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 8809ec2ad8..4f962cda5c 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -275,10 +275,31 @@ int nb_cli_apply_changes_clear_pending(struct vty *vty, return nb_cli_apply_changes_internal(vty, xpath_base_abs, true); } -int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input, - struct list *output) +int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath, const char *value) +{ + struct nb_cfg_change *param; + + if (vty->num_rpc_params == VTY_MAXCFGCHANGES) { + /* Not expected to happen. */ + vty_out(vty, + "%% Exceeded the maximum number of params (%u) for a single command\n\n", + VTY_MAXCFGCHANGES); + return CMD_WARNING; + } + + param = &vty->rpc_params[vty->num_rpc_params++]; + strlcpy(param->xpath, xpath, sizeof(param->xpath)); + param->value = value; + + return CMD_SUCCESS; +} + +int nb_cli_rpc(struct vty *vty, const char *xpath, struct lyd_node **output_p) { struct nb_node *nb_node; + struct lyd_node *input = NULL; + struct lyd_node *output = NULL; + LY_ERR err; int ret; char errmsg[BUFSIZ] = {0}; @@ -289,12 +310,62 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input, return CMD_WARNING; } + /* create input tree */ + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL, + &input); + assert(err == LY_SUCCESS); + + for (size_t i = 0; i < vty->num_rpc_params; i++) { + err = lyd_new_path(input, ly_native_ctx, + vty->rpc_params[i].xpath, + vty->rpc_params[i].value, 0, NULL); + assert(err == LY_SUCCESS); + } + + if (vty_mgmt_fe_enabled()) { + char *data = NULL; + + err = lyd_print_mem(&data, input, LYD_JSON, LYD_PRINT_SHRINK); + assert(err == LY_SUCCESS); + + ret = vty_mgmt_send_rpc_req(vty, LYD_JSON, xpath, data); + + free(data); + lyd_free_all(input); + + if (ret < 0) + return CMD_WARNING; + return CMD_SUCCESS; + } + + /* validate input tree to create implicit defaults */ + err = lyd_validate_op(input, NULL, LYD_TYPE_RPC_YANG, NULL); + assert(err == LY_SUCCESS); + + /* create output tree root for population in the callback */ + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL, + &output); + assert(err == LY_SUCCESS); + ret = nb_callback_rpc(nb_node, xpath, input, output, errmsg, sizeof(errmsg)); + + /* validate output tree to create implicit defaults */ + err = lyd_validate_op(output, NULL, LYD_TYPE_REPLY_YANG, NULL); + assert(err == LY_SUCCESS); + + lyd_free_all(input); + vty->num_rpc_params = 0; + switch (ret) { case NB_OK: + if (output_p) + *output_p = output; + else + lyd_free_all(output); return CMD_SUCCESS; default: + lyd_free_all(output); if (strlen(errmsg)) vty_show_nb_errors(vty, ret, errmsg); return CMD_WARNING; diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h index 1a45794d45..4c8dc50bd2 100644 --- a/lib/northbound_cli.h +++ b/lib/northbound_cli.h @@ -80,7 +80,23 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...) PRINTFRR(2, 3); /* - * Execute a YANG RPC or Action. + * Add an input child node for an RPC or an action. + * + * vty + * The vty context. + * + * xpath + * XPath of the child being added, relative to the input container. + * + * value + * Value of the child being added. Can be NULL for containers and leafs of + * type 'empty'. + */ +extern int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath, + const char *value); + +/* + * Execute a YANG RPC or Action using the enqueued input parameters. * * vty * The vty terminal to dump any error. @@ -88,20 +104,16 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, * xpath * XPath of the YANG RPC or Action node. * - * input - * List of 'yang_data' structures containing the RPC input parameters. It - * can be set to NULL when there are no input parameters. - * - * output - * List of 'yang_data' structures used to retrieve the RPC output parameters. - * It can be set to NULL when it's known that the given YANG RPC or Action - * doesn't have any output parameters. + * output_p + * A pointer to the libyang data node that will hold the output data tree. + * It can be set to NULL if the caller is not interested in processing the + * output. The caller is responsible for freeing the output data tree. * * Returns: * CMD_SUCCESS on success, CMD_WARNING otherwise. */ -extern int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input, - struct list *output); +extern int nb_cli_rpc(struct vty *vty, const char *xpath, + struct lyd_node **output_p); /* * Show CLI commands associated to the given YANG data node. diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp index 7957752589..612ec3981b 100644 --- a/lib/northbound_grpc.cpp +++ b/lib/northbound_grpc.cpp @@ -1011,12 +1011,11 @@ grpc::Status HandleUnaryExecute( grpc_debug("%s: entered", __func__); struct nb_node *nb_node; - struct list *input_list; - struct list *output_list; - struct listnode *node; - struct yang_data *data; + struct lyd_node *input_tree, *output_tree, *child; const char *xpath; char errmsg[BUFSIZ] = {0}; + char path[XPATH_MAXLEN]; + LY_ERR err; // Request: string path = 1; xpath = tag->request.path().c_str(); @@ -1032,40 +1031,66 @@ grpc::Status HandleUnaryExecute( return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Unknown data path"); - input_list = yang_data_list_new(); - output_list = yang_data_list_new(); + // Create input data tree. + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, + (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &input_tree); + if (err != LY_SUCCESS) { + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, + "Invalid data path"); + } // Read input parameters. auto input = tag->request.input(); for (const frr::PathValue &pv : input) { // Request: repeated PathValue input = 2; - data = yang_data_new(pv.path().c_str(), pv.value().c_str()); - listnode_add(input_list, data); + err = lyd_new_path(input_tree, ly_native_ctx, pv.path().c_str(), + pv.value().c_str(), 0, NULL); + if (err != LY_SUCCESS) { + lyd_free_tree(input_tree); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, + "Invalid input data"); + } + } + + // Validate input data. + err = lyd_validate_op(input_tree, NULL, LYD_TYPE_RPC_YANG, NULL); + if (err != LY_SUCCESS) { + lyd_free_tree(input_tree); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, + "Invalid input data"); + } + + // Create output data tree. + err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, + (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &output_tree); + if (err != LY_SUCCESS) { + lyd_free_tree(input_tree); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, + "Invalid data path"); } // Execute callback registered for this XPath. - if (nb_callback_rpc(nb_node, xpath, input_list, output_list, errmsg, - sizeof(errmsg)) - != NB_OK) { + if (nb_callback_rpc(nb_node, xpath, input_tree, output_tree, errmsg, + sizeof(errmsg)) != NB_OK) { flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s", __func__, xpath); - list_delete(&input_list); - list_delete(&output_list); + lyd_free_tree(input_tree); + lyd_free_tree(output_tree); return grpc::Status(grpc::StatusCode::INTERNAL, "RPC failed"); } // Process output parameters. - for (ALL_LIST_ELEMENTS_RO(output_list, node, data)) { + LY_LIST_FOR (lyd_child(output_tree), child) { // Response: repeated PathValue output = 1; frr::PathValue *pv = tag->response.add_output(); - pv->set_path(data->xpath); - pv->set_value(data->value); + pv->set_path(lyd_path(child, LYD_PATH_STD, path, sizeof(path))); + pv->set_value(yang_dnode_get_string(child, NULL)); } // Release memory. - list_delete(&input_list); - list_delete(&output_list); + lyd_free_tree(input_tree); + lyd_free_tree(output_tree); return grpc::Status::OK; } diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c index 7e7190f5a4..5f38c970c7 100644 --- a/lib/northbound_oper.c +++ b/lib/northbound_oper.c @@ -1556,8 +1556,9 @@ static enum nb_error nb_op_yield(struct nb_op_yield_state *ys) unsigned long min_us = MAX(1, NB_OP_WALK_INTERVAL_US / 50000); struct timeval tv = { .tv_sec = 0, .tv_usec = min_us }; - DEBUGD(&nb_dbg_events, "NB oper-state: yielding %s for %lus (should_batch %d)", - ys->xpath, tv.tv_usec, ys->should_batch); + DEBUGD(&nb_dbg_events, + "NB oper-state: yielding %s for %lldus (should_batch %d)", + ys->xpath, (long long)tv.tv_usec, ys->should_batch); if (ys->should_batch) { /* diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c index 640334926d..0ec7610a9a 100644 --- a/lib/northbound_sysrepo.c +++ b/lib/northbound_sysrepo.c @@ -377,16 +377,11 @@ static int frr_sr_state_cb(sr_session_ctx_t *session, uint32_t sub_id, return SR_ERR_OK; } static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, - const char *xpath, const sr_val_t *sr_input, - const size_t input_cnt, sr_event_t sr_ev, - uint32_t request_id, sr_val_t **sr_output, - size_t *sr_output_cnt, void *private_ctx) + const char *xpath, const struct lyd_node *input, + sr_event_t sr_ev, uint32_t request_id, + struct lyd_node *output, void *private_ctx) { struct nb_node *nb_node; - struct list *input; - struct list *output; - struct yang_data *data; - size_t cb_output_cnt; int ret = SR_ERR_OK; char errmsg[BUFSIZ] = {0}; @@ -397,19 +392,6 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, return SR_ERR_INTERNAL; } - input = yang_data_list_new(); - output = yang_data_list_new(); - - /* Process input. */ - for (size_t i = 0; i < input_cnt; i++) { - char value_str[YANG_VALUE_MAXLEN]; - - sr_val_to_buff(&sr_input[i], value_str, sizeof(value_str)); - - data = yang_data_new(xpath, value_str); - listnode_add(input, data); - } - /* Execute callback registered for this XPath. */ if (nb_callback_rpc(nb_node, xpath, input, output, errmsg, sizeof(errmsg)) @@ -417,44 +399,8 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s", __func__, xpath); ret = SR_ERR_OPERATION_FAILED; - goto exit; } - /* Process output. */ - if (listcount(output) > 0) { - sr_val_t *values = NULL; - struct listnode *node; - int i = 0; - - cb_output_cnt = listcount(output); - ret = sr_new_values(cb_output_cnt, &values); - if (ret != SR_ERR_OK) { - flog_err(EC_LIB_LIBSYSREPO, "%s: sr_new_values(): %s", - __func__, sr_strerror(ret)); - goto exit; - } - - for (ALL_LIST_ELEMENTS_RO(output, node, data)) { - if (yang_data_frr2sr(data, &values[i++]) != 0) { - flog_err( - EC_LIB_SYSREPO_DATA_CONVERT, - "%s: failed to convert data to Sysrepo format", - __func__); - ret = SR_ERR_INTERNAL; - sr_free_values(values, cb_output_cnt); - goto exit; - } - } - - *sr_output = values; - *sr_output_cnt = cb_output_cnt; - } - -exit: - /* Release memory. */ - list_delete(&input); - list_delete(&output); - return ret; } @@ -579,8 +525,9 @@ static int frr_sr_subscribe_rpc(const struct lysc_node *snode, void *arg) DEBUGD(&nb_dbg_client_sysrepo, "sysrepo: providing RPC to '%s'", nb_node->xpath); - ret = sr_rpc_subscribe(session, nb_node->xpath, frr_sr_config_rpc_cb, - NULL, 0, 0, &module->sr_subscription); + ret = sr_rpc_subscribe_tree(session, nb_node->xpath, + frr_sr_config_rpc_cb, NULL, 0, 0, + &module->sr_subscription); if (ret != SR_ERR_OK) flog_err(EC_LIB_LIBSYSREPO, "sr_rpc_subscribe(): %s", sr_strerror(ret)); diff --git a/lib/resolver.c b/lib/resolver.c index d8245e3816..901ccf8132 100644 --- a/lib/resolver.c +++ b/lib/resolver.c @@ -104,7 +104,7 @@ static void resolver_cb_timeout(struct event *t) { struct resolver_state *r = EVENT_ARG(t); - ares_process(r->channel, NULL, NULL); + ares_process_fd(r->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); resolver_update_timeouts(r); } @@ -179,7 +179,56 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable, resolver_fd_drop_maybe(resfd); } +#if (ARES_VERSION >= 0x011c00) +static void ares_address_cb(void *arg, int status, int timeouts, + struct ares_addrinfo *result) +{ + struct resolver_query *query = (struct resolver_query *)arg; + union sockunion addr[16]; + void (*callback)(struct resolver_query *q, const char *err, int ret, + union sockunion *s); + size_t i; + struct ares_addrinfo_node *node; + callback = query->callback; + query->callback = NULL; + + if (status != ARES_SUCCESS) { + if (resolver_debug) + zlog_debug("[%p] Resolving failed (%s)", + query, ares_strerror(status)); + + callback(query, ares_strerror(status), -1, NULL); + if (result) + ares_freeaddrinfo(result); + return; + } + + + node = result->nodes; + for (i = 0; i < array_size(addr) && node; i++) { + memset(&addr[i], 0, sizeof(addr[i])); + addr[i].sa.sa_family = node->ai_family; + switch (node->ai_family) { + case AF_INET: + memcpy(&addr[i].sin.sin_addr, node->ai_addr, + node->ai_addrlen); + break; + case AF_INET6: + memcpy(&addr[i].sin6.sin6_addr, node->ai_addr, + node->ai_addrlen); + break; + } + node = node->ai_next; + } + + if (resolver_debug) + zlog_debug("[%p] Resolved with %d results", query, (int)i); + + callback(query, NULL, i, &addr[0]); + ares_freeaddrinfo(result); +} +#else static void ares_address_cb(void *arg, int status, int timeouts, struct hostent *he) { @@ -222,6 +271,8 @@ static void ares_address_cb(void *arg, int status, int timeouts, callback(query, NULL, i, &addr[0]); } +#endif + static void resolver_cb_literal(struct event *t) { struct resolver_query *query = EVENT_ARG(t); @@ -240,6 +291,14 @@ void resolver_resolve(struct resolver_query *query, int af, vrf_id_t vrf_id, int, union sockunion *)) { int ret; +#if (ARES_VERSION >= 0x011c00) + struct ares_addrinfo_hints hints = { + .ai_flags = 0, + .ai_family = af, + .ai_socktype = 0, /* any of SOCK_STREAM or SOCK_DGRAM */ + .ai_protocol = 0 /* any protocol */ + }; +#endif if (hostname == NULL) return; @@ -278,7 +337,13 @@ void resolver_resolve(struct resolver_query *query, int af, vrf_id_t vrf_id, __func__, vrf_id, safe_strerror(errno)); return; } + +#if (ARES_VERSION >= 0x011c00) + ares_getaddrinfo(state.channel, hostname, NULL, &hints, ares_address_cb, + query); +#else ares_gethostbyname(state.channel, hostname, af, ares_address_cb, query); +#endif ret = vrf_switchback_to_initial(); if (ret < 0) flog_err_sys(EC_LIB_SOCKET, diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 88b341cac0..a12a07c14f 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -1252,14 +1252,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode, } else if (IS_SET_EXTCOMMUNITY_LB(action)) { enum ecommunity_lb_type lb_type; char str[VTY_BUFSIZ]; - uint16_t bandwidth; + uint32_t bandwidth; lb_type = yang_dnode_get_enum( dnode, "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type"); switch (lb_type) { case EXPLICIT_BANDWIDTH: - bandwidth = yang_dnode_get_uint16( + bandwidth = yang_dnode_get_uint32( dnode, "./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth"); snprintf(str, sizeof(str), "%d", bandwidth); diff --git a/lib/stream.c b/lib/stream.c index c6de3aefa1..fa20ebdbe7 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -1241,9 +1241,7 @@ void stream_fifo_init(struct stream_fifo *fifo) /* Add new stream to fifo. */ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s) { -#if defined DEV_BUILD size_t max, curmax; -#endif if (fifo->tail) fifo->tail->next = s; @@ -1252,15 +1250,11 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s) fifo->tail = s; fifo->tail->next = NULL; -#if !defined DEV_BUILD - atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release); -#else max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release); curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed); if (max > curmax) atomic_store_explicit(&fifo->max_count, max, memory_order_relaxed); -#endif } void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s) diff --git a/lib/subdir.am b/lib/subdir.am index 5ec6adf4c0..221c0b1e1d 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -153,6 +153,7 @@ nodist_lib_libfrr_la_SOURCES = \ yang/frr-nexthop.yang.c \ yang/ietf/frr-deviations-ietf-key-chain.yang.c \ yang/ietf/ietf-routing-types.yang.c \ + yang/ietf/ietf-netconf-acm.yang.c \ yang/ietf/ietf-key-chain.yang.c \ yang/ietf/ietf-interfaces.yang.c \ yang/ietf/ietf-bgp-types.yang.c \ @@ -39,6 +39,7 @@ #include "libfrr.h" #include "frrstr.h" #include "lib_errors.h" +#include <libyang/version.h> #include "northbound_cli.h" #include "printfrr.h" #include "json.h" @@ -3670,15 +3671,24 @@ static ssize_t vty_mgmt_libyang_print(void *user_data, const void *buf, } static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, - struct ly_err_item *ei) + const struct ly_err_item *ei) { +#if (LY_VERSION_MAJOR < 3) +#define data_path path +#else +#define data_path data_path +#endif bool have_apptag = ei->apptag && ei->apptag[0] != 0; - bool have_path = ei->path && ei->path[0] != 0; + bool have_path = ei->data_path && ei->data_path[0] != 0; bool have_msg = ei->msg && ei->msg[0] != 0; const char *severity = NULL; const char *evalid = NULL; const char *ecode = NULL; +#if (LY_VERSION_MAJOR < 3) LY_ERR err = ei->no; +#else + LY_ERR err = ei->err; +#endif if (ei->level == LY_LLERR) severity = "error"; @@ -3703,7 +3713,8 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, vty_out(vty, "<error-validation>%s</error-validation>\n", evalid); if (have_path) - vty_out(vty, "<error-path>%s</error-path>\n", ei->path); + vty_out(vty, "<error-path>%s</error-path>\n", + ei->data_path); if (have_apptag) vty_out(vty, "<error-app-tag>%s</error-app-tag>\n", ei->apptag); @@ -3722,7 +3733,7 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, if (evalid) vty_out(vty, ", \"error-validation\": \"%s\"", evalid); if (have_path) - vty_out(vty, ", \"error-path\": \"%s\"", ei->path); + vty_out(vty, ", \"error-path\": \"%s\"", ei->data_path); if (have_apptag) vty_out(vty, ", \"error-app-tag\": \"%s\"", ei->apptag); if (have_msg) @@ -3739,18 +3750,19 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format, if (evalid) vty_out(vty, " invalid: %s", evalid); if (have_path) - vty_out(vty, " path: %s", ei->path); + vty_out(vty, " path: %s", ei->data_path); if (have_apptag) vty_out(vty, " app-tag: %s", ei->apptag); if (have_msg) vty_out(vty, " msg: %s", ei->msg); break; } +#undef data_path } static uint vty_out_yang_errors(struct vty *vty, LYD_FORMAT format) { - struct ly_err_item *ei = ly_err_first(ly_native_ctx); + const struct ly_err_item *ei = ly_err_first(ly_native_ctx); uint count; if (!ei) @@ -3843,6 +3855,26 @@ static int vty_mgmt_edit_result_notified(struct mgmt_fe_client *client, return 0; } +static int vty_mgmt_rpc_result_notified(struct mgmt_fe_client *client, + uintptr_t user_data, uint64_t client_id, + uint64_t session_id, + uintptr_t session_ctx, uint64_t req_id, + const char *result) +{ + struct vty *vty = (struct vty *)session_ctx; + + debug_fe_client("RPC request for client 0x%" PRIx64 " req-id %" PRIu64 + " was successful", + client_id, req_id); + + if (result) + vty_out(vty, "%s\n", result); + + vty_mgmt_resume_response(vty, CMD_SUCCESS); + + return 0; +} + static int vty_mgmt_error_notified(struct mgmt_fe_client *client, uintptr_t user_data, uint64_t client_id, uint64_t session_id, uintptr_t session_ctx, @@ -3885,6 +3917,7 @@ static struct mgmt_fe_client_cbs mgmt_cbs = { .get_data_notify = vty_mgmt_get_data_result_notified, .get_tree_notify = vty_mgmt_get_tree_result_notified, .edit_notify = vty_mgmt_edit_result_notified, + .rpc_notify = vty_mgmt_rpc_result_notified, .error_notify = vty_mgmt_error_notified, }; @@ -4162,6 +4195,25 @@ int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore, return 0; } +int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type, + const char *xpath, const char *data) +{ + vty->mgmt_req_id++; + + if (mgmt_fe_send_rpc_req(mgmt_fe_client, vty->mgmt_session_id, + vty->mgmt_req_id, request_type, xpath, data)) { + zlog_err("Failed to send RPC to MGMTD session-id: %" PRIu64 + " req-id %" PRIu64 ".", + vty->mgmt_session_id, vty->mgmt_req_id); + vty_out(vty, "Failed to send RPC to MGMTD!\n"); + return -1; + } + + vty->mgmt_req_pending_cmd = "MESSAGE_RPC_REQ"; + + return 0; +} + /* Install vty's own commands like `who' command. */ void vty_init(struct event_loop *master_thread, bool do_command_logging) { @@ -122,6 +122,10 @@ struct vty { size_t num_cfg_changes; struct nb_cfg_change cfg_changes[VTY_MAXCFGCHANGES]; + /* Input parameters */ + size_t num_rpc_params; + struct nb_cfg_change rpc_params[VTY_MAXCFGCHANGES]; + /* XPath of the current node */ int xpath_index; char xpath[VTY_MAXDEPTH][XPATH_MAXLEN]; @@ -423,6 +427,8 @@ extern int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore, LYD_FORMAT request_type, uint8_t flags, uint8_t operation, const char *xpath, const char *data); +extern int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type, + const char *xpath, const char *data); extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id, bool lock, bool scok); extern void vty_mgmt_resume_response(struct vty *vty, int ret); diff --git a/lib/yang.c b/lib/yang.c index 013a762842..702fcf436d 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -11,6 +11,7 @@ #include "lib_errors.h" #include "yang.h" #include "yang_translator.h" +#include <libyang/version.h> #include "northbound.h" #include "frrstr.h" @@ -19,6 +20,17 @@ DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module"); DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure"); +/* Safe to remove after libyang 2.2.8 */ +#if (LY_VERSION_MAJOR < 3) +#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ + set) \ + lyd_find_xpath3(ctx_node, tree, xpath, vars, set) +#else +#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \ + set) \ + lyd_find_xpath3(ctx_node, tree, xpath, LY_VALUE_JSON, NULL, vars, set) +#endif + /* libyang container. */ struct ly_ctx *ly_native_ctx; @@ -653,6 +665,16 @@ void yang_dnode_free(struct lyd_node *dnode) lyd_free_all(dnode); } +void yang_dnode_rpc_output_add(struct lyd_node *output, const char *xpath, + const char *value) +{ + LY_ERR err; + + err = lyd_new_path(output, ly_native_ctx, xpath, value, + LYD_NEW_PATH_OUTPUT | LYD_NEW_PATH_UPDATE, NULL); + assert(err == LY_SUCCESS); +} + struct yang_data *yang_data_new(const char *xpath, const char *value) { struct yang_data *data; @@ -702,7 +724,12 @@ struct yang_data *yang_data_list_find(const struct list *list, } /* Make libyang log its errors using FRR logging infrastructure. */ -static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) +static void ly_zlog_cb(LY_LOG_LEVEL level, const char *msg, const char *data_path +#if !(LY_VERSION_MAJOR < 3) + , + const char *schema_path, uint64_t line +#endif +) { int priority = LOG_ERR; @@ -719,8 +746,14 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) break; } - if (path) - zlog(priority, "libyang: %s (%s)", msg, path); + if (data_path) + zlog(priority, "libyang: %s (%s)", msg, data_path); +#if !(LY_VERSION_MAJOR < 3) + else if (schema_path) + zlog(priority, "libyang %s (%s)\n", msg, schema_path); + else if (line) + zlog(priority, "libyang %s (line %" PRIu64 ")\n", msg, line); +#endif else zlog(priority, "libyang: %s", msg); } @@ -747,7 +780,8 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, return err; } - err = lyd_find_xpath3(NULL, tree, xpath, NULL, &set); + err = yang_lyd_find_xpath3(NULL, tree, xpath, LY_VALUE_JSON, NULL, NULL, + &set); if (err) { zlog_err("Failed to parse notification: %s", ly_last_errmsg()); lyd_free_all(tree); @@ -764,6 +798,63 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, return LY_SUCCESS; } +LY_ERR yang_parse_rpc(const char *xpath, LYD_FORMAT format, const char *data, + bool reply, struct lyd_node **rpc) +{ + const struct lysc_node *snode; + struct lyd_node *parent = NULL; + struct ly_in *in = NULL; + LY_ERR err; + + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + if (!snode) { + zlog_err("Failed to find RPC/action schema node: %s", xpath); + return LY_ENOTFOUND; + } + + /* If it's an action, create its parent */ + if (snode->nodetype == LYS_ACTION) { + char *parent_xpath = XSTRDUP(MTYPE_TMP, xpath); + + if (yang_xpath_pop_node(parent_xpath) != NB_OK) { + XFREE(MTYPE_TMP, parent_xpath); + zlog_err("Invalid action xpath: %s", xpath); + return LY_EINVAL; + } + + err = lyd_new_path2(NULL, ly_native_ctx, parent_xpath, NULL, 0, + 0, 0, NULL, &parent); + XFREE(MTYPE_TMP, parent_xpath); + if (err) { + zlog_err("Failed to create parent node for action: %s", + ly_last_errmsg()); + return err; + } + } else if (snode->nodetype != LYS_RPC) { + zlog_err("Schema node is not an RPC/action: %s", xpath); + return LY_EINVAL; + } + + err = ly_in_new_memory(data, &in); + if (err) { + lyd_free_all(parent); + zlog_err("Failed to initialize ly_in: %s", ly_last_errmsg()); + return err; + } + + err = lyd_parse_op(ly_native_ctx, parent, in, format, + reply ? LYD_TYPE_REPLY_YANG : LYD_TYPE_RPC_YANG, + NULL, rpc); + ly_in_free(in, 0); + if (err) { + lyd_free_all(parent); + zlog_err("Failed to parse RPC/action: %s", ly_last_errmsg()); + return err; + } + + return LY_SUCCESS; +} + static ssize_t yang_print_darr(void *arg, const void *buf, size_t count) { uint8_t *dst = darr_append_n(*(uint8_t **)arg, count); @@ -840,23 +931,29 @@ char *yang_convert_lyd_format(const char *data, size_t data_len, const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len) { - struct ly_err_item *ei; + const struct ly_err_item *ei; ei = ly_err_first(ly_ctx); if (!ei) return ""; strlcpy(buf, "YANG error(s):\n", buf_len); +#if (LY_VERSION_MAJOR < 3) +#define data_path path +#else +#define data_path data_path +#endif for (; ei; ei = ei->next) { - if (ei->path) { + if (ei->data_path) { strlcat(buf, " Path: ", buf_len); - strlcat(buf, ei->path, buf_len); + strlcat(buf, ei->data_path, buf_len); strlcat(buf, "\n", buf_len); } strlcat(buf, " Error: ", buf_len); strlcat(buf, ei->msg, buf_len); strlcat(buf, "\n", buf_len); } +#undef data_path ly_err_clean(ly_ctx, NULL); @@ -908,7 +1005,12 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile) void yang_init(bool embedded_modules, bool defer_compile) { /* Initialize libyang global parameters that affect all containers. */ - ly_set_log_clb(ly_log_cb, 1); + ly_set_log_clb(ly_zlog_cb +#if (LY_VERSION_MAJOR < 3) + , + 1 +#endif + ); ly_log_options(LY_LOLOG | LY_LOSTORE); /* Initialize libyang container for native models. */ @@ -1246,7 +1348,8 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath) *root = lyd_first_sibling(*root); - err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set); + err = yang_lyd_find_xpath3(NULL, *root, xpath, LY_VALUE_JSON, NULL, + NULL, &set); if (err) { flog_err_sys(EC_LIB_LIBYANG, "cannot obtain specific result for xpath \"%s\": %s", diff --git a/lib/yang.h b/lib/yang.h index 25703b1879..57131f478b 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -536,6 +536,21 @@ extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode); extern void yang_dnode_free(struct lyd_node *dnode); /* + * Add a libyang data node to an RPC/action output container. + * + * output + * RPC/action output container. + * + * xpath + * XPath of the data node to add, relative to the output container. + * + * value + * String representing the value of the data node. + */ +extern void yang_dnode_rpc_output_add(struct lyd_node *output, + const char *xpath, const char *value); + +/* * Create a new yang_data structure. * * xpath @@ -620,6 +635,25 @@ extern LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format, const char *data, struct lyd_node **notif); /* + * Parse a YANG RPC. + * + * Args: + * xpath: xpath of an RPC/action. + * format: LYD_FORMAT of input data. + * data: input data. + * reply: true if the data represents a reply to an RPC/action. + * rpc: pointer to the libyang data tree to store the parsed RPC/action. + * If data represents an action, the pointer to the action node is + * still returned, but it's part of the full data tree with all its + * parents. + * + * Returns: + * LY_ERR from underlying calls. + */ +LY_ERR yang_parse_rpc(const char *xpath, LYD_FORMAT format, const char *data, + bool reply, struct lyd_node **rpc); + +/* * "Print" the yang tree in `root` into dynamic sized array. * * Args: diff --git a/lib/zclient.c b/lib/zclient.c index 4cbd04c116..c5b1e72380 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1040,7 +1040,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, } if (api_nh->weight) - stream_putl(s, api_nh->weight); + stream_putq(s, api_nh->weight); /* Router MAC for EVPN routes. */ if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN)) @@ -1125,6 +1125,7 @@ int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l) stream_put(s, l->name, strlen(l->name)); stream_putw(s, l->prefix.prefixlen); stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix)); + stream_putc(s, l->flags); return 0; } @@ -1140,6 +1141,7 @@ int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l) STREAM_GETW(s, l->prefix.prefixlen); STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix)); l->prefix.family = AF_INET6; + STREAM_GETC(s, l->flags); return 0; stream_failure: @@ -1412,7 +1414,7 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, } if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT)) - STREAM_GETL(s, api_nh->weight); + STREAM_GETQ(s, api_nh->weight); /* Router MAC for EVPN routes. */ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) @@ -4670,21 +4672,25 @@ char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len) return buf; } - snprintfrr( - buf, len, "%s%s%s%s%s%s%s%s%s%s", - CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion " - : "", - CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance " - : "", - CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "", - CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed " - : ""); + snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s", + CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion " + : "", + + CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance " + : "", + + CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "", + CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) + ? "Offload Failed " + : "", + CHECK_FLAG(flags, ZEBRA_FLAG_OUTOFSYNC) ? "OutOfSync " : ""); + return buf; } diff --git a/lib/zclient.h b/lib/zclient.h index 1bf91064e2..3759f94542 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -441,7 +441,7 @@ struct zapi_nexthop { struct ethaddr rmac; - uint32_t weight; + uint64_t weight; /* Backup nexthops, for IP-FRR, TI-LFA, etc */ uint8_t backup_num; diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index 830c410676..81574d1a56 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -98,6 +98,10 @@ static const char *const ripd_oper_xpaths[] = { "/ietf-key-chain:key-chains", NULL, }; +static const char *const ripd_rpc_xpaths[] = { + "/frr-ripd", + NULL, +}; #endif #if HAVE_RIPNGD @@ -113,6 +117,10 @@ static const char *const ripngd_oper_xpaths[] = { "/frr-ripngd:ripngd", NULL, }; +static const char *const ripngd_rpc_xpaths[] = { + "/frr-ripngd", + NULL, +}; #endif #if HAVE_STATICD @@ -147,6 +155,15 @@ static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { [MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths, }; +static const char *const *be_client_rpc_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { +#ifdef HAVE_RIPD + [MGMTD_BE_CLIENT_ID_RIPD] = ripd_rpc_xpaths, +#endif +#ifdef HAVE_RIPNGD + [MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_rpc_xpaths, +#endif +}; + /* * We would like to have a better ADT than one with O(n) comparisons * @@ -159,6 +176,7 @@ static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { static struct mgmt_be_xpath_map *be_cfg_xpath_map; static struct mgmt_be_xpath_map *be_oper_xpath_map; static struct mgmt_be_xpath_map *be_notif_xpath_map; +static struct mgmt_be_xpath_map *be_rpc_xpath_map; static struct event_loop *mgmt_loop; static struct msg_server mgmt_be_server = {.fd = -1}; @@ -173,8 +191,8 @@ static struct mgmt_be_client_adapter static void mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter); -static bool be_is_client_interested(const char *xpath, - enum mgmt_be_client_id id, bool config); +static bool be_is_client_interested(const char *xpath, enum mgmt_be_client_id id, + enum mgmt_be_xpath_subscr_type type); const char *mgmt_be_client_id2name(enum mgmt_be_client_id id) { @@ -223,16 +241,25 @@ mgmt_be_find_adapter_by_name(const char *name) } static void mgmt_register_client_xpath(enum mgmt_be_client_id id, - const char *xpath, bool config, bool oper) + const char *xpath, + enum mgmt_be_xpath_subscr_type type) { struct mgmt_be_xpath_map **maps, *map; - if (config) + switch (type) { + case MGMT_BE_XPATH_SUBSCR_TYPE_CFG: maps = &be_cfg_xpath_map; - else if (oper) + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_OPER: maps = &be_oper_xpath_map; - else + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF: maps = &be_notif_xpath_map; + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_RPC: + maps = &be_rpc_xpath_map; + break; + } darr_foreach_p (*maps, map) { if (!strcmp(xpath, map->xpath_prefix)) { @@ -260,18 +287,28 @@ static void mgmt_be_xpath_map_init(void) /* Initialize the common config init map */ for (init = be_client_config_xpaths[id]; init && *init; init++) { __dbg(" - CFG XPATH: '%s'", *init); - mgmt_register_client_xpath(id, *init, true, false); + mgmt_register_client_xpath(id, *init, + MGMT_BE_XPATH_SUBSCR_TYPE_CFG); } /* Initialize the common oper init map */ for (init = be_client_oper_xpaths[id]; init && *init; init++) { __dbg(" - OPER XPATH: '%s'", *init); - mgmt_register_client_xpath(id, *init, false, true); + mgmt_register_client_xpath(id, *init, + MGMT_BE_XPATH_SUBSCR_TYPE_OPER); + } + + /* Initialize the common RPC init map */ + for (init = be_client_rpc_xpaths[id]; init && *init; init++) { + __dbg(" - RPC XPATH: '%s'", *init); + mgmt_register_client_xpath(id, *init, + MGMT_BE_XPATH_SUBSCR_TYPE_RPC); } } __dbg("Total Cfg XPath Maps: %u", darr_len(be_cfg_xpath_map)); __dbg("Total Oper XPath Maps: %u", darr_len(be_oper_xpath_map)); + __dbg("Total RPC XPath Maps: %u", darr_len(be_rpc_xpath_map)); } static void mgmt_be_xpath_map_cleanup(void) @@ -289,6 +326,10 @@ static void mgmt_be_xpath_map_cleanup(void) darr_foreach_p (be_notif_xpath_map, map) XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix); darr_free(be_notif_xpath_map); + + darr_foreach_p (be_rpc_xpath_map, map) + XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix); + darr_free(be_rpc_xpath_map); } @@ -405,11 +446,12 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter, */ switch ((int)be_msg->message_case) { case MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ: - __dbg("Got SUBSCR_REQ from '%s' to register xpaths config: %zu oper: %zu notif: %zu", + __dbg("Got SUBSCR_REQ from '%s' to register xpaths config: %zu oper: %zu notif: %zu rpc: %zu", be_msg->subscr_req->client_name, be_msg->subscr_req->n_config_xpaths, be_msg->subscr_req->n_oper_xpaths, - be_msg->subscr_req->n_notif_xpaths); + be_msg->subscr_req->n_notif_xpaths, + be_msg->subscr_req->n_rpc_xpaths); if (strlen(be_msg->subscr_req->client_name)) { strlcpy(adapter->name, be_msg->subscr_req->client_name, @@ -432,22 +474,29 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter, num = be_msg->subscr_req->n_config_xpaths; for (i = 0; i < num; i++) { xpath = be_msg->subscr_req->config_xpaths[i]; - mgmt_register_client_xpath(adapter->id, xpath, true, - false); + mgmt_register_client_xpath(adapter->id, xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_CFG); } num = be_msg->subscr_req->n_oper_xpaths; for (i = 0; i < num; i++) { xpath = be_msg->subscr_req->oper_xpaths[i]; - mgmt_register_client_xpath(adapter->id, xpath, false, - true); + mgmt_register_client_xpath(adapter->id, xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_OPER); } num = be_msg->subscr_req->n_notif_xpaths; for (i = 0; i < num; i++) { xpath = be_msg->subscr_req->notif_xpaths[i]; - mgmt_register_client_xpath(adapter->id, xpath, false, - false); + mgmt_register_client_xpath(adapter->id, xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF); + } + + num = be_msg->subscr_req->n_rpc_xpaths; + for (i = 0; i < num; i++) { + xpath = be_msg->subscr_req->rpc_xpaths[i]; + mgmt_register_client_xpath(adapter->id, xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_RPC); } mgmt_be_send_subscr_reply(adapter, true); @@ -638,6 +687,7 @@ static void be_adapter_handle_native_msg(struct mgmt_be_client_adapter *adapter, { struct mgmt_msg_notify_data *notify_msg; struct mgmt_msg_tree_data *tree_msg; + struct mgmt_msg_rpc_reply *rpc_msg; struct mgmt_msg_error *error_msg; /* get the transaction */ @@ -662,6 +712,15 @@ static void be_adapter_handle_native_msg(struct mgmt_be_client_adapter *adapter, /* Forward the reply to the txn module */ mgmt_txn_notify_tree_data_reply(adapter, tree_msg, msg_len); break; + case MGMT_MSG_CODE_RPC_REPLY: + /* RPC reply from a backend client */ + rpc_msg = (typeof(rpc_msg))msg; + __dbg("Got RPC_REPLY from '%s' txn-id %" PRIx64, adapter->name, + msg->refer_id); + + /* Forward the reply to the txn module */ + mgmt_txn_notify_rpc_reply(adapter, rpc_msg, msg_len); + break; case MGMT_MSG_CODE_NOTIFY: notify_msg = (typeof(notify_msg))msg; __dbg("Got NOTIFY from '%s'", adapter->name); @@ -882,7 +941,8 @@ void mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter, goto walk_cont; xpath = lyd_path(dnode, LYD_PATH_STD, NULL, 0); - if (be_is_client_interested(xpath, adapter->id, true)) + if (be_is_client_interested(xpath, adapter->id, + MGMT_BE_XPATH_SUBSCR_TYPE_CFG)) nb_config_diff_add_change(*changes, NB_CB_CREATE, &seq, dnode); else LYD_TREE_DFS_continue = 1; /* skip any subtree */ @@ -893,13 +953,27 @@ void mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter, } } -uint64_t mgmt_be_interested_clients(const char *xpath, bool config) +uint64_t mgmt_be_interested_clients(const char *xpath, + enum mgmt_be_xpath_subscr_type type) { - struct mgmt_be_xpath_map *maps, *map; + struct mgmt_be_xpath_map *maps = NULL, *map; enum mgmt_be_client_id id; uint64_t clients; - maps = config ? be_cfg_xpath_map : be_oper_xpath_map; + switch (type) { + case MGMT_BE_XPATH_SUBSCR_TYPE_CFG: + maps = be_cfg_xpath_map; + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_OPER: + maps = be_oper_xpath_map; + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF: + maps = be_notif_xpath_map; + break; + case MGMT_BE_XPATH_SUBSCR_TYPE_RPC: + maps = be_rpc_xpath_map; + break; + } clients = 0; @@ -928,8 +1002,8 @@ uint64_t mgmt_be_interested_clients(const char *xpath, bool config) * Returns: * Interested or not. */ -static bool be_is_client_interested(const char *xpath, - enum mgmt_be_client_id id, bool config) +static bool be_is_client_interested(const char *xpath, enum mgmt_be_client_id id, + enum mgmt_be_xpath_subscr_type type) { uint64_t clients; @@ -938,7 +1012,7 @@ static bool be_is_client_interested(const char *xpath, __dbg("Checking client: %s for xpath: '%s'", mgmt_be_client_id2name(id), xpath); - clients = mgmt_be_interested_clients(xpath, config); + clients = mgmt_be_interested_clients(xpath, type); if (IS_IDBIT_SET(clients, id)) { __dbg("client: %s: interested", mgmt_be_client_id2name(id)); return true; @@ -998,23 +1072,41 @@ void mgmt_be_xpath_register_write(struct vty *vty) darr_len(be_oper_xpath_map)); darr_foreach_p (be_oper_xpath_map, map) be_show_xpath_register(vty, map); + + vty_out(vty, "\nMGMTD Backend NOTIFY XPath Registry: Count: %u\n", + darr_len(be_notif_xpath_map)); + darr_foreach_p (be_notif_xpath_map, map) + be_show_xpath_register(vty, map); + + vty_out(vty, "\nMGMTD Backend RPC XPath Registry: Count: %u\n", + darr_len(be_rpc_xpath_map)); + darr_foreach_p (be_rpc_xpath_map, map) + be_show_xpath_register(vty, map); } void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath) { enum mgmt_be_client_id id; struct mgmt_be_client_adapter *adapter; - uint64_t cclients, oclients, combined; - - cclients = mgmt_be_interested_clients(xpath, true); - oclients = mgmt_be_interested_clients(xpath, false); - combined = cclients | oclients; + uint64_t cclients, nclients, oclients, rclients, combined; + + cclients = mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_CFG); + oclients = mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_OPER); + nclients = mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF); + rclients = mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_RPC); + combined = cclients | nclients | oclients | rclients; vty_out(vty, "XPath: '%s'\n", xpath); FOREACH_BE_CLIENT_BITS (id, combined) { - vty_out(vty, " -- Client: '%s'\tconfig:%d oper:%d\n", + vty_out(vty, + " -- Client: '%s'\tconfig:%d notify:%d oper:%d rpc:%d\n", mgmt_be_client_id2name(id), IS_IDBIT_SET(cclients, id), - IS_IDBIT_SET(oclients, id)); + IS_IDBIT_SET(nclients, id), IS_IDBIT_SET(oclients, id), + IS_IDBIT_SET(rclients, id)); adapter = mgmt_be_get_adapter_by_id(id); if (adapter) vty_out(vty, " -- Adapter: %p\n", adapter); diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h index 491410aa15..c9f2ab1b7a 100644 --- a/mgmtd/mgmt_be_adapter.h +++ b/mgmtd/mgmt_be_adapter.h @@ -235,15 +235,23 @@ extern void mgmt_be_xpath_register_write(struct vty *vty); */ extern int mgmt_be_send_native(enum mgmt_be_client_id id, void *msg); +enum mgmt_be_xpath_subscr_type { + MGMT_BE_XPATH_SUBSCR_TYPE_CFG, + MGMT_BE_XPATH_SUBSCR_TYPE_OPER, + MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF, + MGMT_BE_XPATH_SUBSCR_TYPE_RPC, +}; + /** * Lookup the clients which are subscribed to a given `xpath` * and the way they are subscribed. * * Args: * xpath - the xpath to check for subscription information. - * config - true for config interest false for oper interest. + * type - type of subscription to check for. */ -extern uint64_t mgmt_be_interested_clients(const char *xpath, bool config); +extern uint64_t mgmt_be_interested_clients(const char *xpath, + enum mgmt_be_xpath_subscr_type type); /** * mgmt_fe_adapter_send_notify() - notify FE clients of a notification. diff --git a/mgmtd/mgmt_be_nb.c b/mgmtd/mgmt_be_nb.c new file mode 100644 index 0000000000..613272d407 --- /dev/null +++ b/mgmtd/mgmt_be_nb.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "config.h" +#include "xref.h" + +XREF_SETUP(); diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index ab0da64d8f..fc1bde0b38 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -1101,6 +1101,47 @@ done: return ret; } +static int fe_adapter_send_rpc_reply(struct mgmt_fe_session_ctx *session, + uint64_t req_id, uint8_t result_type, + const struct lyd_node *result) +{ + struct mgmt_msg_rpc_reply *msg; + uint8_t **darrp = NULL; + int ret; + + msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc_reply, 0, + MTYPE_MSG_NATIVE_RPC_REPLY); + msg->refer_id = session->session_id; + msg->req_id = req_id; + msg->code = MGMT_MSG_CODE_RPC_REPLY; + msg->result_type = result_type; + + if (result) { + darrp = mgmt_msg_native_get_darrp(msg); + ret = yang_print_tree_append(darrp, result, result_type, 0); + if (ret != LY_SUCCESS) { + __log_err("Error building rpc-reply result for client %s session-id %" PRIu64 + " req-id %" PRIu64 " result type %u", + session->adapter->name, session->session_id, + req_id, result_type); + goto done; + } + } + + __dbg("Sending rpc-reply from adapter %s to session-id %" PRIu64 + " req-id %" PRIu64 " len %u", + session->adapter->name, session->session_id, req_id, + mgmt_msg_native_get_msg_len(msg)); + + ret = fe_adapter_send_native_msg(session->adapter, msg, + mgmt_msg_native_get_msg_len(msg), + false); +done: + mgmt_msg_native_free_msg(msg); + + return ret; +} + static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session, uint64_t req_id, const char *xpath) { @@ -1215,7 +1256,8 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session, } darr_free(snodes); - clients = mgmt_be_interested_clients(msg->xpath, false); + clients = mgmt_be_interested_clients(msg->xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_OPER); if (!clients && !CHECK_FLAG(msg->flags, GET_DATA_FLAG_CONFIG)) { __dbg("No backends provide xpath: %s for txn-id: %" PRIu64 " session-id: %" PRIu64, @@ -1270,7 +1312,7 @@ static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session, } xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data); - if (!xpath || !data) { + if (!xpath) { fe_adapter_send_error(session, msg->req_id, false, -EINVAL, "Invalid message"); return; @@ -1360,6 +1402,90 @@ static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session, } /** + * fe_adapter_handle_rpc() - Handle an RPC message from an FE client. + * @session: the client session. + * @msg_raw: the message data. + * @msg_len: the length of the message data. + */ +static void fe_adapter_handle_rpc(struct mgmt_fe_session_ctx *session, + void *__msg, size_t msg_len) +{ + struct mgmt_msg_rpc *msg = __msg; + const struct lysc_node *snode; + const char *xpath, *data; + uint64_t req_id = msg->req_id; + uint64_t clients; + int ret; + + __dbg("Received RPC request from client %s for session-id %" PRIu64 + " req-id %" PRIu64, + session->adapter->name, session->session_id, msg->req_id); + + xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data); + if (!xpath) { + fe_adapter_send_error(session, req_id, false, -EINVAL, + "Invalid message"); + return; + } + + if (session->txn_id != MGMTD_TXN_ID_NONE) { + fe_adapter_send_error(session, req_id, false, -EINPROGRESS, + "Transaction in progress txn-id: %" PRIu64 + " for session-id: %" PRIu64, + session->txn_id, session->session_id); + return; + } + + snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); + if (!snode) { + fe_adapter_send_error(session, req_id, false, -ENOENT, + "No such path: %s", xpath); + return; + } + + if (snode->nodetype != LYS_RPC && snode->nodetype != LYS_ACTION) { + fe_adapter_send_error(session, req_id, false, -EINVAL, + "Not an RPC or action path: %s", xpath); + return; + } + + clients = mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_RPC); + if (!clients) { + __dbg("No backends implement xpath: %s for txn-id: %" PRIu64 + " session-id: %" PRIu64, + xpath, session->txn_id, session->session_id); + + fe_adapter_send_error(session, req_id, false, -ENOENT, + "No backends implement xpath: %s", xpath); + return; + } + + /* Start a RPC Transaction */ + session->txn_id = mgmt_create_txn(session->session_id, + MGMTD_TXN_TYPE_RPC); + if (session->txn_id == MGMTD_SESSION_ID_NONE) { + fe_adapter_send_error(session, req_id, false, -EINPROGRESS, + "Failed to create an RPC transaction"); + return; + } + + __dbg("Created new rpc txn-id: %" PRIu64 " for session-id: %" PRIu64, + session->txn_id, session->session_id); + + /* Create an RPC request under the transaction */ + ret = mgmt_txn_send_rpc(session->txn_id, req_id, clients, + msg->request_type, xpath, data, + mgmt_msg_native_data_len_decode(msg, msg_len)); + if (ret) { + /* destroy the just created txn */ + mgmt_destroy_txn(&session->txn_id); + fe_adapter_send_error(session, req_id, false, -EINPROGRESS, + "Failed to create an RPC transaction"); + } +} + +/** * Handle a native encoded message from the FE client. */ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter, @@ -1383,6 +1509,9 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter, case MGMT_MSG_CODE_EDIT: fe_adapter_handle_edit(session, msg, msg_len); break; + case MGMT_MSG_CODE_RPC: + fe_adapter_handle_rpc(session, msg, msg_len); + break; default: __log_err("unknown native message session-id %" PRIu64 " req-id %" PRIu64 " code %u to FE adapter %s", @@ -1622,6 +1751,24 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id, return ret; } +int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id, + uint64_t req_id, LYD_FORMAT result_type, + const struct lyd_node *result) +{ + struct mgmt_fe_session_ctx *session; + int ret; + + session = mgmt_session_id2ctx(session_id); + if (!session || session->txn_id != txn_id) + return -1; + + ret = fe_adapter_send_rpc_reply(session, req_id, result_type, result); + + mgmt_destroy_txn(&session->txn_id); + + return ret; +} + int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id, uint64_t req_id, bool unlock, bool commit, const char *xpath, int16_t error, diff --git a/mgmtd/mgmt_fe_adapter.h b/mgmtd/mgmt_fe_adapter.h index 8d61ffe910..61d6cfae13 100644 --- a/mgmtd/mgmt_fe_adapter.h +++ b/mgmtd/mgmt_fe_adapter.h @@ -163,6 +163,26 @@ mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id, int partial_error, bool short_circuit_ok); /** + * Send RPC reply back to client. + * + * This also cleans up and frees the transaction. + * + * Args: + * session_id: the session. + * txn_id: the txn_id this data pertains to + * req_id: the req id for the rpc message + * result_type: the format of the result data. + * result: the results. + * + * Return: + * the return value from the underlying send function. + */ +extern int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id, + uint64_t req_id, + LYD_FORMAT result_type, + const struct lyd_node *result); + +/** * Send edit reply back to client. If error is not 0, a native error is sent. * * This also cleans up and frees the transaction. diff --git a/mgmtd/mgmt_memory.c b/mgmtd/mgmt_memory.c index 0fce61aa97..72ccca0626 100644 --- a/mgmtd/mgmt_memory.c +++ b/mgmtd/mgmt_memory.c @@ -20,6 +20,7 @@ DEFINE_MGROUP(MGMTD, "mgmt"); DEFINE_MTYPE(MGMTD, MGMTD, "instance"); DEFINE_MTYPE(MGMTD, MGMTD_XPATH, "xpath regex"); +DEFINE_MTYPE(MGMTD, MGMTD_ERR, "error"); DEFINE_MTYPE(MGMTD, MGMTD_BE_ADPATER, "backend adapter"); DEFINE_MTYPE(MGMTD, MGMTD_FE_ADPATER, "frontend adapter"); DEFINE_MTYPE(MGMTD, MGMTD_FE_SESSION, "frontend session"); @@ -30,5 +31,6 @@ DEFINE_MTYPE(MGMTD, MGMTD_TXN_COMMCFG_REQ, "txn commit-config requests"); DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETDATA_REQ, "txn get-data requests"); DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETDATA_REPLY, "txn get-data replies"); DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETTREE_REQ, "txn get-tree requests"); +DEFINE_MTYPE(MGMTD, MGMTD_TXN_RPC_REQ, "txn rpc requests"); DEFINE_MTYPE(MGMTD, MGMTD_TXN_CFG_BATCH, "txn config batches"); DEFINE_MTYPE(MGMTD, MGMTD_CMT_INFO, "commit info"); diff --git a/mgmtd/mgmt_memory.h b/mgmtd/mgmt_memory.h index d5b6aa632e..e28586ed83 100644 --- a/mgmtd/mgmt_memory.h +++ b/mgmtd/mgmt_memory.h @@ -14,6 +14,7 @@ DECLARE_MGROUP(MGMTD); DECLARE_MTYPE(MGMTD); DECLARE_MTYPE(MGMTD_XPATH); +DECLARE_MTYPE(MGMTD_ERR); DECLARE_MTYPE(MGMTD_BE_ADPATER); DECLARE_MTYPE(MGMTD_FE_ADPATER); DECLARE_MTYPE(MGMTD_FE_SESSION); @@ -24,6 +25,7 @@ DECLARE_MTYPE(MGMTD_TXN_COMMCFG_REQ); DECLARE_MTYPE(MGMTD_TXN_GETDATA_REQ); DECLARE_MTYPE(MGMTD_TXN_GETDATA_REPLY); DECLARE_MTYPE(MGMTD_TXN_GETTREE_REQ); +DECLARE_MTYPE(MGMTD_TXN_RPC_REQ); DECLARE_MTYPE(MGMTD_TXN_CFG_BATCH); DECLARE_MTYPE(MGMTD_BE_ADAPTER_MSG_BUF); DECLARE_MTYPE(MGMTD_CMT_INFO); diff --git a/mgmtd/mgmt_testc.c b/mgmtd/mgmt_testc.c index a33a55efca..8bb07ed068 100644 --- a/mgmtd/mgmt_testc.c +++ b/mgmtd/mgmt_testc.c @@ -18,6 +18,7 @@ /* ---------------- */ static void async_notification(struct nb_cb_notify_args *args); +static int rpc_callback(struct nb_cb_rpc_args *args); static void sigusr1(void); static void sigint(void); @@ -87,6 +88,10 @@ static const struct frr_yang_module_info frr_ripd_info = { .cbs.notify = async_notification, }, { + .xpath = "/frr-ripd:clear-rip-route", + .cbs.rpc = rpc_callback, + }, + { .xpath = NULL, } } @@ -113,6 +118,7 @@ FRR_DAEMON_INFO(mgmtd_testc, MGMTD_TESTC, /* clang-format on */ const char **__notif_xpaths; +const char **__rpc_xpaths; struct mgmt_be_client_cbs __client_cbs = {}; struct event *event_timeout; @@ -134,6 +140,7 @@ static void quit(int exit_code) { EVENT_OFF(event_timeout); darr_free(__client_cbs.notif_xpaths); + darr_free(__client_cbs.rpc_xpaths); frr_fini(); @@ -152,6 +159,12 @@ static void timeout(struct event *event) quit(1); } +static void success(struct event *event) +{ + zlog_notice("Success, exiting"); + quit(0); +} + static void async_notification(struct nb_cb_notify_args *args) { zlog_notice("Received YANG notification"); @@ -163,6 +176,23 @@ static void async_notification(struct nb_cb_notify_args *args) quit(0); } +static int rpc_callback(struct nb_cb_rpc_args *args) +{ + const char *vrf = NULL; + + zlog_notice("Received YANG RPC"); + + if (yang_dnode_exists(args->input, "vrf")) + vrf = yang_dnode_get_string(args->input, "vrf"); + + printf("{\"frr-ripd:clear-rip-route\": {\"vrf\": \"%s\"}}\n", vrf); + + event_cancel(&event_timeout); + event_add_timer(master, success, NULL, 1, NULL); + + return 0; +} + int main(int argc, char **argv) { int f_listen = 0; @@ -217,6 +247,10 @@ int main(int argc, char **argv) __client_cbs.nnotif_xpaths = darr_len(__notif_xpaths); } + darr_push(__rpc_xpaths, "/frr-ripd:clear-rip-route"); + __client_cbs.rpc_xpaths = __rpc_xpaths; + __client_cbs.nrpc_xpaths = darr_len(__rpc_xpaths); + mgmt_be_client = mgmt_be_client_create("mgmtd-testc", &__client_cbs, 0, master); diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 901163c6e6..0a80b3bbf7 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -29,6 +29,7 @@ enum mgmt_txn_event { MGMTD_TXN_PROC_COMMITCFG, MGMTD_TXN_PROC_GETCFG, MGMTD_TXN_PROC_GETTREE, + MGMTD_TXN_PROC_RPC, MGMTD_TXN_COMMITCFG_TIMEOUT, }; @@ -188,6 +189,15 @@ struct txn_req_get_tree { struct lyd_node *client_results; /* result tree from clients */ }; +struct txn_req_rpc { + char *xpath; /* xpath of rpc/action to invoke */ + uint64_t sent_clients; /* Bitmask of clients sent req to */ + uint64_t recv_clients; /* Bitmask of clients recv reply from */ + uint8_t result_type; /* LYD_FORMAT for results */ + char *errstr; /* error string */ + struct lyd_node *client_results; /* result tree from clients */ +}; + struct mgmt_txn_req { struct mgmt_txn_ctx *txn; enum mgmt_txn_event req_event; @@ -196,6 +206,7 @@ struct mgmt_txn_req { struct mgmt_set_cfg_req *set_cfg; struct mgmt_get_data_req *get_data; struct txn_req_get_tree *get_tree; + struct txn_req_rpc *rpc; struct mgmt_commit_cfg_req commit_cfg; } req; @@ -221,6 +232,7 @@ struct mgmt_txn_ctx { struct event *proc_get_tree; struct event *comm_cfg_timeout; struct event *get_tree_timeout; + struct event *rpc_timeout; struct event *clnup; /* List of backend adapters involved in this transaction */ @@ -253,6 +265,10 @@ struct mgmt_txn_ctx { */ struct mgmt_txn_reqs_head get_tree_reqs; /* + * List of pending rpc requests. + */ + struct mgmt_txn_reqs_head rpc_reqs; + /* * There will always be one commit-config allowed for a given * transaction/session. No need to maintain lists for it. */ @@ -416,6 +432,15 @@ static struct mgmt_txn_req *mgmt_txn_req_alloc(struct mgmt_txn_ctx *txn, " session-id: %" PRIu64, txn_req->req_id, txn->txn_id, txn->session_id); break; + case MGMTD_TXN_PROC_RPC: + txn_req->req.rpc = XCALLOC(MTYPE_MGMTD_TXN_RPC_REQ, + sizeof(struct txn_req_rpc)); + assert(txn_req->req.rpc); + mgmt_txn_reqs_add_tail(&txn->rpc_reqs, txn_req); + __dbg("Added a new RPC req-id: %" PRIu64 " txn-id: %" PRIu64 + " session-id: %" PRIu64, + txn_req->req_id, txn->txn_id, txn->session_id); + break; case MGMTD_TXN_COMMITCFG_TIMEOUT: break; } @@ -506,6 +531,15 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req) XFREE(MTYPE_MGMTD_XPATH, (*txn_req)->req.get_tree->xpath); XFREE(MTYPE_MGMTD_TXN_GETTREE_REQ, (*txn_req)->req.get_tree); break; + case MGMTD_TXN_PROC_RPC: + __dbg("Deleting RPC req-id: %" PRIu64 " txn-id: %" PRIu64, + (*txn_req)->req_id, (*txn_req)->txn->txn_id); + req_list = &(*txn_req)->txn->rpc_reqs; + lyd_free_all((*txn_req)->req.rpc->client_results); + XFREE(MTYPE_MGMTD_ERR, (*txn_req)->req.rpc->errstr); + XFREE(MTYPE_MGMTD_XPATH, (*txn_req)->req.rpc->xpath); + XFREE(MTYPE_MGMTD_TXN_RPC_REQ, (*txn_req)->req.rpc); + break; case MGMTD_TXN_COMMITCFG_TIMEOUT: break; } @@ -880,7 +914,9 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, __dbg("XPATH: %s, Value: '%s'", xpath, value ? value : "NIL"); - clients = mgmt_be_interested_clients(xpath, true); + clients = + mgmt_be_interested_clients(xpath, + MGMT_BE_XPATH_SUBSCR_TYPE_CFG); chg_clients = 0; @@ -1306,6 +1342,33 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn, return ret; } +static int txn_rpc_done(struct mgmt_txn_ctx *txn, struct mgmt_txn_req *txn_req) +{ + struct txn_req_rpc *rpc = txn_req->req.rpc; + uint64_t req_id = txn_req->req_id; + + /* cancel timer and send reply onward */ + EVENT_OFF(txn->rpc_timeout); + + if (rpc->errstr) + mgmt_fe_adapter_txn_error(txn->txn_id, req_id, false, -1, + rpc->errstr); + else if (mgmt_fe_adapter_send_rpc_reply(txn->session_id, txn->txn_id, + req_id, rpc->result_type, + rpc->client_results)) { + __log_err("Error sending the results of RPC for txn-id %" PRIu64 + " req_id %" PRIu64 " to requested type %u", + txn->txn_id, req_id, rpc->result_type); + + (void)mgmt_fe_adapter_txn_error(txn->txn_id, req_id, false, -1, + "Error converting results of RPC"); + } + + /* we're done with the request */ + mgmt_txn_req_free(&txn_req); + + return 0; +} static void txn_get_tree_timeout(struct event *thread) { @@ -1333,6 +1396,31 @@ static void txn_get_tree_timeout(struct event *thread) txn_get_tree_data_done(txn, txn_req); } +static void txn_rpc_timeout(struct event *thread) +{ + struct mgmt_txn_ctx *txn; + struct mgmt_txn_req *txn_req; + + txn_req = (struct mgmt_txn_req *)EVENT_ARG(thread); + txn = txn_req->txn; + + assert(txn); + assert(txn->type == MGMTD_TXN_TYPE_RPC); + + __log_err("Backend timeout txn-id: %" PRIu64 " ending rpc", txn->txn_id); + + /* + * Send a get-tree data reply. + * + * NOTE: The transaction cleanup will be triggered from Front-end + * adapter. + */ + + txn_req->req.rpc->errstr = + XSTRDUP(MTYPE_MGMTD_ERR, "Operation on the backend timed-out"); + txn_rpc_done(txn, txn_req); +} + /* * Send CFG_APPLY_REQs to all the backend client. * @@ -1516,6 +1604,7 @@ static void mgmt_txn_send_getcfg_reply_data(struct mgmt_txn_req *txn_req, case MGMTD_TXN_PROC_SETCFG: case MGMTD_TXN_PROC_COMMITCFG: case MGMTD_TXN_PROC_GETTREE: + case MGMTD_TXN_PROC_RPC: case MGMTD_TXN_COMMITCFG_TIMEOUT: __log_err("Invalid Txn-Req-Event %u", txn_req->req_event); break; @@ -1721,6 +1810,7 @@ static struct mgmt_txn_ctx *mgmt_txn_create_new(uint64_t session_id, mgmt_txn_reqs_init(&txn->set_cfg_reqs); mgmt_txn_reqs_init(&txn->get_cfg_reqs); mgmt_txn_reqs_init(&txn->get_tree_reqs); + mgmt_txn_reqs_init(&txn->rpc_reqs); txn->commit_cfg_req = NULL; txn->refcount = 0; if (!mgmt_txn_mm->next_txn_id) @@ -1890,6 +1980,7 @@ static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn, &txn->comm_cfg_timeout); break; case MGMTD_TXN_PROC_GETTREE: + case MGMTD_TXN_PROC_RPC: assert(!"code bug do not register this event"); break; } @@ -2496,6 +2587,64 @@ reply: return 0; } +int mgmt_txn_send_rpc(uint64_t txn_id, uint64_t req_id, uint64_t clients, + LYD_FORMAT result_type, const char *xpath, + const char *data, size_t data_len) +{ + struct mgmt_txn_ctx *txn; + struct mgmt_txn_req *txn_req; + struct mgmt_msg_rpc *msg; + struct txn_req_rpc *rpc; + uint64_t id; + int ret; + + txn = mgmt_txn_id2ctx(txn_id); + if (!txn) + return -1; + + txn_req = mgmt_txn_req_alloc(txn, req_id, MGMTD_TXN_PROC_RPC); + rpc = txn_req->req.rpc; + rpc->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath); + rpc->result_type = result_type; + + msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0, + MTYPE_MSG_NATIVE_RPC); + msg->refer_id = txn_id; + msg->req_id = req_id; + msg->code = MGMT_MSG_CODE_RPC; + msg->request_type = result_type; + + mgmt_msg_native_xpath_encode(msg, xpath); + if (data) + mgmt_msg_native_append(msg, data, data_len); + + assert(clients); + FOREACH_BE_CLIENT_BITS (id, clients) { + ret = mgmt_be_send_native(id, msg); + if (ret) { + __log_err("Could not send rpc message to backend client %s", + mgmt_be_client_id2name(id)); + continue; + } + + __dbg("Sent rpc req to backend client %s", + mgmt_be_client_id2name(id)); + + /* record that we sent the request to the client */ + rpc->sent_clients |= (1u << id); + } + + mgmt_msg_native_free_msg(msg); + + if (!rpc->sent_clients) + return txn_rpc_done(txn, txn_req); + + event_add_timer(mgmt_txn_tm, txn_rpc_timeout, txn_req, + MGMTD_TXN_RPC_MAX_DELAY_SEC, &txn->rpc_timeout); + + return 0; +} + /* * Error reply from the backend client. */ @@ -2506,6 +2655,7 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter, enum mgmt_be_client_id id = adapter->id; struct mgmt_txn_ctx *txn = mgmt_txn_id2ctx(txn_id); struct txn_req_get_tree *get_tree; + struct txn_req_rpc *rpc; struct mgmt_txn_req *txn_req; if (!txn) { @@ -2518,6 +2668,10 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter, FOREACH_TXN_REQ_IN_LIST (&txn->get_tree_reqs, txn_req) if (txn_req->req_id == req_id) break; + if (!txn_req) + FOREACH_TXN_REQ_IN_LIST (&txn->rpc_reqs, txn_req) + if (txn_req->req_id == req_id) + break; if (!txn_req) { __log_err("Error reply from %s for txn-id %" PRIu64 " cannot find req_id %" PRIu64, @@ -2538,6 +2692,17 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter, if (get_tree->recv_clients != get_tree->sent_clients) return 0; return txn_get_tree_data_done(txn, txn_req); + case MGMTD_TXN_PROC_RPC: + rpc = txn_req->req.rpc; + rpc->recv_clients |= (1u << id); + if (errstr) { + XFREE(MTYPE_MGMTD_ERR, rpc->errstr); + rpc->errstr = XSTRDUP(MTYPE_MGMTD_ERR, errstr); + } + /* check if done yet */ + if (rpc->recv_clients != rpc->sent_clients) + return 0; + return txn_rpc_done(txn, txn_req); /* non-native message events */ case MGMTD_TXN_PROC_SETCFG: @@ -2625,6 +2790,77 @@ int mgmt_txn_notify_tree_data_reply(struct mgmt_be_client_adapter *adapter, return txn_get_tree_data_done(txn, txn_req); } +int mgmt_txn_notify_rpc_reply(struct mgmt_be_client_adapter *adapter, + struct mgmt_msg_rpc_reply *reply_msg, + size_t msg_len) +{ + uint64_t txn_id = reply_msg->refer_id; + uint64_t req_id = reply_msg->req_id; + enum mgmt_be_client_id id = adapter->id; + struct mgmt_txn_ctx *txn = mgmt_txn_id2ctx(txn_id); + struct mgmt_txn_req *txn_req; + struct txn_req_rpc *rpc; + struct lyd_node *tree; + size_t data_len = msg_len - sizeof(*reply_msg); + LY_ERR err = LY_SUCCESS; + + if (!txn) { + __log_err("RPC reply from %s for a missing txn-id %" PRIu64, + adapter->name, txn_id); + return -1; + } + + /* Find the request. */ + FOREACH_TXN_REQ_IN_LIST (&txn->rpc_reqs, txn_req) + if (txn_req->req_id == req_id) + break; + if (!txn_req) { + __log_err("RPC reply from %s for txn-id %" PRIu64 + " missing req_id %" PRIu64, + adapter->name, txn_id, req_id); + return -1; + } + + rpc = txn_req->req.rpc; + + tree = NULL; + if (data_len) + err = yang_parse_rpc(rpc->xpath, reply_msg->result_type, + reply_msg->data, true, &tree); + if (err) { + __log_err("RPC reply from %s for txn-id %" PRIu64 + " req_id %" PRIu64 " error parsing result of type %u: %s", + adapter->name, txn_id, req_id, reply_msg->result_type, + ly_strerrcode(err)); + } + if (!err && tree) { + if (!rpc->client_results) + rpc->client_results = tree; + else + err = lyd_merge_siblings(&rpc->client_results, tree, + LYD_MERGE_DESTRUCT); + if (err) { + __log_err("RPC reply from %s for txn-id %" PRIu64 + " req_id %" PRIu64 " error merging result: %s", + adapter->name, txn_id, req_id, + ly_strerrcode(err)); + } + } + if (err) { + XFREE(MTYPE_MGMTD_ERR, rpc->errstr); + rpc->errstr = XSTRDUP(MTYPE_MGMTD_ERR, + "Cannot parse result from the backend"); + } + + rpc->recv_clients |= (1u << id); + + /* check if done yet */ + if (rpc->recv_clients != rpc->sent_clients) + return 0; + + return txn_rpc_done(txn, txn_req); +} + void mgmt_txn_status_write(struct vty *vty) { struct mgmt_txn_ctx *txn; diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h index aeb74469f1..b6ca288675 100644 --- a/mgmtd/mgmt_txn.h +++ b/mgmtd/mgmt_txn.h @@ -21,6 +21,7 @@ #define MGMTD_TXN_CFG_COMMIT_MAX_DELAY_SEC 600 #define MGMTD_TXN_GET_TREE_MAX_DELAY_SEC 600 +#define MGMTD_TXN_RPC_MAX_DELAY_SEC 60 #define MGMTD_TXN_CLEANUP_DELAY_USEC 10 @@ -48,7 +49,8 @@ struct mgmt_edit_req; enum mgmt_txn_type { MGMTD_TXN_TYPE_NONE = 0, MGMTD_TXN_TYPE_CONFIG, - MGMTD_TXN_TYPE_SHOW + MGMTD_TXN_TYPE_SHOW, + MGMTD_TXN_TYPE_RPC, }; static inline const char *mgmt_txn_type2str(enum mgmt_txn_type type) @@ -60,6 +62,8 @@ static inline const char *mgmt_txn_type2str(enum mgmt_txn_type type) return "CONFIG"; case MGMTD_TXN_TYPE_SHOW: return "SHOW"; + case MGMTD_TXN_TYPE_RPC: + return "RPC"; } return "Unknown"; @@ -246,6 +250,25 @@ mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id, Mgmtd__DatastoreId ds_id, LYD_FORMAT request_type, uint8_t flags, uint8_t operation, const char *xpath, const char *data); +/** + * Send RPC request. + * + * Args: + * txn_id: Transaction identifier. + * req_id: FE client request identifier. + * clients: Bitmask of clients to send RPC to. + * result_type: LYD_FORMAT result format. + * xpath: The xpath of the RPC. + * data: The input parameters data tree. + * data_len: The length of the input parameters data. + * + * Return: + * 0 on success. + */ +extern int mgmt_txn_send_rpc(uint64_t txn_id, uint64_t req_id, uint64_t clients, + LYD_FORMAT result_type, const char *xpath, + const char *data, size_t data_len); + /* * Notifiy backend adapter on connection. */ @@ -312,6 +335,18 @@ extern int mgmt_txn_notify_tree_data_reply(struct mgmt_be_client_adapter *adapte struct mgmt_msg_tree_data *data_msg, size_t msg_len); +/** + * Process a reply from a backend client to our RPC request + * + * Args: + * adapter: The adapter that received the result. + * reply_msg: The message from the backend. + * msg_len: Total length of the message. + */ +extern int mgmt_txn_notify_rpc_reply(struct mgmt_be_client_adapter *adapter, + struct mgmt_msg_rpc_reply *reply_msg, + size_t msg_len); + /* * Dump transaction status to vty. */ diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index 61d0760e05..8ccb463577 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -296,6 +296,21 @@ DEFPY(mgmt_edit, mgmt_edit_cmd, return CMD_SUCCESS; } +DEFPY(mgmt_rpc, mgmt_rpc_cmd, + "mgmt rpc XPATH [json|xml]$fmt [DATA]", + MGMTD_STR + "Invoke RPC\n" + "XPath expression specifying the YANG data path\n" + "JSON input format (default)\n" + "XML input format\n" + "Input data tree\n") +{ + LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON; + + vty_mgmt_send_rpc_req(vty, format, xpath, data); + return CMD_SUCCESS; +} + DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd, "show mgmt get-config [candidate|operational|running]$dsname WORD$path", SHOW_STR MGMTD_STR @@ -702,6 +717,7 @@ void mgmt_vty_init(void) install_element(CONFIG_NODE, &mgmt_remove_config_data_cmd); install_element(CONFIG_NODE, &mgmt_replace_config_data_cmd); install_element(CONFIG_NODE, &mgmt_edit_cmd); + install_element(CONFIG_NODE, &mgmt_rpc_cmd); install_element(CONFIG_NODE, &mgmt_load_config_cmd); install_element(CONFIG_NODE, &mgmt_save_config_cmd); install_element(CONFIG_NODE, &mgmt_rollback_cmd); diff --git a/mgmtd/subdir.am b/mgmtd/subdir.am index 1624c6e4f9..14544c4f05 100644 --- a/mgmtd/subdir.am +++ b/mgmtd/subdir.am @@ -16,6 +16,7 @@ clippy_scan += \ lib_LTLIBRARIES += mgmtd/libmgmt_be_nb.la mgmtd_libmgmt_be_nb_la_SOURCES = \ + mgmtd/mgmt_be_nb.c \ zebra/zebra_cli.c \ # end nodist_mgmtd_libmgmt_be_nb_la_SOURCES = \ @@ -61,7 +62,6 @@ mgmtd_mgmtd_SOURCES = \ nodist_mgmtd_mgmtd_SOURCES = \ yang/frr-zebra.yang.c \ yang/frr-zebra-route-map.yang.c \ - yang/ietf/ietf-netconf-acm.yang.c \ yang/ietf/ietf-netconf.yang.c \ yang/ietf/ietf-netconf-with-defaults.yang.c \ # nothing diff --git a/mlag/mlag_pb.c b/mlag/mlag_pb.c new file mode 100644 index 0000000000..01c4f0b319 --- /dev/null +++ b/mlag/mlag_pb.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: ISC +/* + * libmlag_pb library stub + */ + +#include "config.h" +#include "xref.h" + +XREF_SETUP(); diff --git a/mlag/subdir.am b/mlag/subdir.am index 376eea8bc9..aa30d33431 100644 --- a/mlag/subdir.am +++ b/mlag/subdir.am @@ -5,6 +5,7 @@ endif mlag_libmlag_pb_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0 mlag_libmlag_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS) mlag_libmlag_pb_la_SOURCES = \ + mlag/mlag_pb.c \ # end nodist_mlag_libmlag_pb_la_SOURCES = \ diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c index acd3b7df97..f779f93486 100644 --- a/nhrpd/nhrp_nhs.c +++ b/nhrpd/nhrp_nhs.c @@ -169,9 +169,15 @@ static void nhrp_reg_send_req(struct event *t) struct nhrp_cie_header *cie; if (!nhrp_peer_check(r->peer, 2)) { - debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU", - &r->peer->vc->remote.nbma); - event_add_timer(master, nhrp_reg_send_req, r, 120, + int renewtime = if_ad->holdtime / 4; + /* RFC 2332 5.2.0.1 says "a retry is sent after an appropriate + * interval." Using holdtime/4, to be shorter than + * recommended renew time (holdtime/3), see RFC2332 Sec 5.2.3 + */ + debugf(NHRP_DEBUG_COMMON, + "NHS: Waiting link for %pSU, retrying in %d seconds", + &r->peer->vc->remote.nbma, renewtime); + event_add_timer(master, nhrp_reg_send_req, r, renewtime, &r->t_register); return; } diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f4202a4a29..d3ff759d33 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -1275,8 +1275,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) continue; } - list_delete_all_node(old_route->nh_list); - ospf6_route_copy_nexthops(old_route, route); old_entry_updated = true; for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, @@ -1330,6 +1328,15 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) } } + /* We added a path or updated a path's nexthops above, + * recompute (old) route nexthops by merging all path nexthops + */ + list_delete_all_node(old_route->nh_list); + for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { + ospf6_merge_nexthops(old_route->nh_list, + o_path->nh_list); + } + if (is_debug) zlog_debug( "%s: Update route: %s %p old cost %u new cost %u nh %u", diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 7bb1619133..52686ed49f 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -33,11 +33,12 @@ struct ospf6_inter_router_lsa { uint32_t router_id; }; -#define OSPF6_ABR_SUMMARY_METRIC(E) (ntohl ((E)->metric & htonl (0x00ffffff))) +#define OSPF6_ABR_SUMMARY_METRIC(E) \ + (ntohl((E)->metric & htonl(OSPF6_EXT_PATH_METRIC_MAX))) #define OSPF6_ABR_SUMMARY_METRIC_SET(E, C) \ { \ (E)->metric &= htonl(0x00000000); \ - (E)->metric |= htonl(0x00ffffff) & htonl(C); \ + (E)->metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & htonl(C); \ } #define OSPF6_ABR_RANGE_CLEAR_COST(range) (range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index d1c2b8bfc9..701704cdc8 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -14,6 +14,7 @@ #include "table.h" #include "plist.h" #include "frrevent.h" +#include "frrstr.h" #include "linklist.h" #include "lib/northbound_cli.h" @@ -1426,10 +1427,9 @@ static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6, } void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, - struct prefix *prefix, - unsigned int nexthop_num, - const struct in6_addr *nexthop, - route_tag_t tag, struct ospf6 *ospf6) + struct prefix *prefix, unsigned int nexthop_num, + const struct in6_addr *nexthop, route_tag_t tag, + struct ospf6 *ospf6, uint32_t metric) { route_map_result_t ret; struct ospf6_route troute; @@ -1472,6 +1472,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, if (ROUTEMAP(red)) { troute.route_option = &tinfo; troute.ospf6 = ospf6; + troute.path.redistribute_cost = metric; tinfo.ifindex = ifindex; tinfo.tag = tag; @@ -1924,7 +1925,7 @@ static void ospf6_redistribute_default_set(struct ospf6 *ospf6, int originate) case DEFAULT_ORIGINATE_ALWAYS: ospf6_asbr_redistribute_add(DEFAULT_ROUTE, 0, (struct prefix *)&p, 0, &nexthop, 0, - ospf6); + ospf6, 0); break; } } @@ -2153,25 +2154,81 @@ static const struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_free, }; +struct ospf6_metric { + enum { metric_increment, metric_decrement, metric_absolute } type; + bool used; + uint32_t metric; +}; + static enum route_map_cmd_result_t ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix, void *object) { - char *metric = rule; - struct ospf6_route *route = object; + struct ospf6_metric *metric; + struct ospf6_route *route; + + /* Fetch routemap's rule information. */ + metric = rule; + route = object; + + /* Set metric out value. */ + if (!metric->used) + return RMAP_OKAY; + + if (route->path.redistribute_cost > OSPF6_EXT_PATH_METRIC_MAX) + route->path.redistribute_cost = OSPF6_EXT_PATH_METRIC_MAX; + + if (metric->type == metric_increment) { + route->path.cost = route->path.redistribute_cost + + metric->metric; + + /* Check overflow */ + if (route->path.cost > OSPF6_EXT_PATH_METRIC_MAX || + route->path.cost < metric->metric) + route->path.cost = OSPF6_EXT_PATH_METRIC_MAX; + } else if (metric->type == metric_decrement) { + route->path.cost = route->path.redistribute_cost - + metric->metric; + + /* Check overflow */ + if (route->path.cost == 0 || + route->path.cost > route->path.redistribute_cost) + route->path.cost = 1; + } else if (metric->type == metric_absolute) + route->path.cost = metric->metric; - route->path.cost = atoi(metric); return RMAP_OKAY; } static void *ospf6_routemap_rule_set_metric_compile(const char *arg) { - uint32_t metric; - char *endp; - metric = strtoul(arg, &endp, 0); - if (metric > OSPF_LS_INFINITY || *endp != '\0') - return NULL; - return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + struct ospf6_metric *metric; + + metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*metric)); + metric->used = false; + + if (all_digit(arg)) + metric->type = metric_absolute; + + if ((arg[0] == '+') && all_digit(arg + 1)) { + metric->type = metric_increment; + arg++; + } + + if ((arg[0] == '-') && all_digit(arg + 1)) { + metric->type = metric_decrement; + arg++; + } + + metric->metric = strtoul(arg, NULL, 10); + + if (metric->metric > OSPF6_EXT_PATH_METRIC_MAX) + metric->metric = OSPF6_EXT_PATH_METRIC_MAX; + + if (metric->metric) + metric->used = true; + + return metric; } static void ospf6_routemap_rule_set_metric_free(void *rule) diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index d63e467278..21e6d898e8 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -94,11 +94,13 @@ struct ospf6_as_external_lsa { #define OSPF6_ASBR_BIT_F ntohl (0x02000000) #define OSPF6_ASBR_BIT_E ntohl (0x04000000) -#define OSPF6_ASBR_METRIC(E) (ntohl ((E)->bits_metric & htonl (0x00ffffff))) +#define OSPF6_ASBR_METRIC(E) \ + (ntohl((E)->bits_metric & htonl(OSPF6_EXT_PATH_METRIC_MAX))) #define OSPF6_ASBR_METRIC_SET(E, C) \ { \ - (E)->bits_metric &= htonl(0xff000000); \ - (E)->bits_metric |= htonl(0x00ffffff) & htonl(C); \ + (E)->bits_metric &= htonl(~OSPF6_EXT_PATH_METRIC_MAX); \ + (E)->bits_metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & \ + htonl(C); \ } extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa); @@ -115,7 +117,8 @@ extern void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, struct prefix *prefix, unsigned int nexthop_num, const struct in6_addr *nexthop, - route_tag_t tag, struct ospf6 *ospf6); + route_tag_t tag, struct ospf6 *ospf6, + uint32_t metric); extern void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex, struct prefix *prefix, struct ospf6 *ospf6); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index b9dace2fe8..7f813ce3cc 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -455,9 +455,9 @@ void ospf6_interface_connected_route_update(struct interface *ifp) } } - if (oi->state == OSPF6_INTERFACE_LOOPBACK || - oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT || - oi->state == OSPF6_INTERFACE_POINTTOPOINT) { + if (oi->type == OSPF_IFTYPE_LOOPBACK || + oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF_IFTYPE_POINTOPOINT) { struct ospf6_route *la_route; la_route = ospf6_route_create(oi->area->ospf6); @@ -475,10 +475,10 @@ void ospf6_interface_connected_route_update(struct interface *ifp) ospf6_route_add(la_route, oi->route_connected); } - if (oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT && + if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT && !oi->p2xp_connected_pfx_include) continue; - if (oi->state == OSPF6_INTERFACE_POINTTOPOINT && + if (oi->type == OSPF_IFTYPE_POINTOPOINT && oi->p2xp_connected_pfx_exclude) continue; @@ -792,8 +792,8 @@ void interface_up(struct event *thread) return; } - /* Recompute cost */ - ospf6_interface_recalculate_cost(oi); + /* Recompute cost & update connected LSAs */ + ospf6_interface_force_recalculate_cost(oi); /* if already enabled, do nothing */ if (oi->state > OSPF6_INTERFACE_DOWN) { @@ -1395,10 +1395,17 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id, } /* show interface */ -DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd, +DEFUN(show_ipv6_ospf6_interface, + show_ipv6_ospf6_interface_ifname_cmd, "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR) + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + IFNAME_STR + JSON_STR) { int idx_ifname = 4; int intf_idx = 5; @@ -1598,11 +1605,18 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc, } /* show interface */ -DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, +DEFUN(show_ipv6_ospf6_interface_traffic, + show_ipv6_ospf6_interface_traffic_cmd, "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR - "Protocol Packet counters\n" IFNAME_STR JSON_STR) + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + "Protocol Packet counters\n" + IFNAME_STR + JSON_STR) { struct ospf6 *ospf6; struct listnode *node; @@ -1631,17 +1645,21 @@ DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd, DEFUN(show_ipv6_ospf6_interface_ifname_prefix, show_ipv6_ospf6_interface_ifname_prefix_cmd, - "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\ - [<\ - detail\ - |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ - >] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR IFNAME_STR + "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix " + "[<detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]>] [json]", + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR IFNAME_STR "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" JSON_STR) + "Display details of the prefixes\n" + OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR + OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" + JSON_STR) { int idx_ifname = 4; int idx_prefix = 6; @@ -1693,17 +1711,23 @@ DEFUN(show_ipv6_ospf6_interface_ifname_prefix, return CMD_SUCCESS; } -DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, - "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\ - [<\ - detail\ - |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ - >] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR "Display connected prefixes to advertise\n" - "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR - OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR - "Display details of the prefixes\n" JSON_STR) +DEFUN(show_ipv6_ospf6_interface_prefix, + show_ipv6_ospf6_interface_prefix_cmd, + "show ipv6 ospf6 [vrf <NAME|all>] interface prefix " + "[<detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]>] [json]", + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + "All VRFs\n" + INTERFACE_STR + "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" + OSPF6_ROUTE_ADDRESS_STR + OSPF6_ROUTE_PREFIX_STR + OSPF6_ROUTE_MATCH_STR + "Display details of the prefixes\n" + JSON_STR) { struct vrf *vrf = NULL; int idx_prefix = 5; @@ -1802,11 +1826,14 @@ void ospf6_interface_stop(struct ospf6_interface *oi) } /* interface variable set command */ -DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd, - "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>", - IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN (ipv6_ospf6_area, + ipv6_ospf6_area_cmd, + "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>", + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1840,11 +1867,15 @@ DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd, return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd, - "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]", - NO_STR IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN (no_ipv6_ospf6_area, + no_ipv6_ospf6_area_cmd, + "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]", + NO_STR + IP6_STR + OSPF6_STR + "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1864,9 +1895,14 @@ DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", - IP6_STR OSPF6_STR "Interface MTU\n" - "OSPFv3 Interface MTU\n") +DEFUN (ipv6_ospf6_ifmtu, + ipv6_ospf6_ifmtu_cmd, + "ipv6 ospf6 ifmtu (1-65535)", + IP6_STR + OSPF6_STR + "Interface MTU\n" + "OSPFv3 Interface MTU\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1915,10 +1951,15 @@ DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd, - "no ipv6 ospf6 ifmtu [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Interface MTU\n" - "OSPFv3 Interface MTU\n") +DEFUN (no_ipv6_ospf6_ifmtu, + no_ipv6_ospf6_ifmtu_cmd, + "no ipv6 ospf6 ifmtu [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interface MTU\n" + "OSPFv3 Interface MTU\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1956,9 +1997,13 @@ DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)", - IP6_STR OSPF6_STR "Interface cost\n" - "Outgoing metric of this interface\n") +DEFUN (ipv6_ospf6_cost, + ipv6_ospf6_cost_cmd, + "ipv6 ospf6 cost (1-65535)", + IP6_STR + OSPF6_STR + "Interface cost\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1989,10 +2034,14 @@ DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, - "no ipv6 ospf6 cost [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n" - "Outgoing metric of this interface\n") +DEFUN (no_ipv6_ospf6_cost, + no_ipv6_ospf6_cost_cmd, + "no ipv6 ospf6 cost [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Calculate interface cost from bandwidth\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2010,11 +2059,12 @@ DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, return CMD_SUCCESS; } -DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd, - "auto-cost reference-bandwidth (1-4294967)", - "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN (auto_cost_reference_bandwidth, + auto_cost_reference_bandwidth_cmd, + "auto-cost reference-bandwidth (1-4294967)", + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); int idx_number = 2; @@ -2041,11 +2091,13 @@ DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd, return CMD_SUCCESS; } -DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd, - "no auto-cost reference-bandwidth [(1-4294967)]", - NO_STR "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN (no_auto_cost_reference_bandwidth, + no_auto_cost_reference_bandwidth_cmd, + "no auto-cost reference-bandwidth [(1-4294967)]", + NO_STR + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); struct ospf6_area *oa; @@ -2064,10 +2116,11 @@ DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd, } -DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd, - "write-multiplier (1-100)", - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN (ospf6_write_multiplier, + ospf6_write_multiplier_cmd, + "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); uint32_t write_oi_count; @@ -2082,10 +2135,12 @@ DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd, return CMD_SUCCESS; } -DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd, - "no write-multiplier (1-100)", - NO_STR "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN (no_ospf6_write_multiplier, + no_ospf6_write_multiplier_cmd, + "no write-multiplier (1-100)", + NO_STR + "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); @@ -2093,9 +2148,13 @@ DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, - "ipv6 ospf6 hello-interval (1-65535)", - IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) +DEFUN (ipv6_ospf6_hellointerval, + ipv6_ospf6_hellointerval_cmd, + "ipv6 ospf6 hello-interval (1-65535)", + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2123,15 +2182,23 @@ DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_hellointerval, no_ipv6_ospf6_hellointerval_cmd, - "no ipv6 ospf6 hello-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) +ALIAS (ipv6_ospf6_hellointerval, + no_ipv6_ospf6_hellointerval_cmd, + "no ipv6 ospf6 hello-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between HELLO packets\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, - "ipv6 ospf6 dead-interval (1-65535)", - IP6_STR OSPF6_STR - "Interval time after which a neighbor is declared down\n" SECONDS_STR) +DEFUN (ipv6_ospf6_deadinterval, + ipv6_ospf6_deadinterval_cmd, + "ipv6 ospf6 dead-interval (1-65535)", + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2149,16 +2216,23 @@ DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_deadinterval, no_ipv6_ospf6_deadinterval_cmd, - "no ipv6 ospf6 dead-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR - "Interval time after which a neighbor is declared down\n" SECONDS_STR) +ALIAS (ipv6_ospf6_deadinterval, + no_ipv6_ospf6_deadinterval_cmd, + "no ipv6 ospf6 dead-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Interval time after which a neighbor is declared down\n" + SECONDS_STR) -DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, +DEFPY(ipv6_ospf6_gr_hdelay, + ipv6_ospf6_gr_hdelay_cmd, "ipv6 ospf6 graceful-restart hello-delay (1-1800)", - IP6_STR OSPF6_STR "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + IP6_STR + OSPF6_STR + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2173,11 +2247,15 @@ DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, return CMD_SUCCESS; } -DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, +DEFPY(no_ipv6_ospf6_gr_hdelay, + no_ipv6_ospf6_gr_hdelay_cmd, "no ipv6 ospf6 graceful-restart hello-delay [(1-1800)]", - NO_STR IP6_STR OSPF6_STR "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + NO_STR + IP6_STR + OSPF6_STR + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2194,9 +2272,13 @@ DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, } /* interface variable set command */ -DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, - "ipv6 ospf6 transmit-delay (1-3600)", - IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) +DEFUN (ipv6_ospf6_transmitdelay, + ipv6_ospf6_transmitdelay_cmd, + "ipv6 ospf6 transmit-delay (1-3600)", + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2214,15 +2296,23 @@ DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_transmitdelay, no_ipv6_ospf6_transmitdelay_cmd, - "no ipv6 ospf6 transmit-delay [(1-3600)]", - NO_STR IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) +ALIAS (ipv6_ospf6_transmitdelay, + no_ipv6_ospf6_transmitdelay_cmd, + "no ipv6 ospf6 transmit-delay [(1-3600)]", + NO_STR + IP6_STR + OSPF6_STR + "Link state transmit delay\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, - "ipv6 ospf6 retransmit-interval (1-65535)", - IP6_STR OSPF6_STR - "Time between retransmitting lost link state advertisements\n" SECONDS_STR) +DEFUN (ipv6_ospf6_retransmitinterval, + ipv6_ospf6_retransmitinterval_cmd, + "ipv6 ospf6 retransmit-interval (1-65535)", + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2240,16 +2330,23 @@ DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_retransmitinterval, no_ipv6_ospf6_retransmitinterval_cmd, - "no ipv6 ospf6 retransmit-interval [(1-65535)]", - NO_STR IP6_STR OSPF6_STR - "Time between retransmitting lost link state advertisements\n" SECONDS_STR) +ALIAS (ipv6_ospf6_retransmitinterval, + no_ipv6_ospf6_retransmitinterval_cmd, + "no ipv6 ospf6 retransmit-interval [(1-65535)]", + NO_STR + IP6_STR + OSPF6_STR + "Time between retransmitting lost link state advertisements\n" + SECONDS_STR) /* interface variable set command */ -DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, - "ipv6 ospf6 priority (0-255)", - IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n") +DEFUN (ipv6_ospf6_priority, + ipv6_ospf6_priority_cmd, + "ipv6 ospf6 priority (0-255)", + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2275,15 +2372,22 @@ DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_priority, no_ipv6_ospf6_priority_cmd, - "no ipv6 ospf6 priority [(0-255)]", - NO_STR IP6_STR OSPF6_STR "Router priority\n" - "Priority value\n") +ALIAS (ipv6_ospf6_priority, + no_ipv6_ospf6_priority_cmd, + "no ipv6 ospf6 priority [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Router priority\n" + "Priority value\n") -DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, - "ipv6 ospf6 instance-id (0-255)", - IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n") +DEFUN (ipv6_ospf6_instance, + ipv6_ospf6_instance_cmd, + "ipv6 ospf6 instance-id (0-255)", + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2301,14 +2405,22 @@ DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_instance, no_ipv6_ospf6_instance_cmd, - "no ipv6 ospf6 instance-id [(0-255)]", - NO_STR IP6_STR OSPF6_STR "Instance ID for this interface\n" - "Instance ID value\n") +ALIAS (ipv6_ospf6_instance, + no_ipv6_ospf6_instance_cmd, + "no ipv6 ospf6 instance-id [(0-255)]", + NO_STR + IP6_STR + OSPF6_STR + "Instance ID for this interface\n" + "Instance ID value\n") -DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", - IP6_STR OSPF6_STR - "Passive interface; no adjacency will be formed on this interface\n") +DEFUN (ipv6_ospf6_passive, + ipv6_ospf6_passive_cmd, + "ipv6 ospf6 passive", + IP6_STR + OSPF6_STR + "Passive interface; no adjacency will be formed on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2334,9 +2446,14 @@ DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive", - NO_STR IP6_STR OSPF6_STR - "passive interface: No Adjacency will be formed on this I/F\n") +DEFUN (no_ipv6_ospf6_passive, + no_ipv6_ospf6_passive_cmd, + "no ipv6 ospf6 passive", + NO_STR + IP6_STR + OSPF6_STR + "passive interface: No Adjacency will be formed on this I/F\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2359,8 +2476,13 @@ DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive", return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore", - IP6_STR OSPF6_STR "Disable MTU mismatch detection on this interface\n") +DEFUN (ipv6_ospf6_mtu_ignore, + ipv6_ospf6_mtu_ignore_cmd, + "ipv6 ospf6 mtu-ignore", + IP6_STR + OSPF6_STR + "Disable MTU mismatch detection on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2376,10 +2498,14 @@ DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore", return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd, - "no ipv6 ospf6 mtu-ignore", - NO_STR IP6_STR OSPF6_STR - "Disable MTU mismatch detection on this interface\n") +DEFUN (no_ipv6_ospf6_mtu_ignore, + no_ipv6_ospf6_mtu_ignore_cmd, + "no ipv6 ospf6 mtu-ignore", + NO_STR + IP6_STR + OSPF6_STR + "Disable MTU mismatch detection on this interface\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2395,11 +2521,14 @@ DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd, +DEFUN(ipv6_ospf6_advertise_prefix_list, + ipv6_ospf6_advertise_prefix_list_cmd, "ipv6 ospf6 advertise prefix-list PREFIXLIST6_NAME", - IP6_STR OSPF6_STR "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n") + IP6_STR + OSPF6_STR + "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_word = 4; @@ -2432,9 +2561,12 @@ DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd, DEFUN(no_ipv6_ospf6_advertise_prefix_list, no_ipv6_ospf6_advertise_prefix_list_cmd, "no ipv6 ospf6 advertise prefix-list [PREFIXLIST6_NAME]", - NO_STR IP6_STR OSPF6_STR "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n") + NO_STR + IP6_STR + OSPF6_STR + "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2462,12 +2594,16 @@ DEFUN(no_ipv6_ospf6_advertise_prefix_list, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd, - "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>", - IP6_STR OSPF6_STR "Network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n" - "Specify OSPF6 point-to-multipoint network\n") +DEFUN (ipv6_ospf6_network, + ipv6_ospf6_network_cmd, + "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>", + IP6_STR + OSPF6_STR + "Network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 point-to-multipoint network\n" + ) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_network = 3; @@ -2506,11 +2642,16 @@ DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd, return CMD_SUCCESS; } -DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, - "no ipv6 ospf6 network [<broadcast|point-to-point>]", - NO_STR IP6_STR OSPF6_STR "Set default network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n") +DEFUN (no_ipv6_ospf6_network, + no_ipv6_ospf6_network_cmd, + "no ipv6 ospf6 network [<broadcast|point-to-point|point-to-multipoint>]", + NO_STR + IP6_STR + OSPF6_STR + "Set default network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 point-to-multipoint network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2537,11 +2678,14 @@ DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd, - "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Only form adjacencies with explicitly configured neighbors\n") +DEFPY (ipv6_ospf6_p2xp_only_cfg_neigh, + ipv6_ospf6_p2xp_only_cfg_neigh_cmd, + "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Only form adjacencies with explicitly configured neighbors\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2561,11 +2705,14 @@ DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd, - "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Do not send multicast hellos\n") +DEFPY (ipv6_ospf6_p2xp_no_multicast_hello, + ipv6_ospf6_p2xp_no_multicast_hello_cmd, + "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Do not send multicast hellos\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2585,13 +2732,16 @@ DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd, - "[no] ipv6 ospf6 p2p-p2mp connected-prefixes <include$incl|exclude$excl>", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Adjust handling of directly connected prefixes\n" - "Advertise prefixes and own /128 (default for PtP)\n" - "Ignore, only advertise own /128 (default for PtMP)\n") +DEFPY (ipv6_ospf6_p2xp_connected_pfx, + ipv6_ospf6_p2xp_connected_pfx_cmd, + "[no] ipv6 ospf6 p2p-p2mp connected-prefixes <include$incl|exclude$excl>", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n" + "Advertise prefixes and own /128 (default for PtP)\n" + "Ignore, only advertise own /128 (default for PtMP)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -2619,11 +2769,14 @@ DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd, return CMD_SUCCESS; } -ALIAS(ipv6_ospf6_p2xp_connected_pfx, no_ipv6_ospf6_p2xp_connected_pfx_cmd, - "no ipv6 ospf6 p2p-p2mp connected-prefixes", - NO_STR IP6_STR OSPF6_STR - "Point-to-point and Point-to-Multipoint parameters\n" - "Adjust handling of directly connected prefixes\n") +ALIAS (ipv6_ospf6_p2xp_connected_pfx, + no_ipv6_ospf6_p2xp_connected_pfx_cmd, + "no ipv6 ospf6 p2p-p2mp connected-prefixes", + NO_STR + IP6_STR + OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n") static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) @@ -2873,9 +3026,16 @@ void ospf6_interface_clear(struct interface *ifp) } /* Clear interface */ -DEFUN(clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd, - "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", - CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR) +DEFUN (clear_ipv6_ospf6_interface, + clear_ipv6_ospf6_interface_cmd, + "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", + CLEAR_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR + INTERFACE_STR + IFNAME_STR + ) { struct vrf *vrf; int idx_vrf = 3; @@ -2916,16 +3076,26 @@ void install_element_ospf6_clear_interface(void) install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); } -DEFUN(debug_ospf6_interface, debug_ospf6_interface_cmd, "debug ospf6 interface", - DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") +DEFUN (debug_ospf6_interface, + debug_ospf6_interface_cmd, + "debug ospf6 interface", + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Interface\n" + ) { OSPF6_DEBUG_INTERFACE_ON(); return CMD_SUCCESS; } -DEFUN(no_debug_ospf6_interface, no_debug_ospf6_interface_cmd, - "no debug ospf6 interface", - NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") +DEFUN (no_debug_ospf6_interface, + no_debug_ospf6_interface_cmd, + "no debug ospf6 interface", + NO_STR + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Interface\n" + ) { OSPF6_DEBUG_INTERFACE_OFF(); return CMD_SUCCESS; @@ -2962,9 +3132,11 @@ void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data) DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, ipv6_ospf6_intf_auth_trailer_keychain_cmd, "ipv6 ospf6 authentication keychain KEYCHAIN_NAME", - IP6_STR OSPF6_STR "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + IP6_STR + OSPF6_STR + "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int keychain_idx = 4; @@ -2994,9 +3166,12 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain, no_ipv6_ospf6_intf_auth_trailer_keychain_cmd, "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]", - NO_STR IP6_STR OSPF6_STR "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + NO_STR + IP6_STR + OSPF6_STR + "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -3018,21 +3193,24 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain, return CMD_SUCCESS; } -DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd, +DEFUN(ipv6_ospf6_intf_auth_trailer_key, + ipv6_ospf6_intf_auth_trailer_key_cmd, "ipv6 ospf6 authentication key-id (1-65535) hash-algo " "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> " "key WORD", - IP6_STR OSPF6_STR "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + IP6_STR + OSPF6_STR + "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int key_id_idx = 4; @@ -3077,17 +3255,20 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_key, "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo " "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> " "key WORD]", - NO_STR IP6_STR OSPF6_STR "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + NO_STR + IP6_STR + OSPF6_STR + "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 8b7afd89a7..0e44f2a142 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -704,10 +704,14 @@ static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost) #include "ospf6d/ospf6_neighbor_clippy.c" #endif -DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n") +DEFPY (ipv6_ospf6_p2xp_neigh, + ipv6_ospf6_p2xp_neigh_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -745,12 +749,16 @@ DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd, return CMD_SUCCESS; } -DEFPY(ipv6_ospf6_p2xp_neigh_cost, ipv6_ospf6_p2xp_neigh_cost_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n" - "Outgoing metric for this neighbor\n" - "Outgoing metric for this neighbor\n") +DEFPY (ipv6_ospf6_p2xp_neigh_cost, + ipv6_ospf6_p2xp_neigh_cost_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n" + "Outgoing metric for this neighbor\n" + "Outgoing metric for this neighbor\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -821,13 +829,16 @@ static void p2xp_unicast_hello_send(struct event *event) ospf6_hello_send_addr(oi, &p2xp_cfg->addr); } -DEFPY(ipv6_ospf6_p2xp_neigh_poll_interval, - ipv6_ospf6_p2xp_neigh_poll_interval_cmd, - "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)", - NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" - "Neighbor link-local address\n" - "Send unicast hellos to neighbor when down\n" - "Unicast hello interval when down (seconds)\n") +DEFPY (ipv6_ospf6_p2xp_neigh_poll_interval, + ipv6_ospf6_p2xp_neigh_poll_interval_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)", + NO_STR + IP6_STR + OSPF6_STR + "Configure static neighbor\n" + "Neighbor link-local address\n" + "Send unicast hellos to neighbor when down\n" + "Unicast hello interval when down (seconds)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi = ifp->info; @@ -1340,13 +1351,18 @@ static void ospf6_neighbor_show_detail_common(struct vty *vty, } } -DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd, +DEFUN(show_ipv6_ospf6_neighbor, + show_ipv6_ospf6_neighbor_cmd, "show ipv6 ospf6 [vrf <NAME|all>] neighbor [<detail|drchoice>] [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR "All VRFs\n" "Neighbor list\n" "Display details\n" - "Display DR choices\n" JSON_STR) + "Display DR choices\n" + JSON_STR) { struct ospf6 *ospf6; struct listnode *node; @@ -1415,12 +1431,17 @@ static int ospf6_neighbor_show_common(struct vty *vty, int argc, return CMD_SUCCESS; } -DEFUN(show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd, +DEFUN(show_ipv6_ospf6_neighbor_one, + show_ipv6_ospf6_neighbor_one_cmd, "show ipv6 ospf6 [vrf <NAME|all>] neighbor A.B.C.D [json]", - SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR + SHOW_STR + IP6_STR + OSPF6_STR + VRF_CMD_HELP_STR "All VRFs\n" "Neighbor list\n" - "Specify Router-ID as IPv4 address notation\n" JSON_STR) + "Specify Router-ID as IPv4 address notation\n" + JSON_STR) { int idx_ipv4 = 4; struct ospf6 *ospf6; @@ -1460,11 +1481,14 @@ void ospf6_neighbor_init(void) &ipv6_ospf6_p2xp_neigh_poll_interval_cmd); } -DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd, - "debug ospf6 neighbor [<state|event>]", - DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN (debug_ospf6_neighbor, + debug_ospf6_neighbor_cmd, + "debug ospf6 neighbor [<state|event>]", + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 3; unsigned char level = 0; @@ -1482,11 +1506,15 @@ DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd, } -DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd, - "no debug ospf6 neighbor [<state|event>]", - NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN (no_debug_ospf6_neighbor, + no_debug_ospf6_neighbor_cmd, + "no debug ospf6 neighbor [<state|event>]", + NO_STR + DEBUG_STR + OSPF6_STR + "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 4; unsigned char level = 0; @@ -1504,8 +1532,12 @@ DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd, } -DEFUN(no_debug_ospf6, no_debug_ospf6_cmd, "no debug ospf6", - NO_STR DEBUG_STR OSPF6_STR) +DEFUN (no_debug_ospf6, + no_debug_ospf6_cmd, + "no debug ospf6", + NO_STR + DEBUG_STR + OSPF6_STR) { unsigned int i; diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 2c1d17efc3..d3c1804658 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -115,6 +115,7 @@ struct ospf6_path { /* Cost */ uint8_t metric_type; uint32_t cost; + uint32_t redistribute_cost; struct prefix ls_prefix; @@ -139,6 +140,8 @@ struct ospf6_path { #define OSPF6_PATH_COST_IS_CONFIGURED(path) (path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC) +#define OSPF6_EXT_PATH_METRIC_MAX 0x00ffffff + #include "prefix.h" #include "table.h" #include "bitfield.h" diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 3245578b07..911f3567d4 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -289,7 +289,7 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS) if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix, api.nexthop_num, nexthop, api.tag, - ospf6); + ospf6, api.metric); else ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix, ospf6); diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 419113e6d7..fcc28c6f9f 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -62,6 +62,11 @@ DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter"); /* List of all active connections. */ struct list *apiserver_list; +/* Indicates that API the server socket local addresss has been + * specified. + */ +struct in_addr ospf_apiserver_addr; + /* ----------------------------------------------------------- * Functions to lookup interfaces * ----------------------------------------------------------- @@ -109,7 +114,21 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp) unsigned short ospf_apiserver_getport(void) { - struct servent *sp = getservbyname("ospfapi", "tcp"); + struct servent *sp = NULL; + char sbuf[16]; + + /* + * Allow the OSPF API server port to be specified per-instance by + * including the instance ID in the /etc/services name. Use the + * prior name if no per-instance service is specified. + */ + if (ospf_instance) { + snprintfrr(sbuf, sizeof(sbuf), "ospfapi-%d", ospf_instance); + sp = getservbyname(sbuf, "tcp"); + } + + if (!sp) + sp = getservbyname("ospfapi", "tcp"); return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT; } @@ -557,8 +576,10 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family) sockopt_reuseaddr(accept_sock); sockopt_reuseport(accept_sock); - /* Bind socket to address and given port. */ - rc = sockunion_bind(accept_sock, &su, port, NULL); + /* Bind socket to optional lcoal address and port. */ + if (ospf_apiserver_addr.s_addr) + sockunion2ip(&su) = ospf_apiserver_addr.s_addr; + rc = sockunion_bind(accept_sock, &su, port, &su); if (rc < 0) { close(accept_sock); /* Close socket */ return rc; diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h index 0aaf67c1f3..4341a9d380 100644 --- a/ospfd/ospf_apiserver.h +++ b/ospfd/ospf_apiserver.h @@ -67,6 +67,14 @@ enum ospf_apiserver_event { }; /* ----------------------------------------------------------- + * External definitions for OSPF API ospfd parameters. + * ----------------------------------------------------------- + */ + +extern int ospf_apiserver_enable; +extern struct in_addr ospf_apiserver_addr; + +/* ----------------------------------------------------------- * Following are functions to manage client connections. * ----------------------------------------------------------- */ diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 319db1efe2..11ac7af7c9 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -19,6 +19,7 @@ #include "zclient.h" #include "bfd.h" #include "ldp_sync.h" +#include "plist.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_bfd.h" @@ -67,6 +68,34 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi) return count; } + +void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi) +{ + struct route_node *rn; + struct ospf_neighbor *nbr = NULL; + struct prefix nbr_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } }; + + if (!oi->nbr_filter) + return; + + /* + * Kill neighbors that don't match the neighbor filter prefix-list + * excluding the neighbor for the router itself and any neighbors + * that are already down. + */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + nbr = rn->info; + if (nbr && nbr != oi->nbr_self && nbr->state != NSM_Down) { + nbr_src_prefix.u.prefix4 = nbr->src; + if (prefix_list_apply(oi->nbr_filter, + (struct prefix *)&( + nbr_src_prefix)) != + PREFIX_PERMIT) + OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr); + } + } +} + int ospf_if_get_output_cost(struct ospf_interface *oi) { /* If all else fails, use default OSPF cost */ @@ -526,6 +555,7 @@ static struct ospf_if_params *ospf_new_if_params(void) UNSET_IF_PARAM(oip, if_area); UNSET_IF_PARAM(oip, opaque_capable); UNSET_IF_PARAM(oip, keychain_name); + UNSET_IF_PARAM(oip, nbr_filter_name); oip->auth_crypt = list_new(); @@ -544,6 +574,7 @@ static void ospf_del_if_params(struct interface *ifp, { list_delete(&oip->auth_crypt); XFREE(MTYPE_OSPF_IF_PARAMS, oip->keychain_name); + XFREE(MTYPE_OSPF_IF_PARAMS, oip->nbr_filter_name); ospf_interface_disable_bfd(ifp, oip); ldp_sync_info_free(&(oip->ldp_sync_info)); XFREE(MTYPE_OSPF_IF_PARAMS, oip); @@ -579,7 +610,8 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr) !OSPF_IF_PARAM_CONFIGURED(oip, if_area) && !OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) && !OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) && - !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) && + !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) && + !OSPF_IF_PARAM_CONFIGURED(oip, nbr_filter_name) && listcount(oip->auth_crypt) == 0) { ospf_del_if_params(ifp, oip); rn->info = NULL; @@ -1382,7 +1414,8 @@ static int ospf_ifp_create(struct interface *ifp) (!OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type) || if_is_loopback(ifp))) { SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); - IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + if (!IF_DEF_PARAMS(ifp)->type_cfg) + IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); } ospf = ifp->vrf->info; diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index 721ab1a9d7..45d0b7943a 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -57,6 +57,7 @@ struct ospf_if_params { DECLARE_IF_PARAM(struct in_addr, if_area); uint32_t if_area_id_fmt; + bool type_cfg; DECLARE_IF_PARAM(uint8_t, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 @@ -124,6 +125,9 @@ struct ospf_if_params { /* Opaque LSA capability at interface level (see RFC5250) */ DECLARE_IF_PARAM(bool, opaque_capable); + + /* Name of prefix-list name for packet source address filtering. */ + DECLARE_IF_PARAM(char *, nbr_filter_name); }; enum { MEMBER_ALLROUTERS = 0, @@ -242,6 +246,9 @@ struct ospf_interface { /* List of configured NBMA neighbor. */ struct list *nbr_nbma; + /* Configured prefix-list for filtering neighbors. */ + struct prefix_list *nbr_filter; + /* Graceful-Restart data. */ struct { struct { @@ -367,6 +374,7 @@ extern void ospf_crypt_key_add(struct list *list, struct crypt_key *key); extern int ospf_crypt_key_delete(struct list *list, uint8_t key_id); extern uint8_t ospf_default_iftype(struct interface *ifp); extern int ospf_interface_neighbor_count(struct ospf_interface *oi); +extern void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi); /* Set all multicast memberships appropriately based on the type and state of the interface. */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index abad6c5b90..9e97abba1c 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -44,6 +44,7 @@ #include "ospfd/ospf_errors.h" #include "ospfd/ospf_ldp_sync.h" #include "ospfd/ospf_routemap_nb.h" +#include "ospfd/ospf_apiserver.h" #define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir #define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i @@ -75,6 +76,7 @@ struct zebra_privs_t ospfd_privs = { const struct option longopts[] = { {"instance", required_argument, NULL, 'n'}, {"apiserver", no_argument, NULL, 'a'}, + {"apiserver_addr", required_argument, NULL, 'l'}, {0} }; @@ -83,10 +85,6 @@ const struct option longopts[] = { /* Master of threads. */ struct event_loop *master; -#ifdef SUPPORT_OSPF_API -extern int ospf_apiserver_enable; -#endif /* SUPPORT_OSPF_API */ - /* SIGHUP handler. */ static void sighup(void) { @@ -193,15 +191,11 @@ static void ospf_config_end(void) /* OSPFd main routine. */ int main(int argc, char **argv) { -#ifdef SUPPORT_OSPF_API - /* OSPF apiserver is disabled by default. */ - ospf_apiserver_enable = 0; -#endif /* SUPPORT_OSPF_API */ - frr_preinit(&ospfd_di, argc, argv); - frr_opt_add("n:a", longopts, + frr_opt_add("n:al:", longopts, " -n, --instance Set the instance id\n" - " -a, --apiserver Enable OSPF apiserver\n"); + " -a, --apiserver Enable OSPF apiserver\n" + " -l, --apiserver_addr Set OSPF apiserver bind address\n"); while (1) { int opt; @@ -223,6 +217,14 @@ int main(int argc, char **argv) case 'a': ospf_apiserver_enable = 1; break; + case 'l': + if (inet_pton(AF_INET, optarg, &ospf_apiserver_addr) <= + 0) { + zlog_err("OSPF: Invalid API Server IPv4 address %s specified", + optarg); + exit(0); + } + break; #endif /* SUPPORT_OSPF_API */ default: frr_help_exit(1); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 60479ddcd1..87aaccad92 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -23,6 +23,7 @@ #endif #include "vrf.h" #include "lib_errors.h" +#include "plist.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -2747,6 +2748,20 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf) oi = ospf_if_lookup_recv_if(ospf, iph->ip_src, ifp); /* + * If a neighbor filter prefix-list is configured, apply it to the IP + * source address and ignore the packet if it doesn't match. + */ + if (oi && oi->nbr_filter) { + struct prefix ip_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } }; + + ip_src_prefix.u.prefix4 = iph->ip_src; + if (prefix_list_apply(oi->nbr_filter, + (struct prefix *)&(ip_src_prefix)) != + PREFIX_PERMIT) + return OSPF_READ_CONTINUE; + } + + /* * ospf_verify_header() relies on a valid "oi" and thus can be called * only after the passive/backbone/other checks below are passed. * These checks in turn access the fields of unverified "ospfh" diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index fc0c143c28..4e1f15361e 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -906,7 +906,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, area = ospf_area_lookup_by_area_id(ospf, *area_id); if (!area) return NULL; - offset++; + offset += IN_ADDR_SIZE; /* Type. */ *type = *offset; @@ -914,7 +914,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, /* LS ID. */ oid2in_addr(offset, IN_ADDR_SIZE, ls_id); - offset++; + offset += IN_ADDR_SIZE; /* Router ID. */ oid2in_addr(offset, IN_ADDR_SIZE, router_id); @@ -971,7 +971,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, } /* Router ID. */ - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; len = offsetlen; @@ -996,11 +996,11 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, /* Fill in value. */ offset = name + v->namelen; oid_copy_in_addr(offset, area_id); - offset++; + offset += IN_ADDR_SIZE; *offset = lsa->data->type; offset++; oid_copy_in_addr(offset, &lsa->data->id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, &lsa->data->adv_router); @@ -1106,7 +1106,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, if (!area) return NULL; - offset++; + offset += IN_ADDR_SIZE; /* Lookup area range. */ oid2in_addr(offset, IN_ADDR_SIZE, range_net); @@ -1135,7 +1135,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, return NULL; do { - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; len = offsetlen; @@ -1157,7 +1157,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, /* Fill in value. */ offset = name + v->namelen; oid_copy_in_addr(offset, area_id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, range_net); return range; @@ -1559,7 +1559,7 @@ static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name, *length = v->namelen + IN_ADDR_SIZE + 1; offset = name + v->namelen; oid_copy_in_addr(offset, ifaddr); - offset++; + offset += IN_ADDR_SIZE; *offset = *ifindex; return oi; } @@ -1703,7 +1703,7 @@ static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name, *length = v->namelen + IN_ADDR_SIZE + 1 + 1; offset = name + v->namelen; oid_copy_in_addr(offset, ifaddr); - offset++; + offset += IN_ADDR_SIZE; *offset = *ifindex; offset++; *offset = OSPF_SNMP_METRIC_VALUE; @@ -2241,7 +2241,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, /* LS ID. */ oid2in_addr(offset, IN_ADDR_SIZE, ls_id); - offset++; + offset += IN_ADDR_SIZE; /* Router ID. */ oid2in_addr(offset, IN_ADDR_SIZE, router_id); @@ -2269,7 +2269,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, oid2in_addr(offset, len, ls_id); - offset++; + offset += IN_ADDR_SIZE; offsetlen -= IN_ADDR_SIZE; /* Router ID. */ @@ -2292,7 +2292,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, *offset = OSPF_AS_EXTERNAL_LSA; offset++; oid_copy_in_addr(offset, &lsa->data->id); - offset++; + offset += IN_ADDR_SIZE; oid_copy_in_addr(offset, &lsa->data->adv_router); return lsa; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4980cd3eca..301320bb0a 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -4085,6 +4085,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, if (use_json) json_object_object_addf(json_ois, json_oi, "%pI4", &oi->address->u.prefix4); + + if (oi->nbr_filter) { + if (use_json) { + json_object_string_add(json_interface_sub, + "nbrFilterPrefixList", + prefix_list_name( + oi->nbr_filter)); + json_object_string_add(json_oi, + "nbrFilterPrefixList", + prefix_list_name( + oi->nbr_filter)); + } else + vty_out(vty, + " Neighbor filter prefix-list: %s\n", + prefix_list_name(oi->nbr_filter)); + } else { + if (use_json) { + json_object_string_add(json_interface_sub, + "nbrFilterPrefixList", + "N/A"); + json_object_string_add(json_oi, + "nbrFilterPrefixList", + "N/A"); + } + } } } @@ -8183,6 +8208,8 @@ static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str, ospf_nbr_timer_update(oi); } + if (params->fast_hello != OSPF_FAST_HELLO_DEFAULT) + ospf_reset_hello_timer(ifp, addr, false); return CMD_SUCCESS; } @@ -8512,6 +8539,8 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd, IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1; } + IF_DEF_PARAMS(ifp)->type_cfg = true; + if (IF_DEF_PARAMS(ifp)->type == old_type && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn && IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood && @@ -8579,6 +8608,7 @@ DEFUN (no_ip_ospf_network, struct route_node *rn; IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + IF_DEF_PARAMS(ifp)->type_cfg = false; IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0; IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = OSPF_P2MP_DELAY_REFLOOD_DEFAULT; @@ -9937,6 +9967,58 @@ DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd, return CMD_SUCCESS; } +DEFPY(ip_ospf_neighbor_filter, ip_ospf_neighbor_filter_addr_cmd, + "[no] ip ospf neighbor-filter ![PREFIXLIST4_NAME]$prefix_list [A.B.C.D]$ip_addr", NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Filter OSPF neighbor packets\n" + "Prefix-List used for filtering\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf_if_params *params; + struct prefix_list *nbr_filter = NULL; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (ip_addr.s_addr != INADDR_ANY) { + params = ospf_get_if_params(ifp, ip_addr); + ospf_if_update_params(ifp, ip_addr); + } + + if (params->nbr_filter_name) + XFREE(MTYPE_OSPF_IF_PARAMS, params->nbr_filter_name); + + if (no) { + UNSET_IF_PARAM(params, nbr_filter_name); + params->nbr_filter_name = NULL; + } else { + SET_IF_PARAM(params, nbr_filter_name); + params->nbr_filter_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS, + prefix_list); + nbr_filter = prefix_list_lookup(AFI_IP, params->nbr_filter_name); + } + + /* + * Determine if there is a change in neighbor filter prefix-list for the + * interface. + */ + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi && + (ip_addr.s_addr == INADDR_ANY || + IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr)) && + oi->nbr_filter != nbr_filter) { + oi->nbr_filter = nbr_filter; + if (oi->nbr_filter) + ospf_intf_neighbor_filter_apply(oi); + } + } + return CMD_SUCCESS; +} + DEFUN (ospf_max_metric_router_lsa_admin, ospf_max_metric_router_lsa_admin_cmd, "max-metric router-lsa administrative", @@ -12128,29 +12210,25 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) do { /* Interface Network print. */ - if (OSPF_IF_PARAM_CONFIGURED(params, type) - && params->type != OSPF_IFTYPE_LOOPBACK) { - if (params->type != ospf_default_iftype(ifp)) { - vty_out(vty, " ip ospf network %s", - ospf_int_type_str - [params->type]); - if (params->type - == OSPF_IFTYPE_POINTOPOINT - && params->ptp_dmvpn) - vty_out(vty, " dmvpn"); - if (params->type == - OSPF_IFTYPE_POINTOMULTIPOINT && - params->p2mp_delay_reflood) - vty_out(vty, " delay-reflood"); - if (params->type == - OSPF_IFTYPE_POINTOMULTIPOINT && - params->p2mp_non_broadcast) - vty_out(vty, " non-broadcast"); - if (params != IF_DEF_PARAMS(ifp) && rn) - vty_out(vty, " %pI4", - &rn->p.u.prefix4); - vty_out(vty, "\n"); - } + if (OSPF_IF_PARAM_CONFIGURED(params, type) && + params->type != OSPF_IFTYPE_LOOPBACK && + params->type_cfg) { + vty_out(vty, " ip ospf network %s", + ospf_int_type_str[params->type]); + if (params->type == OSPF_IFTYPE_POINTOPOINT && + params->ptp_dmvpn) + vty_out(vty, " dmvpn"); + if (params->type == + OSPF_IFTYPE_POINTOMULTIPOINT && + params->p2mp_delay_reflood) + vty_out(vty, " delay-reflood"); + if (params->type == + OSPF_IFTYPE_POINTOMULTIPOINT && + params->p2mp_non_broadcast) + vty_out(vty, " non-broadcast"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); } /* OSPF interface authentication print */ @@ -12360,6 +12438,15 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) vty_out(vty, "\n"); } + /* neighbor-filter print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, nbr_filter_name)) { + vty_out(vty, " ip ospf neighbor-filter %s", + params->nbr_filter_name); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + while (1) { if (rn == NULL) rn = route_top(IF_OIFS_PARAMS(ifp)); @@ -13176,6 +13263,9 @@ static void ospf_vty_if_init(void) /* "ip ospf prefix-suppression" commands. */ install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_addr_cmd); + /* "ip ospf neighbor-filter" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_neighbor_filter_addr_cmd); + /* These commands are compatibitliy for previous version. */ install_element(INTERFACE_NODE, &ospf_authentication_key_cmd); install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index bb6cc3a89c..2c518f2c9e 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1769,6 +1769,7 @@ static void ospf_prefix_list_update(struct prefix_list *plist) int type; int abr_inv = 0; struct ospf_area *area; + struct ospf_interface *oi; struct listnode *node, *n1; /* If OSPF instatnce does not exist, return right now. */ @@ -1824,6 +1825,19 @@ static void ospf_prefix_list_update(struct prefix_list *plist) } } + /* Update interface neighbor-filter lists. */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (OSPF_IF_PARAM(oi, nbr_filter_name) && + strcmp(OSPF_IF_PARAM(oi, nbr_filter_name), + prefix_list_name(plist)) == 0) { + oi->nbr_filter = prefix_list_lookup( + AFI_IP, + OSPF_IF_PARAM(oi, nbr_filter_name)); + if (oi->nbr_filter) + ospf_intf_neighbor_filter_apply(oi); + } + } + /* Schedule ABR task. */ if (IS_OSPF_ABR(ospf) && abr_inv) ospf_schedule_abr_task(ospf); diff --git a/pathd/path_main.c b/pathd/path_main.c index fe636c51be..23cbb9cced 100644 --- a/pathd/path_main.c +++ b/pathd/path_main.c @@ -58,7 +58,7 @@ static void sighup(void) static void sigint(void) { zlog_notice("Terminating on signal"); - zlog_notice("Unregisterfrom opaque,etc "); + zlog_notice("Unregister from opaque,etc "); pathd_shutdown(); exit(0); diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c index 645fa50856..ba03315c82 100644 --- a/pathd/path_zebra.c +++ b/pathd/path_zebra.c @@ -29,6 +29,17 @@ static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS); struct zclient *zclient; static struct zclient *zclient_sync; +/* Event to retry synch zapi setup for label-manager */ +static struct event *t_sync_connect; + +enum path_sync_level { + PATH_SYNC_NONE = 0, + PATH_SYNC_CONN, + PATH_SYNC_HELLO, + PATH_SYNC_DONE +}; +static enum path_sync_level path_sync_client_level; + /* Global Variables */ bool g_has_router_id_v4 = false; bool g_has_router_id_v6 = false; @@ -236,26 +247,48 @@ void path_zebra_release_label(mpls_label_t label) zlog_warn("%s: error releasing label range!", __func__); } -static void path_zebra_label_manager_connect(void) +/* + * Initialize and connect the synchronous zclient session for the + * label-manager. This is prepared to retry on error. + */ +static void path_zebra_label_manager_connect(struct event *event) { - /* Connect to label manager. */ - while (zclient_socket_connect(zclient_sync) < 0) { - zlog_warn("%s: error connecting synchronous zclient!", - __func__); - sleep(1); + if (path_sync_client_level == PATH_SYNC_NONE) { + /* Connect to label manager. */ + if (zclient_socket_connect(zclient_sync) < 0) { + zlog_warn("%s: error connecting synchronous zclient!", + __func__); + event_add_timer(master, path_zebra_label_manager_connect, + NULL, 1, &t_sync_connect); + return; + } + set_nonblocking(zclient_sync->sock); + + path_sync_client_level = PATH_SYNC_CONN; } - set_nonblocking(zclient_sync->sock); /* Send hello to notify zebra this is a synchronous client */ - while (zclient_send_hello(zclient_sync) < 0) { - zlog_warn("%s: Error sending hello for synchronous zclient!", - __func__); - sleep(1); + if (path_sync_client_level == PATH_SYNC_CONN) { + if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { + zlog_warn("%s: Error sending hello for synchronous zclient!", + __func__); + event_add_timer(master, path_zebra_label_manager_connect, + NULL, 1, &t_sync_connect); + return; + } + + path_sync_client_level = PATH_SYNC_HELLO; } - while (lm_label_manager_connect(zclient_sync, 0) != 0) { - zlog_warn("%s: error connecting to label manager!", __func__); - sleep(1); + if (path_sync_client_level == PATH_SYNC_HELLO) { + if (lm_label_manager_connect(zclient_sync, 0) != 0) { + zlog_warn("%s: error connecting to label manager!", + __func__); + event_add_timer(master, path_zebra_label_manager_connect, + NULL, 1, &t_sync_connect); + return; + } + path_sync_client_level = PATH_SYNC_DONE; } } @@ -334,13 +367,15 @@ void path_zebra_init(struct event_loop *master) zclient_sync->privs = &pathd_privs; /* Connect to the LM. */ - path_zebra_label_manager_connect(); + t_sync_connect = NULL; + path_zebra_label_manager_connect(NULL); } void path_zebra_stop(void) { zclient_stop(zclient); zclient_free(zclient); + event_cancel(&t_sync_connect); zclient_stop(zclient_sync); zclient_free(zclient_sync); } diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c index 4db11572d8..ec912700d1 100644 --- a/pimd/pim6_cmd.c +++ b/pimd/pim6_cmd.c @@ -244,7 +244,7 @@ DEFPY (interface_no_ipv6_pim, DEFPY (interface_ipv6_pim_drprio, interface_ipv6_pim_drprio_cmd, - "ipv6 pim drpriority (1-4294967295)", + "ipv6 pim drpriority (0-4294967295)", IPV6_STR PIM_STR "Set the Designated Router Election Priority\n" @@ -255,7 +255,7 @@ DEFPY (interface_ipv6_pim_drprio, DEFPY (interface_no_ipv6_pim_drprio, interface_no_ipv6_pim_drprio_cmd, - "no ipv6 pim drpriority [(1-4294967295)]", + "no ipv6 pim drpriority [(0-4294967295)]", NO_STR IPV6_STR PIM_STR diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 15d3904c37..a2d756a96a 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3956,7 +3956,7 @@ DEFUN (interface_no_ip_igmp_last_member_query_interval, DEFUN (interface_ip_pim_drprio, interface_ip_pim_drprio_cmd, - "ip pim drpriority (1-4294967295)", + "ip pim drpriority (0-4294967295)", IP_STR PIM_STR "Set the Designated Router Election Priority\n" @@ -3969,7 +3969,7 @@ DEFUN (interface_ip_pim_drprio, DEFUN (interface_no_ip_pim_drprio, interface_no_ip_pim_drprio_cmd, - "no ip pim drpriority [(1-4294967295)]", + "no ip pim drpriority [(0-4294967295)]", NO_STR IP_STR PIM_STR diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index ee318d45e3..5e50a09355 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -287,8 +287,15 @@ int pim_process_no_rp_kat_cmd(struct vty *vty) sizeof(rs_timer_xpath)); /* RFC4601 */ - v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s", - rs_timer_xpath); + /* Check if register suppress time is configured or assigned + * the default register suppress time. + */ + if (yang_dnode_exists(vty->candidate_config->dnode, rs_timer_xpath)) + v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s", + rs_timer_xpath); + else + v = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; + v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT; if (v > UINT16_MAX) v = UINT16_MAX; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index da55189941..8f9e41039a 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -342,6 +342,13 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, ch->sg_str, ch->interface->name); } + /* pim_upstream_update_join_desired looks at up->channel_oil, + * but that's updated from pim_forward_stop(). Need this here + * so we correctly determine join_desired right below. + */ + if (new_state == PIM_IFJOIN_NOINFO) + pim_forward_stop(ch); + /* Record uptime of state transition to/from NOINFO */ @@ -619,7 +626,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg, static void ifjoin_to_noinfo(struct pim_ifchannel *ch) { pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO); - pim_forward_stop(ch); PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 01da699dbd..b149b5a2a9 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -109,12 +109,12 @@ static void pim_reg_stop_upstream(struct pim_instance *pim, up->reg_state = PIM_REG_PRUNE; pim_channel_del_oif(up->channel_oil, pim->regiface, PIM_OIF_FLAG_PROTO_PIM, __func__); - pim_upstream_start_register_stop_timer(up, 0); + pim_upstream_start_register_probe_timer(up); pim_vxlan_update_sg_reg_state(pim, up, false); break; case PIM_REG_JOIN_PENDING: up->reg_state = PIM_REG_PRUNE; - pim_upstream_start_register_stop_timer(up, 0); + pim_upstream_start_register_probe_timer(up); return; } } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 556d25b822..7417f31137 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1687,6 +1687,8 @@ const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str, return state_str; } +static void pim_upstream_start_register_stop_timer(struct pim_upstream *up); + static void pim_upstream_register_stop_timer(struct event *t) { struct pim_interface *pim_ifp; @@ -1734,7 +1736,7 @@ static void pim_upstream_register_stop_timer(struct event *t) return; } up->reg_state = PIM_REG_JOIN_PENDING; - pim_upstream_start_register_stop_timer(up, 1); + pim_upstream_start_register_stop_timer(up); if (((up->channel_oil->cc.lastused / 100) > pim->keep_alive_time) @@ -1752,34 +1754,59 @@ static void pim_upstream_register_stop_timer(struct event *t) } } -void pim_upstream_start_register_stop_timer(struct pim_upstream *up, - int null_register) +static void pim_upstream_start_register_stop_timer(struct pim_upstream *up) { uint32_t time; EVENT_OFF(up->t_rs_timer); - if (!null_register) { - uint32_t lower = (0.5 * router->register_suppress_time); - uint32_t upper = (1.5 * router->register_suppress_time); - time = lower + (frr_weak_random() % (upper - lower + 1)); - /* Make sure we don't wrap around */ - if (time >= router->register_probe_time) - time -= router->register_probe_time; - else - time = 0; - } else - time = router->register_probe_time; + time = router->register_probe_time; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug( - "%s: (S,G)=%s Starting upstream register stop timer %d", - __func__, up->sg_str, time); - } + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%s Starting upstream register stop timer %d", + __func__, up->sg_str, time); event_add_timer(router->master, pim_upstream_register_stop_timer, up, time, &up->t_rs_timer); } +static void pim_upstream_register_probe_timer(struct event *t) +{ + struct pim_upstream *up = EVENT_ARG(t); + + if (!up->rpf.source_nexthop.interface || + !up->rpf.source_nexthop.interface->info) { + if (PIM_DEBUG_PIM_REG) + zlog_debug("cannot send Null register for %pSG, no path to RP", + &up->sg); + } else + pim_null_register_send(up); + + pim_upstream_start_register_stop_timer(up); +} + +void pim_upstream_start_register_probe_timer(struct pim_upstream *up) +{ + uint32_t time; + + EVENT_OFF(up->t_rs_timer); + + uint32_t lower = (0.5 * router->register_suppress_time); + uint32_t upper = (1.5 * router->register_suppress_time); + time = lower + (frr_weak_random() % (upper - lower + 1)); + /* Make sure we don't wrap around */ + if (time >= router->register_probe_time) + time -= router->register_probe_time; + else + time = 0; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%s Starting upstream register stop null probe timer %d", + __func__, up->sg_str, time); + + event_add_timer(router->master, pim_upstream_register_probe_timer, up, + time, &up->t_rs_timer); +} + int pim_upstream_inherited_olist_decide(struct pim_instance *pim, struct pim_upstream *up) { diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 62649cd949..8b4a35be39 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -331,8 +331,7 @@ int pim_upstream_is_sg_rpt(struct pim_upstream *up); void pim_upstream_set_sptbit(struct pim_upstream *up, struct interface *incoming); -void pim_upstream_start_register_stop_timer(struct pim_upstream *up, - int null_register); +void pim_upstream_start_register_probe_timer(struct pim_upstream *up); void pim_upstream_send_join(struct pim_upstream *up); diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py index 60119fbac0..668724ab2a 100644 --- a/python/clippy/__init__.py +++ b/python/clippy/__init__.py @@ -20,6 +20,7 @@ from _clippy import ( CMD_ATTR_HIDDEN, CMD_ATTR_DEPRECATED, CMD_ATTR_NOSH, + elf_notes, ) diff --git a/python/clippy/elf.py b/python/clippy/elf.py index cc442eeda9..fd348428f0 100644 --- a/python/clippy/elf.py +++ b/python/clippy/elf.py @@ -458,7 +458,16 @@ class ELFSubset(object): - `this[123:str]` - extract until null byte. The slice stop value is the `str` type (or, technically, `unicode`.) """ - return self._obj[k] + if k.start < getattr(self._obj, "len", float("+Inf")): + return self._obj[k] + + real_sect = self._elffile.get_section_addr(self._obj.sh_addr + k.start) + offs = self._obj.sh_addr - real_sect.sh_addr + if k.stop is str: + new_k = slice(k.start + offs, str) + else: + new_k = slice(k.start + offs, k.stop + offs) + return real_sect[new_k] def getreloc(self, offset): """ diff --git a/python/xrelfo.py b/python/xrelfo.py index a40b19e5fb..07cd74071f 100644 --- a/python/xrelfo.py +++ b/python/xrelfo.py @@ -22,7 +22,7 @@ import argparse from clippy.uidhash import uidhash from clippy.elf import * -from clippy import frr_top_src, CmdAttr +from clippy import frr_top_src, CmdAttr, elf_notes from tiabwarfo import FieldApplicator from xref2vtysh import CommandEntry @@ -327,6 +327,7 @@ class Xrelfo(dict): } ) self._xrefs = [] + self.note_warn = False def load_file(self, filename): orig_filename = filename @@ -395,6 +396,15 @@ class Xrelfo(dict): ptrs = edf.iter_data(XrefPtr, slice(start, end)) else: + if elf_notes: + self.note_warn = True + sys.stderr.write( + """%s: warning: binary has no FRRouting.XREF note +%s- one of FRR_MODULE_SETUP, FRR_DAEMON_INFO or XREF_SETUP must be used +""" + % (orig_filename, orig_filename) + ) + xrefarray = edf.get_section("xref_array") if xrefarray is None: raise ValueError("file has neither xref note nor xref_array section") @@ -471,6 +481,9 @@ def _main(args): sys.stderr.write("while processing %s:\n" % (fn)) traceback.print_exc() + if xrelfo.note_warn and args.Werror: + errors += 1 + for option in dir(args): if option.startswith("W") and option != "Werror": checks = sorted(xrelfo.check(args)) @@ -10,3 +10,8 @@ /* * Main file for the qpb library. */ + +#include "config.h" +#include "xref.h" + +XREF_SETUP(); diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index 4d4349b81a..7066485be0 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -1233,6 +1233,23 @@ DEFPY_YANG(no_rip_distribute_list_prefix, return nb_cli_apply_changes(vty, NULL); } +/* + * XPath: /frr-ripd:clear-rip-route + */ +DEFPY_YANG (clear_ip_rip, + clear_ip_rip_cmd, + "clear ip rip [vrf WORD]", + CLEAR_STR + IP_STR + "Clear IP RIP database\n" + VRF_CMD_HELP_STR) +{ + if (vrf) + nb_cli_rpc_enqueue(vty, "vrf", vrf); + + return nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", NULL); +} + /* RIP node structure. */ static struct cmd_node rip_node = { .name = "rip", @@ -1295,6 +1312,8 @@ void rip_cli_init(void) install_element(INTERFACE_NODE, &ip_rip_bfd_profile_cmd); install_element(INTERFACE_NODE, &no_ip_rip_bfd_profile_cmd); + install_element(ENABLE_NODE, &clear_ip_rip_cmd); + if_rmap_init(RIP_NODE); } /* clang-format off */ diff --git a/ripd/rip_nb_rpcs.c b/ripd/rip_nb_rpcs.c index bbe3d0f0f8..5d3d7145b1 100644 --- a/ripd/rip_nb_rpcs.c +++ b/ripd/rip_nb_rpcs.c @@ -68,12 +68,11 @@ static void clear_rip_route(struct rip *rip) int clear_rip_route_rpc(struct nb_cb_rpc_args *args) { struct rip *rip; - struct yang_data *yang_vrf; - yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath, - "input/vrf"); - if (yang_vrf) { - rip = rip_lookup_by_vrf_name(yang_vrf->value); + if (args->input && yang_dnode_exists(args->input, "vrf")) { + const char *name = yang_dnode_get_string(args->input, "vrf"); + + rip = rip_lookup_by_vrf_name(name); if (rip) clear_rip_route(rip); } else { diff --git a/ripd/ripd.c b/ripd/ripd.c index e3220a9267..b8a140c9ca 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3254,38 +3254,6 @@ DEFUN (show_ip_rip_status, return CMD_SUCCESS; } -#include "ripd/ripd_clippy.c" - -/* - * XPath: /frr-ripd:clear-rip-route - */ -DEFPY_YANG (clear_ip_rip, - clear_ip_rip_cmd, - "clear ip rip [vrf WORD]", - CLEAR_STR - IP_STR - "Clear IP RIP database\n" - VRF_CMD_HELP_STR) -{ - struct list *input; - int ret; - - input = list_new(); - if (vrf) { - struct yang_data *yang_vrf; - - yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf", - vrf); - listnode_add(input, yang_vrf); - } - - ret = nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", input, NULL); - - list_delete(&input); - - return ret; -} - /* Distribute-list update functions. */ static void rip_distribute_update(struct distribute_ctx *ctx, struct distribute *dist) @@ -3660,7 +3628,6 @@ void rip_init(void) /* Install rip commands. */ install_element(VIEW_NODE, &show_ip_rip_cmd); install_element(VIEW_NODE, &show_ip_rip_status_cmd); - install_element(ENABLE_NODE, &clear_ip_rip_cmd); /* Debug related init. */ rip_debug_init(); diff --git a/ripd/subdir.am b/ripd/subdir.am index 7fb3726077..aed8d249fe 100644 --- a/ripd/subdir.am +++ b/ripd/subdir.am @@ -33,7 +33,6 @@ ripd_ripd_SOURCES = \ clippy_scan += \ ripd/rip_bfd.c \ ripd/rip_cli.c \ - ripd/ripd.c \ # end noinst_HEADERS += \ diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index 4806861fe0..99cb68ea32 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -624,6 +624,23 @@ DEFPY_YANG(no_ripng_ipv6_distribute_list_prefix, return nb_cli_apply_changes(vty, NULL); } +/* + * XPath: /frr-ripngd:clear-ripng-route + */ +DEFPY_YANG (clear_ipv6_rip, + clear_ipv6_rip_cmd, + "clear ipv6 ripng [vrf WORD]", + CLEAR_STR + IPV6_STR + "Clear IPv6 RIP database\n" + VRF_CMD_HELP_STR) +{ + if (vrf) + nb_cli_rpc_enqueue(vty, "vrf", vrf); + + return nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", NULL); +} + /* RIPng node structure. */ static struct cmd_node cmd_ripng_node = { .name = "ripng", @@ -663,6 +680,8 @@ void ripng_cli_init(void) install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd); + install_element(ENABLE_NODE, &clear_ipv6_rip_cmd); + if_rmap_init(RIPNG_NODE); } diff --git a/ripngd/ripng_nb_rpcs.c b/ripngd/ripng_nb_rpcs.c index b23572d492..5498bbfc8e 100644 --- a/ripngd/ripng_nb_rpcs.c +++ b/ripngd/ripng_nb_rpcs.c @@ -70,12 +70,11 @@ static void clear_ripng_route(struct ripng *ripng) int clear_ripng_route_rpc(struct nb_cb_rpc_args *args) { struct ripng *ripng; - struct yang_data *yang_vrf; - yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath, - "input/vrf"); - if (yang_vrf) { - ripng = ripng_lookup_by_vrf_name(yang_vrf->value); + if (args->input && yang_dnode_exists(args->input, "vrf")) { + const char *name = yang_dnode_get_string(args->input, "vrf"); + + ripng = ripng_lookup_by_vrf_name(name); if (ripng) clear_ripng_route(ripng); } else { diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 80b9013e0f..f4dadf377d 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2231,38 +2231,6 @@ DEFUN (show_ipv6_ripng_status, return CMD_SUCCESS; } -#include "ripngd/ripngd_clippy.c" - -/* - * XPath: /frr-ripngd:clear-ripng-route - */ -DEFPY_YANG (clear_ipv6_rip, - clear_ipv6_rip_cmd, - "clear ipv6 ripng [vrf WORD]", - CLEAR_STR - IPV6_STR - "Clear IPv6 RIP database\n" - VRF_CMD_HELP_STR) -{ - struct list *input; - int ret; - - input = list_new(); - if (vrf) { - struct yang_data *yang_vrf; - - yang_vrf = yang_data_new( - "/frr-ripngd:clear-ripng-route/input/vrf", vrf); - listnode_add(input, yang_vrf); - } - - ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL); - - list_delete(&input); - - return ret; -} - /* Update ECMP routes to zebra when ECMP is disabled. */ void ripng_ecmp_disable(struct ripng *ripng) { @@ -2680,7 +2648,6 @@ void ripng_init(void) /* Install ripng commands. */ install_element(VIEW_NODE, &show_ipv6_ripng_cmd); install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd); - install_element(ENABLE_NODE, &clear_ipv6_rip_cmd); ripng_if_init(); ripng_debug_init(); diff --git a/ripngd/subdir.am b/ripngd/subdir.am index a88114432d..83e376b555 100644 --- a/ripngd/subdir.am +++ b/ripngd/subdir.am @@ -27,7 +27,6 @@ ripngd_ripngd_SOURCES = \ clippy_scan += \ ripngd/ripng_cli.c \ - ripngd/ripngd.c \ # end noinst_HEADERS += \ diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 07050ab93b..21c596bf71 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -448,6 +448,7 @@ DEFPY (install_seg6local_routes, End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\ End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\ End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\ + End_DX6$seg6l_enddx6 X:X::X:X$seg6l_enddx6_nh6|\ End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\ End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\ End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\ @@ -467,6 +468,8 @@ DEFPY (install_seg6local_routes, "Redirect table id to use\n" "SRv6 End.DX4 function to use\n" "V4 Nexthop address to use\n" + "SRv6 End.DX6 function to use\n" + "V6 Nexthop address to use\n" "SRv6 End.DT6 function to use\n" "Redirect table id to use\n" "SRv6 End.DT4 function to use\n" @@ -516,6 +519,9 @@ DEFPY (install_seg6local_routes, if (seg6l_enddx4) { action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4; ctx.nh4 = seg6l_enddx4_nh4; + } else if (seg6l_enddx6) { + action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6; + ctx.nh6 = seg6l_enddx6_nh6; } else if (seg6l_endx) { action = ZEBRA_SEG6_LOCAL_ACTION_END_X; ctx.nh6 = seg6l_endx_nh6; diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c index 8f7e7c5f8c..321f158668 100644 --- a/tests/lib/northbound/test_oper_data.c +++ b/tests/lib/northbound/test_oper_data.c @@ -14,6 +14,7 @@ #include "lib_vty.h" #include "log.h" #include "northbound.h" +#include "northbound_cli.h" static struct event_loop *master; @@ -200,6 +201,19 @@ static struct yang_data *frr_test_module_vrfs_vrf_routes_route_active_get_elem( return NULL; } +/* + * XPath: /frr-test-module:frr-test-module/vrfs/vrf/ping + */ +static int frr_test_module_vrfs_vrf_ping(struct nb_cb_rpc_args *args) +{ + const char *vrf = yang_dnode_get_string(args->input, "../name"); + const char *data = yang_dnode_get_string(args->input, "data"); + + yang_dnode_rpc_output_add(args->output, "vrf", vrf); + yang_dnode_rpc_output_add(args->output, "data-out", data); + + return NB_OK; +} /* * XPath: /frr-test-module:frr-test-module/c1value @@ -263,6 +277,10 @@ const struct frr_yang_module_info frr_test_module_info = { .cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_active_get_elem, }, { + .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/ping", + .cbs.rpc = frr_test_module_vrfs_vrf_ping, + }, + { .xpath = "/frr-test-module:frr-test-module/c1value", .cbs.get_elem = frr_test_module_c1value_get_elem, }, @@ -277,6 +295,33 @@ const struct frr_yang_module_info frr_test_module_info = { }; /* clang-format on */ +DEFUN(test_rpc, test_rpc_cmd, "test rpc", + "Test\n" + "RPC\n") +{ + struct lyd_node *output = NULL; + char xpath[XPATH_MAXLEN]; + int ret; + + snprintf(xpath, sizeof(xpath), + "/frr-test-module:frr-test-module/vrfs/vrf[name='testname']/ping"); + + nb_cli_rpc_enqueue(vty, "data", "testdata"); + + ret = nb_cli_rpc(vty, xpath, &output); + if (ret != CMD_SUCCESS) { + vty_out(vty, "RPC failed\n"); + return ret; + } + + vty_out(vty, "vrf %s data %s\n", yang_dnode_get_string(output, "vrf"), + yang_dnode_get_string(output, "data-out")); + + yang_dnode_free(output); + + return CMD_SUCCESS; +} + static const struct frr_yang_module_info *const modules[] = { &frr_test_module_info, }; @@ -416,6 +461,8 @@ int main(int argc, char **argv) lib_cmd_init(); nb_init(master, modules, array_size(modules), false); + install_element(ENABLE_NODE, &test_rpc_cmd); + /* Create artificial data. */ create_data(num_vrfs, num_interfaces, num_routes); diff --git a/tests/lib/northbound/test_oper_data.in b/tests/lib/northbound/test_oper_data.in index a6c4f874f5..f7c44cad31 100644 --- a/tests/lib/northbound/test_oper_data.in +++ b/tests/lib/northbound/test_oper_data.in @@ -1 +1,2 @@ show yang operational-data /frr-test-module:frr-test-module +test rpc diff --git a/tests/lib/northbound/test_oper_data.refout b/tests/lib/northbound/test_oper_data.refout index aa930fe127..7c56564143 100644 --- a/tests/lib/northbound/test_oper_data.refout +++ b/tests/lib/northbound/test_oper_data.refout @@ -119,5 +119,7 @@ test# show yang operational-data /frr-test-module:frr-test-module }
}
}
+test# test rpc +vrf testname data testdata test# end. diff --git a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py index 705937ef93..d478e9902f 100644 --- a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py +++ b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py @@ -130,13 +130,15 @@ def test_bfd_loss_intermediate(): pytest.skip(tgen.errors) r1 = tgen.gears["r1"] - expected = { "as":101, "peers":{ "2001:db8:4::1": { "state":"Established" } } } - test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected) + expected = {"as": 101, "peers": {"2001:db8:4::1": {"state": "Established"}}} + test_func = partial( + topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected + ) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg ='"r1" has not established bgp peering yet' + assertmsg = '"r1" has not established bgp peering yet' assert result is None, assertmsg - #assert False + # assert False logger.info("removing IPv6 address from r2 to simulate loss of connectivity") # Disable r2-eth0 ipv6 address cmd = 'vtysh -c "configure terminal" -c "interface r2-eth1" -c "no ipv6 address 2001:db8:4::2/64"' diff --git a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py index 30f4a2f9b5..fee5f2d536 100644 --- a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py +++ b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py @@ -81,8 +81,7 @@ def setup_module(mod): for rname, router in router_list.items(): router.load_config( - TopoRouter.RD_ZEBRA, - os.path.join(CWD, "{}/zebra.conf".format(rname)) + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) ) router.load_config( TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname)) @@ -114,8 +113,8 @@ def test_bfd_connection(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) logger.info("waiting for bfd peers to go up") - router = tgen.gears['r1'] - json_file = "{}/{}/bfd_peers_status.json".format(CWD, 'r1') + router = tgen.gears["r1"] + json_file = "{}/{}/bfd_peers_status.json".format(CWD, "r1") expected = json.loads(open(json_file).read()) test_func = partial( diff --git a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py index 5d5f1659e9..4883e847c9 100644 --- a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py +++ b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py @@ -44,8 +44,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py index 6d17cdb4d9..e0c1b4953e 100644 --- a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py +++ b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py @@ -117,7 +117,9 @@ def test_bgp_color_extended_communities(): test_func = functools.partial(_bgp_check_route, r2, True) _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) - assert result is None, "10.10.10.0/24 ext community is correctly not installed, but SHOULD be" + assert ( + result is None + ), "10.10.10.0/24 ext community is correctly not installed, but SHOULD be" if __name__ == "__main__": diff --git a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py index 000ea6075b..fdae9a3aa7 100644 --- a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py +++ b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py @@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py index 4180bfcdf6..e9114bdbab 100644 --- a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py +++ b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py @@ -17,7 +17,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -27,8 +27,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")} diff --git a/tests/topotests/bgp_confed1/test_bgp_confed1.py b/tests/topotests/bgp_confed1/test_bgp_confed1.py index 57a8522020..7b37f4f6c7 100644 --- a/tests/topotests/bgp_confed1/test_bgp_confed1.py +++ b/tests/topotests/bgp_confed1/test_bgp_confed1.py @@ -32,7 +32,7 @@ pytestmark = [pytest.mark.bgpd] def build_topo(tgen): - for routern in range(1, 5): + for routern in range(1, 5): tgen.add_router("r{}".format(routern)) switch = tgen.add_switch("s1") @@ -47,8 +47,8 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r3"]) -def setup_module(mod): +def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) tgen.start_topology() @@ -67,6 +67,7 @@ def setup_module(mod): # Initialize all routers. tgen.start_router() + def teardown_module(_mod): "Teardown the pytest environment" tgen = get_topogen() diff --git a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py index 5310d3b595..7bc0050109 100644 --- a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py +++ b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py @@ -18,7 +18,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")} diff --git a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py index a0014c72e6..05e07486ae 100644 --- a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py +++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py @@ -30,8 +30,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 5): diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py index 6156968ded..50a1938ae3 100644 --- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py +++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py @@ -325,12 +325,14 @@ def teardown_module(): ) logger.info("=" * 40) + ##################################################### # # Testcases # ##################################################### + def test_verify_bgp_default_originate_in_IBGP_p0(request): """ Verify BGP default-originate route with IBGP peer @@ -396,7 +398,9 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): step("After changing the BGP AS Path Verify the BGP Convergence") BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) - assert BGP_CONVERGENCE is True, " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format( + assert ( + BGP_CONVERGENCE is True + ), " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format( BGP_CONVERGENCE ) @@ -413,8 +417,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): } } result = create_static_routes(tgen, static_routes_input) - assert result is True, "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format( - tc_name,static_routes_input, result + assert ( + result is True + ), "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format( + tc_name, static_routes_input, result ) step("verify IPv4 and IPv6 static route are configured and up on R1") for addr_type in ADDR_TYPES: @@ -429,8 +435,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input) - assert result is True, "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format( - tc_name,static_routes_input, result + assert ( + result is True + ), "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -483,7 +491,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): }, } result = create_router_bgp(tgen, topo, redistribute_static) - assert result is True, "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format( + tc_name, result + ) step( "After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2" @@ -517,13 +529,17 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format( - tc_name, static_routes_input,result + assert ( + result is True + ), "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format( + tc_name, static_routes_input, result ) result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format( - tc_name, static_routes_input , result + assert ( + result is True + ), "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -547,7 +563,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format( + tc_name, result + ) step( "After configuring default-originate command , verify default routes are advertised on R2 " @@ -574,12 +594,16 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request): } result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format( tc_name, result ) result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format( tc_name, result ) step( @@ -686,7 +710,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): step("After changing the BGP AS Path Verify the BGP Convergence") BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) - assert BGP_CONVERGENCE is True, "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format( + assert ( + BGP_CONVERGENCE is True + ), "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format( BGP_CONVERGENCE ) @@ -703,7 +729,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): } } result = create_static_routes(tgen, static_routes_input) - assert result is True, "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format( tc_name, result ) step("verify IPv4 and IPv6 static route are configured and up on R1") @@ -719,8 +747,10 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input) - assert result is True, "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format( - tc_name, static_routes_input,result + assert ( + result is True + ), "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -773,7 +803,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): }, } result = create_router_bgp(tgen, topo, redistribute_static) - assert result is True, "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format( + tc_name, result + ) step( "After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2" @@ -806,11 +840,15 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format( tc_name, result ) result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format( tc_name, result ) snapshot1 = get_prefix_count_route(tgen, topo, dut="r2", peer="r3") @@ -830,7 +868,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format( + tc_name, result + ) step( "After configuring default-originate command , verify default routes are advertised on R2 on both BGP RIB and FIB" @@ -853,13 +895,17 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): } result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format( - tc_name, NETWORK1_1,result + assert ( + result is True + ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format( + tc_name, NETWORK1_1, result ) result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input) - assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format( - tc_name,NETWORK1_1, result + assert ( + result is True + ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format( + tc_name, NETWORK1_1, result ) step( @@ -875,7 +921,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request): metric=0, expected_aspath="4000", ) - assert result is True, "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format( + tc_name, result + ) step( "Taking the snapshot2 of the prefix count after configuring the default originate" @@ -968,7 +1018,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): step("After changing the BGP AS Path Verify the BGP Convergence") BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) - assert BGP_CONVERGENCE is True, "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format( + assert ( + BGP_CONVERGENCE is True + ), "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format( BGP_CONVERGENCE ) @@ -989,7 +1041,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_static_routes(tgen, static_routes_input) - assert result is True, "Testcase {} : Static Configuration is Failed \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Static Configuration is Failed \n Error: {}".format( tc_name, result ) @@ -1010,8 +1064,10 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r0", static_routes_input) - assert result is True, "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format( - tc_name, static_routes_input,result + assert ( + result is True + ), "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -1028,7 +1084,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, redistribute_static) - assert result is True, "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format( + tc_name, result + ) step("verify IPv4 and IPv6 static route are configured and up on R1") for addr_type in ADDR_TYPES: @@ -1047,13 +1107,17 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input) - assert result is True, "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format( - tc_name,static_routes_input, result + assert ( + result is True + ), "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format( + tc_name, static_routes_input, result ) result = verify_bgp_rib(tgen, addr_type, "r1", static_routes_input) - assert result is True, "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format( - tc_name, static_routes_input,result + assert ( + result is True + ), "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -1094,7 +1158,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the prefix list \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the prefix list \n Error: {}".format( + tc_name, result + ) step( "Configure IPV4 and IPv6 route-map (RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6) respectively on R1" @@ -1120,7 +1188,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_route_maps(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the route map \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) step( "Configure default-originate with route-map (RMv4 and RMv6) on R1, on BGP IPv4 and IPv6 address family " @@ -1142,7 +1214,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed to configure the default originate \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the default originate \n Error: {}".format( + tc_name, result + ) step("Verify the default route is received in BGP RIB and FIB") step( @@ -1167,7 +1243,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format( tc_name, result ) @@ -1178,7 +1256,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format( tc_name, result ) step("Remove route-map RMv4 and RMv6 from default-originate command in R1") @@ -1196,7 +1276,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format( + tc_name, result + ) step( "Verify BGP RIB and FIB After removing route-map , default route still present on R2" @@ -1221,7 +1305,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format( tc_name, result ) @@ -1232,7 +1318,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format( tc_name, result ) @@ -1266,7 +1354,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format( + tc_name, result + ) step( "After configuring default-originate command , verify default routes are advertised on R2 " @@ -1290,7 +1382,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format( tc_name, result ) @@ -1301,7 +1395,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], ) - assert result is True, "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format( tc_name, result ) @@ -1345,7 +1441,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to delete the prefix list Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to delete the prefix list Error: {}".format( + tc_name, result + ) step( "Verify BGP RIB and FIB After deleting prefix-list , verify IPv4 and IPv6 default route got removed from DUT " @@ -1426,7 +1526,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the prefix lists Error: {}".format( + tc_name, result + ) step( "After configuring the Prefixlist cross checking the BGP Default route is configured again , before deleting the route map" @@ -1452,7 +1556,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], expected=True, ) - assert result is True, "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format( tc_name, result ) @@ -1464,14 +1570,20 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request): next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], expected=True, ) - assert result is True, "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format( tc_name, result ) step("Deleting the routemap") input_dict = {"r1": {"route_maps": ["RMv4", "RMv6"]}} result = delete_route_maps(tgen, input_dict) - assert result is True, "Testcase {} : Failed to delete the Route-map \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to delete the Route-map \n Error: {}".format( + tc_name, result + ) step( "Verify BGP RIB and FIB ,After deleting route-map , verify IPv4 and IPv6 default route got removed from DUT" @@ -1605,7 +1717,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_static_routes(tgen, static_routes_input) - assert result is True, "Testcase {} : Failed to configure the static routes \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed to configure the static routes \n Error: {}".format( tc_name, result ) step("verify IPv4 and IPv6 static route are configured and up on R4") @@ -1625,8 +1739,10 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input) - assert result is True, "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format( - tc_name, static_routes_input,result + assert ( + result is True + ), "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format( + tc_name, static_routes_input, result ) step( @@ -1643,7 +1759,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, redistribute_static) - assert result is True, "Testcase {} : Failed to configure the redistribute static \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the redistribute static \n Error: {}".format( + tc_name, result + ) step("verify IPv4 and IPv6 static route are configured and up on R3") for addr_type in ADDR_TYPES: @@ -1662,11 +1782,15 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input) - assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format( tc_name, result ) result = verify_bgp_rib(tgen, addr_type, "r3", static_routes_input) - assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format( tc_name, result ) @@ -1698,12 +1822,20 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the prefix lists \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the prefix lists \n Error: {}".format( + tc_name, result + ) step("verify IPv4 and IPv6 Prefix list got configured on R3") input_dict = {"r3": {"prefix_lists": ["Pv4", "Pv6"]}} result = verify_prefix_lists(tgen, input_dict) - assert result is True, "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format(tc_name,input_dict, result) + assert ( + result is True + ), "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format( + tc_name, input_dict, result + ) step( "Configure IPv4 and IPv6 route-map ( RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6 ) respectively on R3" @@ -1729,7 +1861,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_route_maps(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the route-map \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the route-map \n Error: {}".format( + tc_name, result + ) step( "Taking the snapshot of the prefix count before configuring the default originate" ) @@ -1754,7 +1890,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed to configure default-originate \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure default-originate \n Error: {}".format( + tc_name, result + ) step("Verify the default route is NOT received in BGP RIB and FIB on R2 ") step( @@ -1836,7 +1976,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to configure the prefix lists Error: {}".format( + tc_name, result + ) step("Verify BGP default route for IPv4 and IPv6 is received on R2") @@ -1859,7 +2003,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type], ) - assert result is True, "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format( tc_name, result ) @@ -1870,7 +2016,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): static_routes_input, next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type], ) - assert result is True, "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format( + assert ( + result is True + ), "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format( tc_name, result ) @@ -1914,7 +2062,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request): } } result = create_prefix_lists(tgen, input_dict_3) - assert result is True, "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format( + tc_name, result + ) step( "After Removing route BGP default route for IPv4 and IPv6 is NOT received on R2" diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py index 59f833b93c..4e8bda55cf 100644 --- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py +++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py @@ -955,6 +955,7 @@ def test_verify_bgp_default_originate_route_map_in_OUT_p1(request): write_test_footer(tc_name) + def test_verify_bgp_default_originate_route_map_in_IN_p1(request): """Verify BGP default originate route-map with IN route-map""" tgen = get_topogen() @@ -1472,6 +1473,7 @@ def test_verify_bgp_default_originate_route_map_in_IN_p1(request): ) write_test_footer(tc_name) + def test_verify_default_originate_after_removing_default_originate_p1(request): """Verify BGP default route after removing default-originate""" @@ -2232,9 +2234,9 @@ def test_verify_default_originate_after_removing_default_originate_p1(request): ) write_test_footer(tc_name) + def test_verify_default_originate_route_with_GR_p1(request): - """ "Verify default-originate route with GR " - """ + """ "Verify default-originate route with GR " """ tgen = get_topogen() global BGP_CONVERGENCE global topo @@ -2250,14 +2252,13 @@ def test_verify_default_originate_route_with_GR_p1(request): if BGP_CONVERGENCE != True: pytest.skip("skipped because of BGP Convergence failure") - step("Configure IPV4 and IPV6 IBGP between R1 and R2 ") step("Configure IPV4 and IPV6 EBGP between R2 to R3 ") - r0_local_as = topo['routers']['r0']['bgp']['local_as'] - r1_local_as = topo['routers']['r1']['bgp']['local_as'] - r2_local_as = topo['routers']['r2']['bgp']['local_as'] - r3_local_as = topo['routers']['r3']['bgp']['local_as'] - r4_local_as = topo['routers']['r4']['bgp']['local_as'] + r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"] + r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"] + r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"] + r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"] + r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"] input_dict = { "r0": { "bgp": { @@ -2336,33 +2337,14 @@ def test_verify_default_originate_route_with_GR_p1(request): "bgp": { "local_as": local_as, "address_family": { - "ipv4": { - "unicast": { - "default_originate":{ - "r2":{ - - } - - } - - } - }, "ipv6": { - "unicast": { - "default_originate":{ - "r2":{ - - } - - } - } - } - } + "ipv4": {"unicast": {"default_originate": {"r2": {}}}}, + "ipv6": {"unicast": {"default_originate": {"r2": {}}}}, + }, } } } result = create_router_bgp(tgen, topo, default_originate_config) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) step( "R2 received default-originate routes and advertised it to R3 , verify on R2 and R3" @@ -2383,17 +2365,28 @@ def test_verify_default_originate_route_with_GR_p1(request): } } - result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type]) + result = verify_fib_routes( + tgen, + addr_type, + "r2", + static_routes_input, + next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], + ) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) - result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type]) + result = verify_bgp_rib( + tgen, + addr_type, + "r2", + static_routes_input, + next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], + ) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) - step(" Kill BGPd session on R2") kill_router_daemons(tgen, "r2", ["bgpd"]) start_router_daemons(tgen, "r2", ["bgpd"]) @@ -2411,17 +2404,30 @@ def test_verify_default_originate_route_with_GR_p1(request): } } - result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type]) + result = verify_fib_routes( + tgen, + addr_type, + "r2", + static_routes_input, + next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], + ) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) - result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type]) + result = verify_bgp_rib( + tgen, + addr_type, + "r2", + static_routes_input, + next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type], + ) assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) write_test_footer(tc_name) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py index 82c4e7e0ab..f67a431c7e 100644 --- a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py +++ b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py @@ -75,6 +75,7 @@ NETWORK1_1 = {"ipv4": "198.51.1.1/32", "ipv6": "2001:DB8::1:1/128"} DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} + def setup_module(mod): """ Sets up the pytest environment @@ -818,11 +819,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): step("Configure IPv4 and IPv6 , EBGP neighbor between R3 and R2") step("Configure IPv4 and IPv6 IBGP neighbor between R3 and R4") - r0_local_as = topo['routers']['r0']['bgp']['local_as'] - r1_local_as = topo['routers']['r1']['bgp']['local_as'] - r2_local_as = topo['routers']['r2']['bgp']['local_as'] - r3_local_as = topo['routers']['r3']['bgp']['local_as'] - r4_local_as = topo['routers']['r4']['bgp']['local_as'] + r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"] + r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"] + r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"] + r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"] + r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"] input_dict = { "r0": { "bgp": { @@ -1026,22 +1027,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "action": "permit", "seq_id": "1", "set": { - "path": { - "as_num": "200", - "as_action": "prepend", - } + "path": { + "as_num": "200", + "as_action": "prepend", } - + }, }, { "action": "permit", "seq_id": "2", "set": { - "path": { - "as_num": "300", - "as_action": "prepend", - } + "path": { + "as_num": "300", + "as_action": "prepend", } + }, }, ], "RMv6": [ @@ -1049,21 +1049,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "action": "permit", "seq_id": "1", "set": { - "path": { - "as_num": "200", - "as_action": "prepend", - } + "path": { + "as_num": "200", + "as_action": "prepend", } + }, }, { "action": "permit", "seq_id": "2", "set": { - "path": { - "as_num": "300", - "as_action": "prepend", - } + "path": { + "as_num": "300", + "as_action": "prepend", } + }, }, ], } @@ -1122,22 +1122,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "action": "permit", "seq_id": "1", "set": { - "path": { - "as_num": "500", - "as_action": "prepend", - } + "path": { + "as_num": "500", + "as_action": "prepend", } - + }, }, { "action": "permit", "seq_id": "2", "set": { - "path": { - "as_num": "600", - "as_action": "prepend", - } + "path": { + "as_num": "600", + "as_action": "prepend", } + }, }, ], "RMv6": [ @@ -1145,21 +1144,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "action": "permit", "seq_id": "1", "set": { - "path": { - "as_num": "500", - "as_action": "prepend", - } + "path": { + "as_num": "500", + "as_action": "prepend", } + }, }, { "action": "permit", "seq_id": "2", "set": { - "path": { - "as_num": "600", - "as_action": "prepend", - } + "path": { + "as_num": "600", + "as_action": "prepend", } + }, }, ], } @@ -1170,7 +1169,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) - step("As path 500 added to IPv4 and IPv6 default -originate route received on R2") result = verify_rib_default_route( tgen, @@ -1232,7 +1230,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " ) - DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"} result = verify_rib_default_route( tgen, @@ -1244,7 +1241,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): expected_aspath="4000 500", ) - step( "Modify route-map seq1 configure metric 50 and route-map seq2 configure metric 100 IPv4 and IPv6 route-map " ) @@ -1294,7 +1290,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " ) - result = verify_rib_default_route( tgen, topo, @@ -1314,7 +1309,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): { "action": "permit", "seq_id": "1", - "set": { "path": { "as_num": "500", @@ -1374,9 +1368,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify AS-prepend is deleted from default originate route and metric value only present on R2 for IPv4 and IPv6 default routes " ) - - - result = verify_rib_default_route( tgen, topo, @@ -1388,7 +1379,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): ) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) - step("Delete metric value from IP4 and IPv6 route-map configured on R3 ") route_map = { "r3": { @@ -1428,8 +1418,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify Metric value deleted from IPv4 and IPv6 default route on R2 ,verify default routes " ) - - result = verify_rib_default_route( tgen, topo, @@ -1443,11 +1431,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) step("Change IPv4 and IPv6 , EBGP to IBGP neighbor between R3 and R2") step("Change IPv4 and IPv6 IBGP to EBGP neighbor between R3 and R4") - r0_local_as = topo['routers']['r0']['bgp']['local_as'] - r1_local_as = topo['routers']['r1']['bgp']['local_as'] - r2_local_as = topo['routers']['r2']['bgp']['local_as'] - r3_local_as = topo['routers']['r3']['bgp']['local_as'] - r4_local_as = topo['routers']['r4']['bgp']['local_as'] + r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"] + r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"] + r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"] + r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"] + r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"] input_dict = { "r0": { "bgp": { @@ -1459,7 +1447,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "local_as": r1_local_as, } }, - "r2": { "bgp": { "local_as": 1111, @@ -1645,8 +1632,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " ) - - result = verify_rib_default_route( tgen, topo, @@ -1656,7 +1641,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): locPrf=50, ) - assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) step( @@ -1708,9 +1692,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "Verify Modified local-preference value received on R2 for IPv4 and IPv6 default routes " ) - - - DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"} result = verify_rib_default_route( tgen, @@ -1724,13 +1705,15 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) # updating the topology with the updated AS-Number to avoid conflict in con configuring the AS updated_topo = topo - updated_topo['routers']['r0']['bgp']['local_as']=get_dut_as_number(tgen,"r0") - updated_topo['routers']['r1']['bgp']['local_as']=get_dut_as_number(tgen,"r1") - updated_topo['routers']['r2']['bgp']['local_as']=get_dut_as_number(tgen,"r2") - updated_topo['routers']['r3']['bgp']['local_as']=get_dut_as_number(tgen,"r3") - updated_topo['routers']['r4']['bgp']['local_as']=get_dut_as_number(tgen,"r4") + updated_topo["routers"]["r0"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r0") + updated_topo["routers"]["r1"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r1") + updated_topo["routers"]["r2"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r2") + updated_topo["routers"]["r3"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r3") + updated_topo["routers"]["r4"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r4") - step("Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ") + step( + "Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command " + ) local_as = get_dut_as_number(tgen, dut="r4") shut_neighbor = { "r4": { @@ -1740,46 +1723,41 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "ipv4": { "unicast": { "neighbor": { - "r3": { - "dest_link": { - "r4": {"shutdown":True} - } - } + "r3": {"dest_link": {"r4": {"shutdown": True}}} } } }, "ipv6": { "unicast": { "neighbor": { - "r3": { - "dest_link": { - "r4": {"shutdown":True} - } - } + "r3": {"dest_link": {"r4": {"shutdown": True}}} } } - } - } + }, + }, } } } result = create_router_bgp(tgen, updated_topo, shut_neighbor) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - interface = topo['routers']['r3']['links']['r4']['interface'] - input_dict = { - "r1": { - "interface_list": [interface], - "status": "down" - } - } + interface = topo["routers"]["r3"]["links"]["r4"]["interface"] + input_dict = {"r1": {"interface_list": [interface], "status": "down"}} result = interface_status(tgen, topo, input_dict) - assert result is True, "Testcase {} : Shut down the interface failed ! \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Shut down the interface failed ! \n Error: {}".format( + tc_name, result + ) step("After shutting the interface verify the BGP convergence") - result = verify_bgp_convergence(tgen,topo,expected=False) - assert result is not True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result) + result = verify_bgp_convergence(tgen, topo, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format( + tc_name, result + ) step("verify default route deleted from R2 ") result = verify_rib_default_route( @@ -1788,8 +1766,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected=False) - assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -1797,11 +1780,17 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected=False) - assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format( tc_name, result) - + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format( + tc_name, result + ) - step("no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ") + step( + "no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command " + ) local_as = get_dut_as_number(tgen, dut="r4") shut_neighbor = { "r4": { @@ -1811,46 +1800,39 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "ipv4": { "unicast": { "neighbor": { - "r3": { - "dest_link": { - "r4": {"shutdown":False} - } - } + "r3": {"dest_link": {"r4": {"shutdown": False}}} } } }, "ipv6": { "unicast": { "neighbor": { - "r3": { - "dest_link": { - "r4": {"shutdown":False} - } - } + "r3": {"dest_link": {"r4": {"shutdown": False}}} } } - } - } + }, + }, } } } result = create_router_bgp(tgen, updated_topo, shut_neighbor) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - interface = topo['routers']['r3']['links']['r4']['interface'] - input_dict = { - "r1": { - "interface_list": [interface], - "status": "up" - } - } + interface = topo["routers"]["r3"]["links"]["r4"]["interface"] + input_dict = {"r1": {"interface_list": [interface], "status": "up"}} result = interface_status(tgen, topo, input_dict) - assert result is True, "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result) + assert ( + result is True + ), "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result) step("After no shutting the interface verify the BGP convergence") - result = verify_bgp_convergence(tgen,topo,expected=True) - assert result is True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result) + result = verify_bgp_convergence(tgen, topo, expected=True) + assert ( + result is True + ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format( + tc_name, result + ) step("After no shut neighbor , verify default route relearn on R2") result = verify_rib_default_route( @@ -1859,8 +1841,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected=True) - assert result is True, "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format( tc_name, result) + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -1868,10 +1855,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected=True) - assert result is True, "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format( tc_name, result) - - + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format( + tc_name, result + ) step("Remove IPv4/IPv6 static route configure on R4") for addr_type in ADDR_TYPES: @@ -1881,7 +1871,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): { "network": [NETWORK1_1[addr_type]], "next_hop": NEXT_HOP_IP[addr_type], - "delete": True + "delete": True, } ] } @@ -1902,12 +1892,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): ] } } - result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=False) - assert result is not True, "Testcase {} : Failed \n Error: {}".format( + result = verify_fib_routes( + tgen, addr_type, "r4", static_routes_input, expected=False + ) + assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) - result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=False) - assert result is not True, "Testcase {} : Failed \n Error: {}".format( + result = verify_bgp_rib( + tgen, addr_type, "r4", static_routes_input, expected=False + ) + assert result is not True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) @@ -1918,8 +1912,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= False) - assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -1927,9 +1926,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= False) - assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format( tc_name, result) - + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format( + tc_name, result + ) step("Configuring the static route back in r4") for addr_type in ADDR_TYPES: @@ -1959,12 +1962,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): ] } } - result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=True) - assert result is True, "Testcase {} : Failed \n Error: {}".format( + result = verify_fib_routes( + tgen, addr_type, "r4", static_routes_input, expected=True + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) - result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=True) - assert result is True, "Testcase {} : Failed \n Error: {}".format( + result = verify_bgp_rib( + tgen, addr_type, "r4", static_routes_input, expected=True + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) @@ -1975,8 +1982,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= True) - assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format( tc_name, result) + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -1984,8 +1996,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= True) - assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format( tc_name, result) + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format( + tc_name, result + ) step("Deactivate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)") @@ -1999,15 +2016,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "r3": {"dest_link": {"r4": {"deactivate": "ipv4"}}} } }, - - },"ipv6": { + }, + "ipv6": { "unicast": { "neighbor": { "r3": {"dest_link": {"r4": {"deactivate": "ipv6"}}} } }, - - } + }, } } } @@ -2022,8 +2038,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= False) - assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -2031,8 +2052,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= False) - assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format( tc_name, result) + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format( + tc_name, result + ) step("Activate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)") @@ -2046,15 +2072,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): "r3": {"dest_link": {"r4": {"activate": "ipv4"}}} } }, - - },"ipv6": { + }, + "ipv6": { "unicast": { "neighbor": { "r3": {"dest_link": {"r4": {"activate": "ipv6"}}} } }, - - } + }, } } } @@ -2064,7 +2089,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): step("Verify bgp convergence.") bgp_convergence = verify_bgp_convergence(tgen, updated_topo) - assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format( + assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format( tc_name, bgp_convergence ) step("After Activating the BGP neighbor , verify default route learned on R2") @@ -2074,8 +2099,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= True) - assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format( tc_name, result) + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format( + tc_name, result + ) result = verify_fib_default_route( tgen, @@ -2083,10 +2113,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request): dut="r2", routes=DEFAULT_ROUTES, expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, - expected= True) - assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format( tc_name, result) + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format( + tc_name, result + ) write_test_footer(tc_name) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py index 9a0f5621dc..8269322215 100644 --- a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py +++ b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} @@ -194,6 +192,7 @@ def test_bgp_check_fqdn(): _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) assert result is None, "FQDN capability disabled, but we still have a hostname" + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py index 7511d57e3e..4d7d46c3e8 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py @@ -20,7 +20,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -29,8 +29,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py index 338886d5f4..26fae17c5e 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py index 4644ef3293..d67bfea45e 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py @@ -18,7 +18,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -28,8 +28,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py index ba95bd1614..9e1f26f21e 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py index aa9ad5f0e8..f6c1e25fd6 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py index 737e694701..128283bbc3 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py index 34f7dc8cd4..d9ccd6979c 100644 --- a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py +++ b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py @@ -35,8 +35,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 4): diff --git a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py index 7d8ddac4c8..b033e9c2eb 100644 --- a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py +++ b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py @@ -37,8 +37,6 @@ from lib import topotest # Required to instantiate the topology builder class. from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd, pytest.mark.pimd] - ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py index 2041a4091d..603f069fe3 100755 --- a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py +++ b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py @@ -179,7 +179,7 @@ def setup_module(mod): pe.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept)) # For all registered routers, load the zebra configuration file - for (name, router) in tgen.routers().items(): + for name, router in tgen.routers().items(): router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(name)) ) @@ -230,11 +230,11 @@ def evpn_gateway_ip_show_op_check(trigger=" "): "zebra_vrf_ipv6": "show ipv6 route vrf vrf-blue json", } - for (name, pe) in tgen.gears.items(): + for name, pe in tgen.gears.items(): if name not in PES: continue - for (cmd_key, command) in show_commands.items(): + for cmd_key, command in show_commands.items(): expected_op_file = "{0}/{1}/{2}_{3}.json".format( CWD, name, cmd_key, trigger ) diff --git a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py index 5781684a88..2df0fd0e6c 100644 --- a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py +++ b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")} diff --git a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py index eb05986fe1..a5e5bdcee9 100644 --- a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py +++ b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py @@ -124,7 +124,8 @@ def test_rt_extcomm_list_delete(): # check for the deletion of the extended community test_func = functools.partial( - _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1") + _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1" + ) _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) assert result, "RT extended community 1.1.1.1:1 was not stripped." @@ -138,7 +139,8 @@ def test_soo_extcomm_list_delete(): # check for the deletion of the extended community test_func = functools.partial( - _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2") + _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2" + ) _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) assert result, "SoO extended community 2.2.2.2:2 was not stripped." @@ -152,7 +154,8 @@ def test_nt_extcomm_list_delete(): # check for the deletion of the extended community test_func = functools.partial( - _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3") + _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3" + ) _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) assert result, "NT extended community 3.3.3.3:0 was not stripped." diff --git a/tests/topotests/bgp_extended_link_bandwidth/__init__.py b/tests/topotests/bgp_extended_link_bandwidth/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/__init__.py diff --git a/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf new file mode 100644 index 0000000000..d0c0813e84 --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf @@ -0,0 +1,32 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +router bgp 65000 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as internal + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.1.2 extended-link-bandwidth + address-family ipv4 unicast + network 10.10.10.40/32 + network 10.10.10.100/32 + network 10.10.10.200/32 + neighbor 192.168.1.2 route-map r2 out + exit-address-family +! +ip prefix-list p40 seq 5 permit 10.10.10.40/32 +ip prefix-list p100 seq 5 permit 10.10.10.100/32 +ip prefix-list p200 seq 5 permit 10.10.10.200/32 +! +route-map r2 permit 10 + match ip address prefix-list p40 + set extcommunity bandwidth 40000 +route-map r2 permit 20 + match ip address prefix-list p100 + set extcommunity bandwidth 100000 +route-map r2 permit 30 + match ip address prefix-list p200 + set extcommunity bandwidth 200000 +exit diff --git a/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf new file mode 100644 index 0000000000..5cad150aef --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf @@ -0,0 +1,10 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! +router bgp 65000 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as internal + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 +! diff --git a/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py new file mode 100644 index 0000000000..e7058f5392 --- /dev/null +++ b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +import os +import re +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_dynamic_capability_role(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail")) + expected = { + "routes": { + "10.10.10.40/32": { + "paths": [ + { + "extendedIpv6Community": { + "string": "LB:65000:5000000000 (40.000 Gbps)", + } + } + ] + }, + "10.10.10.100/32": { + "paths": [ + { + "extendedIpv6Community": { + "string": "LB:65000:12500000000 (100.000 Gbps)", + } + } + ] + }, + "10.10.10.200/32": { + "paths": [ + { + "extendedIpv6Community": { + "string": "LB:65000:25000000000 (200.000 Gbps)", + } + } + ] + }, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_converge, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see link bandwidths as expected" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py index eef122b369..a5db20e474 100644 --- a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py +++ b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py @@ -17,7 +17,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf index 50d1583873..3d4d3a8ee5 100644 --- a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf +++ b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf @@ -1,3 +1,10 @@ +! +interface lo + ip address 172.16.255.1/32 +! +interface r1-eth0 + ip address 192.168.255.1/24 +! router bgp 65001 no bgp ebgp-requires-policy bgp graceful-restart diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf deleted file mode 100644 index e65bfb2c3a..0000000000 --- a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf +++ /dev/null @@ -1,7 +0,0 @@ -! -interface lo - ip address 172.16.255.1/32 -! -interface r1-eth0 - ip address 192.168.255.1/24 -! diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf index 97418ca9a0..f5ba4eae05 100644 --- a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf +++ b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf @@ -1,3 +1,8 @@ +no zebra nexthop kernel enable +! +interface r2-eth0 + ip address 192.168.255.2/24 +! router bgp 65002 no bgp ebgp-requires-policy bgp graceful-restart diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf deleted file mode 100644 index 758d797ad6..0000000000 --- a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf +++ /dev/null @@ -1,5 +0,0 @@ -no zebra nexthop kernel enable -! -interface r2-eth0 - ip address 192.168.255.2/24 -! diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf new file mode 100644 index 0000000000..1d84ec6eee --- /dev/null +++ b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf @@ -0,0 +1,19 @@ +no zebra nexthop kernel enable +! +interface lo + ip address 172.16.255.3/32 +! +interface r3-eth0 + ip address 192.168.34.3/24 +! +router bgp 65003 + no bgp ebgp-requires-policy + bgp graceful-restart preserve-fw-state + neighbor 192.168.34.4 remote-as external + neighbor 192.168.34.4 timers 1 3 + neighbor 192.168.34.4 timers connect 1 + neighbor 192.168.34.4 graceful-restart + address-family ipv4 + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf new file mode 100644 index 0000000000..58907916f4 --- /dev/null +++ b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf @@ -0,0 +1,13 @@ +no zebra nexthop kernel enable +! +interface r4-eth0 + ip address 192.168.34.4/24 +! +router bgp 65004 + no bgp ebgp-requires-policy + bgp graceful-restart preserve-fw-state + neighbor 192.168.34.3 remote-as external + neighbor 192.168.34.3 timers 1 3 + neighbor 192.168.34.3 timers connect 1 + neighbor 192.168.34.3 graceful-restart +! diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py new file mode 100644 index 0000000000..2354c0cd3d --- /dev/null +++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +""" +Test if routes are retained during BGP restarts using + Graceful Restart per-neighbor. +""" + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.common_config import step, stop_router + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + for routern in range(1, 5): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_gr_restart_retain_routes(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r4 = tgen.gears["r4"] + + def _bgp_converge(): + output = json.loads(r4.vtysh_cmd("show bgp ipv4 neighbors 192.168.34.3 json")) + expected = { + "192.168.34.3": { + "bgpState": "Established", + "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}}, + } + } + return topotest.json_cmp(output, expected) + + def _bgp_check_bgp_retained_routes(): + output = json.loads(r4.vtysh_cmd("show bgp ipv4 unicast 172.16.255.3/32 json")) + expected = {"paths": [{"stale": True}]} + return topotest.json_cmp(output, expected) + + def _bgp_check_kernel_retained_routes(): + output = json.loads( + r4.cmd("ip -j route show 172.16.255.3/32 proto bgp dev r4-eth0") + ) + expected = [{"dst": "172.16.255.3", "gateway": "192.168.34.3", "metric": 20}] + return topotest.json_cmp(output, expected) + + step("Initial BGP converge") + test_func = functools.partial(_bgp_converge) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed to see BGP convergence on R4" + + step("Restart R3") + stop_router(tgen, "r3") + + step("Check if routes (BGP) are retained at R4") + test_func = functools.partial(_bgp_check_bgp_retained_routes) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed to see BGP retained routes on R4" + + step("Check if routes (Kernel) are retained at R4") + assert ( + _bgp_check_kernel_retained_routes() is None + ), "Failed to retain BGP routes in kernel on R4" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py index a820b4b221..abf737ff34 100644 --- a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py +++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py @@ -42,13 +42,8 @@ def setup_module(mod): router_list = tgen.routers() - for i, (rname, router) in enumerate(router_list.items(), 1): - router.load_config( - TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) - ) - router.load_config( - TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) - ) + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) tgen.start_router() @@ -83,8 +78,10 @@ def test_bgp_gr_restart_retain_routes(): return topotest.json_cmp(output, expected) def _bgp_check_kernel_retained_routes(): - output = json.loads(r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0")) - expected = [{"dst":"172.16.255.1","gateway":"192.168.255.1","metric":20}] + output = json.loads( + r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0") + ) + expected = [{"dst": "172.16.255.1", "gateway": "192.168.255.1", "metric": 20}] return topotest.json_cmp(output, expected) step("Initial BGP converge") @@ -101,7 +98,9 @@ def test_bgp_gr_restart_retain_routes(): assert result is None, "Failed to see BGP retained routes on R2" step("Check if routes (Kernel) are retained at R2") - assert _bgp_check_kernel_retained_routes() is None, "Failed to retain BGP routes in kernel on R2" + assert ( + _bgp_check_kernel_retained_routes() is None + ), "Failed to retain BGP routes in kernel on R2" if __name__ == "__main__": diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py index 6cd92e293d..c9666601aa 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py @@ -7,18 +7,36 @@ luCommand("ce1", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up luCommand("ce2", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180) luCommand("ce3", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180) luCommand( - "r1", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60) + "r1", + 'vtysh -c "show ip route ospf"', + "2.2.2.2", + "wait", + "OSPF Route has Arrived", + 60, +) luCommand( "r1", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60 ) luCommand( - "r3", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60) + "r3", + 'vtysh -c "show ip route ospf"', + "2.2.2.2", + "wait", + "OSPF Route has Arrived", + 60, +) luCommand( "r3", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60 ) luCommand( - "r4", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60) + "r4", + 'vtysh -c "show ip route ospf"', + "2.2.2.2", + "wait", + "OSPF Route has Arrived", + 60, +) luCommand( "r4", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60 ) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py index e05bf21ea9..2ce4bc59be 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py @@ -70,7 +70,7 @@ else: "See all sharp routes in rib on ce1", wait, wait_time=10, - ) + ) luCommand( "ce2", 'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33', @@ -79,7 +79,7 @@ else: "See all sharp routes in rib on ce2", wait, wait_time=10, - ) + ) rtrs = ["ce1", "ce2", "ce3"] for rtr in rtrs: diff --git a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py index 483c048d25..7023e3a503 100644 --- a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py +++ b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py @@ -137,7 +137,9 @@ def test_bgp_large_comm_list_match_any(): step("BGP filtering check with large-community-list on R3") test_func = functools.partial(_bgp_converge) _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) - assert result is None, "Failed to filter BGP UPDATES with large-community-list on R3" + assert ( + result is None + ), "Failed to filter BGP UPDATES with large-community-list on R3" if __name__ == "__main__": diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json index dfc4171bad..6289a2eea3 100644 --- a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json +++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json @@ -4,7 +4,7 @@ { "valid":true, "multipath":true, - "extendedCommunity":{ + "extendedIpv6Community":{ "string":"LB:65302:125000 (1.000 Mbps)" }, "nexthops":[ diff --git a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf index 4014bfbc8b..e4ed92db1d 100644 --- a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf +++ b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf @@ -13,6 +13,7 @@ router bgp 65302 bgp bestpath as-path multipath-relax no bgp ebgp-requires-policy neighbor 11.1.2.5 remote-as external + neighbor 11.1.2.5 extended-link-bandwidth neighbor 11.1.2.5 timers 3 10 neighbor 11.1.5.2 remote-as external neighbor 11.1.5.2 timers 3 10 diff --git a/tests/topotests/bgp_llgr/test_bgp_llgr.py b/tests/topotests/bgp_llgr/test_bgp_llgr.py index d604871303..d7897cfcb9 100644 --- a/tests/topotests/bgp_llgr/test_bgp_llgr.py +++ b/tests/topotests/bgp_llgr/test_bgp_llgr.py @@ -36,8 +36,6 @@ from lib.common_config import ( step, ) -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(0, 6): diff --git a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py index 26e8fe9701..c84fce6a9d 100644 --- a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py +++ b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py @@ -35,7 +35,7 @@ from lib.common_config import ( verify_rib, step, check_address_types, - check_router_status + check_router_status, ) from lib.topolog import logger diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py index cb8fa1e9f9..cfaab9bbe2 100644 --- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py +++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py @@ -48,7 +48,7 @@ from lib.common_config import ( verify_rib, step, check_address_types, - check_router_status + check_router_status, ) from lib.topolog import logger @@ -163,7 +163,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -190,7 +192,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py index e9234f5172..bacef47664 100644 --- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py +++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py @@ -229,7 +229,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -256,7 +258,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } @@ -832,7 +836,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request): "neighbor": { "r2": { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -861,7 +867,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request): "neighbor": { "r4": { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -1395,7 +1403,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -1422,7 +1432,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } @@ -1593,7 +1605,10 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request): { "action": "permit", "set": { - "path": {"as_num": "1.1000 1.1000", "as_action": "prepend"} + "path": { + "as_num": "1.1000 1.1000", + "as_action": "prepend", + } }, } ] @@ -1778,7 +1793,9 @@ def test_verify_bgp_local_as_in_iBGP_p0(request): "neighbor": { "r4": { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -2137,7 +2154,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request): "neighbor": { "r2": { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -2166,7 +2185,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request): "neighbor": { "r4": { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -2484,7 +2505,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -2511,7 +2534,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } @@ -2824,7 +2849,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -2851,7 +2878,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } @@ -3164,7 +3193,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -3191,7 +3222,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } @@ -3354,7 +3387,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request): "neighbor": { neighbor: { "dest_link": { - "r3": {"local_asn": {"local_as": "1.110"}} + "r3": { + "local_asn": {"local_as": "1.110"} + } } } } @@ -3381,7 +3416,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request): "neighbor": { neighbor: { "dest_link": { - dut: {"local_asn": {"remote_as": "1.110"}} + dut: { + "local_asn": {"remote_as": "1.110"} + } } } } diff --git a/tests/topotests/bgp_oad/test_bgp_oad.py b/tests/topotests/bgp_oad/test_bgp_oad.py index b26c548357..a2ca37a2b7 100644 --- a/tests/topotests/bgp_oad/test_bgp_oad.py +++ b/tests/topotests/bgp_oad/test_bgp_oad.py @@ -17,7 +17,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -27,8 +27,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2", "r4"), "s2": ("r2", "r3"), "s3": ("r4", "r5")} diff --git a/tests/topotests/bgp_orf/test_bgp_orf.py b/tests/topotests/bgp_orf/test_bgp_orf.py index 7f45a242c9..47c0556884 100644 --- a/tests/topotests/bgp_orf/test_bgp_orf.py +++ b/tests/topotests/bgp_orf/test_bgp_orf.py @@ -20,7 +20,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -29,8 +29,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg index 7fb9210ecf..dccec7d154 100644 --- a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg +++ b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg @@ -1,8 +1,8 @@ neighbor 10.0.0.1 { - router-id 10.0.0.2; - local-address 10.0.0.2; - local-as 65001; - peer-as 65002; + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65001; capability { route-refresh; @@ -12,13 +12,28 @@ neighbor 10.0.0.1 { route 192.168.100.101/32 { atomic-aggregate; community 65001:101; - next-hop 10.0.0.2; + next-hop 10.0.0.254; } route 192.168.100.102/32 { - originator-id 10.0.0.2; + originator-id 10.0.0.254; community 65001:102; - next-hop 10.0.0.2; + next-hop 10.0.0.254; + } + } +} + +neighbor 10.0.0.2 { + router-id 10.0.0.254; + local-address 10.0.0.254; + local-as 65254; + peer-as 65254; + + static { + route 192.168.100.101/32 { + # AIGP invalid attribute: flagged as transitive + optional. + attribute [0x1a 0xc0 0x00000064]; + next-hop 10.0.0.254; } } } diff --git a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf b/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf deleted file mode 100644 index c96f354cc5..0000000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf +++ /dev/null @@ -1,6 +0,0 @@ -! -router bgp 65002 - no bgp ebgp-requires-policy - neighbor 10.0.0.2 remote-as external - neighbor 10.0.0.2 timers 3 10 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/frr.conf b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf new file mode 100644 index 0000000000..ae7fbdd9a9 --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r1/frr.conf @@ -0,0 +1,9 @@ +! +interface r1-eth0 + ip address 10.0.0.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as external + neighbor 10.0.0.254 timers 3 10 +! diff --git a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf b/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf deleted file mode 100644 index 51a1b2657c..0000000000 --- a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf +++ /dev/null @@ -1,4 +0,0 @@ -! -interface r1-eth0 - ip address 10.0.0.1/24 -! diff --git a/tests/topotests/bgp_path_attribute_discard/r2/frr.conf b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf new file mode 100644 index 0000000000..1dafbdd8e1 --- /dev/null +++ b/tests/topotests/bgp_path_attribute_discard/r2/frr.conf @@ -0,0 +1,10 @@ +! +interface r2-eth0 + ip address 10.0.0.2/24 +! +router bgp 65254 + no bgp ebgp-requires-policy + neighbor 10.0.0.254 remote-as internal + neighbor 10.0.0.254 timers 3 10 + neighbor 10.0.0.254 path-attribute discard 26 +! diff --git a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py index c97cd0bdda..bd8cd8e18a 100644 --- a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py +++ b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py @@ -31,10 +31,12 @@ pytestmark = [pytest.mark.bgpd] def build_topo(tgen): r1 = tgen.add_router("r1") - peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1") + r2 = tgen.add_router("r2") + peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.254", defaultRoute="via 10.0.0.1") switch = tgen.add_switch("s1") switch.add_link(r1) + switch.add_link(r2) switch.add_link(peer1) @@ -42,10 +44,10 @@ def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) tgen.start_topology() - router = tgen.gears["r1"] - router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")) - router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf")) - router.start() + for _, (rname, router) in enumerate(tgen.routers().items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() peer = tgen.gears["peer1"] peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env")) @@ -63,6 +65,7 @@ def test_bgp_path_attribute_discard(): pytest.skip(tgen.errors) r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] def _bgp_converge(): output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json detail")) @@ -103,7 +106,7 @@ def test_bgp_path_attribute_discard(): """ configure terminal router bgp - neighbor 10.0.0.2 path-attribute discard 6 8 + neighbor 10.0.0.254 path-attribute discard 6 8 """ ) @@ -139,6 +142,28 @@ def test_bgp_path_attribute_discard(): result is None ), "Failed to discard path attributes (atomic-aggregate, community)" + def _bgp_check_if_aigp_invalid_attribute_discarded(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail")) + expected = { + "routes": { + "192.168.100.101/32": { + "paths": [ + { + "valid": True, + "aigpMetric": None, + } + ], + }, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_check_if_aigp_invalid_attribute_discarded) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) + assert ( + result is None + ), "Failed to discard AIGP invalid path attribute (iBGP session)" + def test_memory_leak(): "Run the memory leak test and report results." diff --git a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py index df390327d4..8504737d82 100644 --- a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py +++ b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py @@ -78,6 +78,7 @@ pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] # Address read from env variables ADDR_TYPES = check_address_types() + #### def setup_module(mod): """ diff --git a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py index bf5737b660..30083b4de2 100644 --- a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py +++ b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py @@ -49,7 +49,11 @@ def setup_module(mod): for routern in range(1, 4): tgen.gears["r{}".format(routern)].cmd("ip link add vrf1 type vrf table 10") tgen.gears["r{}".format(routern)].cmd("ip link set vrf1 up") - tgen.gears["r{}".format(routern)].cmd("ip address add dev vrf1 {}.{}.{}.{}/32".format(routern, routern, routern,routern)) + tgen.gears["r{}".format(routern)].cmd( + "ip address add dev vrf1 {}.{}.{}.{}/32".format( + routern, routern, routern, routern + ) + ) tgen.gears["r2"].cmd("ip address add dev vrf1 192.0.2.8/32") tgen.gears["r3"].cmd("ip address add dev vrf1 192.0.2.8/32") @@ -74,6 +78,7 @@ def teardown_module(mod): tgen = get_topogen() tgen.stop_topology() + def test_bgp_path_selection_ecmp(): tgen = get_topogen() @@ -97,7 +102,7 @@ def test_bgp_path_selection_ecmp(): "aspath": {"string": "65002"}, "multipath": True, "nexthops": [{"ip": "192.0.2.3", "metric": 20}], - } + }, ] } @@ -117,7 +122,9 @@ def test_bgp_path_selection_vpn_ecmp(): def _bgp_check_path_selection_vpn_ecmp(): output = json.loads( - tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json") + tgen.gears["r1"].vtysh_cmd( + "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json" + ) ) expected = { "paths": [ @@ -132,7 +139,7 @@ def test_bgp_path_selection_vpn_ecmp(): "aspath": {"string": "65002"}, "multipath": True, "nexthops": [{"ip": "192.0.2.3", "metric": 20}], - } + }, ] } @@ -160,13 +167,13 @@ def test_bgp_path_selection_metric(): "valid": True, "aspath": {"string": "65002"}, "nexthops": [{"ip": "192.0.2.2", "metric": 10}], - "bestpath":{ "selectionReason":"IGP Metric"}, + "bestpath": {"selectionReason": "IGP Metric"}, }, { "valid": True, "aspath": {"string": "65002"}, "nexthops": [{"ip": "192.0.2.3", "metric": 20}], - } + }, ] } @@ -189,7 +196,9 @@ def test_bgp_path_selection_vpn_metric(): def _bgp_check_path_selection_vpn_metric(): output = json.loads( - tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json") + tgen.gears["r1"].vtysh_cmd( + "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json" + ) ) expected = { "paths": [ @@ -197,13 +206,13 @@ def test_bgp_path_selection_vpn_metric(): "valid": True, "aspath": {"string": "65002"}, "nexthops": [{"ip": "192.0.2.2", "metric": 10}], - "bestpath":{ "selectionReason":"IGP Metric"}, + "bestpath": {"selectionReason": "IGP Metric"}, }, { "valid": True, "aspath": {"string": "65002"}, "nexthops": [{"ip": "192.0.2.3", "metric": 20}], - } + }, ] } diff --git a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py index 2eb936aaa0..9269826233 100644 --- a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py +++ b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.common_config import step -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")} diff --git a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py index 0eb244717e..5d6440ce6a 100644 --- a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py +++ b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py index 2ae6f7fc9e..d9402f2743 100644 --- a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py +++ b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py index 5c7cc8eae3..ef7c94bbab 100644 --- a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py +++ b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py @@ -18,7 +18,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py index 412ecc12ef..d50d67b60e 100644 --- a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py +++ b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py @@ -403,7 +403,6 @@ def test_route_summarisation_with_summary_only_p1(request): ) for action, value in zip(["removed", "add"], [True, False]): - step( "{} static routes as below: " "(no) ip route 10.1.1.0/24 and (no) ip route 10.1.2.0/24" @@ -815,7 +814,11 @@ def test_route_summarisation_with_as_set_p1(request): ) for addr_type in ADDR_TYPES: - for pfx, seq_id, network, in zip( + for ( + pfx, + seq_id, + network, + ) in zip( [1, 2, 3, 4, 5], [10, 20, 30, 40, 50], [NETWORK_1_1, NETWORK_1_2, NETWORK_1_3, NETWORK_1_4, NETWORK_1_5], diff --git a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py index 15a077da2e..f7a66fdad1 100644 --- a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py +++ b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py @@ -15,7 +15,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py index a06e3edc44..93a514bf6a 100644 --- a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py +++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py @@ -16,7 +16,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py index 23cf041b68..18b7831a4a 100644 --- a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py +++ b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py @@ -15,7 +15,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 4): diff --git a/tests/topotests/bgp_software_version/test_bgp_software_version.py b/tests/topotests/bgp_software_version/test_bgp_software_version.py index 25e646cf42..c867208d39 100644 --- a/tests/topotests/bgp_software_version/test_bgp_software_version.py +++ b/tests/topotests/bgp_software_version/test_bgp_software_version.py @@ -17,7 +17,7 @@ import json import pytest import functools -pytestmark = pytest.mark.bgpd +pytestmark = [pytest.mark.bgpd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] - def setup_module(mod): topodef = {"s1": ("r1", "r2")} diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py index 900d0c296e..f0c9144248 100755 --- a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py +++ b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py @@ -37,10 +37,12 @@ def setup_module(mod): tgen.start_topology() for rname, router in tgen.routers().items(): - router.load_config(TopoRouter.RD_ZEBRA, - os.path.join(CWD, '{}/zebra.conf'.format(rname))) - router.load_config(TopoRouter.RD_BGP, - os.path.join(CWD, '{}/bgpd.conf'.format(rname))) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) tgen.gears["pe1"].run("ip link add vrf10 type vrf table 10") tgen.gears["pe1"].run("ip link set vrf10 up") @@ -62,7 +64,7 @@ def open_json_file(path): return json.load(f) except IOError: assert False, "Could not read file {}".format(path) - + def check(name, command, checker): tgen = get_topogen() @@ -80,25 +82,25 @@ def check(name, command, checker): def check_vrf10_bgp_rib(output): - expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD) + expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) def check_default_bgp_vpn_rib(output): - expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD) + expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) def check_vrf20_bgp_rib(output): - expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD) + expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) def check_vrf20_rib(output): - expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD) + expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py index fd8a78b485..ec14ef065f 100644 --- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py +++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py @@ -217,6 +217,7 @@ def test_bgp_allow_as_in(): assertmsg = '"r2" 192.168.1.1/32 route should be gone' assert result is None, assertmsg + def test_local_vs_non_local(): tgen = get_topogen() @@ -229,7 +230,7 @@ def test_local_vs_non_local(): paths = output["paths"] for i in range(len(paths)): if "fibPending" in paths[i]: - assert(False), "Route 60.0.0.0/24 should not have fibPending" + assert False, "Route 60.0.0.0/24 should not have fibPending" if __name__ == "__main__": diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py index e7948eaaac..4855d5c7d2 100644 --- a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py +++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py @@ -36,8 +36,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -pytestmark = [pytest.mark.bgpd] - def build_topo(tgen): for routern in range(1, 3): diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py index 6fe044fcea..aeb9bf529d 100644 --- a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py +++ b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py @@ -46,7 +46,7 @@ from lib.bgp import ( verify_bgp_rib, verify_bgp_timers_and_functionality, verify_router_id, - verify_tcp_mss + verify_tcp_mss, ) from lib.common_config import ( kill_router_daemons, @@ -54,6 +54,7 @@ from lib.common_config import ( addKernelRoute, apply_raw_config, check_address_types, + check_router_status, create_prefix_lists, create_route_maps, create_static_routes, @@ -66,10 +67,9 @@ from lib.common_config import ( verify_fib_routes, verify_rib, write_test_footer, - write_test_header + write_test_header, ) -pytestmark = [pytest.mark.bgpd] # Global variables NETWORK1_1 = {"ipv4": "1.1.1.1/32", "ipv6": "1::1/128"} NETWORK1_2 = {"ipv4": "1.1.1.2/32", "ipv6": "1::2/128"} @@ -85,7 +85,8 @@ NETWORK5_2 = {"ipv4": "5.1.1.2/32", "ipv6": "5::2/128"} NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} ## File name -TCPDUMP_FILE="test_tcp_packet_test.txt" +TCPDUMP_FILE = "test_tcp_packet_test.txt" + def setup_module(mod): """ @@ -93,7 +94,7 @@ def setup_module(mod): * `mod`: module name """ - global topo,TCPDUMP_FILE + global topo, TCPDUMP_FILE # Required linux kernel version for this suite to run. result = required_linux_kernel_version("4.15") @@ -128,6 +129,7 @@ def setup_module(mod): step("Running setup_module() done") + def teardown_module(): """Teardown the pytest environment""" @@ -138,9 +140,7 @@ def teardown_module(): # Stop toplogy and Remove tmp files tgen.stop_topology() - step( - "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) - ) + step("Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))) step("=" * 40) @@ -150,6 +150,7 @@ def teardown_module(): # ##################################################### + def test_bgp_vrf_tcp_mss(request): tgen = get_topogen() tc_name = request.node.name @@ -280,34 +281,34 @@ def test_bgp_vrf_tcp_mss(request): step("Verify the static Routes in R2 on RED VRF") for addr_type in ADDR_TYPES: static_routes_input = { - "r3": { - "static_routes": [ - { - "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - ] + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + ] } } dut = "r2" @@ -317,34 +318,34 @@ def test_bgp_vrf_tcp_mss(request): step("Verify the static Routes in R1 on RED VRF") for addr_type in ADDR_TYPES: static_routes_input = { - "r3": { - "static_routes": [ - { - "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - { - "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]], - "next_hop": NEXT_HOP_IP[addr_type], - "vrf": "RED", - }, - ] + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + { + "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED", + }, + ] } } dut = "r1" @@ -404,9 +405,6 @@ def test_bgp_vrf_tcp_mss(request): tcp_mss_result ) - - - step("Enabling tcp-mss 500 between R2 and R3 of VRF Default") TCP_MSS = 500 raw_config = { @@ -440,8 +438,6 @@ def test_bgp_vrf_tcp_mss(request): result = apply_raw_config(tgen, raw_config) assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) - - step("Clear BGP at router R2 and R3") for addr_type in ADDR_TYPES: clear_bgp(tgen, topo, "r2", addr_type) @@ -550,7 +546,6 @@ def test_bgp_vrf_tcp_mss(request): tcp_mss_result is not True ), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result) - step("Removing tcp-mss 500 between R2 and R3 of VRF Default ") TCP_MSS = 500 raw_config = { diff --git a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py index 6f313be628..31743c8a6d 100644 --- a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py +++ b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py @@ -52,30 +52,32 @@ def build_topo(tgen): switch = tgen.add_switch("s3") switch.add_link(tgen.gears["r2"]) + def _populate_iface(): tgen = get_topogen() cmds_list = [ - 'ip link add vrf1 type vrf table 10', - 'echo 10 > /proc/sys/net/mpls/platform_labels', - 'ip link set dev vrf1 up', - 'ip link set dev {0}-eth1 master vrf1', - 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input', - 'ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}', - 'ip link set dev {0}-gre0 up', - 'echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input', + "ip link add vrf1 type vrf table 10", + "echo 10 > /proc/sys/net/mpls/platform_labels", + "ip link set dev vrf1 up", + "ip link set dev {0}-eth1 master vrf1", + "echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input", + "ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}", + "ip link set dev {0}-gre0 up", + "echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input", ] for cmd in cmds_list: - input = cmd.format('r1', '1', '2') - logger.info('input: ' + cmd) - output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2')) - logger.info('output: ' + output) + input = cmd.format("r1", "1", "2") + logger.info("input: " + cmd) + output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2")) + logger.info("output: " + output) for cmd in cmds_list: - input = cmd.format('r2', '2', '1') - logger.info('input: ' + cmd) - output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1')) - logger.info('output: ' + output) + input = cmd.format("r2", "2", "1") + logger.info("input: " + cmd) + output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1")) + logger.info("output: " + output) + def setup_module(mod): "Sets up the pytest environment" @@ -113,13 +115,13 @@ def test_protocols_convergence(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - router = tgen.gears['r1'] + router = tgen.gears["r1"] logger.info("Dump some context for r1") router.vtysh_cmd("show bgp ipv4 vpn") router.vtysh_cmd("show bgp summary") router.vtysh_cmd("show bgp vrf vrf1 ipv4") router.vtysh_cmd("show running-config") - router = tgen.gears['r2'] + router = tgen.gears["r2"] logger.info("Dump some context for r2") router.vtysh_cmd("show bgp ipv4 vpn") router.vtysh_cmd("show bgp summary") @@ -128,11 +130,11 @@ def test_protocols_convergence(): # Check IPv4 routing tables on r1 logger.info("Checking IPv4 routes for convergence on r1") - router = tgen.gears['r1'] + router = tgen.gears["r1"] json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name) if not os.path.isfile(json_file): logger.info("skipping file {}".format(json_file)) - assert 0, 'ipv4_routes.json file not found' + assert 0, "ipv4_routes.json file not found" return expected = json.loads(open(json_file).read()) @@ -148,10 +150,10 @@ def test_protocols_convergence(): # Check BGP IPv4 routing tables on r2 not installed logger.info("Checking BGP IPv4 routes for convergence on r2") - router = tgen.gears['r2'] + router = tgen.gears["r2"] json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name) if not os.path.isfile(json_file): - assert 0, 'bgp_ipv4_routes.json file not found' + assert 0, "bgp_ipv4_routes.json file not found" expected = json.loads(open(json_file).read()) test_func = partial( @@ -163,7 +165,8 @@ def test_protocols_convergence(): _, result = topotest.run_and_expect(test_func, None, count=40, wait=2) assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg - + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py index 1787021ebc..726afcb6ae 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py @@ -851,23 +851,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request): result = verify_bgp_rib( tgen, addr_type, "r3", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes["r3"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes["r3"]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, "r3", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes["r3"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes["r3"]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, "r3", static_routes) @@ -924,23 +926,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request): result = verify_bgp_rib( tgen, addr_type, "r3", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes["r3"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes["r3"]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, "r3", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes["r3"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes["r3"]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, "r3", static_routes) @@ -1153,23 +1157,25 @@ def test_dynamic_import_routes_delete_static_route_p1(request): result = verify_bgp_rib( tgen, addr_type, "r2", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes["r2"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes["r2"]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, "r2", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) step("Delete static routes from vrf BLUE") @@ -1209,21 +1215,23 @@ def test_dynamic_import_routes_delete_static_route_p1(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib(tgen, addr_type, dut, static_routes, expected=False) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) step("Delete static routes from vrf default") diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py index c7fbc01eb1..45d7b0309e 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py @@ -320,7 +320,6 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request): for dut, vrf_name, vrf_import, as_num in zip( ["r2", "r4"], ["GREEN", "BLUE"], ["RED", "default"], [2, 4] ): - for action, value in zip(["Delete", "Re-add"], [True, False]): step("{} the import command on {} router".format(action, dut)) temp = {} @@ -357,23 +356,25 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request): result = verify_bgp_rib( tgen, addr_type, "r4", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes["r4"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes["r4"]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, "r4", static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes["r4"]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes["r4"]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, "r4", static_routes) diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py index 02950eb3d2..d29edf59b8 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py @@ -495,23 +495,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, dut, static_routes) @@ -882,23 +884,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, dut, static_routes) diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py index 4b18903429..c118ffc090 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py @@ -356,23 +356,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, dut, static_routes) @@ -503,23 +505,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, dut, static_routes) @@ -882,23 +886,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request): result = verify_bgp_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed \nError {}\n" + "Routes {} still in BGP table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) result = verify_rib( tgen, addr_type, dut, static_routes, expected=False ) - assert ( - result is not True - ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format( - tc_name, - result, - static_routes[dut]["static_routes"][0]["network"], + assert result is not True, ( + "Testcase {} : Failed Error {}" + "Routes {} still in Route table".format( + tc_name, + result, + static_routes[dut]["static_routes"][0]["network"], + ) ) else: result = verify_bgp_rib(tgen, addr_type, dut, static_routes) diff --git a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py index 244db6c46a..b20819264d 100755 --- a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py +++ b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py @@ -37,10 +37,12 @@ def setup_module(mod): tgen.start_topology() for rname, router in tgen.routers().items(): - router.load_config(TopoRouter.RD_ZEBRA, - os.path.join(CWD, '{}/zebra.conf'.format(rname))) - router.load_config(TopoRouter.RD_BGP, - os.path.join(CWD, '{}/bgpd.conf'.format(rname))) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) tgen.gears["pe1"].run("ip link add vrf10 type vrf table 10") tgen.gears["pe1"].run("ip link set vrf10 up") @@ -62,22 +64,22 @@ def open_json_file(path): return json.load(f) except IOError: assert False, "Could not read file {}".format(path) - + def check_vrf10_rib(output): - expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD) + expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) def check_default_vpn_rib(output): - expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD) + expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) def check_vrf20_rib(output): - expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD) + expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD) actual = json.loads(output) return topotest.json_cmp(actual, expected) diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py index 5d93964380..3cb31809fe 100644 --- a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py +++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py @@ -43,7 +43,7 @@ from lib.common_config import ( step, create_static_routes, check_router_status, - apply_raw_config + apply_raw_config, ) from lib.topolog import logger @@ -51,7 +51,7 @@ from lib.bgp import ( verify_bgp_convergence, create_router_bgp, verify_bgp_rib, - verify_bgp_bestpath + verify_bgp_bestpath, ) from lib.topojson import build_config_from_json @@ -84,10 +84,8 @@ VRF_LIST = ["RED", "BLUE", "GREEN"] COMM_VAL_1 = "100:100" COMM_VAL_2 = "500:500" COMM_VAL_3 = "600:600" -BESTPATH = { - "ipv4": "0.0.0.0", - "ipv6": "::" -} +BESTPATH = {"ipv4": "0.0.0.0", "ipv6": "::"} + def setup_module(mod): """ @@ -158,6 +156,7 @@ def teardown_module(): # ##################################################### + def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request): """ Verify ECMP for imported routes from different VRFs. @@ -170,136 +169,130 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request): check_router_status(tgen) reset_config_on_routers(tgen) - step("Configure same static routes in tenant vrfs RED and GREEN on router " - "R3 and redistribute in respective BGP process") + step( + "Configure same static routes in tenant vrfs RED and GREEN on router " + "R3 and redistribute in respective BGP process" + ) for vrf_name in ["RED", "GREEN"]: for addr_type in ADDR_TYPES: if vrf_name == "GREEN": - next_hop_vrf = topo["routers"]["r1"]["links"][ - "r3-link3"][addr_type].split("/")[0] + next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][ + addr_type + ].split("/")[0] else: - next_hop_vrf = topo["routers"]["r2"]["links"][ - "r3-link1"][addr_type].split("/")[0] + next_hop_vrf = topo["routers"]["r2"]["links"]["r3-link1"][ + addr_type + ].split("/")[0] static_routes = { "r3": { "static_routes": [ { "network": [NETWORK1_1[addr_type]], "next_hop": next_hop_vrf, - "vrf": vrf_name + "vrf": vrf_name, } ] } } result = create_static_routes(tgen, static_routes) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) step("Redistribute static route on BGP VRF : {}".format(vrf_name)) temp = {} for addr_type in ADDR_TYPES: - temp.update({ - addr_type: { - "unicast": { - "redistribute": [{ - "redist_type": "static" - }] - } - } - }) + temp.update( + {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}} + ) - redist_dict = {"r3": {"bgp": [{ - "vrf": vrf_name, "local_as": 3, "address_family": temp - }]}} + redist_dict = { + "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]} + } result = create_router_bgp(tgen, topo, redist_dict) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) - step("Verify that configured static routes are installed in respective " - "BGP table for vrf RED & GREEN") + step( + "Verify that configured static routes are installed in respective " + "BGP table for vrf RED & GREEN" + ) for vrf_name in ["RED", "GREEN"]: for addr_type in ADDR_TYPES: if vrf_name == "GREEN": - next_hop_vrf = topo["routers"]["r1"]["links"][ - "r3-link3"][addr_type].split("/")[0] + next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][ + addr_type + ].split("/")[0] else: - next_hop_vrf = topo["routers"]["r2"]["links"][ - "r3-link1"][addr_type].split("/")[0] + next_hop_vrf = topo["routers"]["r2"]["links"]["r3-link1"][ + addr_type + ].split("/")[0] static_routes = { "r3": { "static_routes": [ - { - "network": [NETWORK1_1[addr_type]], - "vrf": vrf_name - } + {"network": [NETWORK1_1[addr_type]], "vrf": vrf_name} ] } } - result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_bgp_rib( + tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) - result = verify_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_rib( + tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) step("Import vrf RED and GREEN into default vrf and Configure ECMP") bgp_val = [] for vrf_name in ["RED", "GREEN"]: temp = {} for addr_type in ADDR_TYPES: - temp.update({ - addr_type: { - "unicast": { - "import": { - "vrf": vrf_name - }, - "maximum_paths": { - "ebgp": 2 + temp.update( + { + addr_type: { + "unicast": { + "import": {"vrf": vrf_name}, + "maximum_paths": {"ebgp": 2}, } } } - }) + ) - bgp_val.append({ - "local_as": 3, "address_family": temp - }) + bgp_val.append({"local_as": 3, "address_family": temp}) import_dict = {"r3": {"bgp": bgp_val}} result = create_router_bgp(tgen, topo, import_dict) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("Configure bgp bestpath on router r3") r3_raw_config = { - "r3": { - "raw_config": [ - "router bgp 3", - "bgp bestpath as-path multipath-relax" - ] - } + "r3": {"raw_config": ["router bgp 3", "bgp bestpath as-path multipath-relax"]} } result = apply_raw_config(tgen, r3_raw_config) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) - step("Verify that routes are imported with two different next-hop vrfs " - "and IPs. Additionally R3 must do ECMP for both the routes.") + step( + "Verify that routes are imported with two different next-hop vrfs " + "and IPs. Additionally R3 must do ECMP for both the routes." + ) for addr_type in ADDR_TYPES: next_hop_vrf = [ - topo["routers"]["r2"]["links"]["r3-link1"][addr_type]. \ - split("/")[0], - topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \ - split("/")[0] - ] + topo["routers"]["r2"]["links"]["r3-link1"][addr_type].split("/")[0], + topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0], + ] static_routes = { "r3": { "static_routes": [ @@ -310,54 +303,61 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request): } } - result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_bgp_rib( + tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) - result = verify_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_rib(tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) - step("Now change the next-hop of static routes in vrf RED and GREEN to " - "same IP address") + step( + "Now change the next-hop of static routes in vrf RED and GREEN to " + "same IP address" + ) for addr_type in ADDR_TYPES: - next_hop_vrf = topo["routers"]["r1"]["links"][ - "r3-link3"][addr_type].split("/")[0] + next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[ + 0 + ] static_routes = { "r3": { "static_routes": [ { "network": [NETWORK1_1[addr_type]], "next_hop": next_hop_vrf, - "vrf": "RED" + "vrf": "RED", }, { "network": [NETWORK1_1[addr_type]], - "next_hop": topo["routers"]["r2"]["links"][ - "r3-link1"][addr_type].split("/")[0], + "next_hop": topo["routers"]["r2"]["links"]["r3-link1"][ + addr_type + ].split("/")[0], "vrf": "RED", - "delete": True - } + "delete": True, + }, ] } } result = create_static_routes(tgen, static_routes) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) - step("Verify that now routes are imported with two different next-hop " - "vrfs but same IPs. Additionally R3 must do ECMP for both the routes") + step( + "Verify that now routes are imported with two different next-hop " + "vrfs but same IPs. Additionally R3 must do ECMP for both the routes" + ) for addr_type in ADDR_TYPES: next_hop_vrf = [ - topo["routers"]["r1"]["links"]["r3-link3"][addr_type].\ - split("/")[0], - topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \ - split("/")[0] - ] + topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0], + topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0], + ] static_routes = { "r3": { "static_routes": [ @@ -368,20 +368,24 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request): } } - result = verify_bgp_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_bgp_rib( + tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf + ) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) - result = verify_rib(tgen, addr_type, "r3", static_routes, - next_hop=next_hop_vrf) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + result = verify_rib(tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) write_test_footer(tc_name) -def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(request): +def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0( + request, +): """ Verify ECMP for imported routes from different VRFs. """ @@ -393,13 +397,15 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_ check_router_status(tgen) reset_config_on_routers(tgen) - step("Configure same static routes on R2 and R3 vrfs and redistribute in BGP " - "for GREEN and RED vrf instances") - for dut, network in zip(["r2", "r3"], [ - [NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]): + step( + "Configure same static routes on R2 and R3 vrfs and redistribute in BGP " + "for GREEN and RED vrf instances" + ) + for dut, network in zip( + ["r2", "r3"], [[NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]] + ): for vrf_name, network_vrf in zip(["RED", "GREEN"], network): - step("Configure static route for VRF : {} on {}".format(vrf_name, - dut)) + step("Configure static route for VRF : {} on {}".format(vrf_name, dut)) for addr_type in ADDR_TYPES: static_routes = { dut: { @@ -407,44 +413,50 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_ { "network": [network_vrf[addr_type]], "next_hop": "blackhole", - "vrf": vrf_name + "vrf": vrf_name, } ] } } result = create_static_routes(tgen, static_routes) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) for dut, as_num in zip(["r2", "r3"], ["2", "3"]): for vrf_name in ["RED", "GREEN"]: step("Redistribute static route on BGP VRF : {}".format(vrf_name)) temp = {} for addr_type in ADDR_TYPES: - temp.update({ - addr_type: { - "unicast": { - "redistribute": [{ - "redist_type": "static" - }] + temp.update( + { + addr_type: { + "unicast": {"redistribute": [{"redist_type": "static"}]} } } - }) + ) - redist_dict = {dut: {"bgp": [{ - "vrf": vrf_name, "local_as": as_num, "address_family": temp - }]}} + redist_dict = { + dut: { + "bgp": [ + {"vrf": vrf_name, "local_as": as_num, "address_family": temp} + ] + } + } result = create_router_bgp(tgen, topo, redist_dict) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) - - step("Verify that R2 and R3 has installed redistributed routes in default " - "and RED vrfs and GREEN respectively:") - for dut, network in zip(["r2", "r3"], - [[NETWORK1_1, NETWORK1_2], - [NETWORK1_1, NETWORK1_2]]): + assert result is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Verify that R2 and R3 has installed redistributed routes in default " + "and RED vrfs and GREEN respectively:" + ) + for dut, network in zip( + ["r2", "r3"], [[NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]] + ): for vrf_name, network_vrf in zip(["RED", "GREEN"], network): for addr_type in ADDR_TYPES: static_routes = { @@ -453,38 +465,32 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_ { "network": [network_vrf[addr_type]], "next_hop": "blackhole", - "vrf": vrf_name + "vrf": vrf_name, } ] } } result = verify_bgp_rib(tgen, addr_type, dut, static_routes) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) step("Import vrf RED's route in vrf GREEN on R3") temp = {} for addr_type in ADDR_TYPES: - temp.update({ - addr_type: { - "unicast": { - "import": { - "vrf": "RED" - } - } - } - }) + temp.update({addr_type: {"unicast": {"import": {"vrf": "RED"}}}}) - import_dict = {"r3": {"bgp": [{ - "vrf": "GREEN", "local_as": 3, "address_family": temp - }]}} + import_dict = { + "r3": {"bgp": [{"vrf": "GREEN", "local_as": 3, "address_family": temp}]} + } result = create_router_bgp(tgen, topo, import_dict) - assert result is True, "Testcase {} :Failed \n Error: {}". \ - format(tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) - step("Verify that locally imported routes are installed over eBGP imported" - " routes from VRF RED into VRF GREEN") + step( + "Verify that locally imported routes are installed over eBGP imported" + " routes from VRF RED into VRF GREEN" + ) for addr_type in ADDR_TYPES: static_routes = { "r3": { @@ -492,7 +498,7 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_ { "network": [NETWORK1_2[addr_type]], "next_hop": "blackhole", - "vrf": "GREEN" + "vrf": "GREEN", } ] } @@ -504,19 +510,21 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_ { "network": NETWORK1_2[addr_type], "bestpath": BESTPATH[addr_type], - "vrf": "GREEN" + "vrf": "GREEN", } ] } } result = verify_bgp_bestpath(tgen, addr_type, input_routes) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) result = verify_rib(tgen, addr_type, "r3", static_routes) - assert result is True, "Testcase {} : Failed \n Error {}". \ - format(tc_name, result) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) write_test_footer(tc_name) diff --git a/tests/topotests/config_timing/test_config_timing.py b/tests/topotests/config_timing/test_config_timing.py index 5c1b97262c..52d196f12a 100644 --- a/tests/topotests/config_timing/test_config_timing.py +++ b/tests/topotests/config_timing/test_config_timing.py @@ -97,8 +97,8 @@ def test_static_timing(): optype = "adding" if add else "removing" iptype = "IPv6" if do_ipv6 else "IPv4" if super_prefix is None: - super_prefix = u"2001::/48" if do_ipv6 else u"10.0.0.0/8" - via = u"lo" + super_prefix = "2001::/48" if do_ipv6 else "10.0.0.0/8" + via = "lo" optyped = "added" if add else "removed" for rname, router in router_list.items(): @@ -161,8 +161,8 @@ def test_static_timing(): prefix_count = 50 prefix_base = [ - [u"10.0.0.0/8", u"11.0.0.0/8"], - [u"2100:1111:2220::/44", u"2100:3333:4440::/44"], + ["10.0.0.0/8", "11.0.0.0/8"], + ["2100:1111:2220::/44", "2100:3333:4440::/44"], ] # This apparently needed to allow for various mgmtd/staticd/zebra connections to form diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py index c6f038b7f6..a2315138cc 100755 --- a/tests/topotests/conftest.py +++ b/tests/topotests/conftest.py @@ -496,7 +496,7 @@ def setup_coverage(config): os.environ["GCOV_PREFIX"] = str(gcdadir) if is_main_runner(): - commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+rw {{}} +") + commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+r {{}} +") commander.cmd_raises(f"mkdir -p {gcdadir}") commander.cmd_raises(f"chown -R root:frr {gcdadir}") commander.cmd_raises(f"chmod 2775 {gcdadir}") @@ -767,18 +767,25 @@ def coverage_finish(terminalreporter, config): bdir = Path(os.environ["FRR_BUILD_DIR"]) gcdadir = Path(os.environ["GCOV_PREFIX"]) - # Get the data files into the build directory - logger.info("Copying gcda files from '%s' to '%s'", gcdadir, bdir) - user = os.environ.get("SUDO_USER", os.environ["USER"]) - commander.cmd_raises(f"chmod -R ugo+r {gcdadir}") + logger.info("Creating .gcno ssymlink from '%s' to '%s'", gcdadir, bdir) commander.cmd_raises( - f"tar -C {gcdadir} -cf - . | su {user} -c 'tar -C {bdir} -xf -'" + f"cd {gcdadir}; bdir={bdir}" + + """ +for f in $(find . -name '*.gcda'); do + f=${f#./}; + f=${f%.gcda}.gcno; + ln -fs $bdir/$f $f; + touch -h -r $bdir/$f $f; + echo $f; +done""" ) # Get the results into a summary file data_file = rundir / "coverage.info" logger.info("Gathering coverage data into: %s", data_file) - commander.cmd_raises(f"lcov --directory {bdir} --capture --output-file {data_file}") + commander.cmd_raises( + f"lcov --directory {gcdadir} --capture --output-file {data_file}" + ) # Get coverage info filtered to a specific set of files report_file = rundir / "coverage.info" diff --git a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py index 3c9392c3f5..b3152f43bc 100644 --- a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py +++ b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py @@ -193,6 +193,7 @@ if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) + # # Auxiliary Functions # diff --git a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py index c0621d75a5..cfcd4a18ea 100644 --- a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py +++ b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py @@ -20,7 +20,7 @@ import pytest import json from functools import partial -pytestmark = [pytest.mark.pimd] +pytestmark = [pytest.mark.pimd, pytest.mark.bgpd] # Save the Current Working Directory to find configuration files. CWD = os.path.dirname(os.path.realpath(__file__)) @@ -32,10 +32,6 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -# Required to instantiate the topology builder class. - -pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd] - ##################################################### ## diff --git a/tests/topotests/example_test/test_template.py b/tests/topotests/example_test/test_template.py index 27975483a8..5728ebaea2 100644 --- a/tests/topotests/example_test/test_template.py +++ b/tests/topotests/example_test/test_template.py @@ -41,6 +41,7 @@ pytestmark = [ # pytest.mark.vrrpd, ] + # Function we pass to Topogen to create the topology def build_topo(tgen): "Build function" diff --git a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py index bb4d02d342..22fc50b914 100644 --- a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py +++ b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py @@ -65,7 +65,8 @@ def setup_module(module): TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)) ) router.load_config( - TopoRouter.RD_FPM_LISTENER, os.path.join(CWD, "{}/fpm_stub.conf".format(rname)) + TopoRouter.RD_FPM_LISTENER, + os.path.join(CWD, "{}/fpm_stub.conf".format(rname)), ) tgen.start_router() diff --git a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py index 6a5f81def6..6689cf4c5e 100755 --- a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py +++ b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py @@ -118,11 +118,19 @@ def setup_module(mod): # For all registered routers, load the zebra configuration file for rname, router in router_list.items(): - router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))) - router.load_config( TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) + ) if rname in ["rt0", "rt9"]: - router.load_config( TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))) - router.load_config( TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname))) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname)) + ) router.run("ip link add dum0 type dummy") router.run("ip link set dum0 up") if rname == "rt0": @@ -145,6 +153,7 @@ def setup_testcase(msg): pytest.skip(tgen.errors) return tgen + def open_json_file(filename): try: with open(filename, "r") as f: @@ -162,7 +171,7 @@ def check_rib(name, cmd, expected_file): expected = open_json_file("{}/{}".format(CWD, expected_file)) return topotest.json_cmp(output, expected) - logger.info("[+] check {} \"{}\" {}".format(name, cmd, expected_file)) + logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file)) tgen = get_topogen() func = partial(_check, name, cmd, expected_file) success, result = topotest.run_and_expect(func, None, count=120, wait=0.5) diff --git a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py index 892f6e1d0e..1a7505dd12 100644 --- a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py +++ b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py @@ -197,13 +197,16 @@ def setup_module(mod): # For all registered routers, load the zebra and isis configuration files for rname, router in tgen.routers().items(): - router.load_config(TopoRouter.RD_ZEBRA, - os.path.join(CWD, '{}/zebra.conf'.format(rname))) - router.load_config(TopoRouter.RD_ISIS, - os.path.join(CWD, '{}/isisd.conf'.format(rname))) - if (os.path.exists('{}/sharpd.conf'.format(rname))): - router.load_config(TopoRouter.RD_SHARP, - os.path.join(CWD, '{}/sharpd.conf'.format(rname))) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) + ) + if os.path.exists("{}/sharpd.conf".format(rname)): + router.load_config( + TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)) + ) # Start routers tgen.start_router() @@ -227,7 +230,9 @@ def router_compare_json_output(rname, command, reference): expected = json.loads(open(filename).read()) # Run test function until we get an result. Wait at most 60 seconds. - test_func = functools.partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) + test_func = functools.partial( + topotest.router_json_cmp, tgen.gears[rname], command, expected + ) _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5) assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) assert diff is None, assertmsg @@ -308,8 +313,10 @@ def test_srv6_locator_step1(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step1/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step1/show_srv6_locator_table.ref", + ) def test_ping_step1(): @@ -326,10 +333,16 @@ def test_ping_step1(): pytest.skip(tgen.errors) # Setup encap route on rt1, decap route on rt2 - tgen.gears["rt1"].vtysh_cmd("sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1") - tgen.gears["rt6"].vtysh_cmd("sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1") - tgen.gears["dst"].vtysh_cmd("sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1") - + tgen.gears["rt1"].vtysh_cmd( + "sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1" + ) + tgen.gears["rt6"].vtysh_cmd( + "sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1" + ) + tgen.gears["dst"].vtysh_cmd( + "sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1" + ) + # Try to ping dst from rt1 check_ping6("rt1", "fc00:0:9::1", True) @@ -412,8 +425,10 @@ def test_srv6_locator_step2(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step2/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step2/show_srv6_locator_table.ref", + ) def test_ping_step2(): @@ -428,7 +443,7 @@ def test_ping_step2(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", False) @@ -512,8 +527,10 @@ def test_srv6_locator_step3(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step3/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step3/show_srv6_locator_table.ref", + ) def test_ping_step3(): @@ -528,7 +545,7 @@ def test_ping_step3(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", True) @@ -608,8 +625,10 @@ def test_srv6_locator_step4(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step4/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step4/show_srv6_locator_table.ref", + ) def test_ping_step4(): @@ -624,7 +643,7 @@ def test_ping_step4(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", False) @@ -704,8 +723,10 @@ def test_srv6_locator_step5(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step5/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step5/show_srv6_locator_table.ref", + ) def test_ping_step5(): @@ -720,7 +741,7 @@ def test_ping_step5(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", True) @@ -799,8 +820,10 @@ def test_srv6_locator_step6(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step6/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step6/show_srv6_locator_table.ref", + ) def test_ping_step6(): @@ -815,7 +838,7 @@ def test_ping_step6(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", False) @@ -895,8 +918,10 @@ def test_srv6_locator_step7(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step7/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step7/show_srv6_locator_table.ref", + ) def test_ping_step7(): @@ -911,7 +936,7 @@ def test_ping_step7(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", True) @@ -990,8 +1015,10 @@ def test_srv6_locator_step8(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step8/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step8/show_srv6_locator_table.ref", + ) def test_ping_step8(): @@ -1006,7 +1033,7 @@ def test_ping_step8(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", False) @@ -1089,8 +1116,10 @@ def test_srv6_locator_step9(): for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: router_compare_json_output( - rname, "show segment-routing srv6 locator json", "step9/show_srv6_locator_table.ref" - ) + rname, + "show segment-routing srv6 locator json", + "step9/show_srv6_locator_table.ref", + ) def test_ping_step9(): @@ -1105,7 +1134,7 @@ def test_ping_step9(): # Skip if previous fatal error condition is raised if tgen.routers_have_failure(): pytest.skip(tgen.errors) - + check_ping6("rt1", "fc00:0:9::1", True) diff --git a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py index 9c70e05784..eb4f31012b 100644 --- a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py +++ b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py @@ -189,10 +189,18 @@ def test_step3(): tgen = setup_testcase("Step3: Add IPv6 on r1 and r2 interfaces") - tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"') - tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"') - tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"') - tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"') + tgen.net["r1"].cmd( + 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"' + ) + tgen.net["r1"].cmd( + 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"' + ) + tgen.net["r2"].cmd( + 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"' + ) + tgen.net["r2"].cmd( + 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"' + ) for rname in ["r1", "r2", "r3", "r4"]: compare_ted_json_output(tgen, rname, "ted_step3.json") @@ -202,8 +210,12 @@ def test_step4(): tgen = setup_testcase("Step4: Modify Prefix SID on router r4") - tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"') - tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"') + tgen.net["r4"].cmd( + 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"' + ) + tgen.net["r4"].cmd( + 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"' + ) for rname in ["r1", "r2", "r3", "r4"]: compare_ted_json_output(tgen, rname, "ted_step4.json") @@ -229,9 +241,15 @@ def test_step6(): tgen = setup_testcase("Step6: Modify link parameters on r2 & r4") - tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"') - tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"') - tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"') + tgen.net["r2"].cmd( + 'vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"' + ) + tgen.net["r4"].cmd( + 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"' + ) + tgen.net["r4"].cmd( + 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"' + ) for rname in ["r1", "r2", "r3", "r4"]: compare_ted_json_output(tgen, rname, "ted_step6.json") diff --git a/tests/topotests/key_sendaccept/test_keychain.py b/tests/topotests/key_sendaccept/test_keychain.py index 111e88aca7..b11d31b981 100644 --- a/tests/topotests/key_sendaccept/test_keychain.py +++ b/tests/topotests/key_sendaccept/test_keychain.py @@ -62,7 +62,7 @@ def test_send_accept(tgen): key chain kc key 1 key-string theSecret - crypto-algorithm md5 + cryptographic-algorithm hmac-sha-256 exit exit """ @@ -74,7 +74,7 @@ exit key chain kc key 1 key-string theSecret - crypto-algorithm md5 + cryptographic-algorithm hmac-sha-256 send-lifetime 00:00:00 Jan 1 2024 infinite accept-lifetime 00:00:00 Jan 1 2024 infinite exit @@ -101,7 +101,7 @@ exit key chain kc key 2 key-string theSecret - crypto-algorithm md5 + cryptographic-algorithm hmac-sha-256 send-lifetime 00:00:00 Jan 1 2024 duration {secs_in_10_years} accept-lifetime 00:00:00 Jan 1 2024 duration {secs_in_10_years} exit @@ -127,7 +127,7 @@ exit key chain kc key 3 key-string theSecret - crypto-algorithm md5 + cryptographic-algorithm hmac-sha-256 send-lifetime 00:00:00 Jan 1 2024 23:59:59 Dec 31 2034 accept-lifetime 00:00:00 Jan 1 2024 23:59:59 Dec 31 2034 exit diff --git a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py index 6c814ee9aa..e1e6b51f64 100644 --- a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py +++ b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py @@ -8,27 +8,29 @@ import struct class BGPOpen: - UNPACK_STR = '!16sHBBHH4sB' + UNPACK_STR = "!16sHBBHH4sB" @classmethod def dissect(cls, data): - (marker, - length, - open_type, - version, - my_as, - hold_time, - bgp_id, - optional_params_len) = struct.unpack_from(cls.UNPACK_STR, data) + ( + marker, + length, + open_type, + version, + my_as, + hold_time, + bgp_id, + optional_params_len, + ) = struct.unpack_from(cls.UNPACK_STR, data) - data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len:] + data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len :] # XXX: parse optional parameters return data, { - 'version': version, - 'my_as': my_as, - 'hold_time': hold_time, - 'bgp_id': ipaddress.ip_address(bgp_id), - 'optional_params_len': optional_params_len, + "version": version, + "my_as": my_as, + "hold_time": hold_time, + "bgp_id": ipaddress.ip_address(bgp_id), + "optional_params_len": optional_params_len, } diff --git a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py index d079b35113..629e175364 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py @@ -10,45 +10,47 @@ from .nlri import NlriIPv4Unicast from .path_attributes import PathAttribute -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class BGPUpdate: - UNPACK_STR = '!16sHBH' + UNPACK_STR = "!16sHBH" STATIC_SIZE = 23 @classmethod def dissect(cls, data): - msg = {'bmp_log_type': 'update'} + msg = {"bmp_log_type": "update"} common_size = struct.calcsize(cls.UNPACK_STR) - (marker, - length, - update_type, - withdrawn_routes_len) = struct.unpack_from(cls.UNPACK_STR, data) + (marker, length, update_type, withdrawn_routes_len) = struct.unpack_from( + cls.UNPACK_STR, data + ) # get withdrawn routes - withdrawn_routes = '' + withdrawn_routes = "" if withdrawn_routes_len: withdrawn_routes = NlriIPv4Unicast.parse( - data[common_size:common_size + withdrawn_routes_len] + data[common_size : common_size + withdrawn_routes_len] ) - msg['bmp_log_type'] = 'withdraw' + msg["bmp_log_type"] = "withdraw" msg.update(withdrawn_routes) # get path attributes (total_path_attrs_len,) = struct.unpack_from( - '!H', data[common_size+withdrawn_routes_len:]) + "!H", data[common_size + withdrawn_routes_len :] + ) if total_path_attrs_len: offset = cls.STATIC_SIZE + withdrawn_routes_len - path_attrs_data = data[offset:offset + total_path_attrs_len] + path_attrs_data = data[offset : offset + total_path_attrs_len] while path_attrs_data: path_attrs_data, pattr = PathAttribute.dissect(path_attrs_data) if pattr: msg = {**msg, **pattr} # get nlri - nlri_len = length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len + nlri_len = ( + length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len + ) if nlri_len > 0: - nlri = NlriIPv4Unicast.parse(data[length - nlri_len:length]) + nlri = NlriIPv4Unicast.parse(data[length - nlri_len : length]) msg.update(nlri) return data[length:], msg diff --git a/tests/topotests/lib/bmp_collector/bgp/update/af.py b/tests/topotests/lib/bmp_collector/bgp/update/af.py index 01af1ae2be..200b15a05d 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/af.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/af.py @@ -19,7 +19,7 @@ SAFI_IP_FLOWSPEC = 133 SAFI_VPN_FLOWSPEC = 134 -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class AddressFamily: def __init__(self, afi, safi): self.afi = afi @@ -31,13 +31,13 @@ class AddressFamily: return (self.afi, self.safi) == (other.afi, other.safi) def __str__(self): - return f'afi: {self.afi}, safi: {self.safi}' + return f"afi: {self.afi}, safi: {self.safi}" def __hash__(self): return hash((self.afi, self.safi)) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class AF: IPv4_UNICAST = AddressFamily(AFI_IP, SAFI_UNICAST) IPv6_UNICAST = AddressFamily(AFI_IP6, SAFI_UNICAST) diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py index c1720f126c..b3625201f4 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py @@ -13,7 +13,8 @@ from .rd import RouteDistinguisher def decode_label(label): # from frr # frr encode just one label - return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xf0) >> 4 + return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xF0) >> 4 + def padding(databin, len_): """ @@ -23,7 +24,8 @@ def padding(databin, len_): """ if len(databin) >= len_: return databin - return databin + b'\0' * (len_ - len(databin)) + return databin + b"\0" * (len_ - len(databin)) + def dissect_nlri(nlri_data, afi, safi): """ @@ -37,35 +39,34 @@ def dissect_nlri(nlri_data, afi, safi): elif addr_family == AF.IPv6_UNICAST: return NlriIPv6Unicast.parse(nlri_data) - return {'ip_prefix': 'Unknown'} + return {"ip_prefix": "Unknown"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Unicast: - @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from('!B', data) + (prefix_len,) = struct.unpack_from("!B", data) prefix = padding(data[1:], 4) - return {'ip_prefix': f'{ipaddress.IPv4Address(prefix)}/{prefix_len}'} + return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Unicast: @staticmethod def parse(data): """parses prefixes from withdrawn_routes or nrli data""" - (prefix_len,) = struct.unpack_from('!B', data) + (prefix_len,) = struct.unpack_from("!B", data) prefix = padding(data[1:], 16) - return {'ip_prefix': f'{ipaddress.IPv6Address(prefix)}/{prefix_len}'} + return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Vpn: - UNPACK_STR = '!B3s8s' + UNPACK_STR = "!B3s8s" @classmethod def parse(cls, data): @@ -74,17 +75,17 @@ class NlriIPv4Vpn: ipv4 = padding(data[offset:], 4) # prefix_len = total_bits_len - label_bits_len - rd_bits_len - prefix_len = bit_len - 3*8 - 8*8 + prefix_len = bit_len - 3 * 8 - 8 * 8 return { - 'label': decode_label(label), - 'rd': str(RouteDistinguisher(rd)), - 'ip_prefix': f'{ipaddress.IPv4Address(ipv4)}/{prefix_len}', + "label": decode_label(label), + "rd": str(RouteDistinguisher(rd)), + "ip_prefix": f"{ipaddress.IPv4Address(ipv4)}/{prefix_len}", } -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Vpn: - UNPACK_STR = '!B3s8s' + UNPACK_STR = "!B3s8s" @classmethod def parse(cls, data): @@ -93,48 +94,49 @@ class NlriIPv6Vpn: offset = struct.calcsize(cls.UNPACK_STR) ipv6 = padding(data[offset:], 16) - prefix_len = bit_len - 3*8 - 8*8 + prefix_len = bit_len - 3 * 8 - 8 * 8 return { - 'label': decode_label(label), - 'rd': str(RouteDistinguisher(rd)), - 'ip_prefix': f'{ipaddress.IPv6Address(ipv6)}/{prefix_len}', + "label": decode_label(label), + "rd": str(RouteDistinguisher(rd)), + "ip_prefix": f"{ipaddress.IPv6Address(ipv6)}/{prefix_len}", } -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4Mpls: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6Mpls: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv4FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriIPv6FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriVpn4FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriVpn6FlowSpec: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class NlriL2EVPN: pass -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ class NlriL2VPNFlowSpec: pass diff --git a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py index 6e82e9c170..3694cb4fe3 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py @@ -38,17 +38,18 @@ ORIGIN_EGP = 0x01 ORIGIN_INCOMPLETE = 0x02 -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttribute: PATH_ATTRS = {} UNKNOWN_ATTR = None - UNPACK_STR = '!BB' + UNPACK_STR = "!BB" @classmethod def register_path_attr(cls, path_attr): def _register_path_attr(subcls): cls.PATH_ATTRS[path_attr] = subcls return subcls + return _register_path_attr @classmethod @@ -61,7 +62,7 @@ class PathAttribute: offset = struct.calcsize(cls.UNPACK_STR) # get attribute length - attr_len_str = '!H' if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else '!B' + attr_len_str = "!H" if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else "!B" (attr_len,) = struct.unpack_from(attr_len_str, data[offset:]) @@ -69,32 +70,34 @@ class PathAttribute: path_attr_cls = cls.lookup_path_attr(type_code) if path_attr_cls == cls.UNKNOWN_ATTR: - return data[offset + attr_len:], None + return data[offset + attr_len :], None - return data[offset+attr_len:], path_attr_cls.dissect(data[offset:offset+attr_len]) + return data[offset + attr_len :], path_attr_cls.dissect( + data[offset : offset + attr_len] + ) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_ORIGIN) class PathAttrOrigin: ORIGIN_STR = { - ORIGIN_IGP: 'IGP', - ORIGIN_EGP: 'EGP', - ORIGIN_INCOMPLETE: 'INCOMPLETE', + ORIGIN_IGP: "IGP", + ORIGIN_EGP: "EGP", + ORIGIN_INCOMPLETE: "INCOMPLETE", } @classmethod def dissect(cls, data): - (origin,) = struct.unpack_from('!B', data) + (origin,) = struct.unpack_from("!B", data) - return {'origin': cls.ORIGIN_STR.get(origin, 'UNKNOWN')} + return {"origin": cls.ORIGIN_STR.get(origin, "UNKNOWN")} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_AS_PATH) class PathAttrAsPath: AS_PATH_TYPE_SET = 0x01 - AS_PATH_TYPE_SEQUENCE= 0x02 + AS_PATH_TYPE_SEQUENCE = 0x02 @staticmethod def get_asn_len(asns): @@ -103,34 +106,34 @@ class PathAttrAsPath: @classmethod def dissect(cls, data): - (_type, _len) = struct.unpack_from('!BB', data) + (_type, _len) = struct.unpack_from("!BB", data) data = data[2:] - _type_str = 'Ordred' if _type == cls.AS_PATH_TYPE_SEQUENCE else 'Raw' + _type_str = "Ordred" if _type == cls.AS_PATH_TYPE_SEQUENCE else "Raw" segment = [] while data: - (asn,) = struct.unpack_from('!I', data) + (asn,) = struct.unpack_from("!I", data) segment.append(asn) data = data[4:] - return {'as_path': ' '.join(str(a) for a in segment)} + return {"as_path": " ".join(str(a) for a in segment)} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_NEXT_HOP) class PathAttrNextHop: @classmethod def dissect(cls, data): - (nexthop,) = struct.unpack_from('!4s', data) - return {'bgp_nexthop': str(ipaddress.IPv4Address(nexthop))} + (nexthop,) = struct.unpack_from("!4s", data) + return {"bgp_nexthop": str(ipaddress.IPv4Address(nexthop))} -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrMultiExitDisc: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_REACH_NLRI) class PathAttrMpReachNLRI: """ @@ -162,7 +165,8 @@ class PathAttrMpReachNLRI: | Network Layer Reachability Information (variable) | +---------------------------------------------------------+ """ - UNPACK_STR = '!HBB' + + UNPACK_STR = "!HBB" NLRI_RESERVED_LEN = 1 @staticmethod @@ -170,35 +174,35 @@ class PathAttrMpReachNLRI: msg = {} if nexthop_len == 4: # IPv4 - (ipv4,) = struct.unpack_from('!4s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4)) + (ipv4,) = struct.unpack_from("!4s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4)) elif nexthop_len == 12: # RD + IPv4 - (rd, ipv4) = struct.unpack_from('!8s4s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4)) - msg['nxhp_rd'] = str(RouteDistinguisher(rd)) + (rd, ipv4) = struct.unpack_from("!8s4s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4)) + msg["nxhp_rd"] = str(RouteDistinguisher(rd)) elif nexthop_len == 16: # IPv6 - (ipv6,) = struct.unpack_from('!16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) + (ipv6,) = struct.unpack_from("!16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) elif nexthop_len == 24: # RD + IPv6 - (rd, ipv6) = struct.unpack_from('!8s16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_rd'] = str(RouteDistinguisher(rd)) + (rd, ipv6) = struct.unpack_from("!8s16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_rd"] = str(RouteDistinguisher(rd)) elif nexthop_len == 32: # IPv6 + IPv6 link-local - (ipv6, link_local)= struct.unpack_from('!16s16s', nexthop_data) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local)) + (ipv6, link_local) = struct.unpack_from("!16s16s", nexthop_data) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local)) elif nexthop_len == 48: # RD + IPv6 + RD + IPv6 link-local - u_str = '!8s16s8s16s' - (rd1, ipv6, rd2, link_local)= struct.unpack_from(u_str, nexthop_data) - msg['nxhp_rd1'] = str(RouteDistinguisher(rd1)) - msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6)) - msg['nxhp_rd2'] = str(RouteDistinguisher(rd2)) - msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local)) + u_str = "!8s16s8s16s" + (rd1, ipv6, rd2, link_local) = struct.unpack_from(u_str, nexthop_data) + msg["nxhp_rd1"] = str(RouteDistinguisher(rd1)) + msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6)) + msg["nxhp_rd2"] = str(RouteDistinguisher(rd2)) + msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local)) return msg @@ -210,10 +214,10 @@ class PathAttrMpReachNLRI: def dissect(cls, data): (afi, safi, nexthop_len) = struct.unpack_from(cls.UNPACK_STR, data) offset = struct.calcsize(cls.UNPACK_STR) - msg = {'afi': afi, 'safi': safi} + msg = {"afi": afi, "safi": safi} # dissect nexthop - nexthop_data = data[offset: offset + nexthop_len] + nexthop_data = data[offset : offset + nexthop_len] nexthop = cls.dissect_nexthop(nexthop_data, nexthop_len) msg.update(nexthop) @@ -227,7 +231,7 @@ class PathAttrMpReachNLRI: return msg -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ @PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_UNREACH_NLRI) class PathAttrMpUnReachNLRI: """ @@ -239,13 +243,14 @@ class PathAttrMpUnReachNLRI: | Withdrawn Routes (variable) | +---------------------------------------------------------+ """ - UNPACK_STR = '!HB' + + UNPACK_STR = "!HB" @classmethod def dissect(cls, data): (afi, safi) = struct.unpack_from(cls.UNPACK_STR, data) offset = struct.calcsize(cls.UNPACK_STR) - msg = {'bmp_log_type': 'withdraw','afi': afi, 'safi': safi} + msg = {"bmp_log_type": "withdraw", "afi": afi, "safi": safi} if data[offset:]: # dissect withdrawn_routes @@ -254,51 +259,51 @@ class PathAttrMpUnReachNLRI: return msg -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLocalPref: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrAtomicAgregate: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrAggregator: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrCommunities: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrOriginatorID: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrClusterList: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrExtendedCommunities: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrPMSITunnel: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLinkState: pass -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class PathAttrLargeCommunities: pass diff --git a/tests/topotests/lib/bmp_collector/bgp/update/rd.py b/tests/topotests/lib/bmp_collector/bgp/update/rd.py index c382fa8340..3f08de5ae9 100644 --- a/tests/topotests/lib/bmp_collector/bgp/update/rd.py +++ b/tests/topotests/lib/bmp_collector/bgp/update/rd.py @@ -7,7 +7,7 @@ import ipaddress import struct -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class RouteDistinguisher: """ type 0: @@ -28,32 +28,32 @@ class RouteDistinguisher: + | 4-bytes AS number (4 bytes)| Service Provider 2 bytes)| +-------------------------------------------------------------------------+ """ + def __init__(self, rd): self.rd = rd self.as_number = None self.admin_ipv4 = None self.four_bytes_as = None self.assigned_sp = None - self.repr_str = '' + self.repr_str = "" self.dissect() def dissect(self): - (rd_type,) = struct.unpack_from('!H', self.rd) + (rd_type,) = struct.unpack_from("!H", self.rd) if rd_type == 0: - (self.as_number, - self.assigned_sp) = struct.unpack_from('!HI', self.rd[2:]) - self.repr_str = f'{self.as_number}:{self.assigned_sp}' + (self.as_number, self.assigned_sp) = struct.unpack_from("!HI", self.rd[2:]) + self.repr_str = f"{self.as_number}:{self.assigned_sp}" elif rd_type == 1: - (self.admin_ipv4, - self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:]) + (self.admin_ipv4, self.assigned_sp) = struct.unpack_from("!IH", self.rd[2:]) ipv4 = str(ipaddress.IPv4Address(self.admin_ipv4)) - self.repr_str = f'{self.as_number}:{self.assigned_sp}' + self.repr_str = f"{self.as_number}:{self.assigned_sp}" elif rd_type == 2: - (self.four_bytes_as, - self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:]) - self.repr_str = f'{self.four_bytes_as}:{self.assigned_sp}' + (self.four_bytes_as, self.assigned_sp) = struct.unpack_from( + "!IH", self.rd[2:] + ) + self.repr_str = f"{self.four_bytes_as}:{self.assigned_sp}" def __str__(self): return self.repr_str diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py index 814813f7f4..8e2e76d154 100644 --- a/tests/topotests/lib/snmptest.py +++ b/tests/topotests/lib/snmptest.py @@ -85,15 +85,18 @@ class SnmpTester(object): return out_dict, out_list def get(self, oid): - cmd = "snmpget {0} {1}".format(self._snmp_config(), oid) - + cmd = "snmpget {0} {1} 2>&1 | grep -v SNMPv2-PDU".format( + self._snmp_config(), oid + ) result = self.router.cmd(cmd) if "not found" in result: return None return self._get_snmp_value(result) def get_next(self, oid): - cmd = "snmpgetnext {0} {1}".format(self._snmp_config(), oid) + cmd = "snmpgetnext {0} {1} 2>&1 | grep -v SNMPv2-PDU".format( + self._snmp_config(), oid + ) result = self.router.cmd(cmd) print("get_next: {}".format(result)) @@ -102,7 +105,9 @@ class SnmpTester(object): return self._get_snmp_value(result) def walk(self, oid): - cmd = "snmpwalk {0} {1}".format(self._snmp_config(), oid) + cmd = "snmpwalk {0} {1} 2>&1 | grep -v SNMPv2-PDU".format( + self._snmp_config(), oid + ) result = self.router.cmd(cmd) return self._parse_multiline(result) diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py index 901e4f623a..148fb04fe5 100644 --- a/tests/topotests/lib/topojson.py +++ b/tests/topotests/lib/topojson.py @@ -227,13 +227,17 @@ def build_topo_from_json(tgen, topo=None): topo["routers"][destRouter]["links"][curSwitch][ "interface" ] = "{}-{}-eth{}".format( - destRouter, curSwitch, topo["routers"][destRouter]["nextIfname"] + destRouter, + curSwitch, + topo["routers"][destRouter]["nextIfname"], ) topo["switches"][curSwitch]["links"][destRouter][ "interface" ] = "{}-{}-eth{}".format( - curSwitch, destRouter, topo["routers"][destRouter]["nextIfname"] + curSwitch, + destRouter, + topo["routers"][destRouter]["nextIfname"], ) topo["routers"][destRouter]["nextIfname"] += 1 diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 985ba536dd..087d8454fc 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -2183,12 +2183,16 @@ class Router(Node): daemon, error.returncode, error.cmd, - '\n:stdout: "{}"'.format(error.stdout.strip()) - if error.stdout - else "", - '\n:stderr: "{}"'.format(error.stderr.strip()) - if error.stderr - else "", + ( + '\n:stdout: "{}"'.format(error.stdout.strip()) + if error.stdout + else "" + ), + ( + '\n:stderr: "{}"'.format(error.stderr.strip()) + if error.stderr + else "" + ), ) else: logger.debug("%s: %s %s started", self, self.routertype, daemon) diff --git a/tests/topotests/mgmt_fe_client/mgmt_pb2.py b/tests/topotests/mgmt_fe_client/mgmt_pb2.py index 0aa8803f7f..44dd2f6688 100644 --- a/tests/topotests/mgmt_fe_client/mgmt_pb2.py +++ b/tests/topotests/mgmt_fe_client/mgmt_pb2.py @@ -7,90 +7,113 @@ from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() - - DESCRIPTOR = _descriptor.FileDescriptor( - name='mgmt.proto', - package='mgmtd', - syntax='proto2', - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd\"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t\"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value\">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue\"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType\"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t\"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08\"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08\"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08\"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12\"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message\"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id\"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04\"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId\"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08\"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t\"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq\"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply\"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath\"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12\"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04' + name="mgmt.proto", + package="mgmtd", + syntax="proto2", + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04', ) _CFGDATAREQTYPE = _descriptor.EnumDescriptor( - name='CfgDataReqType', - full_name='mgmtd.CfgDataReqType', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='REQ_TYPE_NONE', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='SET_DATA', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='DELETE_DATA', index=2, number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=3674, - serialized_end=3740, + name="CfgDataReqType", + full_name="mgmtd.CfgDataReqType", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="REQ_TYPE_NONE", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="SET_DATA", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="DELETE_DATA", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=3674, + serialized_end=3740, ) _sym_db.RegisterEnumDescriptor(_CFGDATAREQTYPE) CfgDataReqType = enum_type_wrapper.EnumTypeWrapper(_CFGDATAREQTYPE) _DATASTOREID = _descriptor.EnumDescriptor( - name='DatastoreId', - full_name='mgmtd.DatastoreId', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='DS_NONE', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='RUNNING_DS', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='CANDIDATE_DS', index=2, number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='OPERATIONAL_DS', index=3, number=3, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='STARTUP_DS', index=4, number=4, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=3742, - serialized_end=3838, + name="DatastoreId", + full_name="mgmtd.DatastoreId", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="DS_NONE", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="RUNNING_DS", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="CANDIDATE_DS", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="OPERATIONAL_DS", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="STARTUP_DS", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=3742, + serialized_end=3838, ) _sym_db.RegisterEnumDescriptor(_DATASTOREID) @@ -105,1885 +128,3341 @@ OPERATIONAL_DS = 3 STARTUP_DS = 4 - _YANGDATAXPATH = _descriptor.Descriptor( - name='YangDataXPath', - full_name='mgmtd.YangDataXPath', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='xpath', full_name='mgmtd.YangDataXPath.xpath', index=0, - number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=21, - serialized_end=51, + name="YangDataXPath", + full_name="mgmtd.YangDataXPath", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="xpath", + full_name="mgmtd.YangDataXPath.xpath", + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=21, + serialized_end=51, ) _YANGDATAVALUE = _descriptor.Descriptor( - name='YangDataValue', - full_name='mgmtd.YangDataValue', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='encoded_str_val', full_name='mgmtd.YangDataValue.encoded_str_val', index=0, - number=100, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='value', full_name='mgmtd.YangDataValue.value', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=53, - serialized_end=104, + name="YangDataValue", + full_name="mgmtd.YangDataValue", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="encoded_str_val", + full_name="mgmtd.YangDataValue.encoded_str_val", + index=0, + number=100, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name="value", + full_name="mgmtd.YangDataValue.value", + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + ), + ], + serialized_start=53, + serialized_end=104, ) _YANGDATA = _descriptor.Descriptor( - name='YangData', - full_name='mgmtd.YangData', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='xpath', full_name='mgmtd.YangData.xpath', index=0, - number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='mgmtd.YangData.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=106, - serialized_end=168, + name="YangData", + full_name="mgmtd.YangData", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="xpath", + full_name="mgmtd.YangData.xpath", + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="mgmtd.YangData.value", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=106, + serialized_end=168, ) _YANGCFGDATAREQ = _descriptor.Descriptor( - name='YangCfgDataReq', - full_name='mgmtd.YangCfgDataReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.YangCfgDataReq.data', index=0, - number=1, type=11, cpp_type=10, label=2, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_type', full_name='mgmtd.YangCfgDataReq.req_type', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=170, - serialized_end=258, + name="YangCfgDataReq", + full_name="mgmtd.YangCfgDataReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.YangCfgDataReq.data", + index=0, + number=1, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_type", + full_name="mgmtd.YangCfgDataReq.req_type", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=170, + serialized_end=258, ) _YANGGETDATAREQ = _descriptor.Descriptor( - name='YangGetDataReq', - full_name='mgmtd.YangGetDataReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.YangGetDataReq.data', index=0, - number=1, type=11, cpp_type=10, label=2, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='next_indx', full_name='mgmtd.YangGetDataReq.next_indx', index=1, - number=2, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=260, - serialized_end=326, + name="YangGetDataReq", + full_name="mgmtd.YangGetDataReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.YangGetDataReq.data", + index=0, + number=1, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="next_indx", + full_name="mgmtd.YangGetDataReq.next_indx", + index=1, + number=2, + type=3, + cpp_type=2, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=260, + serialized_end=326, ) _BESUBSCRIBEREQ = _descriptor.Descriptor( - name='BeSubscribeReq', - full_name='mgmtd.BeSubscribeReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='client_name', full_name='mgmtd.BeSubscribeReq.client_name', index=0, - number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='subscribe_xpaths', full_name='mgmtd.BeSubscribeReq.subscribe_xpaths', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='xpath_reg', full_name='mgmtd.BeSubscribeReq.xpath_reg', index=2, - number=3, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=328, - serialized_end=410, + name="BeSubscribeReq", + full_name="mgmtd.BeSubscribeReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="client_name", + full_name="mgmtd.BeSubscribeReq.client_name", + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="subscribe_xpaths", + full_name="mgmtd.BeSubscribeReq.subscribe_xpaths", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="xpath_reg", + full_name="mgmtd.BeSubscribeReq.xpath_reg", + index=2, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=328, + serialized_end=410, ) _BESUBSCRIBEREPLY = _descriptor.Descriptor( - name='BeSubscribeReply', - full_name='mgmtd.BeSubscribeReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.BeSubscribeReply.success', index=0, - number=1, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=412, - serialized_end=447, + name="BeSubscribeReply", + full_name="mgmtd.BeSubscribeReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.BeSubscribeReply.success", + index=0, + number=1, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=412, + serialized_end=447, ) _BETXNREQ = _descriptor.Descriptor( - name='BeTxnReq', - full_name='mgmtd.BeTxnReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeTxnReq.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='create', full_name='mgmtd.BeTxnReq.create', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=449, - serialized_end=491, + name="BeTxnReq", + full_name="mgmtd.BeTxnReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeTxnReq.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="create", + full_name="mgmtd.BeTxnReq.create", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=449, + serialized_end=491, ) _BETXNREPLY = _descriptor.Descriptor( - name='BeTxnReply', - full_name='mgmtd.BeTxnReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeTxnReply.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='create', full_name='mgmtd.BeTxnReply.create', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.BeTxnReply.success', index=2, - number=3, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=493, - serialized_end=554, + name="BeTxnReply", + full_name="mgmtd.BeTxnReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeTxnReply.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="create", + full_name="mgmtd.BeTxnReply.create", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.BeTxnReply.success", + index=2, + number=3, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=493, + serialized_end=554, ) _BECFGDATACREATEREQ = _descriptor.Descriptor( - name='BeCfgDataCreateReq', - full_name='mgmtd.BeCfgDataCreateReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeCfgDataCreateReq.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='data_req', full_name='mgmtd.BeCfgDataCreateReq.data_req', index=1, - number=2, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='end_of_data', full_name='mgmtd.BeCfgDataCreateReq.end_of_data', index=2, - number=3, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=556, - serialized_end=654, + name="BeCfgDataCreateReq", + full_name="mgmtd.BeCfgDataCreateReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeCfgDataCreateReq.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data_req", + full_name="mgmtd.BeCfgDataCreateReq.data_req", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="end_of_data", + full_name="mgmtd.BeCfgDataCreateReq.end_of_data", + index=2, + number=3, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=556, + serialized_end=654, ) _BECFGDATACREATEREPLY = _descriptor.Descriptor( - name='BeCfgDataCreateReply', - full_name='mgmtd.BeCfgDataCreateReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeCfgDataCreateReply.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.BeCfgDataCreateReply.success', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.BeCfgDataCreateReply.error_if_any', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=656, - serialized_end=733, + name="BeCfgDataCreateReply", + full_name="mgmtd.BeCfgDataCreateReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeCfgDataCreateReply.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.BeCfgDataCreateReply.success", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.BeCfgDataCreateReply.error_if_any", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=656, + serialized_end=733, ) _BECFGDATAAPPLYREQ = _descriptor.Descriptor( - name='BeCfgDataApplyReq', - full_name='mgmtd.BeCfgDataApplyReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeCfgDataApplyReq.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=735, - serialized_end=770, + name="BeCfgDataApplyReq", + full_name="mgmtd.BeCfgDataApplyReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeCfgDataApplyReq.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=735, + serialized_end=770, ) _BECFGDATAAPPLYREPLY = _descriptor.Descriptor( - name='BeCfgDataApplyReply', - full_name='mgmtd.BeCfgDataApplyReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='txn_id', full_name='mgmtd.BeCfgDataApplyReply.txn_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.BeCfgDataApplyReply.success', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.BeCfgDataApplyReply.error_if_any', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=772, - serialized_end=848, + name="BeCfgDataApplyReply", + full_name="mgmtd.BeCfgDataApplyReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="txn_id", + full_name="mgmtd.BeCfgDataApplyReply.txn_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.BeCfgDataApplyReply.success", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.BeCfgDataApplyReply.error_if_any", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=772, + serialized_end=848, ) _YANGDATAREPLY = _descriptor.Descriptor( - name='YangDataReply', - full_name='mgmtd.YangDataReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.YangDataReply.data', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='next_indx', full_name='mgmtd.YangDataReply.next_indx', index=1, - number=2, type=3, cpp_type=2, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=850, - serialized_end=915, + name="YangDataReply", + full_name="mgmtd.YangDataReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.YangDataReply.data", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="next_indx", + full_name="mgmtd.YangDataReply.next_indx", + index=1, + number=2, + type=3, + cpp_type=2, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=850, + serialized_end=915, ) _BEMESSAGE = _descriptor.Descriptor( - name='BeMessage', - full_name='mgmtd.BeMessage', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='subscr_req', full_name='mgmtd.BeMessage.subscr_req', index=0, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='subscr_reply', full_name='mgmtd.BeMessage.subscr_reply', index=1, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='txn_req', full_name='mgmtd.BeMessage.txn_req', index=2, - number=4, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='txn_reply', full_name='mgmtd.BeMessage.txn_reply', index=3, - number=5, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='cfg_data_req', full_name='mgmtd.BeMessage.cfg_data_req', index=4, - number=6, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='cfg_data_reply', full_name='mgmtd.BeMessage.cfg_data_reply', index=5, - number=7, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='cfg_apply_req', full_name='mgmtd.BeMessage.cfg_apply_req', index=6, - number=8, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='cfg_apply_reply', full_name='mgmtd.BeMessage.cfg_apply_reply', index=7, - number=9, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='message', full_name='mgmtd.BeMessage.message', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=918, - serialized_end=1322, + name="BeMessage", + full_name="mgmtd.BeMessage", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="subscr_req", + full_name="mgmtd.BeMessage.subscr_req", + index=0, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="subscr_reply", + full_name="mgmtd.BeMessage.subscr_reply", + index=1, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="txn_req", + full_name="mgmtd.BeMessage.txn_req", + index=2, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="txn_reply", + full_name="mgmtd.BeMessage.txn_reply", + index=3, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="cfg_data_req", + full_name="mgmtd.BeMessage.cfg_data_req", + index=4, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="cfg_data_reply", + full_name="mgmtd.BeMessage.cfg_data_reply", + index=5, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="cfg_apply_req", + full_name="mgmtd.BeMessage.cfg_apply_req", + index=6, + number=8, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="cfg_apply_reply", + full_name="mgmtd.BeMessage.cfg_apply_reply", + index=7, + number=9, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name="message", + full_name="mgmtd.BeMessage.message", + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + ), + ], + serialized_start=918, + serialized_end=1322, ) _FEREGISTERREQ = _descriptor.Descriptor( - name='FeRegisterReq', - full_name='mgmtd.FeRegisterReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='client_name', full_name='mgmtd.FeRegisterReq.client_name', index=0, - number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1324, - serialized_end=1360, + name="FeRegisterReq", + full_name="mgmtd.FeRegisterReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="client_name", + full_name="mgmtd.FeRegisterReq.client_name", + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1324, + serialized_end=1360, ) _FESESSIONREQ = _descriptor.Descriptor( - name='FeSessionReq', - full_name='mgmtd.FeSessionReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='create', full_name='mgmtd.FeSessionReq.create', index=0, - number=1, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='client_conn_id', full_name='mgmtd.FeSessionReq.client_conn_id', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeSessionReq.session_id', index=2, - number=3, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='id', full_name='mgmtd.FeSessionReq.id', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=1362, - serialized_end=1446, + name="FeSessionReq", + full_name="mgmtd.FeSessionReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="create", + full_name="mgmtd.FeSessionReq.create", + index=0, + number=1, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="client_conn_id", + full_name="mgmtd.FeSessionReq.client_conn_id", + index=1, + number=2, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeSessionReq.session_id", + index=2, + number=3, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name="id", + full_name="mgmtd.FeSessionReq.id", + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + ), + ], + serialized_start=1362, + serialized_end=1446, ) _FESESSIONREPLY = _descriptor.Descriptor( - name='FeSessionReply', - full_name='mgmtd.FeSessionReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='create', full_name='mgmtd.FeSessionReply.create', index=0, - number=1, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.FeSessionReply.success', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='client_conn_id', full_name='mgmtd.FeSessionReply.client_conn_id', index=2, - number=3, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeSessionReply.session_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1448, - serialized_end=1541, + name="FeSessionReply", + full_name="mgmtd.FeSessionReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="create", + full_name="mgmtd.FeSessionReply.create", + index=0, + number=1, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.FeSessionReply.success", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="client_conn_id", + full_name="mgmtd.FeSessionReply.client_conn_id", + index=2, + number=3, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeSessionReply.session_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1448, + serialized_end=1541, ) _FELOCKDSREQ = _descriptor.Descriptor( - name='FeLockDsReq', - full_name='mgmtd.FeLockDsReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeLockDsReq.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeLockDsReq.req_id', index=1, - number=2, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeLockDsReq.ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='lock', full_name='mgmtd.FeLockDsReq.lock', index=3, - number=4, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1543, - serialized_end=1641, + name="FeLockDsReq", + full_name="mgmtd.FeLockDsReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeLockDsReq.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeLockDsReq.req_id", + index=1, + number=2, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeLockDsReq.ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="lock", + full_name="mgmtd.FeLockDsReq.lock", + index=3, + number=4, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1543, + serialized_end=1641, ) _FELOCKDSREPLY = _descriptor.Descriptor( - name='FeLockDsReply', - full_name='mgmtd.FeLockDsReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeLockDsReply.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeLockDsReply.req_id', index=1, - number=2, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeLockDsReply.ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='lock', full_name='mgmtd.FeLockDsReply.lock', index=3, - number=4, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.FeLockDsReply.success', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.FeLockDsReply.error_if_any', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1644, - serialized_end=1783, + name="FeLockDsReply", + full_name="mgmtd.FeLockDsReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeLockDsReply.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeLockDsReply.req_id", + index=1, + number=2, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeLockDsReply.ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="lock", + full_name="mgmtd.FeLockDsReply.lock", + index=3, + number=4, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.FeLockDsReply.success", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.FeLockDsReply.error_if_any", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1644, + serialized_end=1783, ) _FESETCONFIGREQ = _descriptor.Descriptor( - name='FeSetConfigReq', - full_name='mgmtd.FeSetConfigReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeSetConfigReq.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeSetConfigReq.ds_id', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeSetConfigReq.req_id', index=2, - number=3, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.FeSetConfigReq.data', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='implicit_commit', full_name='mgmtd.FeSetConfigReq.implicit_commit', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='commit_ds_id', full_name='mgmtd.FeSetConfigReq.commit_ds_id', index=5, - number=6, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1786, - serialized_end=1977, + name="FeSetConfigReq", + full_name="mgmtd.FeSetConfigReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeSetConfigReq.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeSetConfigReq.ds_id", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeSetConfigReq.req_id", + index=2, + number=3, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.FeSetConfigReq.data", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="implicit_commit", + full_name="mgmtd.FeSetConfigReq.implicit_commit", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="commit_ds_id", + full_name="mgmtd.FeSetConfigReq.commit_ds_id", + index=5, + number=6, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1786, + serialized_end=1977, ) _FESETCONFIGREPLY = _descriptor.Descriptor( - name='FeSetConfigReply', - full_name='mgmtd.FeSetConfigReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeSetConfigReply.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeSetConfigReply.ds_id', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeSetConfigReply.req_id', index=2, - number=3, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.FeSetConfigReply.success', index=3, - number=4, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='implicit_commit', full_name='mgmtd.FeSetConfigReply.implicit_commit', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.FeSetConfigReply.error_if_any', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1980, - serialized_end=2133, + name="FeSetConfigReply", + full_name="mgmtd.FeSetConfigReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeSetConfigReply.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeSetConfigReply.ds_id", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeSetConfigReply.req_id", + index=2, + number=3, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.FeSetConfigReply.success", + index=3, + number=4, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="implicit_commit", + full_name="mgmtd.FeSetConfigReply.implicit_commit", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.FeSetConfigReply.error_if_any", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1980, + serialized_end=2133, ) _FECOMMITCONFIGREQ = _descriptor.Descriptor( - name='FeCommitConfigReq', - full_name='mgmtd.FeCommitConfigReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeCommitConfigReq.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='src_ds_id', full_name='mgmtd.FeCommitConfigReq.src_ds_id', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='dst_ds_id', full_name='mgmtd.FeCommitConfigReq.dst_ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeCommitConfigReq.req_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='validate_only', full_name='mgmtd.FeCommitConfigReq.validate_only', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='abort', full_name='mgmtd.FeCommitConfigReq.abort', index=5, - number=6, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2136, - serialized_end=2307, + name="FeCommitConfigReq", + full_name="mgmtd.FeCommitConfigReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeCommitConfigReq.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="src_ds_id", + full_name="mgmtd.FeCommitConfigReq.src_ds_id", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="dst_ds_id", + full_name="mgmtd.FeCommitConfigReq.dst_ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeCommitConfigReq.req_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="validate_only", + full_name="mgmtd.FeCommitConfigReq.validate_only", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="abort", + full_name="mgmtd.FeCommitConfigReq.abort", + index=5, + number=6, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2136, + serialized_end=2307, ) _FECOMMITCONFIGREPLY = _descriptor.Descriptor( - name='FeCommitConfigReply', - full_name='mgmtd.FeCommitConfigReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeCommitConfigReply.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='src_ds_id', full_name='mgmtd.FeCommitConfigReply.src_ds_id', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='dst_ds_id', full_name='mgmtd.FeCommitConfigReply.dst_ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeCommitConfigReply.req_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='validate_only', full_name='mgmtd.FeCommitConfigReply.validate_only', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.FeCommitConfigReply.success', index=5, - number=6, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='abort', full_name='mgmtd.FeCommitConfigReply.abort', index=6, - number=7, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.FeCommitConfigReply.error_if_any', index=7, - number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2310, - serialized_end=2522, + name="FeCommitConfigReply", + full_name="mgmtd.FeCommitConfigReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeCommitConfigReply.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="src_ds_id", + full_name="mgmtd.FeCommitConfigReply.src_ds_id", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="dst_ds_id", + full_name="mgmtd.FeCommitConfigReply.dst_ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeCommitConfigReply.req_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="validate_only", + full_name="mgmtd.FeCommitConfigReply.validate_only", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.FeCommitConfigReply.success", + index=5, + number=6, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="abort", + full_name="mgmtd.FeCommitConfigReply.abort", + index=6, + number=7, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.FeCommitConfigReply.error_if_any", + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2310, + serialized_end=2522, ) _FEGETREQ = _descriptor.Descriptor( - name='FeGetReq', - full_name='mgmtd.FeGetReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeGetReq.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='config', full_name='mgmtd.FeGetReq.config', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeGetReq.ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeGetReq.req_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.FeGetReq.data', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2525, - serialized_end=2659, + name="FeGetReq", + full_name="mgmtd.FeGetReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeGetReq.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="config", + full_name="mgmtd.FeGetReq.config", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeGetReq.ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeGetReq.req_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.FeGetReq.data", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2525, + serialized_end=2659, ) _FEGETREPLY = _descriptor.Descriptor( - name='FeGetReply', - full_name='mgmtd.FeGetReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeGetReply.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='config', full_name='mgmtd.FeGetReply.config', index=1, - number=2, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeGetReply.ds_id', index=2, - number=3, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeGetReply.req_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='success', full_name='mgmtd.FeGetReply.success', index=4, - number=5, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error_if_any', full_name='mgmtd.FeGetReply.error_if_any', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.FeGetReply.data', index=6, - number=7, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2662, - serialized_end=2836, + name="FeGetReply", + full_name="mgmtd.FeGetReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeGetReply.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="config", + full_name="mgmtd.FeGetReply.config", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeGetReply.ds_id", + index=2, + number=3, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeGetReply.req_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="success", + full_name="mgmtd.FeGetReply.success", + index=4, + number=5, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error_if_any", + full_name="mgmtd.FeGetReply.error_if_any", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.FeGetReply.data", + index=6, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2662, + serialized_end=2836, ) _FENOTIFYDATAREQ = _descriptor.Descriptor( - name='FeNotifyDataReq', - full_name='mgmtd.FeNotifyDataReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='data', full_name='mgmtd.FeNotifyDataReq.data', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2838, - serialized_end=2886, + name="FeNotifyDataReq", + full_name="mgmtd.FeNotifyDataReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="data", + full_name="mgmtd.FeNotifyDataReq.data", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2838, + serialized_end=2886, ) _FEREGISTERNOTIFYREQ = _descriptor.Descriptor( - name='FeRegisterNotifyReq', - full_name='mgmtd.FeRegisterNotifyReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='session_id', full_name='mgmtd.FeRegisterNotifyReq.session_id', index=0, - number=1, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='ds_id', full_name='mgmtd.FeRegisterNotifyReq.ds_id', index=1, - number=2, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='register_req', full_name='mgmtd.FeRegisterNotifyReq.register_req', index=2, - number=3, type=8, cpp_type=7, label=2, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='req_id', full_name='mgmtd.FeRegisterNotifyReq.req_id', index=3, - number=4, type=4, cpp_type=4, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='data_xpath', full_name='mgmtd.FeRegisterNotifyReq.data_xpath', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2889, - serialized_end=3045, + name="FeRegisterNotifyReq", + full_name="mgmtd.FeRegisterNotifyReq", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="session_id", + full_name="mgmtd.FeRegisterNotifyReq.session_id", + index=0, + number=1, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ds_id", + full_name="mgmtd.FeRegisterNotifyReq.ds_id", + index=1, + number=2, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="register_req", + full_name="mgmtd.FeRegisterNotifyReq.register_req", + index=2, + number=3, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="req_id", + full_name="mgmtd.FeRegisterNotifyReq.req_id", + index=3, + number=4, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data_xpath", + full_name="mgmtd.FeRegisterNotifyReq.data_xpath", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2889, + serialized_end=3045, ) _FEMESSAGE = _descriptor.Descriptor( - name='FeMessage', - full_name='mgmtd.FeMessage', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='register_req', full_name='mgmtd.FeMessage.register_req', index=0, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='session_req', full_name='mgmtd.FeMessage.session_req', index=1, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='session_reply', full_name='mgmtd.FeMessage.session_reply', index=2, - number=4, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='lockds_req', full_name='mgmtd.FeMessage.lockds_req', index=3, - number=5, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='lockds_reply', full_name='mgmtd.FeMessage.lockds_reply', index=4, - number=6, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='setcfg_req', full_name='mgmtd.FeMessage.setcfg_req', index=5, - number=7, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='setcfg_reply', full_name='mgmtd.FeMessage.setcfg_reply', index=6, - number=8, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='commcfg_req', full_name='mgmtd.FeMessage.commcfg_req', index=7, - number=9, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='commcfg_reply', full_name='mgmtd.FeMessage.commcfg_reply', index=8, - number=10, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='get_req', full_name='mgmtd.FeMessage.get_req', index=9, - number=11, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='get_reply', full_name='mgmtd.FeMessage.get_reply', index=10, - number=12, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='notify_data_req', full_name='mgmtd.FeMessage.notify_data_req', index=11, - number=15, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='regnotify_req', full_name='mgmtd.FeMessage.regnotify_req', index=12, - number=16, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='message', full_name='mgmtd.FeMessage.message', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=3048, - serialized_end=3672, -) - -_YANGDATAVALUE.oneofs_by_name['value'].fields.append( - _YANGDATAVALUE.fields_by_name['encoded_str_val']) -_YANGDATAVALUE.fields_by_name['encoded_str_val'].containing_oneof = _YANGDATAVALUE.oneofs_by_name['value'] -_YANGDATA.fields_by_name['value'].message_type = _YANGDATAVALUE -_YANGCFGDATAREQ.fields_by_name['data'].message_type = _YANGDATA -_YANGCFGDATAREQ.fields_by_name['req_type'].enum_type = _CFGDATAREQTYPE -_YANGGETDATAREQ.fields_by_name['data'].message_type = _YANGDATA -_BECFGDATACREATEREQ.fields_by_name['data_req'].message_type = _YANGCFGDATAREQ -_YANGDATAREPLY.fields_by_name['data'].message_type = _YANGDATA -_BEMESSAGE.fields_by_name['subscr_req'].message_type = _BESUBSCRIBEREQ -_BEMESSAGE.fields_by_name['subscr_reply'].message_type = _BESUBSCRIBEREPLY -_BEMESSAGE.fields_by_name['txn_req'].message_type = _BETXNREQ -_BEMESSAGE.fields_by_name['txn_reply'].message_type = _BETXNREPLY -_BEMESSAGE.fields_by_name['cfg_data_req'].message_type = _BECFGDATACREATEREQ -_BEMESSAGE.fields_by_name['cfg_data_reply'].message_type = _BECFGDATACREATEREPLY -_BEMESSAGE.fields_by_name['cfg_apply_req'].message_type = _BECFGDATAAPPLYREQ -_BEMESSAGE.fields_by_name['cfg_apply_reply'].message_type = _BECFGDATAAPPLYREPLY -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['subscr_req']) -_BEMESSAGE.fields_by_name['subscr_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['subscr_reply']) -_BEMESSAGE.fields_by_name['subscr_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['txn_req']) -_BEMESSAGE.fields_by_name['txn_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['txn_reply']) -_BEMESSAGE.fields_by_name['txn_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['cfg_data_req']) -_BEMESSAGE.fields_by_name['cfg_data_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['cfg_data_reply']) -_BEMESSAGE.fields_by_name['cfg_data_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['cfg_apply_req']) -_BEMESSAGE.fields_by_name['cfg_apply_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_BEMESSAGE.oneofs_by_name['message'].fields.append( - _BEMESSAGE.fields_by_name['cfg_apply_reply']) -_BEMESSAGE.fields_by_name['cfg_apply_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message'] -_FESESSIONREQ.oneofs_by_name['id'].fields.append( - _FESESSIONREQ.fields_by_name['client_conn_id']) -_FESESSIONREQ.fields_by_name['client_conn_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id'] -_FESESSIONREQ.oneofs_by_name['id'].fields.append( - _FESESSIONREQ.fields_by_name['session_id']) -_FESESSIONREQ.fields_by_name['session_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id'] -_FELOCKDSREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FELOCKDSREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FESETCONFIGREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FESETCONFIGREQ.fields_by_name['data'].message_type = _YANGCFGDATAREQ -_FESETCONFIGREQ.fields_by_name['commit_ds_id'].enum_type = _DATASTOREID -_FESETCONFIGREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FECOMMITCONFIGREQ.fields_by_name['src_ds_id'].enum_type = _DATASTOREID -_FECOMMITCONFIGREQ.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID -_FECOMMITCONFIGREPLY.fields_by_name['src_ds_id'].enum_type = _DATASTOREID -_FECOMMITCONFIGREPLY.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID -_FEGETREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FEGETREQ.fields_by_name['data'].message_type = _YANGGETDATAREQ -_FEGETREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FEGETREPLY.fields_by_name['data'].message_type = _YANGDATAREPLY -_FENOTIFYDATAREQ.fields_by_name['data'].message_type = _YANGDATA -_FEREGISTERNOTIFYREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID -_FEREGISTERNOTIFYREQ.fields_by_name['data_xpath'].message_type = _YANGDATAXPATH -_FEMESSAGE.fields_by_name['register_req'].message_type = _FEREGISTERREQ -_FEMESSAGE.fields_by_name['session_req'].message_type = _FESESSIONREQ -_FEMESSAGE.fields_by_name['session_reply'].message_type = _FESESSIONREPLY -_FEMESSAGE.fields_by_name['lockds_req'].message_type = _FELOCKDSREQ -_FEMESSAGE.fields_by_name['lockds_reply'].message_type = _FELOCKDSREPLY -_FEMESSAGE.fields_by_name['setcfg_req'].message_type = _FESETCONFIGREQ -_FEMESSAGE.fields_by_name['setcfg_reply'].message_type = _FESETCONFIGREPLY -_FEMESSAGE.fields_by_name['commcfg_req'].message_type = _FECOMMITCONFIGREQ -_FEMESSAGE.fields_by_name['commcfg_reply'].message_type = _FECOMMITCONFIGREPLY -_FEMESSAGE.fields_by_name['get_req'].message_type = _FEGETREQ -_FEMESSAGE.fields_by_name['get_reply'].message_type = _FEGETREPLY -_FEMESSAGE.fields_by_name['notify_data_req'].message_type = _FENOTIFYDATAREQ -_FEMESSAGE.fields_by_name['regnotify_req'].message_type = _FEREGISTERNOTIFYREQ -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['register_req']) -_FEMESSAGE.fields_by_name['register_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['session_req']) -_FEMESSAGE.fields_by_name['session_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['session_reply']) -_FEMESSAGE.fields_by_name['session_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['lockds_req']) -_FEMESSAGE.fields_by_name['lockds_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['lockds_reply']) -_FEMESSAGE.fields_by_name['lockds_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['setcfg_req']) -_FEMESSAGE.fields_by_name['setcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['setcfg_reply']) -_FEMESSAGE.fields_by_name['setcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['commcfg_req']) -_FEMESSAGE.fields_by_name['commcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['commcfg_reply']) -_FEMESSAGE.fields_by_name['commcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['get_req']) -_FEMESSAGE.fields_by_name['get_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['get_reply']) -_FEMESSAGE.fields_by_name['get_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['notify_data_req']) -_FEMESSAGE.fields_by_name['notify_data_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -_FEMESSAGE.oneofs_by_name['message'].fields.append( - _FEMESSAGE.fields_by_name['regnotify_req']) -_FEMESSAGE.fields_by_name['regnotify_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message'] -DESCRIPTOR.message_types_by_name['YangDataXPath'] = _YANGDATAXPATH -DESCRIPTOR.message_types_by_name['YangDataValue'] = _YANGDATAVALUE -DESCRIPTOR.message_types_by_name['YangData'] = _YANGDATA -DESCRIPTOR.message_types_by_name['YangCfgDataReq'] = _YANGCFGDATAREQ -DESCRIPTOR.message_types_by_name['YangGetDataReq'] = _YANGGETDATAREQ -DESCRIPTOR.message_types_by_name['BeSubscribeReq'] = _BESUBSCRIBEREQ -DESCRIPTOR.message_types_by_name['BeSubscribeReply'] = _BESUBSCRIBEREPLY -DESCRIPTOR.message_types_by_name['BeTxnReq'] = _BETXNREQ -DESCRIPTOR.message_types_by_name['BeTxnReply'] = _BETXNREPLY -DESCRIPTOR.message_types_by_name['BeCfgDataCreateReq'] = _BECFGDATACREATEREQ -DESCRIPTOR.message_types_by_name['BeCfgDataCreateReply'] = _BECFGDATACREATEREPLY -DESCRIPTOR.message_types_by_name['BeCfgDataApplyReq'] = _BECFGDATAAPPLYREQ -DESCRIPTOR.message_types_by_name['BeCfgDataApplyReply'] = _BECFGDATAAPPLYREPLY -DESCRIPTOR.message_types_by_name['YangDataReply'] = _YANGDATAREPLY -DESCRIPTOR.message_types_by_name['BeMessage'] = _BEMESSAGE -DESCRIPTOR.message_types_by_name['FeRegisterReq'] = _FEREGISTERREQ -DESCRIPTOR.message_types_by_name['FeSessionReq'] = _FESESSIONREQ -DESCRIPTOR.message_types_by_name['FeSessionReply'] = _FESESSIONREPLY -DESCRIPTOR.message_types_by_name['FeLockDsReq'] = _FELOCKDSREQ -DESCRIPTOR.message_types_by_name['FeLockDsReply'] = _FELOCKDSREPLY -DESCRIPTOR.message_types_by_name['FeSetConfigReq'] = _FESETCONFIGREQ -DESCRIPTOR.message_types_by_name['FeSetConfigReply'] = _FESETCONFIGREPLY -DESCRIPTOR.message_types_by_name['FeCommitConfigReq'] = _FECOMMITCONFIGREQ -DESCRIPTOR.message_types_by_name['FeCommitConfigReply'] = _FECOMMITCONFIGREPLY -DESCRIPTOR.message_types_by_name['FeGetReq'] = _FEGETREQ -DESCRIPTOR.message_types_by_name['FeGetReply'] = _FEGETREPLY -DESCRIPTOR.message_types_by_name['FeNotifyDataReq'] = _FENOTIFYDATAREQ -DESCRIPTOR.message_types_by_name['FeRegisterNotifyReq'] = _FEREGISTERNOTIFYREQ -DESCRIPTOR.message_types_by_name['FeMessage'] = _FEMESSAGE -DESCRIPTOR.enum_types_by_name['CfgDataReqType'] = _CFGDATAREQTYPE -DESCRIPTOR.enum_types_by_name['DatastoreId'] = _DATASTOREID + name="FeMessage", + full_name="mgmtd.FeMessage", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="register_req", + full_name="mgmtd.FeMessage.register_req", + index=0, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="session_req", + full_name="mgmtd.FeMessage.session_req", + index=1, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="session_reply", + full_name="mgmtd.FeMessage.session_reply", + index=2, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="lockds_req", + full_name="mgmtd.FeMessage.lockds_req", + index=3, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="lockds_reply", + full_name="mgmtd.FeMessage.lockds_reply", + index=4, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="setcfg_req", + full_name="mgmtd.FeMessage.setcfg_req", + index=5, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="setcfg_reply", + full_name="mgmtd.FeMessage.setcfg_reply", + index=6, + number=8, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="commcfg_req", + full_name="mgmtd.FeMessage.commcfg_req", + index=7, + number=9, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="commcfg_reply", + full_name="mgmtd.FeMessage.commcfg_reply", + index=8, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="get_req", + full_name="mgmtd.FeMessage.get_req", + index=9, + number=11, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="get_reply", + full_name="mgmtd.FeMessage.get_reply", + index=10, + number=12, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="notify_data_req", + full_name="mgmtd.FeMessage.notify_data_req", + index=11, + number=15, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="regnotify_req", + full_name="mgmtd.FeMessage.regnotify_req", + index=12, + number=16, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name="message", + full_name="mgmtd.FeMessage.message", + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + ), + ], + serialized_start=3048, + serialized_end=3672, +) + +_YANGDATAVALUE.oneofs_by_name["value"].fields.append( + _YANGDATAVALUE.fields_by_name["encoded_str_val"] +) +_YANGDATAVALUE.fields_by_name[ + "encoded_str_val" +].containing_oneof = _YANGDATAVALUE.oneofs_by_name["value"] +_YANGDATA.fields_by_name["value"].message_type = _YANGDATAVALUE +_YANGCFGDATAREQ.fields_by_name["data"].message_type = _YANGDATA +_YANGCFGDATAREQ.fields_by_name["req_type"].enum_type = _CFGDATAREQTYPE +_YANGGETDATAREQ.fields_by_name["data"].message_type = _YANGDATA +_BECFGDATACREATEREQ.fields_by_name["data_req"].message_type = _YANGCFGDATAREQ +_YANGDATAREPLY.fields_by_name["data"].message_type = _YANGDATA +_BEMESSAGE.fields_by_name["subscr_req"].message_type = _BESUBSCRIBEREQ +_BEMESSAGE.fields_by_name["subscr_reply"].message_type = _BESUBSCRIBEREPLY +_BEMESSAGE.fields_by_name["txn_req"].message_type = _BETXNREQ +_BEMESSAGE.fields_by_name["txn_reply"].message_type = _BETXNREPLY +_BEMESSAGE.fields_by_name["cfg_data_req"].message_type = _BECFGDATACREATEREQ +_BEMESSAGE.fields_by_name["cfg_data_reply"].message_type = _BECFGDATACREATEREPLY +_BEMESSAGE.fields_by_name["cfg_apply_req"].message_type = _BECFGDATAAPPLYREQ +_BEMESSAGE.fields_by_name["cfg_apply_reply"].message_type = _BECFGDATAAPPLYREPLY +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["subscr_req"] +) +_BEMESSAGE.fields_by_name["subscr_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["subscr_reply"] +) +_BEMESSAGE.fields_by_name["subscr_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append(_BEMESSAGE.fields_by_name["txn_req"]) +_BEMESSAGE.fields_by_name["txn_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["txn_reply"] +) +_BEMESSAGE.fields_by_name["txn_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["cfg_data_req"] +) +_BEMESSAGE.fields_by_name["cfg_data_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["cfg_data_reply"] +) +_BEMESSAGE.fields_by_name[ + "cfg_data_reply" +].containing_oneof = _BEMESSAGE.oneofs_by_name["message"] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["cfg_apply_req"] +) +_BEMESSAGE.fields_by_name["cfg_apply_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[ + "message" +] +_BEMESSAGE.oneofs_by_name["message"].fields.append( + _BEMESSAGE.fields_by_name["cfg_apply_reply"] +) +_BEMESSAGE.fields_by_name[ + "cfg_apply_reply" +].containing_oneof = _BEMESSAGE.oneofs_by_name["message"] +_FESESSIONREQ.oneofs_by_name["id"].fields.append( + _FESESSIONREQ.fields_by_name["client_conn_id"] +) +_FESESSIONREQ.fields_by_name[ + "client_conn_id" +].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"] +_FESESSIONREQ.oneofs_by_name["id"].fields.append( + _FESESSIONREQ.fields_by_name["session_id"] +) +_FESESSIONREQ.fields_by_name[ + "session_id" +].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"] +_FELOCKDSREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FELOCKDSREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FESETCONFIGREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FESETCONFIGREQ.fields_by_name["data"].message_type = _YANGCFGDATAREQ +_FESETCONFIGREQ.fields_by_name["commit_ds_id"].enum_type = _DATASTOREID +_FESETCONFIGREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FECOMMITCONFIGREQ.fields_by_name["src_ds_id"].enum_type = _DATASTOREID +_FECOMMITCONFIGREQ.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID +_FECOMMITCONFIGREPLY.fields_by_name["src_ds_id"].enum_type = _DATASTOREID +_FECOMMITCONFIGREPLY.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID +_FEGETREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FEGETREQ.fields_by_name["data"].message_type = _YANGGETDATAREQ +_FEGETREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FEGETREPLY.fields_by_name["data"].message_type = _YANGDATAREPLY +_FENOTIFYDATAREQ.fields_by_name["data"].message_type = _YANGDATA +_FEREGISTERNOTIFYREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID +_FEREGISTERNOTIFYREQ.fields_by_name["data_xpath"].message_type = _YANGDATAXPATH +_FEMESSAGE.fields_by_name["register_req"].message_type = _FEREGISTERREQ +_FEMESSAGE.fields_by_name["session_req"].message_type = _FESESSIONREQ +_FEMESSAGE.fields_by_name["session_reply"].message_type = _FESESSIONREPLY +_FEMESSAGE.fields_by_name["lockds_req"].message_type = _FELOCKDSREQ +_FEMESSAGE.fields_by_name["lockds_reply"].message_type = _FELOCKDSREPLY +_FEMESSAGE.fields_by_name["setcfg_req"].message_type = _FESETCONFIGREQ +_FEMESSAGE.fields_by_name["setcfg_reply"].message_type = _FESETCONFIGREPLY +_FEMESSAGE.fields_by_name["commcfg_req"].message_type = _FECOMMITCONFIGREQ +_FEMESSAGE.fields_by_name["commcfg_reply"].message_type = _FECOMMITCONFIGREPLY +_FEMESSAGE.fields_by_name["get_req"].message_type = _FEGETREQ +_FEMESSAGE.fields_by_name["get_reply"].message_type = _FEGETREPLY +_FEMESSAGE.fields_by_name["notify_data_req"].message_type = _FENOTIFYDATAREQ +_FEMESSAGE.fields_by_name["regnotify_req"].message_type = _FEREGISTERNOTIFYREQ +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["register_req"] +) +_FEMESSAGE.fields_by_name["register_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["session_req"] +) +_FEMESSAGE.fields_by_name["session_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["session_reply"] +) +_FEMESSAGE.fields_by_name["session_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["lockds_req"] +) +_FEMESSAGE.fields_by_name["lockds_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["lockds_reply"] +) +_FEMESSAGE.fields_by_name["lockds_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["setcfg_req"] +) +_FEMESSAGE.fields_by_name["setcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["setcfg_reply"] +) +_FEMESSAGE.fields_by_name["setcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["commcfg_req"] +) +_FEMESSAGE.fields_by_name["commcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["commcfg_reply"] +) +_FEMESSAGE.fields_by_name["commcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append(_FEMESSAGE.fields_by_name["get_req"]) +_FEMESSAGE.fields_by_name["get_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["get_reply"] +) +_FEMESSAGE.fields_by_name["get_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["notify_data_req"] +) +_FEMESSAGE.fields_by_name[ + "notify_data_req" +].containing_oneof = _FEMESSAGE.oneofs_by_name["message"] +_FEMESSAGE.oneofs_by_name["message"].fields.append( + _FEMESSAGE.fields_by_name["regnotify_req"] +) +_FEMESSAGE.fields_by_name["regnotify_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[ + "message" +] +DESCRIPTOR.message_types_by_name["YangDataXPath"] = _YANGDATAXPATH +DESCRIPTOR.message_types_by_name["YangDataValue"] = _YANGDATAVALUE +DESCRIPTOR.message_types_by_name["YangData"] = _YANGDATA +DESCRIPTOR.message_types_by_name["YangCfgDataReq"] = _YANGCFGDATAREQ +DESCRIPTOR.message_types_by_name["YangGetDataReq"] = _YANGGETDATAREQ +DESCRIPTOR.message_types_by_name["BeSubscribeReq"] = _BESUBSCRIBEREQ +DESCRIPTOR.message_types_by_name["BeSubscribeReply"] = _BESUBSCRIBEREPLY +DESCRIPTOR.message_types_by_name["BeTxnReq"] = _BETXNREQ +DESCRIPTOR.message_types_by_name["BeTxnReply"] = _BETXNREPLY +DESCRIPTOR.message_types_by_name["BeCfgDataCreateReq"] = _BECFGDATACREATEREQ +DESCRIPTOR.message_types_by_name["BeCfgDataCreateReply"] = _BECFGDATACREATEREPLY +DESCRIPTOR.message_types_by_name["BeCfgDataApplyReq"] = _BECFGDATAAPPLYREQ +DESCRIPTOR.message_types_by_name["BeCfgDataApplyReply"] = _BECFGDATAAPPLYREPLY +DESCRIPTOR.message_types_by_name["YangDataReply"] = _YANGDATAREPLY +DESCRIPTOR.message_types_by_name["BeMessage"] = _BEMESSAGE +DESCRIPTOR.message_types_by_name["FeRegisterReq"] = _FEREGISTERREQ +DESCRIPTOR.message_types_by_name["FeSessionReq"] = _FESESSIONREQ +DESCRIPTOR.message_types_by_name["FeSessionReply"] = _FESESSIONREPLY +DESCRIPTOR.message_types_by_name["FeLockDsReq"] = _FELOCKDSREQ +DESCRIPTOR.message_types_by_name["FeLockDsReply"] = _FELOCKDSREPLY +DESCRIPTOR.message_types_by_name["FeSetConfigReq"] = _FESETCONFIGREQ +DESCRIPTOR.message_types_by_name["FeSetConfigReply"] = _FESETCONFIGREPLY +DESCRIPTOR.message_types_by_name["FeCommitConfigReq"] = _FECOMMITCONFIGREQ +DESCRIPTOR.message_types_by_name["FeCommitConfigReply"] = _FECOMMITCONFIGREPLY +DESCRIPTOR.message_types_by_name["FeGetReq"] = _FEGETREQ +DESCRIPTOR.message_types_by_name["FeGetReply"] = _FEGETREPLY +DESCRIPTOR.message_types_by_name["FeNotifyDataReq"] = _FENOTIFYDATAREQ +DESCRIPTOR.message_types_by_name["FeRegisterNotifyReq"] = _FEREGISTERNOTIFYREQ +DESCRIPTOR.message_types_by_name["FeMessage"] = _FEMESSAGE +DESCRIPTOR.enum_types_by_name["CfgDataReqType"] = _CFGDATAREQTYPE +DESCRIPTOR.enum_types_by_name["DatastoreId"] = _DATASTOREID _sym_db.RegisterFileDescriptor(DESCRIPTOR) -YangDataXPath = _reflection.GeneratedProtocolMessageType('YangDataXPath', (_message.Message,), { - 'DESCRIPTOR' : _YANGDATAXPATH, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath) - }) +YangDataXPath = _reflection.GeneratedProtocolMessageType( + "YangDataXPath", + (_message.Message,), + { + "DESCRIPTOR": _YANGDATAXPATH, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath) + }, +) _sym_db.RegisterMessage(YangDataXPath) -YangDataValue = _reflection.GeneratedProtocolMessageType('YangDataValue', (_message.Message,), { - 'DESCRIPTOR' : _YANGDATAVALUE, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue) - }) +YangDataValue = _reflection.GeneratedProtocolMessageType( + "YangDataValue", + (_message.Message,), + { + "DESCRIPTOR": _YANGDATAVALUE, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue) + }, +) _sym_db.RegisterMessage(YangDataValue) -YangData = _reflection.GeneratedProtocolMessageType('YangData', (_message.Message,), { - 'DESCRIPTOR' : _YANGDATA, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangData) - }) +YangData = _reflection.GeneratedProtocolMessageType( + "YangData", + (_message.Message,), + { + "DESCRIPTOR": _YANGDATA, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangData) + }, +) _sym_db.RegisterMessage(YangData) -YangCfgDataReq = _reflection.GeneratedProtocolMessageType('YangCfgDataReq', (_message.Message,), { - 'DESCRIPTOR' : _YANGCFGDATAREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq) - }) +YangCfgDataReq = _reflection.GeneratedProtocolMessageType( + "YangCfgDataReq", + (_message.Message,), + { + "DESCRIPTOR": _YANGCFGDATAREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq) + }, +) _sym_db.RegisterMessage(YangCfgDataReq) -YangGetDataReq = _reflection.GeneratedProtocolMessageType('YangGetDataReq', (_message.Message,), { - 'DESCRIPTOR' : _YANGGETDATAREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq) - }) +YangGetDataReq = _reflection.GeneratedProtocolMessageType( + "YangGetDataReq", + (_message.Message,), + { + "DESCRIPTOR": _YANGGETDATAREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq) + }, +) _sym_db.RegisterMessage(YangGetDataReq) -BeSubscribeReq = _reflection.GeneratedProtocolMessageType('BeSubscribeReq', (_message.Message,), { - 'DESCRIPTOR' : _BESUBSCRIBEREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq) - }) +BeSubscribeReq = _reflection.GeneratedProtocolMessageType( + "BeSubscribeReq", + (_message.Message,), + { + "DESCRIPTOR": _BESUBSCRIBEREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq) + }, +) _sym_db.RegisterMessage(BeSubscribeReq) -BeSubscribeReply = _reflection.GeneratedProtocolMessageType('BeSubscribeReply', (_message.Message,), { - 'DESCRIPTOR' : _BESUBSCRIBEREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply) - }) +BeSubscribeReply = _reflection.GeneratedProtocolMessageType( + "BeSubscribeReply", + (_message.Message,), + { + "DESCRIPTOR": _BESUBSCRIBEREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply) + }, +) _sym_db.RegisterMessage(BeSubscribeReply) -BeTxnReq = _reflection.GeneratedProtocolMessageType('BeTxnReq', (_message.Message,), { - 'DESCRIPTOR' : _BETXNREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq) - }) +BeTxnReq = _reflection.GeneratedProtocolMessageType( + "BeTxnReq", + (_message.Message,), + { + "DESCRIPTOR": _BETXNREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq) + }, +) _sym_db.RegisterMessage(BeTxnReq) -BeTxnReply = _reflection.GeneratedProtocolMessageType('BeTxnReply', (_message.Message,), { - 'DESCRIPTOR' : _BETXNREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply) - }) +BeTxnReply = _reflection.GeneratedProtocolMessageType( + "BeTxnReply", + (_message.Message,), + { + "DESCRIPTOR": _BETXNREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply) + }, +) _sym_db.RegisterMessage(BeTxnReply) -BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReq', (_message.Message,), { - 'DESCRIPTOR' : _BECFGDATACREATEREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq) - }) +BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType( + "BeCfgDataCreateReq", + (_message.Message,), + { + "DESCRIPTOR": _BECFGDATACREATEREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq) + }, +) _sym_db.RegisterMessage(BeCfgDataCreateReq) -BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReply', (_message.Message,), { - 'DESCRIPTOR' : _BECFGDATACREATEREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply) - }) +BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType( + "BeCfgDataCreateReply", + (_message.Message,), + { + "DESCRIPTOR": _BECFGDATACREATEREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply) + }, +) _sym_db.RegisterMessage(BeCfgDataCreateReply) -BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReq', (_message.Message,), { - 'DESCRIPTOR' : _BECFGDATAAPPLYREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq) - }) +BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType( + "BeCfgDataApplyReq", + (_message.Message,), + { + "DESCRIPTOR": _BECFGDATAAPPLYREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq) + }, +) _sym_db.RegisterMessage(BeCfgDataApplyReq) -BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReply', (_message.Message,), { - 'DESCRIPTOR' : _BECFGDATAAPPLYREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply) - }) +BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType( + "BeCfgDataApplyReply", + (_message.Message,), + { + "DESCRIPTOR": _BECFGDATAAPPLYREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply) + }, +) _sym_db.RegisterMessage(BeCfgDataApplyReply) -YangDataReply = _reflection.GeneratedProtocolMessageType('YangDataReply', (_message.Message,), { - 'DESCRIPTOR' : _YANGDATAREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply) - }) +YangDataReply = _reflection.GeneratedProtocolMessageType( + "YangDataReply", + (_message.Message,), + { + "DESCRIPTOR": _YANGDATAREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply) + }, +) _sym_db.RegisterMessage(YangDataReply) -BeMessage = _reflection.GeneratedProtocolMessageType('BeMessage', (_message.Message,), { - 'DESCRIPTOR' : _BEMESSAGE, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.BeMessage) - }) +BeMessage = _reflection.GeneratedProtocolMessageType( + "BeMessage", + (_message.Message,), + { + "DESCRIPTOR": _BEMESSAGE, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.BeMessage) + }, +) _sym_db.RegisterMessage(BeMessage) -FeRegisterReq = _reflection.GeneratedProtocolMessageType('FeRegisterReq', (_message.Message,), { - 'DESCRIPTOR' : _FEREGISTERREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq) - }) +FeRegisterReq = _reflection.GeneratedProtocolMessageType( + "FeRegisterReq", + (_message.Message,), + { + "DESCRIPTOR": _FEREGISTERREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq) + }, +) _sym_db.RegisterMessage(FeRegisterReq) -FeSessionReq = _reflection.GeneratedProtocolMessageType('FeSessionReq', (_message.Message,), { - 'DESCRIPTOR' : _FESESSIONREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq) - }) +FeSessionReq = _reflection.GeneratedProtocolMessageType( + "FeSessionReq", + (_message.Message,), + { + "DESCRIPTOR": _FESESSIONREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq) + }, +) _sym_db.RegisterMessage(FeSessionReq) -FeSessionReply = _reflection.GeneratedProtocolMessageType('FeSessionReply', (_message.Message,), { - 'DESCRIPTOR' : _FESESSIONREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply) - }) +FeSessionReply = _reflection.GeneratedProtocolMessageType( + "FeSessionReply", + (_message.Message,), + { + "DESCRIPTOR": _FESESSIONREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply) + }, +) _sym_db.RegisterMessage(FeSessionReply) -FeLockDsReq = _reflection.GeneratedProtocolMessageType('FeLockDsReq', (_message.Message,), { - 'DESCRIPTOR' : _FELOCKDSREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq) - }) +FeLockDsReq = _reflection.GeneratedProtocolMessageType( + "FeLockDsReq", + (_message.Message,), + { + "DESCRIPTOR": _FELOCKDSREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq) + }, +) _sym_db.RegisterMessage(FeLockDsReq) -FeLockDsReply = _reflection.GeneratedProtocolMessageType('FeLockDsReply', (_message.Message,), { - 'DESCRIPTOR' : _FELOCKDSREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply) - }) +FeLockDsReply = _reflection.GeneratedProtocolMessageType( + "FeLockDsReply", + (_message.Message,), + { + "DESCRIPTOR": _FELOCKDSREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply) + }, +) _sym_db.RegisterMessage(FeLockDsReply) -FeSetConfigReq = _reflection.GeneratedProtocolMessageType('FeSetConfigReq', (_message.Message,), { - 'DESCRIPTOR' : _FESETCONFIGREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq) - }) +FeSetConfigReq = _reflection.GeneratedProtocolMessageType( + "FeSetConfigReq", + (_message.Message,), + { + "DESCRIPTOR": _FESETCONFIGREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq) + }, +) _sym_db.RegisterMessage(FeSetConfigReq) -FeSetConfigReply = _reflection.GeneratedProtocolMessageType('FeSetConfigReply', (_message.Message,), { - 'DESCRIPTOR' : _FESETCONFIGREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply) - }) +FeSetConfigReply = _reflection.GeneratedProtocolMessageType( + "FeSetConfigReply", + (_message.Message,), + { + "DESCRIPTOR": _FESETCONFIGREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply) + }, +) _sym_db.RegisterMessage(FeSetConfigReply) -FeCommitConfigReq = _reflection.GeneratedProtocolMessageType('FeCommitConfigReq', (_message.Message,), { - 'DESCRIPTOR' : _FECOMMITCONFIGREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq) - }) +FeCommitConfigReq = _reflection.GeneratedProtocolMessageType( + "FeCommitConfigReq", + (_message.Message,), + { + "DESCRIPTOR": _FECOMMITCONFIGREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq) + }, +) _sym_db.RegisterMessage(FeCommitConfigReq) -FeCommitConfigReply = _reflection.GeneratedProtocolMessageType('FeCommitConfigReply', (_message.Message,), { - 'DESCRIPTOR' : _FECOMMITCONFIGREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply) - }) +FeCommitConfigReply = _reflection.GeneratedProtocolMessageType( + "FeCommitConfigReply", + (_message.Message,), + { + "DESCRIPTOR": _FECOMMITCONFIGREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply) + }, +) _sym_db.RegisterMessage(FeCommitConfigReply) -FeGetReq = _reflection.GeneratedProtocolMessageType('FeGetReq', (_message.Message,), { - 'DESCRIPTOR' : _FEGETREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq) - }) +FeGetReq = _reflection.GeneratedProtocolMessageType( + "FeGetReq", + (_message.Message,), + { + "DESCRIPTOR": _FEGETREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq) + }, +) _sym_db.RegisterMessage(FeGetReq) -FeGetReply = _reflection.GeneratedProtocolMessageType('FeGetReply', (_message.Message,), { - 'DESCRIPTOR' : _FEGETREPLY, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply) - }) +FeGetReply = _reflection.GeneratedProtocolMessageType( + "FeGetReply", + (_message.Message,), + { + "DESCRIPTOR": _FEGETREPLY, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply) + }, +) _sym_db.RegisterMessage(FeGetReply) -FeNotifyDataReq = _reflection.GeneratedProtocolMessageType('FeNotifyDataReq', (_message.Message,), { - 'DESCRIPTOR' : _FENOTIFYDATAREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq) - }) +FeNotifyDataReq = _reflection.GeneratedProtocolMessageType( + "FeNotifyDataReq", + (_message.Message,), + { + "DESCRIPTOR": _FENOTIFYDATAREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq) + }, +) _sym_db.RegisterMessage(FeNotifyDataReq) -FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType('FeRegisterNotifyReq', (_message.Message,), { - 'DESCRIPTOR' : _FEREGISTERNOTIFYREQ, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq) - }) +FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType( + "FeRegisterNotifyReq", + (_message.Message,), + { + "DESCRIPTOR": _FEREGISTERNOTIFYREQ, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq) + }, +) _sym_db.RegisterMessage(FeRegisterNotifyReq) -FeMessage = _reflection.GeneratedProtocolMessageType('FeMessage', (_message.Message,), { - 'DESCRIPTOR' : _FEMESSAGE, - '__module__' : 'mgmt_pb2' - # @@protoc_insertion_point(class_scope:mgmtd.FeMessage) - }) +FeMessage = _reflection.GeneratedProtocolMessageType( + "FeMessage", + (_message.Message,), + { + "DESCRIPTOR": _FEMESSAGE, + "__module__": "mgmt_pb2", + # @@protoc_insertion_point(class_scope:mgmtd.FeMessage) + }, +) _sym_db.RegisterMessage(FeMessage) diff --git a/tests/topotests/mgmt_oper/oper.py b/tests/topotests/mgmt_oper/oper.py index 0f6c3cdf5f..162c1eb5cc 100644 --- a/tests/topotests/mgmt_oper/oper.py +++ b/tests/topotests/mgmt_oper/oper.py @@ -62,7 +62,8 @@ def disable_debug(router): router.vtysh_cmd("no debug northbound callbacks configuration") -def do_oper_test(tgen, query_results): +@retry(retry_timeout=30, initial_wait=1) +def _do_oper_test(tgen, qr): r1 = tgen.gears["r1"].net qcmd = ( @@ -73,50 +74,55 @@ def do_oper_test(tgen, query_results): r"""| sed -e 's/"if-index": [0-9][0-9]*/"if-index": "rubout"/'""" r"""| sed -e 's/"id": [0-9][0-9]*/"id": "rubout"/'""" ) - - doreset = True + # Don't use this for now. dd_json_cmp = None - for qr in query_results: - step(f"Perform query '{qr[0]}'", reset=doreset) - if doreset: - doreset = False - expected = open(qr[1], encoding="ascii").read() - output = r1.cmd_nostatus(qcmd.format(qr[0], qr[2] if len(qr) > 2 else "")) - - try: - ojson = json.loads(output) - except json.decoder.JSONDecodeError as error: - logging.error("Error decoding json: %s\noutput:\n%s", error, output) - raise - - try: - ejson = json.loads(expected) - except json.decoder.JSONDecodeError as error: - logging.error( - "Error decoding json exp result: %s\noutput:\n%s", error, expected + + expected = open(qr[1], encoding="ascii").read() + output = r1.cmd_nostatus(qcmd.format(qr[0], qr[2] if len(qr) > 2 else "")) + + try: + ojson = json.loads(output) + except json.decoder.JSONDecodeError as error: + logging.error("Error decoding json: %s\noutput:\n%s", error, output) + raise + + try: + ejson = json.loads(expected) + except json.decoder.JSONDecodeError as error: + logging.error( + "Error decoding json exp result: %s\noutput:\n%s", error, expected + ) + raise + + if dd_json_cmp: + cmpout = json_cmp(ojson, ejson, exact_match=True) + if cmpout: + logging.warning( + "-------DIFF---------\n%s\n---------DIFF----------", + pprint.pformat(cmpout), ) - raise - - if dd_json_cmp: - cmpout = json_cmp(ojson, ejson, exact_match=True) - if cmpout: - logging.warning( - "-------DIFF---------\n%s\n---------DIFF----------", - pprint.pformat(cmpout), - ) - else: - cmpout = tt_json_cmp(ojson, ejson, exact=True) - if cmpout: - logging.warning( - "-------EXPECT--------\n%s\n------END-EXPECT------", - json.dumps(ejson, indent=4), - ) - logging.warning( - "--------GOT----------\n%s\n-------END-GOT--------", - json.dumps(ojson, indent=4), - ) - - assert cmpout is None + else: + cmpout = tt_json_cmp(ojson, ejson, exact=True) + if cmpout: + logging.warning( + "-------EXPECT--------\n%s\n------END-EXPECT------", + json.dumps(ejson, indent=4), + ) + logging.warning( + "--------GOT----------\n%s\n-------END-GOT--------", + json.dumps(ojson, indent=4), + ) + + assert cmpout is None + + +def do_oper_test(tgen, query_results): + reset = True + for qr in query_results: + step(f"Perform query '{qr[0]}'", reset=reset) + if reset: + reset = False + _do_oper_test(tgen, qr) def get_ip_networks(super_prefix, count): diff --git a/tests/topotests/mgmt_oper/test_oper.py b/tests/topotests/mgmt_oper/test_oper.py index 6971eafc57..8b8a51c29e 100644 --- a/tests/topotests/mgmt_oper/test_oper.py +++ b/tests/topotests/mgmt_oper/test_oper.py @@ -95,7 +95,6 @@ def test_oper(tgen): check_kernel_32(r1, "12.12.12.12", 1, "") check_kernel_32(r1, "13.13.13.13", 1, "red") check_kernel_32(r1, "14.14.14.14", 1, "red") - time.sleep(2) do_oper_test(tgen, query_results) diff --git a/tests/topotests/mgmt_oper/test_scale.py b/tests/topotests/mgmt_oper/test_scale.py index 41c2b8cd78..87794d7d66 100644 --- a/tests/topotests/mgmt_oper/test_scale.py +++ b/tests/topotests/mgmt_oper/test_scale.py @@ -52,7 +52,6 @@ def test_oper_simple(tgen): r1 = tgen.gears["r1"].net - time.sleep(2) count = 20 * 1000 vrf = None # "red" diff --git a/tests/topotests/mgmt_rpc/r1/frr.conf b/tests/topotests/mgmt_rpc/r1/frr.conf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/mgmt_rpc/r1/frr.conf diff --git a/tests/topotests/mgmt_rpc/test_rpc.py b/tests/topotests/mgmt_rpc/test_rpc.py new file mode 100644 index 0000000000..618d9022ce --- /dev/null +++ b/tests/topotests/mgmt_rpc/test_rpc.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 eval: (blacken-mode 1) -*- +# SPDX-License-Identifier: ISC +# +# March 21 2024, Igor Ryzhov <iryzhov@nfware.com> +# +# Copyright (c) 2024, NFWare Inc. +# + +""" +Test YANG Notifications +""" +import json +import os +import threading + +import pytest +from lib.topogen import Topogen +from lib.topotest import json_cmp + +pytestmark = [pytest.mark.ripd, pytest.mark.mgmtd] + +CWD = os.path.dirname(os.path.realpath(__file__)) + + +@pytest.fixture(scope="module") +def tgen(request): + "Setup/Teardown the environment and provide tgen argument to tests" + + topodef = {"s1": ("r1",)} + + tgen = Topogen(topodef, request.module.__name__) + tgen.start_topology() + + router_list = tgen.routers() + for rname, router in router_list.items(): + router.load_frr_config("frr.conf") + + tgen.start_router() + yield tgen + tgen.stop_topology() + + +def test_backend_rpc(tgen): + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + + be_client_path = "/usr/lib/frr/mgmtd_testc" + rc, _, _ = r1.net.cmd_status(be_client_path + " --help") + + if rc: + pytest.skip("No mgmtd_testc") + + out = [] + + def run_testc(): + output = r1.net.cmd_raises( + be_client_path + " --timeout 10 --log file:mgmt_testc.log" + ) + out.append(json.loads(output)) + + t = threading.Thread(target=run_testc) + t.start() + + r1.vtysh_cmd("clear ip rip vrf testname") + + t.join() + + jsout = out[0] + + expected = {"frr-ripd:clear-rip-route": {"vrf": "testname"}} + result = json_cmp(jsout, expected) + assert result is None diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py index 9ee411206d..1775c9baed 100644 --- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py +++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py @@ -202,7 +202,6 @@ def teardown_module(): def clear_bsrp_data(tgen, topo): - """ clear bsm databas after test" Parameters @@ -218,7 +217,6 @@ def clear_bsrp_data(tgen, topo): """ for dut in tgen.routers(): - rnode = tgen.routers()[dut] logger.info("[DUT: %s]: clear_bsrp_data") diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py index 302a778585..e4df508909 100644 --- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py +++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py @@ -182,7 +182,6 @@ def teardown_module(): def clear_bsrp_data(tgen, topo): - """ clear bsm databas after test" Parameters @@ -198,7 +197,6 @@ def clear_bsrp_data(tgen, topo): """ for dut in tgen.routers(): - rnode = tgen.routers()[dut] logger.info("[DUT: %s]: clear_bsrp_data") diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py index 1de6eac897..f87a90d198 100755 --- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py +++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py @@ -42,7 +42,7 @@ import time from time import sleep import pytest -pytestmark = pytest.mark.pimd +pytestmark = [pytest.mark.pimd] # Save the Current Working Directory to find configuration files. CWD = os.path.dirname(os.path.realpath(__file__)) @@ -83,8 +83,6 @@ from lib.topolog import logger from lib.topojson import build_config_from_json -pytestmark = [pytest.mark.pimd] - TOPOLOGY = """ diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py index 17f52cb860..b62f7bbfc9 100755 --- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py +++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py @@ -37,7 +37,7 @@ import sys import time import pytest -pytestmark = pytest.mark.pimd +pytestmark = [pytest.mark.pimd] # Save the Current Working Directory to find configuration files. CWD = os.path.dirname(os.path.realpath(__file__)) @@ -81,8 +81,6 @@ from lib.topolog import logger from lib.topojson import build_config_from_json -pytestmark = [pytest.mark.pimd] - TOPOLOGY = """ diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py index 2c1241c0cc..ae27546703 100755 --- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py +++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py @@ -45,7 +45,7 @@ from time import sleep import json import functools -pytestmark = pytest.mark.pimd +pytestmark = [pytest.mark.pimd] # Save the Current Working Directory to find configuration files. CWD = os.path.dirname(os.path.realpath(__file__)) @@ -91,7 +91,6 @@ from lib.topolog import logger from lib.topojson import build_config_from_json CWD = os.path.dirname(os.path.realpath(__file__)) -pytestmark = pytest.mark.pimd TOPOLOGY = """ @@ -265,11 +264,14 @@ def verify_state_incremented(state_before, state_after): for intf, v2 in v1.items(): for state, value in v2.items(): if value >= state_after[ttype][intf][state]: - errormsg = "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]" % ( - intf, - state, - value, - state_after[ttype][intf][state], + errormsg = ( + "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]" + % ( + intf, + state, + value, + state_after[ttype][intf][state], + ) ) return errormsg @@ -328,7 +330,6 @@ def find_tos_in_tcpdump(tgen, router, message, cap_file): filepath = os.path.join(tgen.logdir, router, cap_file) with open(filepath) as f: - if len(re.findall(message, f.read())) < 1: errormsg = "[DUT: %s]: Verify Message: %s in tcpdump" " [FAILED!!]" % ( router, diff --git a/tests/topotests/munet/__main__.py b/tests/topotests/munet/__main__.py index 4419ab94a2..e50fea6915 100644 --- a/tests/topotests/munet/__main__.py +++ b/tests/topotests/munet/__main__.py @@ -16,6 +16,7 @@ import sys from . import cli from . import parser +from .args import add_launch_args from .base import get_event_loop from .cleanup import cleanup_previous from .compat import PytestConfig @@ -106,59 +107,35 @@ def main(*args): cap.add_argument( "--project-root", help="directory to stop searching for kinds config at" ) + rap = ap.add_argument_group(title="Runtime", description="runtime related options") + add_launch_args(rap.add_argument) + + # Move to munet.args? rap.add_argument( "-C", "--cleanup", action="store_true", help="Remove the entire rundir (not just node subdirs) prior to running.", ) - rap.add_argument( - "--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on" - ) - rap.add_argument( - "--gdb-breakpoints", - metavar="BREAKPOINT-LIST", - help="comma-sep list of breakpoints to set", - ) - rap.add_argument( - "--host", - action="store_true", - help="no isolation for top namespace, bridges exposed to default namespace", - ) - rap.add_argument( - "--pcap", - metavar="TARGET-LIST", - help="comma-sep list of capture targets (NETWORK or NODE:IFNAME)", - ) - rap.add_argument( - "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on" - ) - rap.add_argument( - "--stderr", - metavar="NODE-LIST", - help="comma-sep list of nodes to open windows viewing stderr", - ) - rap.add_argument( - "--stdout", - metavar="NODE-LIST", - help="comma-sep list of nodes to open windows viewing stdout", - ) + # Move to munet.args? rap.add_argument( "--topology-only", action="store_true", help="Do not run any node commands", ) - rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS) rap.add_argument( "--validate-only", action="store_true", help="Validate the config against the schema definition", ) + rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS) + rap.add_argument("-v", "--verbose", action="store_true", help="be verbose") rap.add_argument( "-V", "--version", action="store_true", help="print the verison number and exit" ) + eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options") eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)") eap.add_argument( @@ -181,7 +158,6 @@ def main(*args): rundir = args.rundir if args.rundir else "/tmp/munet" args.rundir = rundir - if args.cleanup: if os.path.exists(rundir): if not os.path.exists(f"{rundir}/config.json"): @@ -193,7 +169,6 @@ def main(*args): sys.exit(1) else: subprocess.run(["/usr/bin/rm", "-rf", rundir], check=True) - subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True) os.environ["MUNET_RUNDIR"] = rundir diff --git a/tests/topotests/munet/args.py b/tests/topotests/munet/args.py new file mode 100644 index 0000000000..49ad891cef --- /dev/null +++ b/tests/topotests/munet/args.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 eval: (blacken-mode 1) -*- +# +# April 14 2024, Christian Hopps <chopps@labn.net> +# +# Copyright (c) 2024, LabN Consulting, L.L.C. +# +"""Common CLI execute argument.""" + + +def add_launch_args(add_func): + + add_func("--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on") + add_func( + "--gdb-breakpoints", + metavar="BREAKPOINT-LIST", + help="comma-sep list of breakpoints to set", + ) + add_func( + "--gdb-use-emacs", + action="store_true", + help="Use emacsclient to run gdb instead of a shell", + ) + + add_func( + "--host", + action="store_true", + help="no isolation for top namespace, bridges exposed to default namespace", + ) + add_func( + "--pcap", + metavar="TARGET-LIST", + help="comma-sep list of capture targets (NETWORK or NODE:IFNAME) or 'all'", + ) + add_func( + "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on" + ) + add_func( + "--stderr", + metavar="NODE-LIST", + help="comma-sep list of nodes to open windows viewing stderr", + ) + add_func( + "--stdout", + metavar="NODE-LIST", + help="comma-sep list of nodes to open windows viewing stdout", + ) + + +def add_testing_args(add_func): + add_func( + "--cli-on-error", + action="store_true", + help="CLI on test failure", + ) + + add_func( + "--coverage", + action="store_true", + help="Enable coverage gathering if supported", + ) + + add_func( + "--cov-build-dir", + help="Specify the build dir for locating coverage data files", + ) + + add_launch_args(add_func) + + add_func( + "--pause", + action="store_true", + help="Pause after each test", + ) + add_func( + "--pause-at-end", + action="store_true", + help="Pause before taking munet down", + ) + add_func( + "--pause-on-error", + action="store_true", + help="Pause after (disables default when --shell or -vtysh given)", + ) + add_func( + "--no-pause-on-error", + dest="pause_on_error", + action="store_false", + help="Do not pause after (disables default when --shell or -vtysh given)", + ) diff --git a/tests/topotests/munet/base.py b/tests/topotests/munet/base.py index 72b5df54b9..a4811f179c 100644 --- a/tests/topotests/munet/base.py +++ b/tests/topotests/munet/base.py @@ -21,6 +21,7 @@ import subprocess import sys import tempfile import time as time_mod + from collections import defaultdict from pathlib import Path from typing import Union @@ -28,8 +29,10 @@ from typing import Union from . import config as munet_config from . import linux + try: import pexpect + from pexpect.fdpexpect import fdspawn from pexpect.popen_spawn import PopenSpawn @@ -273,6 +276,9 @@ def get_event_loop(): """ policy = asyncio.get_event_loop_policy() loop = policy.get_event_loop() + if not hasattr(os, "pidfd_open"): + return loop + owatcher = policy.get_child_watcher() logging.debug( "event_loop_fixture: global policy %s, current loop %s, current watcher %s", diff --git a/tests/topotests/munet/mucmd.py b/tests/topotests/munet/mucmd.py index 5518c6dcfe..d6101e1a55 100644 --- a/tests/topotests/munet/mucmd.py +++ b/tests/topotests/munet/mucmd.py @@ -9,7 +9,6 @@ import argparse import json import os -import subprocess import sys from pathlib import Path @@ -90,17 +89,12 @@ def main(*args): ecmd = "/usr/bin/nsenter" eargs = [ecmd] - output = subprocess.check_output(["/usr/bin/nsenter", "--help"], encoding="utf-8") - if " -a," in output: - eargs.append("-a") - else: - # -U doesn't work - for flag in ["-u", "-i", "-m", "-n", "-C", "-T"]: - if f" {flag}," in output: - eargs.append(flag) + # start mucmd same way base process is started + eargs.append(f"--mount=/proc/{pid}/ns/mnt") + eargs.append(f"--net=/proc/{pid}/ns/net") eargs.append(f"--pid=/proc/{pid}/ns/pid_for_children") + eargs.append(f"--uts=/proc/{pid}/ns/uts") eargs.append(f"--wd={rundir}") - eargs.extend(["-t", pid]) eargs += args.shellcmd # print("Using ", eargs) return os.execvpe(ecmd, eargs, {**env, **envcfg}) diff --git a/tests/topotests/munet/munet-schema.json b/tests/topotests/munet/munet-schema.json index a1dcd878dd..7d577e63b3 100644 --- a/tests/topotests/munet/munet-schema.json +++ b/tests/topotests/munet/munet-schema.json @@ -99,6 +99,15 @@ "server-port": { "type": "number" }, + "ssh-identity-file": { + "type": "string" + }, + "ssh-user": { + "type": "string" + }, + "ssh-password": { + "type": "string" + }, "qemu": { "type": "object", "properties": { @@ -108,6 +117,15 @@ "disk": { "type": "string" }, + "disk-driver": { + "type": "string" + }, + "disk-template": { + "type": "string" + }, + "initial-cmd": { + "type": "string" + }, "kerenel": { "type": "string" }, @@ -141,6 +159,9 @@ "password": { "type": "string" }, + "initial-password": { + "type": "string" + }, "expects": { "type": "array", "items": { @@ -407,6 +428,15 @@ "server-port": { "type": "number" }, + "ssh-identity-file": { + "type": "string" + }, + "ssh-user": { + "type": "string" + }, + "ssh-password": { + "type": "string" + }, "qemu": { "type": "object", "properties": { @@ -416,6 +446,15 @@ "disk": { "type": "string" }, + "disk-driver": { + "type": "string" + }, + "disk-template": { + "type": "string" + }, + "initial-cmd": { + "type": "string" + }, "kerenel": { "type": "string" }, @@ -449,6 +488,9 @@ "password": { "type": "string" }, + "initial-password": { + "type": "string" + }, "expects": { "type": "array", "items": { diff --git a/tests/topotests/munet/mutest/__main__.py b/tests/topotests/munet/mutest/__main__.py index c87031112d..d94e702c52 100644 --- a/tests/topotests/munet/mutest/__main__.py +++ b/tests/topotests/munet/mutest/__main__.py @@ -21,8 +21,11 @@ from pathlib import Path from typing import Union from munet import parser +from munet.args import add_testing_args from munet.base import Bridge from munet.base import get_event_loop +from munet.cli import async_cli +from munet.compat import PytestConfig from munet.mutest import userapi as uapi from munet.native import L3NodeMixin from munet.native import Munet @@ -36,7 +39,9 @@ root_logger = logging.getLogger("") exec_formatter = logging.Formatter("%(asctime)s %(levelname)5s: %(name)s: %(message)s") -async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = False): +async def get_unet( + config: dict, croot: Path, rundir: Path, args: Namespace, unshare: bool = False +): """Create and run a new Munet topology. The topology is built from the given ``config`` to run inside the path indicated @@ -48,6 +53,7 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals value will be modified and stored in the built ``Munet`` object. croot: common root of all tests, used to search for ``kinds.yaml`` files. rundir: the path to the run directory for this topology. + args: argparse args unshare: True to unshare the process into it's own private namespace. Yields: @@ -58,7 +64,11 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals try: try: unet = await async_build_topology( - config, rundir=str(rundir), unshare_inline=unshare + config, + rundir=str(rundir), + args=args, + pytestconfig=PytestConfig(args), + unshare_inline=unshare, ) except Exception as error: logging.debug("unet build failed: %s", error, exc_info=True) @@ -221,9 +231,13 @@ async def execute_test( targets["."] = unet tc = uapi.TestCase( - str(test_num), test_name, test, targets, logger, reslog, args.full_summary + str(test_num), test_name, test, targets, args, logger, reslog, args.full_summary ) - passed, failed, e = tc.execute() + try: + passed, failed, e = tc.execute() + except uapi.CLIOnErrorError as error: + await async_cli(unet) + passed, failed, e = 0, 0, error run_time = time.time() - tc.info.start_time @@ -278,6 +292,10 @@ async def run_tests(args): start_time = time.time() try: for dirpath in tests: + if args.validate_only: + parser.validate_config(configs[dirpath], reslog, args) + continue + test_files = tests[dirpath] for test in test_files: tnum += 1 @@ -294,10 +312,12 @@ async def run_tests(args): root_logger.addHandler(exec_handler) try: - async for unet in get_unet(config, common, rundir): + async for unet in get_unet(config, common, rundir, args): + if not printed_header: print_header(reslog, unet) printed_header = True + passed, failed, e = await execute_test( unet, test, args, tnum, exec_handler ) @@ -321,6 +341,9 @@ async def run_tests(args): except KeyboardInterrupt: pass + if args.validate_only: + return False + run_time = time.time() - start_time tnum = 0 tpassed = 0 @@ -386,32 +409,43 @@ async def async_main(args): def main(): ap = ArgumentParser() ap.add_argument( - "--dist", - type=int, - nargs="?", - const=-1, - default=0, - action="store", - metavar="NUM-THREADS", - help="Run in parallel, value is num. of threads or no value for auto", + "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose" ) - ap.add_argument("-d", "--rundir", help="runtime directory for tempfiles, logs, etc") ap.add_argument( + "-V", "--version", action="store_true", help="print the verison number and exit" + ) + ap.add_argument("paths", nargs="*", help="Paths to collect tests from") + + rap = ap.add_argument_group(title="Runtime", description="runtime related options") + rap.add_argument( + "-d", "--rundir", help="runtime directory for tempfiles, logs, etc" + ) + add_testing_args(rap.add_argument) + + eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options") + eap.add_argument( "--file-select", default="mutest_*.py", help="shell glob for finding tests" ) - ap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)") - ap.add_argument( - "-V", + eap.add_argument( "--full-summary", action="store_true", help="print full summary headers from docstrings", ) - ap.add_argument( - "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose" + eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)") + eap.add_argument( + "--validate-only", + action="store_true", + help="Validate the munet configs against the schema definition", ) - ap.add_argument("paths", nargs="*", help="Paths to collect tests from") + args = ap.parse_args() + if args.version: + from importlib import metadata # pylint: disable=C0415 + + print(metadata.version("munet")) + sys.exit(0) + rundir = args.rundir if args.rundir else "/tmp/mutest" args.rundir = Path(rundir) os.environ["MUNET_RUNDIR"] = rundir diff --git a/tests/topotests/munet/mutest/userapi.py b/tests/topotests/munet/mutest/userapi.py index 7967dd0c09..f42fbc1893 100644 --- a/tests/topotests/munet/mutest/userapi.py +++ b/tests/topotests/munet/mutest/userapi.py @@ -65,8 +65,11 @@ import json import logging import pprint import re +import subprocess +import sys import time +from argparse import Namespace from pathlib import Path from typing import Any from typing import Union @@ -76,6 +79,51 @@ from deepdiff import DeepDiff as json_cmp from munet.base import Commander +class ScriptError(Exception): + """An unrecoverable script failure.""" + + +class CLIOnErrorError(Exception): + """Enter CLI after error.""" + + +def pause_test(desc=""): + isatty = sys.stdout.isatty() + if not isatty: + desc = f" for {desc}" if desc else "" + logging.info("NO PAUSE on non-tty terminal%s", desc) + return + + while True: + if desc: + print(f"\n== PAUSING: {desc} ==") + try: + user = input('PAUSED, "cli" for CLI, "pdb" to debug, "Enter" to continue: ') + except EOFError: + print("^D...continuing") + break + user = user.strip() + if user == "cli": + raise CLIOnErrorError() + if user == "pdb": + breakpoint() # pylint: disable=W1515 + elif user: + print(f'Unrecognized input: "{user}"') + else: + break + + +def act_on_result(success, args, desc=""): + if args.pause: + pause_test(desc) + elif success: + return + if args.cli_on_error: + raise CLIOnErrorError() + if args.pause_on_error: + pause_test(desc) + + class TestCaseInfo: """Object to hold nestable TestCase Results.""" @@ -140,6 +188,7 @@ class TestCase: name: str, path: Path, targets: dict, + args: Namespace, output_logger: logging.Logger = None, result_logger: logging.Logger = None, full_summary: bool = False, @@ -157,6 +206,7 @@ class TestCase: self.__in_section = False self.targets = targets + self.args = args self.last = "" self.last_m = None @@ -285,7 +335,10 @@ class TestCase: # Extract any docstring as a title. if print_header: - title = locals()[f"_{name}"].__doc__.lstrip() + title = locals()[f"_{name}"].__doc__ + if title is None: + title = "" + title = title.lstrip() if self.__short_doc_header and (title := title.lstrip()): if (idx := title.find("\n")) != -1: title = title[:idx].strip() @@ -299,6 +352,10 @@ class TestCase: # Here's where we can do async in the future if we want. # result = await locals()[f"_{name}"](_ok_result) + except ScriptError as error: + return error + except CLIOnErrorError: + raise except Exception as error: logging.error( "Unexpected exception executing %s: %s", name, error, exc_info=True @@ -381,7 +438,9 @@ class TestCase: target: the target to execute the command on. cmd: string to execut on the target. """ - out = self.targets[target].cmd_nostatus(cmd, warn=False) + out = self.targets[target].cmd_nostatus( + cmd, stdin=subprocess.DEVNULL, warn=False + ) self.last = out = out.rstrip() report = out if out else "<no output>" self.logf("COMMAND OUTPUT:\n%s", report) @@ -398,12 +457,14 @@ class TestCase: target: the target to execute the command on. cmd: string to execute on the target. """ - out = self.targets[target].cmd_nostatus(cmd, warn=False) + out = self.targets[target].cmd_nostatus( + cmd, stdin=subprocess.DEVNULL, warn=False + ) self.last = out = out.rstrip() try: js = json.loads(out) except Exception as error: - js = {} + js = None self.olog.warning( "JSON load failed. Check command output is in JSON format: %s", error, @@ -482,20 +543,29 @@ class TestCase: exact_match: if True then the json must exactly match. """ js = self._command_json(target, cmd) + if js is None: + return expect_fail, {} + try: + # Convert to string to validate the input is valid JSON + if not isinstance(match, str): + match = json.dumps(match) expect = json.loads(match) except Exception as error: expect = {} self.olog.warning( "JSON load failed. Check match value is in JSON format: %s", error ) + return expect_fail, {} if exact_match: deep_diff = json_cmp(expect, js) # Convert DeepDiff completely into dicts or lists at all levels json_diff = json.loads(deep_diff.to_json()) else: - deep_diff = json_cmp(expect, js, ignore_order=True) + deep_diff = json_cmp( + expect, js, ignore_order=True, cutoff_intersection_for_pairs=1 + ) # Convert DeepDiff completely into dicts or lists at all levels json_diff = json.loads(deep_diff.to_json()) # Remove new fields in json object from diff @@ -570,6 +640,7 @@ class TestCase: """ path = Path(pathname) path = self.info.path.parent.joinpath(path) + do_cli = False self.oplogf( "include: new path: %s create section: %s currently __in_section: %s", @@ -589,7 +660,12 @@ class TestCase: self.info.path = path self.oplogf("include: swapped info path: new %s old %s", path, old_path) - self.__exec_script(path, print_header=new_section, add_newline=new_section) + try: + e = self.__exec_script( + path, print_header=new_section, add_newline=new_section + ) + except CLIOnErrorError: + do_cli = True if new_section: # Something within the section creating include has also created a section @@ -616,6 +692,11 @@ class TestCase: self.info.path = old_path self.oplogf("include: restored info path: %s", old_path) + if do_cli: + raise CLIOnErrorError() + if e: + raise ScriptError(e) + def __end_section(self): self.oplogf("__end_section: __in_section: %s", self.__in_section) info = self.__pop_execinfo() @@ -719,6 +800,7 @@ class TestCase: ) if desc: self.__post_result(target, success, desc) + act_on_result(success, self.args, desc) return success, ret def test_step(self, expr_or_value: Any, desc: str, target: str = "") -> bool: @@ -728,6 +810,7 @@ class TestCase: """ success = bool(expr_or_value) self.__post_result(target, success, desc) + act_on_result(success, self.args, desc) return success def match_step_json( @@ -760,6 +843,7 @@ class TestCase: ) if desc: self.__post_result(target, success, desc) + act_on_result(success, self.args, desc) return success, ret def wait_step( @@ -808,6 +892,7 @@ class TestCase: ) if desc: self.__post_result(target, success, desc) + act_on_result(success, self.args, desc) return success, ret def wait_step_json( @@ -846,6 +931,7 @@ class TestCase: ) if desc: self.__post_result(target, success, desc) + act_on_result(success, self.args, desc) return success, ret diff --git a/tests/topotests/munet/native.py b/tests/topotests/munet/native.py index 4fbbb85603..de0f0ffc6c 100644 --- a/tests/topotests/munet/native.py +++ b/tests/topotests/munet/native.py @@ -8,8 +8,10 @@ # pylint: disable=protected-access """A module that defines objects for standalone use.""" import asyncio +import base64 import errno import getpass +import glob import ipaddress import logging import os @@ -394,6 +396,10 @@ class NodeMixin: async def async_cleanup_cmd(self): """Run the configured cleanup commands for this node.""" + if self.cleanup_called: + return + self.cleanup_called = True + return await self._async_cleanup_cmd() def has_ready_cmd(self) -> bool: @@ -433,14 +439,14 @@ class NodeMixin: outopt = outopt if outopt is not None else "" if outopt == "all" or self.name in outopt.split(","): outname = stdout.name if hasattr(stdout, "name") else stdout - self.run_in_window(f"tail -F {outname}", title=f"O:{self.name}") + self.run_in_window(f"tail -n+1 -F {outname}", title=f"O:{self.name}") if stderr: erropt = self.unet.cfgopt.getoption("--stderr") erropt = erropt if erropt is not None else "" if erropt == "all" or self.name in erropt.split(","): errname = stderr.name if hasattr(stderr, "name") else stderr - self.run_in_window(f"tail -F {errname}", title=f"E:{self.name}") + self.run_in_window(f"tail -n+1 -F {errname}", title=f"E:{self.name}") def pytest_hook_open_shell(self): if not self.unet: @@ -615,9 +621,6 @@ class SSHRemote(NodeMixin, Commander): self.logger.info("%s: created", self) - def has_ready_cmd(self) -> bool: - return bool(self.config.get("ready-cmd", "").strip()) - def _get_pre_cmd(self, use_str, use_pty, ns_only=False, **kwargs): pre_cmd = [] if self.unet: @@ -1522,11 +1525,14 @@ class L3ContainerNode(L3NodeMixin, LinuxNamespace): async def async_cleanup_cmd(self): """Run the configured cleanup commands for this node.""" + if self.cleanup_called: + return self.cleanup_called = True if "cleanup-cmd" not in self.config: return + # The opposite of other types, the container needs cmd_p running if not self.cmd_p: self.logger.warning("async_cleanup_cmd: container no longer running") return @@ -1639,7 +1645,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): rundir=os.path.join(self.rundir, self.name), configdir=self.unet.config_dirname, ) - self.ssh_keyfile = self.qemu_config.get("sshkey") + self.ssh_keyfile = self.config.get("ssh-identity-file") + if not self.ssh_keyfile: + self.ssh_keyfile = self.qemu_config.get("sshkey") + + self.ssh_user = self.config.get("ssh-user") + if not self.ssh_user: + self.ssh_user = self.qemu_config.get("sshuser", "root") + + self.disk_created = False @property def is_vm(self): @@ -1680,10 +1694,9 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): self.__base_cmd_pty = list(self.__base_cmd) self.__base_cmd_pty.append("-t") - user = self.qemu_config.get("sshuser", "root") - self.__base_cmd.append(f"{user}@{mgmt_ip}") + self.__base_cmd.append(f"{self.ssh_user}@{mgmt_ip}") self.__base_cmd.append("--") - self.__base_cmd_pty.append(f"{user}@{mgmt_ip}") + self.__base_cmd_pty.append(f"{self.ssh_user}@{mgmt_ip}") # self.__base_cmd_pty.append("--") return True @@ -1810,15 +1823,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): if args: self.extra_mounts += args - async def run_cmd(self): + async def _run_cmd(self, cmd_node): """Run the configured commands for this node inside VM.""" self.logger.debug( "[rundir %s exists %s]", self.rundir, os.path.exists(self.rundir) ) - cmd = self.config.get("cmd", "").strip() + cmd = self.config.get(cmd_node, "").strip() if not cmd: - self.logger.debug("%s: no `cmd` to run", self) + self.logger.debug("%s: no `%s` to run", self, cmd_node) return None shell_cmd = self.config.get("shell", "/bin/bash") @@ -1837,15 +1850,17 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): cmd += "\n" # Write a copy to the rundir - cmdpath = os.path.join(self.rundir, "cmd.shebang") + cmdpath = os.path.join(self.rundir, f"{cmd_node}.shebang") with open(cmdpath, mode="w+", encoding="utf-8") as cmdfile: cmdfile.write(cmd) commander.cmd_raises(f"chmod 755 {cmdpath}") # Now write a copy inside the VM - self.conrepl.cmd_status("cat > /tmp/cmd.shebang << EOF\n" + cmd + "\nEOF") - self.conrepl.cmd_status("chmod 755 /tmp/cmd.shebang") - cmds = "/tmp/cmd.shebang" + self.conrepl.cmd_status( + f"cat > /tmp/{cmd_node}.shebang << EOF\n" + cmd + "\nEOF" + ) + self.conrepl.cmd_status(f"chmod 755 /tmp/{cmd_node}.shebang") + cmds = f"/tmp/{cmd_node}.shebang" else: cmd = cmd.replace("%CONFIGDIR%", str(self.unet.config_dirname)) cmd = cmd.replace("%RUNDIR%", str(self.rundir)) @@ -1883,16 +1898,22 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): # When run_command supports async_ arg we can use the above... self.cmd_p = now_proc(self.cmdrepl.run_command(cmds, timeout=120)) - - # stdout and err both combined into logfile from the spawned repl - stdout = os.path.join(self.rundir, "_cmdcon-log.txt") - self.pytest_hook_run_cmd(stdout, None) else: # If we only have a console we can't run in parallel, so run to completion self.cmd_p = now_proc(self.conrepl.run_command(cmds, timeout=120)) return self.cmd_p + async def run_cmd(self): + if self.disk_created: + await self._run_cmd("initial-cmd") + await self._run_cmd("cmd") + + # stdout and err both combined into logfile from the spawned repl + if self.cmdrepl: + stdout = os.path.join(self.rundir, "_cmdcon-log.txt") + self.pytest_hook_run_cmd(stdout, None) + # InterfaceMixin override # We need a name unique in the shared namespace. def get_ns_ifname(self, ifname): @@ -2044,24 +2065,44 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): async def gather_coverage_data(self): con = self.conrepl + gcda_root = "/sys/kernel/debug/gcov" + dest = "/tmp/gcov-data.tgz" + + if gcda_root != "/sys/kernel/debug/gcov": + con.cmd_raises( + rf"cd {gcda_root} && find * -name '*.gc??' " + "| tar -cf - -T - | gzip -c > {dest}" + ) + else: + # Some tars dont try and read 0 length files so we need to copy them. + tmpdir = con.cmd_raises("mktemp -d").strip() + con.cmd_raises( + rf"cd {gcda_root} && find -type d -exec mkdir -p {tmpdir}/{{}} \;" + ) + con.cmd_raises( + rf"cd {gcda_root} && " + rf"find -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;" + ) + con.cmd_raises( + rf"cd {gcda_root} && " + rf"find -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;" + ) + con.cmd_raises( + rf"cd {tmpdir} && " + rf"find * -name '*.gc??' | tar -cf - -T - | gzip -c > {dest}" + ) + con.cmd_raises(rf"rm -rf {tmpdir}") - gcda = "/sys/kernel/debug/gcov" - tmpdir = con.cmd_raises("mktemp -d").strip() - dest = "/gcov-data.tgz" - con.cmd_raises(rf"find {gcda} -type d -exec mkdir -p {tmpdir}/{{}} \;") - con.cmd_raises( - rf"find {gcda} -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;" - ) - con.cmd_raises( - rf"find {gcda} -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;" - ) - con.cmd_raises(rf"tar cf - -C {tmpdir} sys | gzip -c > {dest}") - con.cmd_raises(rf"rm -rf {tmpdir}") self.logger.info("Saved coverage data in VM at %s", dest) + ldest = os.path.join(self.rundir, "gcov-data.tgz") if self.use_ssh: - ldest = os.path.join(self.rundir, "gcov-data.tgz") self.cmd_raises(["/bin/cat", dest], stdout=open(ldest, "wb")) self.logger.info("Saved coverage data on host at %s", ldest) + else: + output = con.cmd_raises(rf"base64 {dest}") + with open(ldest, "wb") as f: + f.write(base64.b64decode(output)) + self.logger.info("Saved coverage data on host at %s", ldest) async def _opencons( self, @@ -2119,6 +2160,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): expects=expects, sends=sends, timeout=timeout, + init_newline=True, trace=True, ) ) @@ -2247,30 +2289,45 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): if not nnics: args += ["-nic", "none"] - dtpl = qc.get("disk-template") + dtplpath = dtpl = qc.get("disk-template") diskpath = disk = qc.get("disk") - if dtpl and not disk: - disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}" - diskpath = os.path.join(self.rundir, disk) + if diskpath: + if diskpath[0] != "/": + diskpath = os.path.join(self.unet.config_dirname, diskpath) + + if dtpl and (not disk or not os.path.exists(diskpath)): + if not disk: + disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}" + diskpath = os.path.join(self.rundir, disk) if self.path_exists(diskpath): logging.debug("Disk '%s' file exists, using.", diskpath) else: - dtplpath = os.path.abspath( - os.path.join( - os.path.dirname(self.unet.config["config_pathname"]), dtpl - ) - ) + if dtplpath[0] != "/": + dtplpath = os.path.join(self.unet.config_dirname, dtpl) logging.info("Create disk '%s' from template '%s'", diskpath, dtplpath) self.cmd_raises( f"qemu-img create -f qcow2 -F qcow2 -b {dtplpath} {diskpath}" ) + self.disk_created = True + disk_driver = qc.get("disk-driver", "virtio") if diskpath: - args.extend( - ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"] - ) - args.extend(["-device", "ahci,id=ahci"]) - args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"]) + if disk_driver == "virtio": + args.extend(["-drive", f"file={diskpath},if=virtio,format=qcow2"]) + else: + args.extend( + ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"] + ) + args.extend(["-device", "ahci,id=ahci"]) + args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"]) + + cidiskpath = qc.get("cloud-init-disk") + if cidiskpath: + if cidiskpath[0] != "/": + cidiskpath = os.path.join(self.unet.config_dirname, cidiskpath) + args.extend(["-drive", f"file={cidiskpath},if=virtio,format=qcow2"]) + + # args.extend(["-display", "vnc=0.0.0.0:40"]) use_stdio = cc.get("stdio", True) has_cmd = self.config.get("cmd") @@ -2360,6 +2417,10 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): if use_cmdcon: confiles.append("_cmdcon") + password = cc.get("password", "") + if self.disk_created: + password = cc.get("initial-password", password) + # # Connect to the console socket, retrying # @@ -2369,7 +2430,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): prompt=prompt, is_bourne=not bool(prompt), user=cc.get("user", "root"), - password=cc.get("password", ""), + password=password, expects=cc.get("expects"), sends=cc.get("sends"), timeout=int(cc.get("timeout", 60)), @@ -2425,6 +2486,8 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace): async def async_cleanup_cmd(self): """Run the configured cleanup commands for this node.""" + if self.cleanup_called: + return self.cleanup_called = True if "cleanup-cmd" not in self.config: @@ -2849,16 +2912,82 @@ ff02::2\tip6-allrouters mtu = kwargs.get("mtu", config.get("mtu")) return super().add_switch(name, cls=cls, config=config, mtu=mtu, **kwargs) + def coverage_setup(self): + bdir = self.cfgopt.getoption("--cov-build-dir") + if not bdir: + # Try and find the build dir using common prefix of gcno files + common = None + cwd = os.getcwd() + for f in glob.iglob(rf"{cwd}/**/*.gcno", recursive=True): + if not common: + common = os.path.dirname(f) + else: + common = os.path.commonprefix([common, f]) + if not common: + break + assert ( + bdir + ), "Can't locate build directory for coverage data, use --cov-build-dir" + + bdir = Path(bdir).resolve() + rundir = Path(self.rundir).resolve() + gcdadir = rundir / "gcda" + os.environ["GCOV_BUILD_DIR"] = str(bdir) + os.environ["GCOV_PREFIX_STRIP"] = str(len(bdir.parts) - 1) + os.environ["GCOV_PREFIX"] = str(gcdadir) + + # commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+rw {{}} +") + group_id = bdir.stat().st_gid + commander.cmd_raises(f"mkdir -p {gcdadir}") + commander.cmd_raises(f"chown -R root:{group_id} {gcdadir}") + commander.cmd_raises(f"chmod 2775 {gcdadir}") + + async def coverage_finish(self): + rundir = Path(self.rundir).resolve() + bdir = Path(os.environ["GCOV_BUILD_DIR"]) + gcdadir = Path(os.environ["GCOV_PREFIX"]) + + # Create GCNO symlinks + self.logger.info("Creating .gcno symlinks from '%s' to '%s'", gcdadir, bdir) + commander.cmd_raises( + f'cd "{gcdadir}"; bdir="{bdir}"' + + """ +for f in $(find . -name '*.gcda'); do + f=${f#./}; + f=${f%.gcda}.gcno; + ln -fs $bdir/$f $f; + touch -h -r $bdir/$f $f; + echo $f; +done""" + ) + + # Get the results into a summary file + data_file = rundir / "coverage.info" + self.logger.info("Gathering coverage data into: %s", data_file) + commander.cmd_raises( + f"lcov --directory {gcdadir} --capture --output-file {data_file}" + ) + + # Get coverage info filtered to a specific set of files + report_file = rundir / "coverage.info" + self.logger.debug("Generating coverage summary: %s", report_file) + output = commander.cmd_raises(f"lcov --summary {data_file}") + self.logger.info("\nCOVERAGE-SUMMARY-START\n%s\nCOVERAGE-SUMMARY-END", output) + # terminalreporter.write( + # f"\nCOVERAGE-SUMMARY-START\n{output}\nCOVERAGE-SUMMARY-END\n" + # ) + async def run(self): tasks = [] hosts = self.hosts.values() launch_nodes = [x for x in hosts if hasattr(x, "launch")] launch_nodes = [x for x in launch_nodes if x.config.get("qemu")] - run_nodes = [x for x in hosts if hasattr(x, "has_run_cmd") and x.has_run_cmd()] - ready_nodes = [ - x for x in hosts if hasattr(x, "has_ready_cmd") and x.has_ready_cmd() - ] + run_nodes = [x for x in hosts if x.has_run_cmd()] + ready_nodes = [x for x in hosts if x.has_ready_cmd()] + + if self.cfgopt.getoption("--coverage"): + self.coverage_setup() pcapopt = self.cfgopt.getoption("--pcap") pcapopt = pcapopt if pcapopt else "" @@ -2940,15 +3069,6 @@ ff02::2\tip6-allrouters self.logger.debug("%s: deleting.", self) - if self.cfgopt.getoption("--coverage"): - nodes = ( - x for x in self.hosts.values() if hasattr(x, "gather_coverage_data") - ) - try: - await asyncio.gather(*(x.gather_coverage_data() for x in nodes)) - except Exception as error: - logging.warning("Error gathering coverage data: %s", error) - pause = bool(self.cfgopt.getoption("--pause-at-end")) pause = pause or bool(self.cfgopt.getoption("--pause")) if pause: @@ -2959,6 +3079,25 @@ ff02::2\tip6-allrouters except Exception as error: self.logger.error("\n...continuing after error: %s", error) + # Run cleanup-cmd's. + nodes = (x for x in self.hosts.values() if x.has_cleanup_cmd()) + try: + await asyncio.gather(*(x.async_cleanup_cmd() for x in nodes)) + except Exception as error: + logging.warning("Error running cleanup cmds: %s", error) + + # Gather any coverage data + if self.cfgopt.getoption("--coverage"): + nodes = ( + x for x in self.hosts.values() if hasattr(x, "gather_coverage_data") + ) + try: + await asyncio.gather(*(x.gather_coverage_data() for x in nodes)) + except Exception as error: + logging.warning("Error gathering coverage data: %s", error) + + await self.coverage_finish() + # XXX should we cancel launch and run tasks? try: diff --git a/tests/topotests/munet/parser.py b/tests/topotests/munet/parser.py index 4fc0c75a60..a8b73a25e7 100644 --- a/tests/topotests/munet/parser.py +++ b/tests/topotests/munet/parser.py @@ -230,7 +230,7 @@ def load_kinds(args, search=None): if args: os.chdir(args.rundir) - args_config = args.kinds_config if args else None + args_config = args.kinds_config if args and hasattr(args, "kinds_config") else None try: if search is None: search = [cwd] @@ -305,7 +305,7 @@ async def async_build_topology( # create search directories from common root if given cpath = Path(config["config_pathname"]).absolute() - project_root = args.project_root if args else None + project_root = args.project_root if args and hasattr(args, "project_root") else None if not search_root: search_root = find_project_root(cpath, project_root) if not search_root: @@ -341,7 +341,11 @@ async def async_build_topology( pytestconfig=pytestconfig, isolated=isolated, pid=top_level_pidns, - unshare_inline=args.unshare_inline if args else unshare_inline, + unshare_inline=( + args.unshare_inline + if args and hasattr(args, "unshare_inline") + else unshare_inline + ), logger=logger, ) diff --git a/tests/topotests/munet/testing/fixtures.py b/tests/topotests/munet/testing/fixtures.py index 3c6d9460ff..4150d28b59 100644 --- a/tests/topotests/munet/testing/fixtures.py +++ b/tests/topotests/munet/testing/fixtures.py @@ -150,7 +150,7 @@ def session_autouse(): @pytest.fixture(autouse=True, scope="module") def module_autouse(request): - logpath = get_test_logdir(request.node.name, True) + logpath = get_test_logdir(request.node.nodeid, True) logpath = os.path.join("/tmp/unet-test", logpath, "pytest-exec.log") with log_handler("module", logpath): sdir = os.path.dirname(os.path.realpath(request.fspath)) @@ -161,7 +161,7 @@ def module_autouse(request): raise Exception("Base Munet was not cleaned up/deleted") -@pytest.fixture(scope="module") +@pytest.fixture(scope="session") def event_loop(): """Create an instance of the default event loop for the session.""" loop = get_event_loop() @@ -213,18 +213,14 @@ async def _unet_impl( param, exc_info=True, ) - pytest.skip( - f"unet fixture: unet build failed: {error}", allow_module_level=True - ) - raise + pytest.fail(f"unet fixture: unet build failed: {error}") try: tasks = await _unet.run() except Exception as error: logging.debug("unet fixture: unet run failed: %s", error, exc_info=True) await _unet.async_delete() - pytest.skip(f"unet fixture: unet run failed: {error}", allow_module_level=True) - raise + pytest.fail(f"unet fixture: unet run failed: {error}") logging.debug("unet fixture: containers running") diff --git a/tests/topotests/munet/testing/hooks.py b/tests/topotests/munet/testing/hooks.py index 985eef9c49..f6f2115367 100644 --- a/tests/topotests/munet/testing/hooks.py +++ b/tests/topotests/munet/testing/hooks.py @@ -18,6 +18,7 @@ import traceback import pytest +from ..args import add_testing_args from ..base import BaseMunet # pylint: disable=import-error from ..cli import cli # pylint: disable=import-error from .util import pause_test @@ -29,85 +30,7 @@ from .util import pause_test def pytest_addoption(parser): - parser.addoption( - "--cli-on-error", - action="store_true", - help="CLI on test failure", - ) - - parser.addoption( - "--coverage", - action="store_true", - help="Enable coverage gathering if supported", - ) - - parser.addoption( - "--gdb", - default="", - metavar="HOST[,HOST...]", - help="Comma-separated list of nodes to launch gdb on, or 'all'", - ) - parser.addoption( - "--gdb-breakpoints", - default="", - metavar="BREAKPOINT[,BREAKPOINT...]", - help="Comma-separated list of breakpoints", - ) - parser.addoption( - "--gdb-use-emacs", - action="store_true", - help="Use emacsclient to run gdb instead of a shell", - ) - - parser.addoption( - "--pcap", - default="", - metavar="NET[,NET...]", - help="Comma-separated list of networks to capture packets on, or 'all'", - ) - - parser.addoption( - "--pause", - action="store_true", - help="Pause after each test", - ) - parser.addoption( - "--pause-at-end", - action="store_true", - help="Pause before taking munet down", - ) - parser.addoption( - "--pause-on-error", - action="store_true", - help="Pause after (disables default when --shell or -vtysh given)", - ) - parser.addoption( - "--no-pause-on-error", - dest="pause_on_error", - action="store_false", - help="Do not pause after (disables default when --shell or -vtysh given)", - ) - - parser.addoption( - "--shell", - default="", - metavar="NODE[,NODE...]", - help="Comma-separated list of nodes to spawn shell on, or 'all'", - ) - - parser.addoption( - "--stdout", - default="", - metavar="NODE[,NODE...]", - help="Comma-separated list of nodes to open tail-f stdout window on, or 'all'", - ) - - parser.addoption( - "--stderr", - default="", - metavar="NODE[,NODE...]", - help="Comma-separated list of nodes to open tail-f stderr window on, or 'all'", - ) + add_testing_args(parser.addoption) def pytest_configure(config): @@ -146,6 +69,18 @@ def pytest_configure(config): elif b and not is_xdist and not have_windows: pytest.exit(f"{winopt} use requires byobu/TMUX/SCREEN/XTerm") + cli_pause = ( + config.getoption("--cli-on-error") + or config.getoption("--pause") + or config.getoption("--pause-at-end") + or config.getoption("--pause-on-error") + ) + if config.getoption("--capture") == "fd" and cli_pause: + pytest.exit( + "CLI is not compatible with `--capture=fd`, " + "please run again with `-s` or other `--capture` value" + ) + def pytest_runtest_makereport(item, call): """Pause or invoke CLI as directed by config.""" diff --git a/tests/topotests/munet/watchlog.py b/tests/topotests/munet/watchlog.py index 27bc3251a6..f764f9dac3 100644 --- a/tests/topotests/munet/watchlog.py +++ b/tests/topotests/munet/watchlog.py @@ -15,6 +15,7 @@ from pathlib import Path class MatchFoundError(Exception): """An error raised when a match is not found.""" + def __init__(self, watchlog, match): self.watchlog = watchlog self.match = match diff --git a/tests/topotests/nb_config/test_nb_config.py b/tests/topotests/nb_config/test_nb_config.py index f699a4e20e..8def19ffd5 100644 --- a/tests/topotests/nb_config/test_nb_config.py +++ b/tests/topotests/nb_config/test_nb_config.py @@ -24,9 +24,7 @@ CWD = os.path.dirname(os.path.realpath(__file__)) def tgen(request): "Setup/Teardown the environment and provide tgen argument to tests" - topodef = { - "s1": ("r1",) - } + topodef = {"s1": ("r1",)} tgen = Topogen(topodef, request.module.__name__) tgen.start_topology() @@ -46,12 +44,14 @@ def test_access_list_config_ordering(tgen): r1 = tgen.gears["r1"] - output = r1.vtysh_multicmd([ - "conf t", - "access-list test seq 1 permit host 10.0.0.1"]) + output = r1.vtysh_multicmd( + ["conf t", "access-list test seq 1 permit host 10.0.0.1"] + ) output = r1.vtysh_cmd("show ip access-list test json") got = json.loads(output) - expected = json.loads('{"ZEBRA":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}') + expected = json.loads( + '{"ZEBRA":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}' + ) result = json_cmp(got, expected) assert result is None @@ -59,11 +59,11 @@ def test_access_list_config_ordering(tgen): # If the northbound mis-orders the create/delete then this test fails. # https://github.com/FRRouting/frr/pull/15423/commits/38b85e0c2bc555b8827dbd2cb6515b6febf548b4 # - output = r1.vtysh_multicmd([ - "conf t", - "access-list test seq 1 permit 10.0.0.0/8"]) + output = r1.vtysh_multicmd(["conf t", "access-list test seq 1 permit 10.0.0.0/8"]) output = r1.vtysh_cmd("show ip access-list test json") got = json.loads(output) - expected = json.loads('{"ZEBRA":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}') + expected = json.loads( + '{"ZEBRA":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}' + ) result = json_cmp(got, expected) assert result is None diff --git a/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf index 2a6c9abd2e..24cd354118 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf @@ -4,31 +4,11 @@ interface r5-eth0 ipv6 ospf6 dead-interval 10 ! interface r5-eth1 - ipv6 ospf6 area 0 - ipv6 ospf6 hello-interval 2 - ipv6 ospf6 dead-interval 10 -! -interface r5-eth2 - ipv6 ospf6 area 0 - ipv6 ospf6 hello-interval 2 - ipv6 ospf6 dead-interval 10 -! -interface r5-eth3 ipv6 ospf6 area 1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! -interface r5-eth4 - ipv6 ospf6 area 1 - ipv6 ospf6 hello-interval 2 - ipv6 ospf6 dead-interval 10 -! -interface r5-eth5 - ipv6 ospf6 area 0 - ipv6 ospf6 hello-interval 2 - ipv6 ospf6 dead-interval 10 -! -interface r5-eth6 +interface r5-eth2 ipv6 ospf6 area 0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 diff --git a/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf index a1f48b51a5..4efaa318a9 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf @@ -1,8 +1,23 @@ interface r6-eth0 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +interface r6-eth1 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +interface r6-eth2 ipv6 ospf6 area 1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! +interface r6-eth3 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! router ospf6 ospf6 router-id 10.254.254.6 redistribute connected diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf index 0e49b0df6c..9b7756e838 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf @@ -1,11 +1,22 @@ -interface lo +interface r7-eth0 ipv6 ospf6 area 1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 ! -interface r7-eth0 +interface r7-eth1 ipv6 ospf6 area 1 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! +interface r7-eth2 + ipv6 ospf6 area 1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +interface r7-eth3 + shutdown +! router ospf6 ospf6 router-id 10.254.254.7 + redistribute connected ! diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf index a410be8f73..1608cad0b0 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf @@ -3,3 +3,6 @@ ipv6 forwarding interface lo ipv6 address 2001:db8:7::1/64 ! +interface r7-eth2 + ipv6 address 2001:db8:8007::1/64 +! diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf index fb5483ce99..33c64979ca 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf @@ -3,6 +3,19 @@ interface r8-eth0 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! +interface r8-eth1 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +interface r8-eth2 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +interface r8-eth3 + shutdown +! router ospf6 ospf6 router-id 10.254.254.8 redistribute connected diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf index 8e343d8f45..e756cd4b95 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf @@ -3,3 +3,6 @@ ipv6 forwarding interface lo ipv6 address 2001:db8:8::1/64 ! +interface r8-eth2 + ipv6 address 2001:db8:8008::1/64 +! diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf deleted file mode 100644 index 57fa8e32ee..0000000000 --- a/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf +++ /dev/null @@ -1,11 +0,0 @@ -interface lo - ipv6 ospf6 area 0 -! -interface r9-eth0 - ipv6 ospf6 area 0 - ipv6 ospf6 hello-interval 2 - ipv6 ospf6 dead-interval 10 -! -router ospf6 - ospf6 router-id 10.254.254.9 -! diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf deleted file mode 100644 index e267496a98..0000000000 --- a/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf +++ /dev/null @@ -1,5 +0,0 @@ -ipv6 forwarding -! -interface lo - ipv6 address 2001:db8:9::1/64 -! diff --git a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py index 2eaccb8348..adf289e2de 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py +++ b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py @@ -3,7 +3,7 @@ # test_ospf6_ecmp_inter_area.py # -# Copyright (c) 2021, 2022 by Martin Buck +# Copyright (c) 2021, 2022, 2024 by Martin Buck # Copyright (c) 2016 by # Network Device Education Foundation, Inc. ("NetDEF") # @@ -11,35 +11,42 @@ r""" test_ospf6_ecmp_inter_area.py: Test OSPFv3 ECMP inter-area nexthop update -Check proper removal of ECMP nexthops after a path used by one nexthop -disappears. We remove a path by bringing down a link required by that -path which is not adjacent to the router being checked. This is important -because when bringing down adjacent links, the kernel might remove the -nexthops itself without ospf6d having to do anything. +Check proper addition and removal of ECMP nexthops in 2 cases: Parallel +paths to one ABR and parallel ABRs. We test nexthop removal triggered by +path removal by bringing down a link required by that path which is not +adjacent to the router being checked. This is important because when +bringing down adjacent links, the kernel might remove the nexthops itself +without ospf6d having to do anything. -Useful as a regression test for #9720. +Useful as a regression test for #9720 and #15777. Topology: - . - Area 0 . Area 1 - . - -- R2 -- . ---- R6 - / \ ./ -R1 -- R3 -- R5 ---- R7 Area 1 - \ / \\ .............. - -- R4 -- \--- R8 Area 0 - \ - -- R9 - -We check routes on R1, primarily those towards R6/7/8/9. Those to R6/7 are -inter-area routes with R5 being ABR, those to R8/9 are intra-area routes -and are used for reference. R6/R8 announce external routes, R7/R9 announce -internal routes. + . + Area 0 . Area 1 + . + -- R2 ------ R5 ----- + / .\ \ + / . | \ +R1 --- R3 ------ R6 ------ R7 + \ / |. | + \ / |. | + -- R4 ---- |. | + / ./ + R8 -- + . + +We check routes on R1, primarily those towards R7/8. Those to R7 are +inter-area routes with R5/6 being ABRs, those to R8 are intra-area routes +and are used for reference. R7/R8 announce one internal and one external +route each. With all links up, we expect 3 ECMP paths and 3 nexthops on R1 towards each -of R6/7/8/9. Then we bring down the R2-R5 link, causing only 2 remaining -paths and 2 nexthops on R1. The test is successful if the number of nexthops -for the routes on R1 is as expected. +of R7/8. Then we bring down the R3-R6 link, causing only 2 remaining +paths and 2 nexthops on R1. Then we bring down the R2-R5 link, causing only +1 remaining path and 1 nexthop on R1. + +The test is successful if the number of nexthops for the routes on R1 is as +expected. """ import os @@ -65,20 +72,24 @@ pytestmark = [pytest.mark.ospf6d] def build_topo(tgen): "Build function" - # Create 9 routers - for routern in range(1, 10): + # Create 8 routers + for routern in range(1, 9): tgen.add_router("r{}".format(routern)) - tgen.gears["r1"].add_link(tgen.gears["r2"]) tgen.gears["r1"].add_link(tgen.gears["r3"]) tgen.gears["r1"].add_link(tgen.gears["r4"]) tgen.gears["r2"].add_link(tgen.gears["r5"]) - tgen.gears["r3"].add_link(tgen.gears["r5"]) - tgen.gears["r4"].add_link(tgen.gears["r5"]) - tgen.gears["r5"].add_link(tgen.gears["r6"]) + tgen.gears["r3"].add_link(tgen.gears["r6"]) + tgen.gears["r4"].add_link(tgen.gears["r6"]) tgen.gears["r5"].add_link(tgen.gears["r7"]) tgen.gears["r5"].add_link(tgen.gears["r8"]) - tgen.gears["r5"].add_link(tgen.gears["r9"]) + tgen.gears["r6"].add_link(tgen.gears["r7"]) + tgen.gears["r6"].add_link(tgen.gears["r8"]) + # Additional "loopback" interfaces. Not used for communication, just to + # hold an address we use to inject intra-/inter-area routes (the one on + # the real "lo" loopback is used for external routes). + tgen.gears["r7"].add_link(tgen.gears["r7"]) + tgen.gears["r8"].add_link(tgen.gears["r8"]) def setup_module(mod): @@ -131,20 +142,19 @@ def test_wait_protocol_convergence(): expect_neighbor_full("r2", "10.254.254.1") expect_neighbor_full("r2", "10.254.254.5") expect_neighbor_full("r3", "10.254.254.1") - expect_neighbor_full("r3", "10.254.254.5") + expect_neighbor_full("r3", "10.254.254.6") expect_neighbor_full("r4", "10.254.254.1") - expect_neighbor_full("r4", "10.254.254.5") + expect_neighbor_full("r4", "10.254.254.6") expect_neighbor_full("r5", "10.254.254.2") - expect_neighbor_full("r5", "10.254.254.3") - expect_neighbor_full("r5", "10.254.254.4") - expect_neighbor_full("r5", "10.254.254.6") expect_neighbor_full("r5", "10.254.254.7") expect_neighbor_full("r5", "10.254.254.8") - expect_neighbor_full("r5", "10.254.254.9") - expect_neighbor_full("r6", "10.254.254.5") + expect_neighbor_full("r6", "10.254.254.3") + expect_neighbor_full("r6", "10.254.254.7") + expect_neighbor_full("r6", "10.254.254.8") expect_neighbor_full("r7", "10.254.254.5") + expect_neighbor_full("r7", "10.254.254.6") expect_neighbor_full("r8", "10.254.254.5") - expect_neighbor_full("r9", "10.254.254.5") + expect_neighbor_full("r8", "10.254.254.6") def test_ecmp_inter_area(): @@ -154,9 +164,16 @@ def test_ecmp_inter_area(): pytest.skip(tgen.errors) def num_nexthops(router): - routes = tgen.gears[router].vtysh_cmd("show ipv6 ospf6 route json", isjson=True) - route_prefixes_infos = sorted(routes.get("routes", {}).items()) - return [len(ri.get("nextHops", [])) for rp, ri in route_prefixes_infos] + # Careful: "show ipv6 ospf6 route json" doesn't work here. It will + # only list one route type per prefix and that might not necessarily + # be the best/selected route. "show ipv6 route ospf6 json" only + # lists selected routes, so that's more useful in this case. + routes = tgen.gears[router].vtysh_cmd("show ipv6 route ospf6 json", isjson=True) + route_prefixes_infos = sorted(routes.items()) + # Note: ri may contain one entry per routing protocol, but since + # we've explicitly requested only ospf6 above, we can count on ri[0] + # being the entry we're looking for. + return [ri[0]["internalNextHopActiveNum"] for rp, ri in route_prefixes_infos] def expect_num_nexthops(router, expected_num_nexthops, count): "Wait until number of nexthops for routes matches expectation" @@ -174,14 +191,22 @@ def test_ecmp_inter_area(): ), "'{}' wrong number of route nexthops".format(router) # Check nexthops pre link-down - expect_num_nexthops("r1", [1, 1, 1, 3, 3, 3, 3, 3, 3, 3], 4) + # tgen.mininet_cli() + expect_num_nexthops("r1", [1, 1, 1, 1, 2, 3, 3, 3, 3], 4) + + logger.info("triggering R3-R6 link down") + tgen.gears["r3"].run("ip link set r3-eth1 down") + + # tgen.mininet_cli() + # Check nexthops post link-down + expect_num_nexthops("r1", [1, 1, 1, 1, 1, 2, 2, 2, 2], 8) - logger.info("triggering R2-R4 link down") + logger.info("triggering R2-R5 link down") tgen.gears["r2"].run("ip link set r2-eth1 down") # tgen.mininet_cli() # Check nexthops post link-down - expect_num_nexthops("r1", [1, 1, 1, 2, 2, 2, 2, 2, 2, 2], 8) + expect_num_nexthops("r1", [1, 1, 1, 1, 1, 1, 1, 1, 1], 8) def teardown_module(_mod): diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py index bd7db644d1..62b8212203 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py @@ -183,7 +183,6 @@ def teardown_module(mod): logger.info("=" * 40) - def red_static(dut, config=True): """Local def for Redstribute static routes inside ospf.""" global topo @@ -367,7 +366,13 @@ def test_ospf_flood_red_tc1_p0(request): }, } result = verify_ospf_database( - tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False + tgen, + topo, + dut, + input_dict_db, + lsatype="router", + rid="100.1.1.0", + expected=False, ) assert result is not True, ( "Testcase {} : Failed \n " @@ -573,7 +578,9 @@ def test_ospf_flood_red_tc2_p0(request): result = verify_ospf_database( tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid ) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) step("Wait for 120 secs and verify that LSA's are not refreshed. ") # get LSA age @@ -636,7 +643,13 @@ def test_ospf_flood_red_tc2_p0(request): }, } result = verify_ospf_database( - tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False + tgen, + topo, + dut, + input_dict_db, + lsatype="router", + rid="100.1.1.0", + expected=False, ) assert result is not True, ( "Testcase {} : Failed \n " @@ -815,7 +828,9 @@ def test_ospf_flood_red_tc3_p0(request): result = verify_ospf_database( tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid ) - assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) step("Wait for 120 secs and verify that LSA's are not refreshed. ") # get LSA age @@ -1022,7 +1037,13 @@ def test_ospf_flood_red_tc3_p0(request): }, } result = verify_ospf_database( - tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False + tgen, + topo, + dut, + input_dict_db, + lsatype="router", + rid="100.1.1.0", + expected=False, ) assert result is not True, ( diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py index d669e21d4d..4a40b3e9ec 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py @@ -165,7 +165,7 @@ def test_ospf_learning_tc15_p0(request): step("Verify that Type 3 summary LSA is originated for the same Area 0") ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv4"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) dut = "r0" input_dict = { diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py index 45c1325917..d169245f4e 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py @@ -177,7 +177,7 @@ def test_ospf_redistribution_tc5_p0(request): step("verify intra area route is calculated for r0-r3 interface ip in R1") ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0] input_dict = { "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} @@ -301,7 +301,7 @@ def test_ospf_redistribution_tc6_p0(request): step("verify intra area route is calculated for r0-r3 interface ip in R1") ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0] input_dict = { "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py index 757d6fb1d5..172f79d458 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py @@ -634,7 +634,7 @@ def test_ospf_show_p1(request): # show ip ospf route ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0] input_dict = { "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py index 46c0da309f..3468a6511b 100644 --- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py +++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py @@ -190,8 +190,10 @@ def test_ospf_gr_helper_tc3_p1(request): ospf_covergence is True ), "OSPF is not after reset config \n Error: {}".format(ospf_covergence) - step("Configure DR priority 100 on R0 and clear ospf neighbors " - "on all the routers.") + step( + "Configure DR priority 100 on R0 and clear ospf neighbors " + "on all the routers." + ) input_dict = { "r0": { diff --git a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py index 9dfe5e1b76..590b0d5e68 100644 --- a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py +++ b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py @@ -64,16 +64,9 @@ def setup_module(module): # This is a sample of configuration loading. r1 = tgen.gears["r1"] - r1.load_config( - TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf") - ) - r1.load_config( - TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"), - "-n 3" - ) - r1.load_config( - TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf") - ) + r1.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")) + r1.load_config(TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"), "-n 3") + r1.load_config(TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf")) tgen.start_router() @@ -103,13 +96,15 @@ def test_install_sharp_instance_routes(): expected = json.loads(open(json_file).read()) test_func = partial( - topotest.router_json_cmp, r1, "show ip route summ json", expected) + topotest.router_json_cmp, r1, "show ip route summ json", expected + ) logger.info("Ensuring that they exist in the rib/fib") _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) assertmsg = '"r1" sharp routes are not installed' assert result is None, assertmsg + def test_ospf_instance_redistribute(): tgen = get_topogen() @@ -124,7 +119,8 @@ def test_ospf_instance_redistribute(): expected = json.loads(open(json_file).read()) test_func = partial( - topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected + ) _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes' @@ -139,7 +135,8 @@ def test_ospf_instance_redistribute(): expected = json.loads(open(json_file).read()) test_func = partial( - topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected + ) _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes' @@ -161,15 +158,14 @@ def test_ospf_instance_default_information(): expected = json.loads(open(json_file).read()) test_func = partial( - topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected) + topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected + ) _, result = topotest.run_and_expect(test_func, None, count=10, wait=1) assertmsg = '"r1" ospf instance 3 does not properly redistribute the default route' assert result is None, assertmsg - if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) - diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py index 792304e19d..ee0a0f6c3b 100644 --- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py +++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py @@ -182,9 +182,7 @@ def test_ospf_convergence(): "show ip ospf vrf {} route".format(vrf), expected, ) - result, diff = topotest.run_and_expect( - test_func, "", count=80, wait=1 - ) + result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1) assertmsg = "OSPF did not converge on {}:\n{}".format(rname, diff) assert result, assertmsg @@ -207,9 +205,7 @@ def test_ospf_kernel_route(): test_func = partial( compare_show_ip_route_vrf, router.name, expected, vrf ) - result, diff = topotest.run_and_expect( - test_func, "", count=80, wait=1 - ) + result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1) assertmsg = 'OSPF IPv4 route mismatch in router "{}": {}'.format( router.name, diff ) diff --git a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py index 432ddf0986..d8cd1322bd 100644 --- a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py +++ b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py @@ -199,9 +199,7 @@ def test_rib_step3(): pytest.skip(tgen.errors) logger.info("Removing NSSA default on rt4") - tgen.net["rt3"].cmd( - 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"' - ) + tgen.net["rt3"].cmd('vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"') for rname in ["rt1", "rt2", "rt3", "rt4"]: router_compare_json_output( diff --git a/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py index 352180b7ce..1f0f87959a 100644 --- a/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py +++ b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py @@ -118,17 +118,21 @@ def teardown_module(mod): tgen.stop_topology() -def verify_p2mp_interface(tgen): +def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter): "Verify the P2MP Configuration and interface settings" - r1 = tgen.gears["r1"] + topo_router = tgen.gears[router] step("Test running configuration for P2MP configuration") rc = 0 - rc, _, _ = tgen.net["r1"].cmd_status( + rc, _, _ = tgen.net[router].cmd_status( "show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False ) - assertmsg = "'ip ospf network point-to-multipoint' applied, but not present in r1 configuration" + assertmsg = ( + "'ip ospf network point-to-multipoint' applied, but not present in " + + router + + "configuration" + ) assert rc, assertmsg step("Test OSPF interface for P2MP settings") @@ -145,11 +149,11 @@ def verify_p2mp_interface(tgen): "networkType": "POINTOMULTIPOINT", "cost": 10, "state": "Point-To-Point", - "nbrCount": 3, - "nbrAdjacentCount": 3, + "nbrCount": nbr_cnt, + "nbrAdjacentCount": nbr_adj_cnt, "prefixSuppression": False, "p2mpDelayReflood": False, - "p2mpNonBroadcast": False, + "nbrFilterPrefixList": nbr_filter, } }, "ipAddress": "10.1.0.1", @@ -161,16 +165,19 @@ def verify_p2mp_interface(tgen): "cost": 10, "state": "Point-To-Point", "opaqueCapable": True, - "nbrCount": 3, - "nbrAdjacentCount": 3, + "nbrCount": nbr_cnt, + "nbrAdjacentCount": nbr_adj_cnt, "prefixSuppression": False, "p2mpDelayReflood": False, - "p2mpNonBroadcast": False, + "nbrFilterPrefixList": nbr_filter, } } } test_func = partial( - topotest.router_json_cmp, r1, "show ip ospf interface r1-eth0 json", input_dict + topotest.router_json_cmp, + topo_router, + "show ip ospf interface r1-eth0 json", + input_dict, ) _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "P2MP Interface Mismatch on router r1" @@ -251,6 +258,23 @@ def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface): assert result is None, assertmsg +def verify_p2mp_neighbor_missing(tgen, router, neighbor): + topo_router = tgen.gears[router] + + step("Verify neighbor " + neighbor + " missing") + input_dict = {"default": {}} + test_func = partial( + topotest.router_json_cmp, + topo_router, + "show ip ospf neighbor " + neighbor + " json", + input_dict, + True, # Require exact match for missing neighbor + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "P2MP Neighbor " + neighbor + " not missing" + assert result is None, assertmsg + + def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface): topo_router = tgen.gears[router] @@ -288,7 +312,7 @@ def test_p2mp_broadcast_interface(): pytest.skip("Skipped because of router(s) failure") step("Verify router r1 interface r1-eth0 p2mp configuration") - verify_p2mp_interface(tgen) + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") step("Verify router r1 p2mp interface r1-eth0 neighbors") verify_p2mp_neighbor( @@ -313,7 +337,7 @@ def test_p2mp_broadcast_interface(): step("Verify router r1 interface r1-eth0 p2mp configuration application") r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint") - verify_p2mp_interface(tgen) + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") step("Verify restablishment of r1-eth0 p2mp neighbors") verify_p2mp_neighbor( @@ -332,6 +356,108 @@ def test_p2mp_broadcast_interface(): verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0") +def test_p2mp_broadcast_neighbor_filter(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("Skipped because of router(s) failure") + + step("Verify router r1 interface r1-eth0 p2mp configuration") + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") + + step("Verify router r1 p2mp interface r1-eth0 neighbors") + verify_p2mp_neighbor( + tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1" + ) + verify_p2mp_neighbor( + tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1" + ) + verify_p2mp_neighbor( + tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1" + ) + + step("Add OSPF interface neighbor-filter to r1") + r1 = tgen.gears["r1"] + r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter") + + step("Verify the R1 configuration of 'ip ospf neighbor-filter nbr-filter'") + neighbor_filter_cfg = ( + tgen.net["r1"] + .cmd( + 'vtysh -c "show running ospfd" | grep "^ ip ospf neighbor-filter nbr-filter"' + ) + .rstrip() + ) + assertmsg = ( + "'ip ospf neighbor-filter nbr-filter' applied, but not present in configuration" + ) + assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg + + step("Verify non-existent neighbor-filter is not applied to r1 interfaces") + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") + + step("Add nbr-filter prefix-list configuration to r1") + r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any") + + step( + "Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent" + ) + verify_p2mp_interface(tgen, "r1", 3, 3, "nbr-filter") + + step("Add nbr-filter prefix-list configuration to block r4") + r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32") + + step( + "Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent" + ) + verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter") + verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4") + + step("Verify route to r4 subnet is now through r2") + verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0") + + step("Add nbr-filter prefix-list configuration to block r2") + r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.2/32") + + step( + "Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent" + ) + verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter") + verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2") + + step("Verify route to r4 and r2 subnet are now through r3") + verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.3", "r1-eth0") + verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.3", "r1-eth0") + + step("Remove neighbor filter configuration and verify") + r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf neighbor-filter") + rc, _, _ = tgen.net["r1"].cmd_status( + "show running ospfd | grep -q 'ip ospf neighbor-filter'", warn=False + ) + assertmsg = "'ip ospf neighbor' not applied, but present in R1 configuration" + assert rc, assertmsg + + step("Verify interface neighbor-filter is removed and neighbors present") + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") + + step("Add neighbor filter configuration and verify neighbors are filtered") + r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter") + verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter") + verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2") + verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4") + + step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor") + r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20") + verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter") + verify_p2mp_neighbor( + tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1" + ) + + step("Delete nbr-filter prefix-list and verify neighbors are present") + r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter") + verify_p2mp_interface(tgen, "r1", 3, 3, "N/A") + + def test_memory_leak(): "Run the memory leak test and report results." tgen = get_topogen() diff --git a/tests/topotests/ospf_single_switch/test_ospf_single_switch.py b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py index 65c918283f..e53b5f5b1e 100644 --- a/tests/topotests/ospf_single_switch/test_ospf_single_switch.py +++ b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py @@ -97,14 +97,18 @@ def is_iproute2_json_supported(): Checks if the command 'ip -j route' is supported. """ try: - output = subprocess.run(['ip', '-j', 'route', 'get', '0.0.0.0'], stdout=subprocess.PIPE).stdout.decode() + output = subprocess.run( + ["ip", "-j", "route", "get", "0.0.0.0"], stdout=subprocess.PIPE + ).stdout.decode() json.loads(output) return True except json.decoder.JSONDecodeError: return False -@pytest.mark.skipif(not is_iproute2_json_supported(), reason="'ip -j route' not supported") +@pytest.mark.skipif( + not is_iproute2_json_supported(), reason="'ip -j route' not supported" +) def test_all_routes_advertised(): tgen = get_topogen() @@ -135,9 +139,13 @@ def test_all_routes_advertised(): ] } } - result = verify_ospf_rib(tgen, router_orig, input_dict, next_hop=network[1]) + result = verify_ospf_rib( + tgen, router_orig, input_dict, next_hop=network[1] + ) assert result is True, "Error: {}".format(result) - result = verify_rib(tgen, "ipv4", router_orig, input_dict, next_hop=network[1]) + result = verify_rib( + tgen, "ipv4", router_orig, input_dict, next_hop=network[1] + ) assert result is True, "Error: {}".format(result) check_route(router_orig, network[0], network[1]) @@ -181,7 +189,9 @@ def check_route(router_name, network, expected_nexthop): output = router.cmd(f"ip -j route get {address}") logger.info(output) routes = json.loads(output) - assert routes[0]["gateway"] == expected_nexthop, f"{router_name} (kernel): no route {address} via {expected_nexthop}" + assert ( + routes[0]["gateway"] == expected_nexthop + ), f"{router_name} (kernel): no route {address} via {expected_nexthop}" if __name__ == "__main__": diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py index 49dd34d650..626a9d3185 100644 --- a/tests/topotests/ospfapi/test_ospf_clientapi.py +++ b/tests/topotests/ospfapi/test_ospf_clientapi.py @@ -277,9 +277,7 @@ def _test_add_data(tgen, apibin): "linkStateId": "230.0.0.2", "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", - "opaqueValues": { - "opaqueData": "00000202" - } + "opaqueValues": {"opaqueData": "00000202"}, }, ], } @@ -330,8 +328,8 @@ def _test_add_data(tgen, apibin): "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", "opaqueValues": { - "opaqueData": "00010101", - } + "opaqueData": "00010101", + }, }, ], } @@ -381,8 +379,8 @@ def _test_add_data(tgen, apibin): "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", "opaqueValues": { - "opaqueData": "deadbeaf01234567", - } + "opaqueData": "deadbeaf01234567", + }, }, ] } @@ -434,8 +432,8 @@ def _test_add_data(tgen, apibin): "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000002", "opaqueValues": { - "opaqueData": "ebadf00d", - } + "opaqueData": "ebadf00d", + }, }, ] } @@ -1664,8 +1662,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin): "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", "opaqueValues": { - "opaqueData": "feedaceedeadbeef", - } + "opaqueData": "feedaceedeadbeef", + }, }, ], } @@ -1695,8 +1693,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin): "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", "opaqueValues": { - "opaqueData": "feedaceecafebeef", - } + "opaqueData": "feedaceecafebeef", + }, }, ], } diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py index 90548fb5ce..5a6c377aef 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py @@ -410,7 +410,7 @@ def test_ospfv3_learning_tc15_p0(request): step("Verify that Type 3 summary LSA is originated for the same Area 0") ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv6"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) input_dict = { "r1": { diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py index 645dea8dec..916f655550 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py @@ -262,7 +262,7 @@ def test_ospfv3_redistribution_tc5_p0(request): step("verify intra area route is calculated for r0-r3 interface ip in R1") ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) llip = get_llip("r0", "r1") assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) @@ -379,7 +379,7 @@ def test_ospfv3_redistribution_tc6_p0(request): step("verify intra area route is calculated for r0-r3 interface ip in R1") ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) llip = get_llip("r0", "r1") assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) nh = llip diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py index 7199f160fe..3bafd27f24 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py @@ -1124,7 +1124,7 @@ def test_ospfv3_show_p1(request): assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] - ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + ip_net = str(ipaddress.ip_interface("{}".format(ip)).network) nh = topo["routers"]["r0"]["links"]["r1"]["ipv6"].split("/")[0] input_dict = { "r1": { diff --git a/tests/topotests/pim_basic/test_pim.py b/tests/topotests/pim_basic/test_pim.py index 24987e516d..85b49aacc6 100644 --- a/tests/topotests/pim_basic/test_pim.py +++ b/tests/topotests/pim_basic/test_pim.py @@ -18,7 +18,7 @@ import pytest import json from functools import partial -pytestmark = pytest.mark.pimd +pytestmark = [pytest.mark.pimd] CWD = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(CWD, "../")) @@ -29,9 +29,6 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -pytestmark = [pytest.mark.pimd] - - def build_topo(tgen): "Build function" diff --git a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py index 71c90931fb..d03d5479fd 100644 --- a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py +++ b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py @@ -32,10 +32,7 @@ pytestmark = [ def tgen(request): "Setup/Teardown the environment and provide tgen argument to tests" - topodef = { - "s1": ("r1", "r2"), - "s2": ("r1", "r3") - } + topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")} tgen = Topogen(topodef, request.module.__name__) tgen.start_topology() @@ -68,16 +65,17 @@ def show_rip_json(router): for route in routes: match = re.match( - r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route) + r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route + ) if match is None: continue route_entry = { - "code": match[1], - "subCode": match[2], - "nextHop": match[4], - "metric": int(match[5]), - "from": match[6], + "code": match[1], + "subCode": match[2], + "nextHop": match[4], + "metric": int(match[5]), + "from": match[6], } if json.get(match[3]) is None: @@ -95,12 +93,8 @@ def expect_routes(router, routes, time_amount): "Internal test function." return topotest.json_cmp(show_rip_json(router), routes) - _, result = topotest.run_and_expect(test_function, - None, - count=time_amount, - wait=1) - assert result is None, "Unexpected routing table in {}".format( - router.name) + _, result = topotest.run_and_expect(test_function, None, count=time_amount, wait=1) + assert result is None, "Unexpected routing table in {}".format(router.name) def expect_bfd_peers(router, peers): @@ -119,91 +113,87 @@ def test_rip_convergence(tgen): "Test that RIP learns the neighbor routes." expect_routes( - tgen.gears["r1"], { - "10.254.254.2/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.2" - }], - "10.254.254.3/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.1.2" - }], - "10.254.254.100/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.2", - }, { - "code": "R", - "subCode": "n", - "from": "192.168.1.2", - }] - }, 40) - - expect_bfd_peers(tgen.gears["r1"], [{ - "peer": "192.168.0.2", - "status": "up", - "receive-interval": 1000, - "transmit-interval": 1000, - }, { - "peer": "192.168.1.2", - "status": "up", - "receive-interval": 1000, - "transmit-interval": 1000, - }]) + tgen.gears["r1"], + { + "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}], + "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.1.2"}], + "10.254.254.100/32": [ + { + "code": "R", + "subCode": "n", + "from": "192.168.0.2", + }, + { + "code": "R", + "subCode": "n", + "from": "192.168.1.2", + }, + ], + }, + 40, + ) + + expect_bfd_peers( + tgen.gears["r1"], + [ + { + "peer": "192.168.0.2", + "status": "up", + "receive-interval": 1000, + "transmit-interval": 1000, + }, + { + "peer": "192.168.1.2", + "status": "up", + "receive-interval": 1000, + "transmit-interval": 1000, + }, + ], + ) expect_routes( - tgen.gears["r2"], { - "10.254.254.1/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.1" - }], - "10.254.254.3/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.1" - }], - "10.254.254.100/32": [{ - "code": "S", - "subCode": "r", - "from": "self" - }] - }, 40) - - expect_bfd_peers(tgen.gears["r2"], [{ - "peer": "192.168.0.1", - "status": "up", - "receive-interval": 1000, - "transmit-interval": 1000, - }]) + tgen.gears["r2"], + { + "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}], + "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}], + "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}], + }, + 40, + ) + + expect_bfd_peers( + tgen.gears["r2"], + [ + { + "peer": "192.168.0.1", + "status": "up", + "receive-interval": 1000, + "transmit-interval": 1000, + } + ], + ) expect_routes( - tgen.gears["r3"], { - "10.254.254.1/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.1.1" - }], - "10.254.254.2/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.1.1" - }], - "10.254.254.100/32": [{ - "code": "S", - "subCode": "r", - "from": "self" - }] - }, 40) - - expect_bfd_peers(tgen.gears["r3"], [{ - "peer": "192.168.1.1", - "status": "up", - "receive-interval": 1000, - "transmit-interval": 1000, - }]) + tgen.gears["r3"], + { + "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}], + "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}], + "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}], + }, + 40, + ) + + expect_bfd_peers( + tgen.gears["r3"], + [ + { + "peer": "192.168.1.1", + "status": "up", + "receive-interval": 1000, + "transmit-interval": 1000, + } + ], + ) def test_rip_bfd_convergence(tgen): @@ -212,30 +202,30 @@ def test_rip_bfd_convergence(tgen): tgen.gears["r3"].link_enable("r3-eth0", False) expect_routes( - tgen.gears["r1"], { - "10.254.254.2/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.2" - }], + tgen.gears["r1"], + { + "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}], "10.254.254.3/32": None, - "10.254.254.100/32": [{ - "code": "R", - "subCode": "n", - "from": "192.168.0.2", - }] - }, 6) + "10.254.254.100/32": [ + { + "code": "R", + "subCode": "n", + "from": "192.168.0.2", + } + ], + }, + 6, + ) expect_routes( - tgen.gears["r3"], { + tgen.gears["r3"], + { "10.254.254.1/32": None, "10.254.254.2/32": None, - "10.254.254.100/32": [{ - "code": "S", - "subCode": "r", - "from": "self" - }] - }, 6) + "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}], + }, + 6, + ) def test_memory_leak(tgen): diff --git a/tests/topotests/route_scale/scale_test_common.py b/tests/topotests/route_scale/scale_test_common.py index 6227e81b98..b3cba1cb4e 100644 --- a/tests/topotests/route_scale/scale_test_common.py +++ b/tests/topotests/route_scale/scale_test_common.py @@ -151,7 +151,7 @@ def route_install_helper(iter): logger.info( "Limited memory available: {}, skipping x32 testcase".format(total_mem) ) - return; + return installed_file = "{}/r1/installed.routes.json".format(CWD) expected_installed = json.loads(open(installed_file).read()) diff --git a/tests/topotests/route_scale/test_route_scale1.py b/tests/topotests/route_scale/test_route_scale1.py index 0f25b28c74..ccbdd51595 100644 --- a/tests/topotests/route_scale/test_route_scale1.py +++ b/tests/topotests/route_scale/test_route_scale1.py @@ -30,35 +30,51 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module +from scale_test_common import ( + scale_build_common, + scale_setup_module, + route_install_helper, + scale_test_memory_leak, + scale_converge_protocols, + scale_teardown_module, +) pytestmark = [pytest.mark.sharpd] + def build(tgen): scale_build_common(tgen) + def setup_module(module): scale_setup_module(module) + def teardown_module(_mod): scale_teardown_module(_mod) + def test_converge_protocols(): scale_converge_protocols() + def test_route_install_2nh(): route_install_helper(1) + def test_route_install_4nh(): route_install_helper(2) + def test_route_install_16nh(): route_install_helper(4) + def test_memory_leak(): scale_test_memory_leak() + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/route_scale/test_route_scale2.py b/tests/topotests/route_scale/test_route_scale2.py index 3b55fcd8f5..e244d4fbbc 100644 --- a/tests/topotests/route_scale/test_route_scale2.py +++ b/tests/topotests/route_scale/test_route_scale2.py @@ -30,35 +30,51 @@ from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger -from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module +from scale_test_common import ( + scale_build_common, + scale_setup_module, + route_install_helper, + scale_test_memory_leak, + scale_converge_protocols, + scale_teardown_module, +) pytestmark = [pytest.mark.sharpd] + def build(tgen): scale_build_common(tgen) + def setup_module(module): scale_setup_module(module) + def teardown_module(_mod): scale_teardown_module(_mod) + def test_converge_protocols(): scale_converge_protocols() + def test_route_install_1nh(): route_install_helper(0) + def test_route_install_8nh(): route_install_helper(3) + def test_route_install_32nh(): route_install_helper(5) + def test_memory_leak(): scale_test_memory_leak() + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py index 4239193317..b8bcab8d93 100755 --- a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py +++ b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py @@ -63,16 +63,16 @@ def teardown_module(mod): def test_zebra_srv6_encap_src_addr(tgen): "Test SRv6 encapsulation source address." - logger.info( - "Test SRv6 encapsulation source address." - ) + logger.info("Test SRv6 encapsulation source address.") r1 = tgen.gears["r1"] # Generate expected results json_file = "{}/r1/expected_srv6_encap_src_addr.json".format(CWD) expected = json.loads(open(json_file).read()) - ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected) + ok = topotest.router_json_cmp_retry( + r1, "show segment-routing srv6 manager json", expected + ) assert ok, '"r1" JSON output mismatches' output = r1.cmd("ip sr tunsrc show") @@ -81,9 +81,7 @@ def test_zebra_srv6_encap_src_addr(tgen): def test_zebra_srv6_encap_src_addr_unset(tgen): "Test SRv6 encapsulation source address unset." - logger.info( - "Test SRv6 encapsulation source address unset." - ) + logger.info("Test SRv6 encapsulation source address unset.") r1 = tgen.gears["r1"] # Unset SRv6 encapsulation source address @@ -101,7 +99,9 @@ def test_zebra_srv6_encap_src_addr_unset(tgen): json_file = "{}/r1/expected_srv6_encap_src_addr_unset.json".format(CWD) expected = json.loads(open(json_file).read()) - ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected) + ok = topotest.router_json_cmp_retry( + r1, "show segment-routing srv6 manager json", expected + ) assert ok, '"r1" JSON output mismatches' output = r1.cmd("ip sr tunsrc show") @@ -110,9 +110,7 @@ def test_zebra_srv6_encap_src_addr_unset(tgen): def test_zebra_srv6_encap_src_addr_set(tgen): "Test SRv6 encapsulation source address set." - logger.info( - "Test SRv6 encapsulation source address set." - ) + logger.info("Test SRv6 encapsulation source address set.") r1 = tgen.gears["r1"] # Set SRv6 encapsulation source address @@ -130,7 +128,9 @@ def test_zebra_srv6_encap_src_addr_set(tgen): json_file = "{}/r1/expected_srv6_encap_src_addr_set.json".format(CWD) expected = json.loads(open(json_file).read()) - ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected) + ok = topotest.router_json_cmp_retry( + r1, "show segment-routing srv6 manager json", expected + ) assert ok, '"r1" JSON output mismatches' output = r1.cmd("ip sr tunsrc show") diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py index 2efc0fdf1b..3e03055acd 100644 --- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py +++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py @@ -65,8 +65,6 @@ ADDR_TYPES = check_address_types() NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"} NEXT_HOP_IP = {} -pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] - def setup_module(mod): """ @@ -551,7 +549,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): protocol = "bgp" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -571,7 +569,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): dut = "r2" ntwk_r2_vm6 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) ).network ) input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}} @@ -914,7 +912,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): protocol = "bgp" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -931,7 +929,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): dut = "r1" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) + "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -945,7 +943,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): dut = "r2" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) + "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -959,7 +957,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request): protocol = "bgp" ntwk_r2_vm6 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) ).network ) input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}} diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py index 0378240959..0fc81aaf1e 100644 --- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py +++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py @@ -547,7 +547,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): protocol = "bgp" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -567,7 +567,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): dut = "r2" ntwk_r2_vm6 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) ).network ) input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}} @@ -910,7 +910,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): protocol = "bgp" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -927,7 +927,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): dut = "r1" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) + "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -941,7 +941,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): dut = "r2" ntwk_r2_vm1 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) + "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type]) ).network ) input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}} @@ -955,7 +955,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request): protocol = "bgp" ntwk_r2_vm6 = str( ipaddress.ip_interface( - u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) + "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type]) ).network ) input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}} diff --git a/tests/topotests/tc_basic/test_tc_basic.py b/tests/topotests/tc_basic/test_tc_basic.py index f64e83c3cb..822d2016a8 100755 --- a/tests/topotests/tc_basic/test_tc_basic.py +++ b/tests/topotests/tc_basic/test_tc_basic.py @@ -22,9 +22,8 @@ sys.path.append(os.path.join(CWD, "../lib/")) from lib.topogen import Topogen, TopoRouter from lib.topolog import logger -pytestmark = [ - pytest.mark.sharpd -] +pytestmark = [pytest.mark.sharpd] + def build_topo(tgen): "Build function" @@ -42,6 +41,7 @@ def build_topo(tgen): switch = tgen.add_switch("s2") switch.add_link(r2) + # New form of setup/teardown using pytest fixture @pytest.fixture(scope="module") def tgen(request): @@ -79,22 +79,28 @@ def skip_on_failure(tgen): if tgen.routers_have_failure(): pytest.skip("skipped because of previous test failure") + def fetch_iproute2_tc_info(r, interface): qdisc = r.cmd("tc qdisc show dev %s" % interface) tclass = r.cmd("tc class show dev %s" % interface) tfilter = r.cmd("tc filter show dev %s" % interface) return qdisc, tclass, tfilter + # =================== # The tests functions # =================== + def test_tc_basic(tgen): "Test installing one pair of filter & class by sharpd" r1 = tgen.gears["r1"] intf = "r1-eth0" - r1.vtysh_cmd("sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit" % intf) + r1.vtysh_cmd( + "sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit" + % intf + ) time.sleep(3) @@ -115,6 +121,7 @@ def test_tc_basic(tgen): assert "dst_port 8001" in tfilter assert "src_port 8000" in tfilter + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] - sys.exit(pytest.main(args))
\ No newline at end of file + sys.exit(pytest.main(args)) diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py index 522c390c39..d970c04ee2 100644 --- a/tests/topotests/zebra_netlink/test_zebra_netlink.py +++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py @@ -94,7 +94,7 @@ def test_zebra_netlink_batching(tgen): } match = {} - base = int(ipaddress.ip_address(u"2.1.3.7")) + base = int(ipaddress.ip_address("2.1.3.7")) for i in range(base, base + count): pfx = str(ipaddress.ip_network((i, 32))) match[pfx] = [dict(entry, prefix=pfx)] diff --git a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py index 6956ab7409..fbef0fefc7 100644 --- a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py +++ b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py @@ -33,30 +33,36 @@ sys.path.append(os.path.join(CWD, "../")) pytestmark = [pytest.mark.sharpd] -#GLOBAL VARIABLES +# GLOBAL VARIABLES NH1 = "2.2.2.32" + def build_topo(tgen): tgen.add_router("r1") switch = tgen.add_switch("sw1") switch.add_link(tgen.gears["r1"]) + def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) tgen.start_topology() router_list = tgen.routers() for rname, router in tgen.routers().items(): - router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))) + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) router.load_config( TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)) ) tgen.start_router() + def teardown_module(_mod): tgen = get_topogen() tgen.stop_topology() + def test_verify_zebra_nh_resolution(request): tgen = get_topogen() tc_name = request.node.name @@ -67,31 +73,18 @@ def test_verify_zebra_nh_resolution(request): step("Configure static route") input_dict_1 = { - "r1": { - "static_routes": [ - {"network": "2.2.2.0/24", "next_hop": "r1-eth0"} - ] - } - } + "r1": {"static_routes": [{"network": "2.2.2.0/24", "next_hop": "r1-eth0"}]} + } result = create_static_routes(tgen, input_dict_1) - assert result is True, "Testcase {} : Failed \n Error: {}".format( - tc_name, result - ) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) step("Verify static routes in RIB of R1") - input_dict_2 = { - "r1": { - "static_routes": [ - {"network": "2.2.2.0/24"} - ] - } - } + input_dict_2 = {"r1": {"static_routes": [{"network": "2.2.2.0/24"}]}} dut = "r1" result = verify_rib(tgen, "ipv4", dut, input_dict_2) - assert result is True, "Testcase {} :Failed \n Error: {}".format( - tc_name, result) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) step("Set the connected flag on the NH tracking entry") r1.vtysh_cmd("sharp watch nexthop 2.2.2.32 connected") @@ -108,8 +101,7 @@ def test_verify_zebra_nh_resolution(request): } result = verify_ip_nht(tgen, input_dict_nh) assert result is True, "Testcase {} : Failed \n" - "Error: Nexthop is missing in RIB".format( - tc_name, result) + "Error: Nexthop is missing in RIB".format(tc_name, result) step("Add a .32/32 route with the NH as itself") r1.vtysh_cmd("sharp install routes 2.2.2.32 nexthop 2.2.2.32 1") @@ -126,11 +118,12 @@ def test_verify_zebra_nh_resolution(request): } result = verify_ip_nht(tgen, input_dict_nh) assert result is True, "Testcase {} : Failed \n" - "Error: Nexthop became unresolved".format( - tc_name, result) + "Error: Nexthop became unresolved".format(tc_name, result) - step("Add a .31/32 route with the NH as 2.2.2.32" - "to verify the NH Resolution behaviour") + step( + "Add a .31/32 route with the NH as 2.2.2.32" + "to verify the NH Resolution behaviour" + ) r1.vtysh_cmd("sharp install routes 2.2.2.31 nexthop 2.2.2.32 1") step("Verify that NH 2.2.2.2/32 doesn't become unresolved") @@ -145,8 +138,8 @@ def test_verify_zebra_nh_resolution(request): } result = verify_ip_nht(tgen, input_dict_nh) assert result is True, "Testcase {} : Failed \n" - "Error: Nexthop became unresolved".format( - tc_name, result) + "Error: Nexthop became unresolved".format(tc_name, result) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/tools/etc/iproute2/rt_protos.d/frr.conf b/tools/etc/iproute2/rt_protos.d/frr.conf index bbb358fc6c..3e0fc2ea37 100644 --- a/tools/etc/iproute2/rt_protos.d/frr.conf +++ b/tools/etc/iproute2/rt_protos.d/frr.conf @@ -12,3 +12,4 @@ 195 pbr 196 static 197 openfabric +198 srte diff --git a/tools/frr-reload.py b/tools/frr-reload.py index b6e67fc7d2..461f0e8c61 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -1083,19 +1083,34 @@ def pim_delete_move_lines(lines_to_add, lines_to_del): # Remove all such depdendent options from delete # pending list. pim_disable = False + lines_to_del_to_del = [] + index = -1 for ctx_keys, line in lines_to_del: + index = index + 1 if ctx_keys[0].startswith("interface") and line and line == "ip pim": pim_disable = True + # no ip msdp peer <> does not accept source so strip it off. + if line and line.startswith("ip msdp peer "): + pim_msdp_peer = re.search("ip msdp peer (\S+) source (\S+)", line) + if pim_msdp_peer: + source_sub_str = "source %s" % pim_msdp_peer.group(2) + new_line = line.replace(source_sub_str, "").strip() + lines_to_del.remove((ctx_keys, line)) + lines_to_del.insert(index, (ctx_keys, new_line)) + if pim_disable: for ctx_keys, line in lines_to_del: if ( ctx_keys[0].startswith("interface") and line - and line.startswith("ip pim ") + and (line.startswith("ip pim ") or line.startswith("ip multicast ")) ): - lines_to_del.remove((ctx_keys, line)) + lines_to_del_to_del.append((ctx_keys, line)) + + for ctx_keys, line in lines_to_del_to_del: + lines_to_del.remove((ctx_keys, line)) return (lines_to_add, lines_to_del) @@ -1460,6 +1475,35 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del): lines_to_add.append((add_cmd, None)) lines_to_del_to_del.append((ctx_keys, None)) + # bgp as-path access-list can be specified without a seq number. + # However, the running config always + # adds `seq X` (sequence number). So, ignore such lines as well. + # Examples: + # bgp as-path access-list important_internet_bgp_as_numbers seq 30 permit _40841_" + re_bgp_as_path = re.search( + "^(bgp )(as-path )(access-list )(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$", + ctx_keys[0], + ) + if re_bgp_as_path: + found = False + tmpline = ( + re_bgp_as_path.group(1) + + re_bgp_as_path.group(2) + + re_bgp_as_path.group(3) + + re_bgp_as_path.group(4) + + re_bgp_as_path.group(6) + + re_bgp_as_path.group(7) + ) + for ctx in lines_to_add: + if ctx[0][0] == tmpline: + lines_to_del_to_del.append((ctx_keys, None)) + lines_to_add_to_del.append(((tmpline,), None)) + found = True + if found is False: + add_cmd = ("no " + ctx_keys[0],) + lines_to_add.append((add_cmd, None)) + lines_to_del_to_del.append((ctx_keys, None)) + if ( len(ctx_keys) == 3 and ctx_keys[0].startswith("router bgp") diff --git a/tools/gcc-plugins/frr-format.c b/tools/gcc-plugins/frr-format.c index 4e2c2d3ba9..963741e479 100644 --- a/tools/gcc-plugins/frr-format.c +++ b/tools/gcc-plugins/frr-format.c @@ -66,6 +66,8 @@ static GTY(()) tree local_pid_t_node; static GTY(()) tree local_uid_t_node; static GTY(()) tree local_gid_t_node; static GTY(()) tree local_time_t_node; +static GTY(()) tree local_suseconds_t_node; +static GTY(()) tree local_suseconds64_t_node; static GTY(()) tree local_socklen_t_node; static GTY(()) tree local_in_addr_t_node; @@ -85,6 +87,8 @@ static struct type_special { { &local_uid_t_node, NULL, &local_uid_t_node, }, { &local_gid_t_node, NULL, &local_gid_t_node, }, { &local_time_t_node, NULL, &local_time_t_node, }, + { &local_suseconds_t_node, NULL, &local_suseconds_t_node, }, + { &local_suseconds64_t_node, NULL, &local_suseconds64_t_node, }, { NULL, NULL, NULL, } }; @@ -4176,6 +4180,8 @@ handle_finish_parse (void *event_data, void *data) setup_type ("uid_t", &local_uid_t_node); setup_type ("gid_t", &local_gid_t_node); setup_type ("time_t", &local_time_t_node); + setup_type ("__suseconds_t", &local_suseconds_t_node); + setup_type ("__suseconds64_t", &local_suseconds64_t_node); setup_type ("socklen_t", &local_socklen_t_node); setup_type ("in_addr_t", &local_in_addr_t_node); diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index e03d1464d3..1a358017dc 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -39,7 +39,6 @@ #include "frrstr.h" #include "json.h" #include "ferr.h" -#include "bgpd/bgp_vty.h" DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy"); diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index c679f3b911..b0858e153c 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -881,9 +881,7 @@ identity set-extcommunity-color { leaf bandwidth { when "../lb-type = 'explicit-bandwidth'"; mandatory true; - type uint16 { - range "1..25600"; - } + type uint32; description "Bandwidth value in Mbps"; } diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 5d7c739c05..d1a08fa976 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -685,7 +685,7 @@ module frr-isisd { type uint32 { range "0..16777215"; } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide' or not(/frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style)"; default "10"; description "Default level-1 metric for this IS-IS circuit."; @@ -695,7 +695,7 @@ module frr-isisd { type uint32 { range "0..16777215"; } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide' or not(/frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style)"; default "10"; description "Default level-2 metric for this IS-IS circuit."; diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang index e9b3f67507..732a38a9e3 100644 --- a/yang/frr-pim.yang +++ b/yang/frr-pim.yang @@ -422,9 +422,7 @@ module frr-pim { } leaf dr-priority { - type uint32 { - range "1..max"; - } + type uint32; default 1; description "DR (Designated Router) priority"; diff --git a/yang/frr-test-module.yang b/yang/frr-test-module.yang index 6cc60e8665..dcf204a956 100644 --- a/yang/frr-test-module.yang +++ b/yang/frr-test-module.yang @@ -80,6 +80,23 @@ module frr-test-module { } } } + action ping { + input { + leaf data { + type string; + } + } + output { + leaf vrf { + type string; + } + // can't use the same name in input and output + // because of a bug in libyang < 2.1.148 + leaf data-out { + type string; + } + } + } } } choice achoice { diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c index a7cccdb98f..037d0b6237 100644 --- a/zebra/debug_nl.c +++ b/zebra/debug_nl.c @@ -534,6 +534,12 @@ const char *rtm_rta2str(int type) return "NH_ID"; case RTA_EXPIRES: return "EXPIRES"; + case RTA_VIA: + return "VIA"; + case RTA_ENCAP_TYPE: + return "RTA_ENCAP_TYPE"; + case RTA_ENCAP: + return "RTA_ENCAP"; default: return "UNKNOWN"; } diff --git a/zebra/fpm_listener.c b/zebra/fpm_listener.c index 5ffc0561bb..5533fa7f8b 100644 --- a/zebra/fpm_listener.c +++ b/zebra/fpm_listener.c @@ -36,6 +36,8 @@ #include "fpm/fpm.h" #include "lib/libfrr.h" +XREF_SETUP(); + struct glob { int server_sock; int sock; @@ -344,17 +346,19 @@ static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas, memset(rtas, 0, num_rtas * sizeof(rtas[0])); for (; len > 0; rta = RTA_NEXT(rta, len)) { + uint16_t type = rta->rta_type & NLA_TYPE_MASK; + if (!RTA_OK(rta, len)) { *err_msg = "Malformed rta"; return 0; } - if (rta->rta_type >= num_rtas) { + if (type >= num_rtas) { warn("Unknown rtattr type %d", rta->rta_type); continue; } - rtas[rta->rta_type] = rta; + rtas[type] = rta; } return 1; diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 5f096e3039..3233519873 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1473,7 +1473,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifi = NLMSG_DATA(h); - /* assume if not default zns, then new VRF */ if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { /* If this is not link add/delete message so print warning. */ zlog_debug("%s: wrong kernel message %s", __func__, diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 8a64a1ea48..d2f1db67ee 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -619,6 +619,11 @@ static void netlink_install_filter(int sock, uint32_t pid, uint32_t dplane_pid) safe_strerror(errno)); } +/* + * Please note, the assumption with this function is that the + * flags passed in that are bit masked with type, we are implicitly + * assuming that this is handling the NLA_F_NESTED ilk. + */ void netlink_parse_rtattr_flags(struct rtattr **tb, int max, struct rtattr *rta, int len, unsigned short flags) { @@ -638,8 +643,19 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, { memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); while (RTA_OK(rta, len)) { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; + /* + * The type may be &'ed with NLA_F_NESTED + * which puts data in the upper 8 bits of the + * rta_type. Mask it off and save the actual + * underlying value to be placed into the array. + * This way we don't accidently crash in the future + * when the kernel sends us new data and we try + * to write well beyond the end of the array. + */ + uint16_t type = rta->rta_type & NLA_TYPE_MASK; + + if (type <= max) + tb[type] = rta; rta = RTA_NEXT(rta, len); } } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index dde4704936..4a15b74004 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1683,6 +1683,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p, sizeof(struct in_addr))) return false; break; + case ZEBRA_SEG6_LOCAL_ACTION_END_DX6: + if (!nl_attr_put32(nlmsg, req_size, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DX6)) + return false; + if (!nl_attr_put(nlmsg, req_size, + SEG6_LOCAL_NH6, &ctx->nh6, + sizeof(struct in_addr))) + return false; + break; case ZEBRA_SEG6_LOCAL_ACTION_END_DT6: if (!nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION, @@ -1714,7 +1724,6 @@ static bool _netlink_route_build_singlepath(const struct prefix *p, return false; break; case ZEBRA_SEG6_LOCAL_ACTION_END_DX2: - case ZEBRA_SEG6_LOCAL_ACTION_END_DX6: case ZEBRA_SEG6_LOCAL_ACTION_END_B6: case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP: case ZEBRA_SEG6_LOCAL_ACTION_END_BM: @@ -2931,6 +2940,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, sizeof(struct in_addr))) return 0; break; + case SEG6_LOCAL_ACTION_END_DX6: + if (!nl_attr_put32(&req->n, + buflen, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DX6)) + return 0; + if (!nl_attr_put(&req->n, buflen, + SEG6_LOCAL_NH6, + &ctx->nh6, + sizeof(struct in_addr))) + return 0; + break; case SEG6_LOCAL_ACTION_END_DT6: if (!nl_attr_put32( &req->n, buflen, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 76cabd1bf0..d585ef996b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1724,7 +1724,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, * Let's convert the weights to a scaled value * between 1 and zrouter.nexthop_weight_scale_value * This is a simple application of a ratio: - * scaled_weight/zrouter.nexthop_weight_scale_value = + * scaled_weight/zrouter.nexthop_weight_scale_value = * weight/max_weight * This translates to: * scaled_weight = weight * zrouter.nexthop_weight_scale_value @@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, for (i = 0; i < nexthop_num; i++) { znh = &nhops[i]; - tmp = (uint64_t)znh->weight * - zrouter.nexthop_weight_scale_value; - znh->weight = MAX(1, ((uint32_t)(tmp / max_weight))); + tmp = znh->weight * zrouter.nexthop_weight_scale_value; + znh->weight = MAX(1, (tmp / max_weight)); } } diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 0d9d912f83..5c19d226b1 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -563,8 +563,9 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if) struct zebra_evpn_access_bd *acc_bd; struct interface *vlan_if; - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("access vlan %d bridge %s add", vid, br_if->name); + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s access vlan %d bridge %s add", __func__, vid, + br_if->name); acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd)); @@ -582,8 +583,8 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if) vlan_if = zvni_map_to_svi(vid, br_if); if (vlan_if) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("vlan %d bridge %s SVI %s set", vid, - br_if->name, vlan_if->name); + zlog_debug("%s vlan %d bridge %s SVI %s set", __func__, + vid, br_if->name, vlan_if->name); acc_bd->vlan_zif = vlan_if->info; } return acc_bd; @@ -731,6 +732,29 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd, } } +/* Lookup API for VxLAN_IF's Bridge, VLAN in EVPN cache */ +int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, struct zebra_if *vxlan_zif) +{ + struct interface *br_if; + struct zebra_evpn_access_bd *acc_bd; + + if (!vid) + return -1; + + br_if = vxlan_zif->brslave_info.br_if; + + if (!br_if) + return -1; + + acc_bd = zebra_evpn_acc_vl_find(vid, br_if); + + if (!acc_bd) + return 0; + + return 1; +} + + /* handle VLAN->VxLAN_IF association */ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id, struct zebra_if *vxlan_zif) @@ -768,8 +792,9 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id, if (acc_bd->zevpn == old_zevpn) return; - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("access vlan %d vni %u ref", acc_bd->vid, vni_id); + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s bridge %s access vlan %d vni %u ref", __func__, + br_if->name, acc_bd->vid, vni_id); if (old_zevpn) zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn); diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h index 34ef79f155..f68e2eae60 100644 --- a/zebra/zebra_evpn_mh.h +++ b/zebra/zebra_evpn_mh.h @@ -378,7 +378,8 @@ extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es, extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS); extern struct zebra_evpn_es_evi * zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn); - +extern int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, + struct zebra_if *vxlan_zif); void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi); void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac); diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index 0f591810b9..240f674b0f 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -384,7 +384,7 @@ void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, return; old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan; - ; + if (old_access_vlan == access_vlan) return; diff --git a/zebra/zebra_nb_rpcs.c b/zebra/zebra_nb_rpcs.c index 083ab3fde6..938193df2f 100644 --- a/zebra/zebra_nb_rpcs.c +++ b/zebra/zebra_nb_rpcs.c @@ -20,48 +20,30 @@ int clear_evpn_dup_addr_rpc(struct nb_cb_rpc_args *args) { struct zebra_vrf *zvrf; int ret = NB_OK; - struct yang_data *yang_dup_choice = NULL, *yang_dup_vni = NULL, - *yang_dup_ip = NULL, *yang_dup_mac = NULL; - - yang_dup_choice = yang_data_list_find(args->input, "%s/%s", args->xpath, - "input/clear-dup-choice"); zvrf = zebra_vrf_get_evpn(); - if (yang_dup_choice - && strcmp(yang_dup_choice->value, "all-case") == 0) { + if (yang_dnode_exists(args->input, "all-vnis")) { zebra_vxlan_clear_dup_detect_vni_all(zvrf); } else { - vni_t vni; + vni_t vni = yang_dnode_get_uint32(args->input, "vni-id"); struct ipaddr host_ip = {.ipa_type = IPADDR_NONE}; struct ethaddr mac; - yang_dup_vni = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id"); - if (yang_dup_vni) { - vni = yang_str2uint32(yang_dup_vni->value); - - yang_dup_mac = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id/mac-addr"); - yang_dup_ip = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id/vni-ipaddr"); - - if (yang_dup_mac) { - yang_str2mac(yang_dup_mac->value, &mac); - ret = zebra_vxlan_clear_dup_detect_vni_mac( - zvrf, vni, &mac, args->errmsg, - args->errmsg_len); - } else if (yang_dup_ip) { - yang_str2ip(yang_dup_ip->value, &host_ip); - ret = zebra_vxlan_clear_dup_detect_vni_ip( - zvrf, vni, &host_ip, args->errmsg, - args->errmsg_len); - } else - ret = zebra_vxlan_clear_dup_detect_vni(zvrf, - vni); + if (yang_dnode_exists(args->input, "mac-addr")) { + yang_dnode_get_mac(&mac, args->input, "mac-addr"); + ret = zebra_vxlan_clear_dup_detect_vni_mac(zvrf, vni, + &mac, + args->errmsg, + args->errmsg_len); + } else if (yang_dnode_exists(args->input, "vni-ipaddr")) { + yang_dnode_get_ip(&host_ip, args->input, "vni-ipaddr"); + ret = zebra_vxlan_clear_dup_detect_vni_ip(zvrf, vni, + &host_ip, + args->errmsg, + args->errmsg_len); + } else { + ret = zebra_vxlan_clear_dup_detect_vni(zvrf, vni); } } if (ret < 0) diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index ff97a11c17..1246e4dba2 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -3664,8 +3664,9 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) "%s: Setting the valid flag for nhe %pNG, interface: %s", __func__, rb_node_dep->nhe, ifp->name); } + /* Check for singleton NHG associated to interface */ - if (nexthop_is_ifindex_type(nh) && + if (!nexthop_is_blackhole(nh) && zebra_nhg_depends_is_empty(rb_node_dep->nhe)) { struct nhg_connected *rb_node_dependent; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 0b5362094e..bdbb059e56 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -3553,56 +3553,17 @@ DEFPY (clear_evpn_dup_addr, "IPv4 address\n" "IPv6 address\n") { - struct ipaddr host_ip = {.ipa_type = IPADDR_NONE }; - int ret = CMD_SUCCESS; - struct list *input; - struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL, - *yang_dup_mac = NULL; - - input = list_new(); - if (!vni_str) { - yang_dup = yang_data_new( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice", - "all-case"); + nb_cli_rpc_enqueue(vty, "all-vnis", NULL); } else { - yang_dup = yang_data_new_uint32( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id", - vni); - if (!is_zero_mac(&mac->eth_addr)) { - yang_dup_mac = yang_data_new_mac( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr", - &mac->eth_addr); - if (yang_dup_mac) - listnode_add(input, yang_dup_mac); - } else if (ip) { - if (sockunion_family(ip) == AF_INET) { - host_ip.ipa_type = IPADDR_V4; - host_ip.ipaddr_v4.s_addr = sockunion2ip(ip); - } else { - host_ip.ipa_type = IPADDR_V6; - memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr, - sizeof(struct in6_addr)); - } - - yang_dup_ip = yang_data_new_ip( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr", - &host_ip); - - if (yang_dup_ip) - listnode_add(input, yang_dup_ip); - } - } - - if (yang_dup) { - listnode_add(input, yang_dup); - ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input, - NULL); + nb_cli_rpc_enqueue(vty, "vni-id", vni_str); + if (mac_str) + nb_cli_rpc_enqueue(vty, "mac-addr", mac_str); + else if (ip_str) + nb_cli_rpc_enqueue(vty, "vni-ipaddr", ip_str); } - list_delete(&input); - - return ret; + return nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", NULL); } DEFPY_HIDDEN (evpn_accept_bgp_seq, diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 89b43f6d22..65dc6638bc 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1759,9 +1759,9 @@ static int svd_remote_nh_add(struct zebra_l3vni *zl3vni, } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "SVD RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX", - &nh->emac, rmac, vtep_ip, host_prefix); + zlog_debug("SVD RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX refcnt %u", + &nh->emac, rmac, vtep_ip, host_prefix, + nh->refcnt); memcpy(&nh->emac, rmac, ETH_ALEN); /* install (update) the nh neigh in kernel */ @@ -2469,11 +2469,26 @@ static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx) /* delete and uninstall nh hash entry */ static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx) { - struct zebra_neigh *n = NULL; + struct zebra_neigh *n = NULL, *svd_nh = NULL; struct zebra_l3vni *zl3vni = NULL; n = (struct zebra_neigh *)bucket->data; zl3vni = (struct zebra_l3vni *)ctx; + + /* remove SVD based remote nexthop neigh entry */ + svd_nh = svd_nh_lookup(&n->ip); + if (svd_nh) { + svd_nh->refcnt--; + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s L3VNI %u remove svd nh %pIA refcnt %u", + __func__, zl3vni->vni, &n->ip, + svd_nh->refcnt); + if (svd_nh->refcnt == 0) { + svd_nh_uninstall(zl3vni, svd_nh); + svd_nh_del(svd_nh); + } + } + zl3vni_nh_uninstall(zl3vni, n); zl3vni_nh_del(zl3vni, n); } diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c index 3cc7e499bf..f4b859b861 100644 --- a/zebra/zebra_vxlan_if.c +++ b/zebra/zebra_vxlan_if.c @@ -506,7 +506,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif, if ((hashcount(ctx->old_vni_table) == 0) || !(old_vni = hash_release(ctx->old_vni_table, &vni_tmp))) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("vxlan %s adding vni(%d, %d)", + zlog_debug("%s vxlan %s adding vni(%d, %d)", __func__, zif->ifp->name, vni->vni, vni->access_vlan); zebra_vxlan_if_vni_entry_add(zif, &vni_tmp); @@ -521,17 +521,39 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif, if (old_vni->access_vlan != vni->access_vlan) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "vxlan %s updating vni(%d, %d) -> vni(%d, %d)", - zif->ifp->name, old_vni->vni, - old_vni->access_vlan, vni->vni, - vni->access_vlan); + zlog_debug("%s vxlan %s updating vni(%d, %d) -> vni(%d, %d)", + __func__, zif->ifp->name, old_vni->vni, + old_vni->access_vlan, vni->vni, + vni->access_vlan); zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni, zif); zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif); zebra_vxlan_if_update_vni(zif->ifp, vni, ctx); zebra_vxlan_vni_free(old_vni); + } else { + int ret; + + ret = zebra_evpn_vl_vxl_bridge_lookup(vni->access_vlan, zif); + /* Here ret value 0 implied bridge vlan mapping is not present + * repopulated. Ignore ret value 1 as it means vlan mapping is + * present in bridge table. + */ + if (ret < 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s vxlan %s vni %u has error accessing bridge table.", + __func__, zif->ifp->name, vni->vni); + } else if (ret == 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s vxlan %s vni (%u, %u) not present in bridge table", + __func__, zif->ifp->name, vni->vni, + vni->access_vlan); + zebra_evpn_vl_vxl_deref(old_vni->access_vlan, + old_vni->vni, zif); + zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif); + zebra_vxlan_if_update_vni(zif->ifp, vni, ctx); + zebra_vxlan_vni_free(old_vni); + } } return 0; @@ -768,6 +790,7 @@ vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif, return vni->vni; } +/* SVD VLAN-VNI mapping update */ int zebra_vxlan_if_vni_table_add_update(struct interface *ifp, struct hash *vni_table) { |
