diff options
113 files changed, 3829 insertions, 598 deletions
diff --git a/babeld/message.c b/babeld/message.c index 15d772eb46..d4ddebff08 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -48,6 +48,13 @@ static const unsigned char tlv_min_length[MESSAGE_MAX + 1] = [ MESSAGE_MH_REQUEST ] = 14, }; +/* Checks whether an AE exists or must be silently ignored */ +static bool +known_ae(int ae) +{ + return ae <= 4; +} + /* Parse a network prefix, encoded in the somewhat baroque compressed representation used by Babel. Return the number of bytes parsed. */ static int @@ -277,6 +284,62 @@ parse_ihu_subtlv(const unsigned char *a, int alen, } static int +parse_request_subtlv(int ae, const unsigned char *a, int alen, + unsigned char *src_prefix, unsigned char *src_plen) +{ + int type, len, i = 0; + int have_src_prefix = 0; + + while(i < alen) { + type = a[0]; + if(type == SUBTLV_PAD1) { + i++; + continue; + } + + if(i + 2 > alen) + goto fail; + + len = a[i + 1]; + if(i + 2 + len > alen) + goto fail; + + if(type == SUBTLV_PADN) { + /* Nothing to do. */ + } else if(type == SUBTLV_SOURCE_PREFIX) { + int rc; + if(len < 1) + goto fail; + if(a[i + 2] == 0) + goto fail; + if(have_src_prefix != 0) + goto fail; + rc = network_prefix(ae, a[i + 2], 0, a + i + 3, NULL, + len - 1, src_prefix); + if(rc < 0) + goto fail; + if(ae==1) + *src_plen = a[i + 2] + 96; + else + *src_plen = a[i + 2]; + have_src_prefix = 1; + } else { + debugf(BABEL_DEBUG_COMMON,"Received unknown%s Route Request sub-TLV %d.", + ((type & 0x80) != 0) ? " mandatory" : "", type); + if((type & 0x80) != 0) + return -1; + } + + i += len + 2; + } + return 1; + + fail: + flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Route Request."); + return -1; +} + +static int network_address(int ae, const unsigned char *a, unsigned int len, unsigned char *a_r) { @@ -612,8 +675,14 @@ parse_packet(const unsigned char *from, struct interface *ifp, interval, neigh, nh, channels, channels_len(channels)); } else if(type == MESSAGE_REQUEST) { - unsigned char prefix[16], plen; - int rc; + unsigned char prefix[16], src_prefix[16], plen, src_plen; + int rc, is_ss; + if(len < 2) goto fail; + if(!known_ae(message[2])) { + debugf(BABEL_DEBUG_COMMON,"Received request with unknown AE %d. Ignoring.", + message[2]); + goto done; + } rc = network_prefix(message[2], message[3], 0, message + 4, NULL, len - 2, prefix); if(rc < 0) goto fail; @@ -621,8 +690,26 @@ parse_packet(const unsigned char *from, struct interface *ifp, debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.", message[2] == 0 ? "any" : format_prefix(prefix, plen), format_address(from), ifp->name); + if(message[2] == 1) { + v4tov6(src_prefix, zeroes); + src_plen = 96; + } else { + memcpy(src_prefix, zeroes, 16); + src_plen = 0; + } + rc = parse_request_subtlv(message[2], message + 4 + rc, + len - 2 - rc, src_prefix, &src_plen); + if(rc < 0) + goto done; + is_ss = !is_default(src_prefix, src_plen); if(message[2] == 0) { struct babel_interface *neigh_ifp =babel_get_if_nfo(neigh->ifp); + if(is_ss) { + /* Wildcard requests don't carry a source prefix. */ + flog_err(EC_BABEL_PACKET, + "Received source-specific wildcard request."); + goto done; + } /* If a neighbour is requesting a full route dump from us, we might as well send it an IHU. */ send_ihu(neigh, NULL); diff --git a/babeld/message.h b/babeld/message.h index 0797a5a77d..7cf062a888 100644 --- a/babeld/message.h +++ b/babeld/message.h @@ -34,6 +34,7 @@ Copyright (c) 2007, 2008 by Juliusz Chroboczek #define SUBTLV_PADN 1 #define SUBTLV_DIVERSITY 2 /* Also known as babelz. */ #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ +#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */ #define SUBTLV_MANDATORY 0x80 extern unsigned short myseqno; diff --git a/babeld/util.h b/babeld/util.h index 8535d4dd6a..ddc6a70d43 100644 --- a/babeld/util.h +++ b/babeld/util.h @@ -104,6 +104,12 @@ void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src); int daemonise(void); extern const unsigned char v4prefix[16]; +static inline bool +is_default(const unsigned char *prefix, int plen) +{ + return plen == 0 || (plen == 96 && v4mapped(prefix)); +} + /* If debugging is disabled, we want to avoid calling format_address for every omitted debugging message. So debug is a macro. But vararg macros are not portable. */ diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 326d7f2efb..66426ab32f 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -185,16 +185,23 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, offset++; } /* Prefix length check. */ - if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8) + if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8) { *error = -1; + return offset; + } /* When packet overflow occur return immediately. */ - if (psize + offset > max_len) + if (psize + offset > max_len) { *error = -1; + return offset; + } /* Defensive coding, double-check * the psize fits in a struct prefix */ - if (psize > (ssize_t)sizeof(prefix_local.u)) + if (psize > (ssize_t)sizeof(prefix_local.u)) { *error = -1; + return offset; + } + memcpy(&prefix_local.u.prefix, &nlri_ptr[offset], psize); offset += psize; switch (type) { @@ -352,8 +359,10 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type, *error = 0; do { - if (loop > BGP_PBR_MATCH_VAL_MAX) + if (loop > BGP_PBR_MATCH_VAL_MAX) { *error = -2; + return offset; + } hex2bin(&nlri_ptr[offset], op); /* if first element, AND bit can not be set */ if (op[1] == 1 && loop == 0) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 05ad4d97e5..ccf198c392 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9292,9 +9292,24 @@ DEFPY (af_sid_vpn_export, return CMD_WARNING_CONFIG_FAILED; if (!yes) { - /* implement me */ - vty_out(vty, "It's not implemented\n"); - return CMD_WARNING_CONFIG_FAILED; + /* when SID is not set, do nothing */ + if ((bgp->vpn_policy[afi].tovpn_sid_index == 0) && + !CHECK_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO)) + return CMD_SUCCESS; + + /* pre-change */ + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, + bgp_get_default(), bgp); + bgp->vpn_policy[afi].tovpn_sid_index = 0; + UNSET_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_SID_AUTO); + + /* post-change */ + vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, + bgp_get_default(), bgp); + + return CMD_SUCCESS; } if (bgp->tovpn_sid_index != 0 || @@ -9333,7 +9348,7 @@ DEFPY (af_sid_vpn_export, zlog_debug("%s: auto sid alloc.", __func__); SET_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_SID_AUTO); - } else { + } else if (sid_idx != 0) { /* SID allocation index-mode */ if (debug) zlog_debug("%s: idx %ld sid alloc.", __func__, sid_idx); diff --git a/configure.ac b/configure.ac index 79288c67e9..b9af768641 100644 --- a/configure.ac +++ b/configure.ac @@ -691,6 +691,8 @@ AC_ARG_ENABLE([ospfapi], AC_ARG_ENABLE([ospfclient], AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI, (this is the default if --disable-ospfapi is set)])) +AC_ARG_WITH([log_timestamp_precision], + AS_HELP_STRING([--with-log-timestamp-precision=ARG], [set startup log timestamp precision, ARG must be 0-12])) AC_ARG_ENABLE([multipath], AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit])) AC_ARG_WITH([service_timeout], @@ -962,8 +964,19 @@ esac AC_DEFINE_UNQUOTED([MULTIPATH_NUM], [$MPATH_NUM], [Maximum number of paths for a route]) -AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use]) +case "${with_log_timestamp_precision}" in +[[0-9]|1[012]]) +;; +"") +;; +*) +AC_MSG_FAILURE([Please specify a number from 0-12 for log precision ARG]) +;; +esac +with_log_timestamp_precision=${with_log_timestamp_precision:-0} +AC_DEFINE_UNQUOTED([LOG_TIMESTAMP_PRECISION], [${with_log_timestamp_precision}], [Startup zlog timestamp precision]) +AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use]) TIMEOUT_MIN=2 case "${with_service_timeout}" in diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst index 6614a568f8..737eb57c85 100644 --- a/doc/user/mgmtd.rst +++ b/doc/user/mgmtd.rst @@ -364,3 +364,46 @@ MGMT Show commands .. clicmd:: show mgmt commit-history This command dumps details of upto last 10 commits handled by MGMTd. + + +MGMT Daemon debug commands +========================== + +The following debug commands enable debugging within the management daemon: + +.. clicmd:: [no] debug mgmt backend + + Enable[/Disable] debugging messages related to backend operations within the + management daemon. + +.. clicmd:: [no] debug mgmt datastore + + Enable[/Disable] debugging messages related to YANG datastore operations + within the management daemon. + +.. clicmd:: [no] debug mgmt frontend + + Enable[/Disable] debugging messages related to frontend operations within the + management daemon. + +.. clicmd:: [no] debug mgmt transaction + + Enable[/Disable] debugging messages related to transactions within the + management daemon. + + +MGMT Client debug commands +========================== + +The following debug commands enable debugging within the management front and +backend clients: + +.. clicmd:: [no] debug mgmt client backend + + Enable[/Disable] debugging messages related to backend operations inside the + backend mgmtd clients. + +.. clicmd:: [no] debug mgmt client frontend + + Enable[/Disable] debugging messages related to frontend operations inside the + frontend mgmtd clients. diff --git a/isisd/isis_flex_algo.c b/isisd/isis_flex_algo.c index 0efc519eab..ef30987b8e 100644 --- a/isisd/isis_flex_algo.c +++ b/isisd/isis_flex_algo.c @@ -45,7 +45,7 @@ void *isis_flex_algo_data_alloc(void *voidarg) struct isis_flex_algo_alloc_arg *arg = voidarg; struct isis_flex_algo_data *data; - data = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*data)); + data = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct isis_flex_algo_data)); for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) { for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { @@ -70,6 +70,7 @@ void isis_flex_algo_data_free(void *voiddata) if (data->spftree[tree][level - 1]) isis_spftree_del( data->spftree[tree][level - 1]); + XFREE(MTYPE_FLEX_ALGO, data); } static struct isis_router_cap_fad * diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index c07083a06d..950d5f359c 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -1191,8 +1191,11 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) rcap_fad = NULL; if (!isis_flex_algo_elected_supported_local_fad( - fa->algorithm, area, &rcap_fad)) + fa->algorithm, area, &rcap_fad)) { + fa->state = false; continue; + } + fa->state = true; lsp_debug("ISIS (%s): SR Algorithm %u", area->area_tag, fa->algorithm); rcap->algo[fa->algorithm] = fa->algorithm; diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 466e96b3a2..de467c8262 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -393,14 +393,14 @@ static void _isis_spftree_del(struct isis_spftree *spftree) isis_vertex_queue_free(&spftree->paths); isis_route_table_info_free(spftree->route_table->info); isis_route_table_info_free(spftree->route_table_backup->info); + route_table_finish(spftree->route_table); + route_table_finish(spftree->route_table_backup); } void isis_spftree_del(struct isis_spftree *spftree) { _isis_spftree_del(spftree); - route_table_finish(spftree->route_table); - route_table_finish(spftree->route_table_backup); spftree->route_table = NULL; XFREE(MTYPE_ISIS_SPFTREE, spftree); @@ -1886,8 +1886,8 @@ void isis_run_spf(struct isis_spftree *spftree) * Flexible-Algorithm. */ if (flex_algo_id_valid(spftree->algorithm) && - !isis_flex_algo_elected_supported(spftree->algorithm, - spftree->area)) { + !flex_algo_get_state(spftree->area->flex_algos, + spftree->algorithm)) { if (!CHECK_FLAG(spftree->flags, F_SPFTREE_DISABLED)) { isis_spftree_clear(spftree); SET_FLAG(spftree->flags, F_SPFTREE_DISABLED); diff --git a/isisd/isisd.c b/isisd/isisd.c index 4b01a18ecd..ea304ba5ef 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -520,6 +520,10 @@ void isis_area_destroy(struct isis_area *area) isis_area_invalidate_routes(area, area->is_type); isis_area_verify_routes(area); +#ifndef FABRICD + flex_algos_free(area->flex_algos); +#endif /* ifndef FABRICD */ + isis_sr_area_term(area); isis_mpls_te_term(area); diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c index dcaf1cc10b..3c5a5d9991 100644 --- a/ldpd/labelmapping.c +++ b/ldpd/labelmapping.c @@ -47,12 +47,11 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) while ((me = TAILQ_FIRST(mh)) != NULL) { /* generate pdu */ if (first) { - if ((buf = ibuf_open(nbr->max_pdu_len + - LDP_HDR_DEAD_LEN)) == NULL) + if ((buf = ibuf_open(nbr->max_pdu_len + LDP_HDR_DEAD_LEN)) == NULL) fatal(__func__); /* real size will be set up later */ - err |= gen_ldp_hdr(buf, 0); + SET_FLAG(err, gen_ldp_hdr(buf, 0)); size = LDP_HDR_SIZE; first = 0; @@ -63,9 +62,9 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) msg_size += len_fec_tlv(&me->map); if (me->map.label != NO_LABEL) msg_size += LABEL_TLV_SIZE; - if (me->map.flags & F_MAP_REQ_ID) + if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID)) msg_size += REQID_TLV_SIZE; - if (me->map.flags & F_MAP_STATUS) + if (CHECK_FLAG(me->map.flags, F_MAP_STATUS)) msg_size += STATUS_SIZE; /* maximum pdu length exceeded, we need a new ldp pdu */ @@ -78,17 +77,17 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) size += msg_size; /* append message and tlvs */ - err |= gen_msg_hdr(buf, type, msg_size); - err |= gen_fec_tlv(buf, &me->map); + SET_FLAG(err, gen_msg_hdr(buf, type, msg_size)); + SET_FLAG(err, gen_fec_tlv(buf, &me->map)); if (me->map.label != NO_LABEL) - err |= gen_label_tlv(buf, me->map.label); - if (me->map.flags & F_MAP_REQ_ID) - err |= gen_reqid_tlv(buf, me->map.requestid); - if (me->map.flags & F_MAP_PW_STATUS) - err |= gen_pw_status_tlv(buf, me->map.pw_status); - if (me->map.flags & F_MAP_STATUS) - err |= gen_status_tlv(buf, me->map.st.status_code, - me->map.st.msg_id, me->map.st.msg_type); + SET_FLAG(err, gen_label_tlv(buf, me->map.label)); + if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID)) + SET_FLAG(err, gen_reqid_tlv(buf, me->map.requestid)); + if (CHECK_FLAG(me->map.flags, F_MAP_PW_STATUS)) + SET_FLAG(err, gen_pw_status_tlv(buf, me->map.pw_status)); + if (CHECK_FLAG(me->map.flags, F_MAP_STATUS)) + SET_FLAG(err, gen_status_tlv(buf, me->map.st.status_code, + me->map.st.msg_id, me->map.st.msg_type)); if (err) { ibuf_free(buf); mapping_list_clr(mh); @@ -172,15 +171,13 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) memset(&map, 0, sizeof(map)); map.msg_id = msg.id; - if ((tlen = tlv_decode_fec_elm(nbr, &msg, buf, feclen, - &map)) == -1) + if ((tlen = tlv_decode_fec_elm(nbr, &msg, buf, feclen, &map)) == -1) goto err; if (map.type == MAP_TYPE_PWID && - !(map.flags & F_MAP_PW_ID) && + !CHECK_FLAG(map.flags, F_MAP_PW_ID) && type != MSG_TYPE_LABELWITHDRAW && type != MSG_TYPE_LABELRELEASE) { - send_notification(nbr->tcp, S_MISS_MSG, msg.id, - msg.type); + send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type); goto err; } @@ -193,8 +190,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) case MSG_TYPE_LABELMAPPING: case MSG_TYPE_LABELREQUEST: case MSG_TYPE_LABELABORTREQ: - session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, - msg.type); + session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, msg.type); goto err; default: break; @@ -211,8 +207,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) switch (type) { case MSG_TYPE_LABELMAPPING: case MSG_TYPE_LABELABORTREQ: - session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, - msg.type); + session_shutdown(nbr, S_UNKNOWN_FEC, msg.id, msg.type); goto err; default: break; @@ -223,8 +218,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) * LDP supports the use of multiple FEC Elements per * FEC for the Label Mapping message only. */ - if (type != MSG_TYPE_LABELMAPPING && - tlen != feclen) { + if (type != MSG_TYPE_LABELMAPPING && tlen != feclen) { session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; } @@ -262,10 +256,10 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) * For Label Mapping messages the Label TLV is mandatory and * should appear right after the FEC TLV. */ - if (current_tlv == 1 && type == MSG_TYPE_LABELMAPPING && - !(tlv_type & TLV_TYPE_GENERICLABEL)) { - send_notification(nbr->tcp, S_MISS_MSG, msg.id, - msg.type); + if (current_tlv == 1 && + type == MSG_TYPE_LABELMAPPING && + !CHECK_FLAG(tlv_type, TLV_TYPE_GENERICLABEL)) { + send_notification(nbr->tcp, S_MISS_MSG, msg.id, msg.type); goto err; } @@ -275,12 +269,11 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) case MSG_TYPE_LABELMAPPING: case MSG_TYPE_LABELREQUEST: if (tlv_len != REQID_TLV_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type); goto err; } - flags |= F_MAP_REQ_ID; + SET_FLAG(flags, F_MAP_REQ_ID); memcpy(&reqbuf, buf, sizeof(reqbuf)); reqid = ntohl(reqbuf); break; @@ -299,8 +292,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) case MSG_TYPE_LABELWITHDRAW: case MSG_TYPE_LABELRELEASE: if (tlv_len != LABEL_TLV_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type); goto err; } @@ -312,8 +304,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) label != MPLS_LABEL_IPV4_EXPLICIT_NULL && label != MPLS_LABEL_IPV6_EXPLICIT_NULL && label != MPLS_LABEL_IMPLICIT_NULL)) { - session_shutdown(nbr, S_BAD_TLV_VAL, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; } break; @@ -329,8 +320,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) case MSG_TYPE_LABELWITHDRAW: case MSG_TYPE_LABELRELEASE: /* unsupported */ - session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, - msg.type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; break; default: @@ -340,8 +330,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) break; case TLV_TYPE_STATUS: if (tlv_len != STATUS_TLV_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, - msg.type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type); goto err; } /* ignore */ @@ -350,12 +339,11 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) switch (type) { case MSG_TYPE_LABELMAPPING: if (tlv_len != PW_STATUS_TLV_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type); goto err; } - flags |= F_MAP_PW_STATUS; + SET_FLAG(flags, F_MAP_PW_STATUS); memcpy(&statusbuf, buf, sizeof(statusbuf)); pw_status = ntohl(statusbuf); break; @@ -365,7 +353,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) } break; default: - if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) + if (!CHECK_FLAG(ntohs(tlv.type), UNKNOWN_FLAG)) send_notification_rtlvs(nbr, S_UNKNOWN_TLV, msg.id, msg.type, tlv_type, tlv_len, buf); /* ignore unknown tlv */ @@ -380,14 +368,13 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) while ((me = TAILQ_FIRST(&mh)) != NULL) { int imsg_type = IMSG_NONE; - me->map.flags |= flags; + SET_FLAG(me->map.flags, flags); switch (me->map.type) { case MAP_TYPE_PREFIX: switch (me->map.fec.prefix.af) { case AF_INET: if (label == MPLS_LABEL_IPV6_EXPLICIT_NULL) { - session_shutdown(nbr, S_BAD_TLV_VAL, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; } if (!nbr->v4_enabled) @@ -395,8 +382,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) break; case AF_INET6: if (label == MPLS_LABEL_IPV4_EXPLICIT_NULL) { - session_shutdown(nbr, S_BAD_TLV_VAL, - msg.id, msg.type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; } if (!nbr->v6_enabled) @@ -408,18 +394,17 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) break; case MAP_TYPE_PWID: if (label <= MPLS_LABEL_RESERVED_MAX) { - session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, - msg.type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type); goto err; } - if (me->map.flags & F_MAP_PW_STATUS) + if (CHECK_FLAG(me->map.flags, F_MAP_PW_STATUS)) me->map.pw_status = pw_status; break; default: break; } me->map.label = label; - if (me->map.flags & F_MAP_REQ_ID) + if (CHECK_FLAG(me->map.flags, F_MAP_REQ_ID)) me->map.requestid = reqid; log_msg_mapping(0, type, nbr, &me->map); @@ -513,11 +498,11 @@ len_fec_tlv(struct map *map) break; case MAP_TYPE_PWID: len += FEC_PWID_ELM_MIN_LEN; - if (map->flags & F_MAP_PW_ID) + if (CHECK_FLAG(map->flags, F_MAP_PW_ID)) len += PW_STATUS_TLV_LEN; - if (map->flags & F_MAP_PW_IFMTU) + if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) len += FEC_SUBTLV_IFMTU_SIZE; - if (map->flags & F_MAP_PW_STATUS) + if (CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) len += PW_STATUS_TLV_SIZE; break; case MAP_TYPE_TYPED_WCARD: @@ -552,15 +537,15 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) switch (map->type) { case MAP_TYPE_WILDCARD: ft.length = htons(sizeof(uint8_t)); - err |= ibuf_add(buf, &ft, sizeof(ft)); - err |= ibuf_add(buf, &map->type, sizeof(map->type)); + SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft))); + SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(map->type))); break; case MAP_TYPE_PREFIX: len = PREFIX_SIZE(map->fec.prefix.prefixlen); ft.length = htons(sizeof(map->type) + sizeof(family) + sizeof(map->fec.prefix.prefixlen) + len); - err |= ibuf_add(buf, &ft, sizeof(ft)); - err |= ibuf_add(buf, &map->type, sizeof(map->type)); + SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft))); + SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(map->type))); switch (map->fec.prefix.af) { case AF_INET: family = htons(AF_IPV4); @@ -572,45 +557,45 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) fatalx("gen_fec_tlv: unknown af"); break; } - err |= ibuf_add(buf, &family, sizeof(family)); - err |= ibuf_add(buf, &map->fec.prefix.prefixlen, - sizeof(map->fec.prefix.prefixlen)); + SET_FLAG(err, ibuf_add(buf, &family, sizeof(family))); + SET_FLAG(err, ibuf_add(buf, &map->fec.prefix.prefixlen, + sizeof(map->fec.prefix.prefixlen))); if (len) - err |= ibuf_add(buf, &map->fec.prefix.prefix, len); + SET_FLAG(err, ibuf_add(buf, &map->fec.prefix.prefix, len)); break; case MAP_TYPE_PWID: - if (map->flags & F_MAP_PW_ID) + if (CHECK_FLAG(map->flags, F_MAP_PW_ID)) pw_len += FEC_PWID_SIZE; - if (map->flags & F_MAP_PW_IFMTU) + if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) pw_len += FEC_SUBTLV_IFMTU_SIZE; len = FEC_PWID_ELM_MIN_LEN + pw_len; ft.length = htons(len); - err |= ibuf_add(buf, &ft, sizeof(ft)); + SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft))); - err |= ibuf_add(buf, &map->type, sizeof(uint8_t)); + SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(uint8_t))); pw_type = map->fec.pwid.type; - if (map->flags & F_MAP_PW_CWORD) - pw_type |= CONTROL_WORD_FLAG; + if (CHECK_FLAG(map->flags, F_MAP_PW_CWORD)) + SET_FLAG(pw_type, CONTROL_WORD_FLAG); pw_type = htons(pw_type); - err |= ibuf_add(buf, &pw_type, sizeof(uint16_t)); - err |= ibuf_add(buf, &pw_len, sizeof(uint8_t)); + SET_FLAG(err, ibuf_add(buf, &pw_type, sizeof(uint16_t))); + SET_FLAG(err, ibuf_add(buf, &pw_len, sizeof(uint8_t))); group_id = htonl(map->fec.pwid.group_id); - err |= ibuf_add(buf, &group_id, sizeof(uint32_t)); - if (map->flags & F_MAP_PW_ID) { + SET_FLAG(err, ibuf_add(buf, &group_id, sizeof(uint32_t))); + if (CHECK_FLAG(map->flags, F_MAP_PW_ID)) { pwid = htonl(map->fec.pwid.pwid); - err |= ibuf_add(buf, &pwid, sizeof(uint32_t)); + SET_FLAG(err, ibuf_add(buf, &pwid, sizeof(uint32_t))); } - if (map->flags & F_MAP_PW_IFMTU) { + if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) { struct subtlv stlv; stlv.type = SUBTLV_IFMTU; stlv.length = FEC_SUBTLV_IFMTU_SIZE; - err |= ibuf_add(buf, &stlv, sizeof(uint16_t)); + SET_FLAG(err, ibuf_add(buf, &stlv, sizeof(uint16_t))); ifmtu = htons(map->fec.pwid.ifmtu); - err |= ibuf_add(buf, &ifmtu, sizeof(uint16_t)); + SET_FLAG(err, ibuf_add(buf, &ifmtu, sizeof(uint16_t))); } break; case MAP_TYPE_TYPED_WCARD: @@ -624,14 +609,14 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) fatalx("gen_fec_tlv: unexpected fec type"); } ft.length = htons(len); - err |= ibuf_add(buf, &ft, sizeof(ft)); - err |= ibuf_add(buf, &map->type, sizeof(uint8_t)); - err |= ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t)); + SET_FLAG(err, ibuf_add(buf, &ft, sizeof(ft))); + SET_FLAG(err, ibuf_add(buf, &map->type, sizeof(uint8_t))); + SET_FLAG(err, ibuf_add(buf, &map->fec.twcard.type, sizeof(uint8_t))); switch (map->fec.twcard.type) { case MAP_TYPE_PREFIX: twcard_len = sizeof(uint16_t); - err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t)); + SET_FLAG(err, ibuf_add(buf, &twcard_len, sizeof(uint8_t))); switch (map->fec.twcard.u.prefix_af) { case AF_INET: @@ -645,13 +630,13 @@ gen_fec_tlv(struct ibuf *buf, struct map *map) break; } - err |= ibuf_add(buf, &family, sizeof(uint16_t)); + SET_FLAG(err, ibuf_add(buf, &family, sizeof(uint16_t))); break; case MAP_TYPE_PWID: twcard_len = sizeof(uint16_t); - err |= ibuf_add(buf, &twcard_len, sizeof(uint8_t)); + SET_FLAG(err, ibuf_add(buf, &twcard_len, sizeof(uint8_t))); pw_type = htons(map->fec.twcard.u.pw_type); - err |= ibuf_add(buf, &pw_type, sizeof(uint16_t)); + SET_FLAG(err, ibuf_add(buf, &pw_type, sizeof(uint16_t))); break; default: fatalx("gen_fec_tlv: unexpected fec type"); @@ -679,21 +664,18 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, if (len == FEC_ELM_WCARD_LEN) return (off); else { - session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type); return (-1); } break; case MAP_TYPE_PREFIX: if (len < FEC_ELM_PREFIX_MIN_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } /* Address Family */ - memcpy(&map->fec.prefix.af, buf + off, - sizeof(map->fec.prefix.af)); + memcpy(&map->fec.prefix.af, buf + off, sizeof(map->fec.prefix.af)); off += sizeof(map->fec.prefix.af); map->fec.prefix.af = ntohs(map->fec.prefix.af); switch (map->fec.prefix.af) { @@ -704,8 +686,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, map->fec.prefix.af = AF_INET6; break; default: - send_notification(nbr->tcp, S_UNSUP_ADDR, msg->id, - msg->type); + send_notification(nbr->tcp, S_UNSUP_ADDR, msg->id, msg->type); return (-1); } @@ -716,19 +697,16 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, && map->fec.prefix.prefixlen > IPV4_MAX_BITLEN) || (map->fec.prefix.af == AF_IPV6 && map->fec.prefix.prefixlen > IPV6_MAX_BITLEN)) { - session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type); return (-1); } if (len < off + PREFIX_SIZE(map->fec.prefix.prefixlen)) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } /* Prefix */ - memset(&map->fec.prefix.prefix, 0, - sizeof(map->fec.prefix.prefix)); + memset(&map->fec.prefix.prefix, 0, sizeof(map->fec.prefix.prefix)); memcpy(&map->fec.prefix.prefix, buf + off, PREFIX_SIZE(map->fec.prefix.prefixlen)); @@ -739,17 +717,16 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, return (off + PREFIX_SIZE(map->fec.prefix.prefixlen)); case MAP_TYPE_PWID: if (len < FEC_PWID_ELM_MIN_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } /* PW type */ memcpy(&map->fec.pwid.type, buf + off, sizeof(uint16_t)); map->fec.pwid.type = ntohs(map->fec.pwid.type); - if (map->fec.pwid.type & CONTROL_WORD_FLAG) { - map->flags |= F_MAP_PW_CWORD; - map->fec.pwid.type &= ~CONTROL_WORD_FLAG; + if (CHECK_FLAG(map->fec.pwid.type, CONTROL_WORD_FLAG)) { + SET_FLAG(map->flags, F_MAP_PW_CWORD); + UNSET_FLAG(map->fec.pwid.type, CONTROL_WORD_FLAG); } off += sizeof(uint16_t); @@ -758,8 +735,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, off += sizeof(uint8_t); if (len != FEC_PWID_ELM_MIN_LEN + pw_len) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } @@ -773,14 +749,13 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, return (off); if (pw_len < sizeof(uint32_t)) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } memcpy(&map->fec.pwid.pwid, buf + off, sizeof(uint32_t)); map->fec.pwid.pwid = ntohl(map->fec.pwid.pwid); - map->flags |= F_MAP_PW_ID; + SET_FLAG(map->flags, F_MAP_PW_ID); off += sizeof(uint32_t); pw_len -= sizeof(uint32_t); @@ -789,29 +764,26 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, struct subtlv stlv; if (pw_len < sizeof(stlv)) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } memcpy(&stlv, buf + off, sizeof(stlv)); if (stlv.length > pw_len) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } switch (stlv.type) { case SUBTLV_IFMTU: if (stlv.length != FEC_SUBTLV_IFMTU_SIZE) { - session_shutdown(nbr, S_BAD_TLV_LEN, - msg->id, msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } memcpy(&map->fec.pwid.ifmtu, buf + off + SUBTLV_HDR_SIZE, sizeof(uint16_t)); map->fec.pwid.ifmtu = ntohs(map->fec.pwid.ifmtu); - map->flags |= F_MAP_PW_IFMTU; + SET_FLAG(map->flags, F_MAP_PW_IFMTU); break; default: /* ignore */ @@ -824,8 +796,7 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, return (off); case MAP_TYPE_TYPED_WCARD: if (len < FEC_ELM_TWCARD_MIN_LEN) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } @@ -834,23 +805,19 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, memcpy(&twcard_len, buf + off, sizeof(uint8_t)); off += sizeof(uint8_t); if (len != FEC_ELM_TWCARD_MIN_LEN + twcard_len) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } switch (map->fec.twcard.type) { case MAP_TYPE_PREFIX: if (twcard_len != sizeof(uint16_t)) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } - memcpy(&map->fec.twcard.u.prefix_af, buf + off, - sizeof(uint16_t)); - map->fec.twcard.u.prefix_af = - ntohs(map->fec.twcard.u.prefix_af); + memcpy(&map->fec.twcard.u.prefix_af, buf + off, sizeof(uint16_t)); + map->fec.twcard.u.prefix_af = ntohs(map->fec.twcard.u.prefix_af); off += sizeof(uint16_t); switch (map->fec.twcard.u.prefix_af) { @@ -861,29 +828,24 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, map->fec.twcard.u.prefix_af = AF_INET6; break; default: - session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_VAL, msg->id, msg->type); return (-1); } break; case MAP_TYPE_PWID: if (twcard_len != sizeof(uint16_t)) { - session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, - msg->type); + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, msg->type); return (-1); } - memcpy(&map->fec.twcard.u.pw_type, buf + off, - sizeof(uint16_t)); - map->fec.twcard.u.pw_type = - ntohs(map->fec.twcard.u.pw_type); + memcpy(&map->fec.twcard.u.pw_type, buf + off, sizeof(uint16_t)); + map->fec.twcard.u.pw_type = ntohs(map->fec.twcard.u.pw_type); /* ignore the reserved bit as per RFC 6667 */ map->fec.twcard.u.pw_type &= ~PW_TWCARD_RESERVED_BIT; off += sizeof(uint16_t); break; default: - send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, - msg->type); + send_notification(nbr->tcp, S_UNKNOWN_FEC, msg->id, msg->type); return (-1); } diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 470580ff5e..cb6b8986b8 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -47,11 +47,9 @@ fec_compare(const struct fec *a, const struct fec *b) switch (a->type) { case FEC_TYPE_IPV4: - if (ntohl(a->u.ipv4.prefix.s_addr) < - ntohl(b->u.ipv4.prefix.s_addr)) + if (ntohl(a->u.ipv4.prefix.s_addr) < ntohl(b->u.ipv4.prefix.s_addr)) return (-1); - if (ntohl(a->u.ipv4.prefix.s_addr) > - ntohl(b->u.ipv4.prefix.s_addr)) + if (ntohl(a->u.ipv4.prefix.s_addr) > ntohl(b->u.ipv4.prefix.s_addr)) return (1); if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen) return (-1); @@ -79,11 +77,9 @@ fec_compare(const struct fec *a, const struct fec *b) return (-1); if (a->u.pwid.pwid > b->u.pwid.pwid) return (1); - if (ntohl(a->u.pwid.lsr_id.s_addr) < - ntohl(b->u.pwid.lsr_id.s_addr)) + if (ntohl(a->u.pwid.lsr_id.s_addr) < ntohl(b->u.pwid.lsr_id.s_addr)) return (-1); - if (ntohl(a->u.pwid.lsr_id.s_addr) > - ntohl(b->u.pwid.lsr_id.s_addr)) + if (ntohl(a->u.pwid.lsr_id.s_addr) > ntohl(b->u.pwid.lsr_id.s_addr)) return (1); return (0); } @@ -261,8 +257,7 @@ fec_add(struct fec *fec) fn->pw_remote_status = PW_FORWARDING; if (fec_insert(&ft, &fn->fec)) - log_warnx("failed to add %s to ft tree", - log_fec(&fn->fec)); + log_warnx("failed to add %s to ft tree", log_fec(&fn->fec)); return (fn); } @@ -338,14 +333,14 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, * installing in kernel and sending to peer */ iface = if_lookup(ldeconf, ifindex); - if ((ldeconf->flags & F_LDPD_ORDERED_CONTROL) && + if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL) && !connected && iface != NULL && fec->type != FEC_TYPE_PWID) - fnh->flags |= F_FEC_NH_DEFER; + SET_FLAG(fnh->flags, F_FEC_NH_DEFER); } - fnh->flags |= F_FEC_NH_NEW; + SET_FLAG(fnh->flags, F_FEC_NH_NEW); if (connected) - fnh->flags |= F_FEC_NH_CONNECTED; + SET_FLAG(fnh->flags, F_FEC_NH_CONNECTED); } void @@ -388,22 +383,22 @@ lde_kernel_update(struct fec *fec) return; LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) { - if (fnh->flags & F_FEC_NH_NEW) { - fnh->flags &= ~F_FEC_NH_NEW; + if (CHECK_FLAG(fnh->flags, F_FEC_NH_NEW)) { + UNSET_FLAG(fnh->flags, F_FEC_NH_NEW); /* * if LDP configured on interface or a static route * clear flag else treat fec as a connected route */ - if (ldeconf->flags & F_LDPD_ENABLED) { + if (CHECK_FLAG(ldeconf->flags, F_LDPD_ENABLED)) { iface = if_lookup(ldeconf,fnh->ifindex); - if (fnh->flags & F_FEC_NH_CONNECTED || + if (CHECK_FLAG(fnh->flags, F_FEC_NH_CONNECTED) || iface || fnh->route_type == ZEBRA_ROUTE_STATIC) - fnh->flags &=~F_FEC_NH_NO_LDP; + UNSET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); else - fnh->flags |= F_FEC_NH_NO_LDP; + SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); } else - fnh->flags |= F_FEC_NH_NO_LDP; + SET_FLAG(fnh->flags, F_FEC_NH_NO_LDP); } else { lde_send_delete_klabel(fn, fnh); fec_nh_del(fnh); @@ -510,7 +505,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) /* RFC 4447 control word and status tlv negotiation */ if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map)) { - if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS) + if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) fn->pw_remote_status = map->pw_status; return; @@ -534,8 +529,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) * the possibility of multipath. */ LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (lde_address_find(ln, fnh->af, - &fnh->nexthop) == NULL) + if (lde_address_find(ln, fnh->af, &fnh->nexthop) == NULL) continue; lde_send_delete_klabel(fn, fnh); @@ -561,9 +555,9 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) * NH so clear flag and send labelmap msg to * peer */ - if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { send_map = true; - fnh->flags &= ~F_FEC_NH_DEFER; + UNSET_FLAG(fnh->flags, F_FEC_NH_DEFER); } fnh->remote_label = map->label; if (fn->local_label != NO_LABEL) @@ -575,9 +569,9 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping) continue; pw->remote_group = map->fec.pwid.group_id; - if (map->flags & F_MAP_PW_IFMTU) + if (CHECK_FLAG(map->flags, F_MAP_PW_IFMTU)) pw->remote_mtu = map->fec.pwid.ifmtu; - if (rcvd_label_mapping && map->flags & F_MAP_PW_STATUS) { + if (rcvd_label_mapping && CHECK_FLAG(map->flags, F_MAP_PW_STATUS)) { pw->remote_status = map->pw_status; fn->pw_remote_status = map->pw_status; } @@ -726,7 +720,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln) /* wildcard label release */ if (map->type == MAP_TYPE_WILDCARD || map->type == MAP_TYPE_TYPED_WCARD || - (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) { + (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) { lde_check_release_wcard(map, ln); return; } @@ -818,7 +812,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln) /* wildcard label withdraw */ if (map->type == MAP_TYPE_WILDCARD || map->type == MAP_TYPE_TYPED_WCARD || - (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) { + (map->type == MAP_TYPE_PWID && !CHECK_FLAG(map->flags, F_MAP_PW_ID))) { lde_check_withdraw_wcard(map, ln); return; } @@ -868,7 +862,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln) return; /* Ordered Control: additional withdraw steps */ - if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { /* LWd.8: for each neighbor other that src of withdraw msg */ RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { if (ln->peerid == lnbr->peerid) @@ -929,8 +923,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) default: break; } - if (map->label != NO_LABEL && map->label != - fnh->remote_label) + if (map->label != NO_LABEL && map->label != fnh->remote_label) continue; lde_send_delete_klabel(fn, fnh); @@ -941,8 +934,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) lde_rlfa_update_clients(f, ln, MPLS_INVALID_LABEL); /* LWd.3: check previously received label mapping */ - if (me && (map->label == NO_LABEL || - map->label == me->map.label)) + if (me && (map->label == NO_LABEL || map->label == me->map.label)) /* * LWd.4: remove record of previously received * label mapping @@ -953,7 +945,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) continue; /* Ordered Control: additional withdraw steps */ - if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + if (CHECK_FLAG(ldeconf->flags, F_LDPD_ORDERED_CONTROL)) { /* * LWd.8: for each neighbor other that src of * withdraw msg @@ -965,16 +957,14 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) /* LWd.9: check if previously sent a label * mapping */ - me = (struct lde_map *)fec_find( - &lnbr->sent_map, &fn->fec); + me = (struct lde_map *)fec_find(&lnbr->sent_map, &fn->fec); /* * LWd.10: does label sent to peer "map" to * withdraw label */ if (me && lde_nbr_is_nexthop(fn, lnbr)) /* LWd.11: send label withdraw */ - lde_send_labelwithdraw(lnbr, fn, NULL, - NULL); + lde_send_labelwithdraw(lnbr, fn, NULL, NULL); } } } diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index d3193b16d7..e66b9e92dd 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -257,8 +257,7 @@ ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data, { if (iev_lde->ibuf.fd == -1) return (0); - return (imsg_compose_event(iev_lde, type, peerid, pid, -1, - data, datalen)); + return (imsg_compose_event(iev_lde, type, peerid, pid, -1, data, datalen)); } /* ARGSUSED */ @@ -309,8 +308,7 @@ static void ldpe_dispatch_main(struct event *thread) switch (imsg.hdr.type) { case IMSG_IFSTATUS: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct kif)) + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kif)) fatalx("IFSTATUS imsg with wrong len"); kif = imsg.data; @@ -336,15 +334,13 @@ static void ldpe_dispatch_main(struct event *thread) } break; case IMSG_NEWADDR: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct kaddr)) + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr)) fatalx("NEWADDR imsg with wrong len"); if_addr_add(imsg.data); break; case IMSG_DELADDR: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct kaddr)) + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kaddr)) fatalx("DELADDR imsg with wrong len"); if_addr_del(imsg.data); @@ -369,8 +365,7 @@ static void ldpe_dispatch_main(struct event *thread) iev_lde->ev_write = NULL; break; case IMSG_INIT: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct ldpd_init)) + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldpd_init)) fatalx("INIT imsg with wrong len"); memcpy(&init, imsg.data, sizeof(init)); @@ -398,14 +393,11 @@ static void ldpe_dispatch_main(struct event *thread) disc_socket = -1; edisc_socket = -1; session_socket = -1; - if ((ldp_af_conf_get(leconf, af))->flags & - F_LDPD_AF_ENABLED) - ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, - af, NULL, 0); + if (CHECK_FLAG((ldp_af_conf_get(leconf, af))->flags, F_LDPD_AF_ENABLED)) + ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, af, NULL, 0); break; case IMSG_SOCKET_NET: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(enum socket_type)) + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(enum socket_type)) fatalx("SOCKET_NET imsg with wrong len"); socket_type = imsg.data; @@ -434,15 +426,13 @@ static void ldpe_dispatch_main(struct event *thread) break; } - ldpe_setup_sockets(af, disc_socket, edisc_socket, - session_socket); + ldpe_setup_sockets(af, disc_socket, edisc_socket, session_socket); if_update_all(af); tnbr_update_all(af); RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { if (nbr->af != af) continue; - nbr->laddr = (ldp_af_conf_get(leconf, - af))->trans_addr; + nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr; #ifdef __OpenBSD__ nbrp = nbr_params_find(leconf, nbr->id); if (nbrp) { @@ -456,8 +446,7 @@ static void ldpe_dispatch_main(struct event *thread) } break; case IMSG_RTRID_UPDATE: - memcpy(&global.rtr_id, imsg.data, - sizeof(global.rtr_id)); + memcpy(&global.rtr_id, imsg.data, sizeof(global.rtr_id)); if (leconf->rtr_id.s_addr == INADDR_ANY) { ldpe_reset_nbrs(AF_UNSPEC); } @@ -465,8 +454,7 @@ static void ldpe_dispatch_main(struct event *thread) tnbr_update_all(AF_UNSPEC); break; case IMSG_RECONF_CONF: - if ((nconf = malloc(sizeof(struct ldpd_conf))) == - NULL) + if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); @@ -546,16 +534,13 @@ static void ldpe_dispatch_main(struct event *thread) memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug)); break; case IMSG_FILTER_UPDATE: - if (imsg.hdr.len != IMSG_HEADER_SIZE + - sizeof(struct ldp_access)) { + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ldp_access)) { log_warnx("%s: wrong imsg len", __func__); break; } laccess = imsg.data; - ldpe_check_filter_af(AF_INET, &leconf->ipv4, - laccess->name); - ldpe_check_filter_af(AF_INET6, &leconf->ipv6, - laccess->name); + ldpe_check_filter_af(AF_INET, &leconf->ipv4, laccess->name); + ldpe_check_filter_af(AF_INET6, &leconf->ipv6, laccess->name); break; case IMSG_LDP_SYNC_IF_STATE_REQUEST: if (imsg.hdr.len != IMSG_HEADER_SIZE + @@ -605,8 +590,7 @@ static void ldpe_dispatch_main(struct event *thread) } break; default: - log_debug("%s: error handling imsg %d", - __func__, imsg.hdr.type); + log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); break; } imsg_free(&imsg); @@ -650,8 +634,7 @@ static void ldpe_dispatch_lde(struct event *thread) case IMSG_RELEASE_ADD: case IMSG_REQUEST_ADD: case IMSG_WITHDRAW_ADD: - if (imsg.hdr.len - IMSG_HEADER_SIZE != - sizeof(struct map)) + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct map)) fatalx("invalid size of map request"); map = imsg.data; @@ -706,8 +689,7 @@ static void ldpe_dispatch_lde(struct event *thread) } break; case IMSG_NOTIFICATION_SEND: - if (imsg.hdr.len - IMSG_HEADER_SIZE != - sizeof(struct notify_msg)) + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct notify_msg)) fatalx("invalid size of OE request"); nm = imsg.data; @@ -741,8 +723,7 @@ static void ldpe_dispatch_lde(struct event *thread) session_shutdown(nbr,S_SHUTDOWN,0,0); break; default: - log_debug("%s: error handling imsg %d", - __func__, imsg.hdr.type); + log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); break; } imsg_free(&imsg); @@ -860,7 +841,7 @@ ldpe_remove_dynamic_tnbrs(int af) if (tnbr->af != af) continue; - tnbr->flags &= ~F_TNBR_DYNAMIC; + UNSET_FLAG(tnbr->flags, F_TNBR_DYNAMIC); tnbr_check(leconf, tnbr); } } diff --git a/lib/command.c b/lib/command.c index 97ea200ff4..7a7ce3f5dc 100644 --- a/lib/command.c +++ b/lib/command.c @@ -31,6 +31,8 @@ #include "jhash.h" #include "hook.h" #include "lib_errors.h" +#include "mgmt_be_client.h" +#include "mgmt_fe_client.h" #include "northbound_cli.h" #include "network.h" #include "routemap.h" @@ -1301,6 +1303,14 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) while (fgets(vty->buf, VTY_BUFSIZ, fp)) { ++(*line_num); + if (vty_log_commands) { + int len = strlen(vty->buf); + + /* now log the command */ + zlog_notice("config-from-file# %.*s", len ? len - 1 : 0, + vty->buf); + } + ret = command_config_read_one_line(vty, NULL, *line_num, 0); if (ret != CMD_SUCCESS && ret != CMD_WARNING @@ -2438,6 +2448,8 @@ const char *host_config_get(void) void cmd_show_lib_debugs(struct vty *vty) { route_map_show_debug(vty); + mgmt_debug_be_client_show_debug(vty); + mgmt_debug_fe_client_show_debug(vty); } void install_default(enum node_type node) diff --git a/lib/flex_algo.c b/lib/flex_algo.c index bafbf8b779..f48117ff1b 100644 --- a/lib/flex_algo.c +++ b/lib/flex_algo.c @@ -17,26 +17,42 @@ #include "flex_algo.h" -DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo Definition"); +DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO_DATABASE, "Flex-Algo database"); +DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo algorithm information"); + +static void _flex_algo_delete(struct flex_algos *flex_algos, + struct flex_algo *fa); struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator, flex_algo_releaser_t releaser) { struct flex_algos *flex_algos; - flex_algos = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*flex_algos)); + flex_algos = + XCALLOC(MTYPE_FLEX_ALGO_DATABASE, sizeof(struct flex_algos)); flex_algos->flex_algos = list_new(); flex_algos->allocator = allocator; flex_algos->releaser = releaser; return flex_algos; } +void flex_algos_free(struct flex_algos *flex_algos) +{ + struct listnode *node, *nnode; + struct flex_algo *fa; + + for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) + _flex_algo_delete(flex_algos, fa); + list_delete(&flex_algos->flex_algos); + XFREE(MTYPE_FLEX_ALGO_DATABASE, flex_algos); +} + struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, uint8_t algorithm, void *arg) { struct flex_algo *fa; - fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*fa)); + fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct flex_algo)); fa->algorithm = algorithm; if (flex_algos->allocator) fa->data = flex_algos->allocator(arg); @@ -47,6 +63,31 @@ struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, return fa; } +static void _flex_algo_delete(struct flex_algos *flex_algos, + struct flex_algo *fa) +{ + if (flex_algos->releaser) + flex_algos->releaser(fa->data); + admin_group_term(&fa->admin_group_exclude_any); + admin_group_term(&fa->admin_group_include_any); + admin_group_term(&fa->admin_group_include_all); + listnode_delete(flex_algos->flex_algos, fa); + XFREE(MTYPE_FLEX_ALGO, fa); +} + + +void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm) +{ + struct listnode *node, *nnode; + struct flex_algo *fa; + + for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) { + if (fa->algorithm != algorithm) + continue; + _flex_algo_delete(flex_algos, fa); + } +} + /** * @brief Look up the local flex-algo object by its algorithm number. * @param algorithm flex-algo algorithm number @@ -79,6 +120,12 @@ bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2) return false; if (fa1->metric_type != fa2->metric_type) return false; + if (fa1->exclude_srlg != fa2->exclude_srlg) + return false; + if (fa1->flags != fa2->flags) + return false; + if (fa1->unsupported_subtlv != fa2->unsupported_subtlv) + return false; if (!admin_group_cmp(&fa1->admin_group_exclude_any, &fa2->admin_group_exclude_any)) @@ -93,25 +140,6 @@ bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2) return true; } -void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm) -{ - struct listnode *node, *nnode; - struct flex_algo *fa; - - for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) { - if (fa->algorithm != algorithm) - continue; - if (flex_algos->releaser) - flex_algos->releaser(fa->data); - admin_group_term(&fa->admin_group_exclude_any); - admin_group_term(&fa->admin_group_include_any); - admin_group_term(&fa->admin_group_include_all); - listnode_delete(flex_algos->flex_algos, fa); - XFREE(MTYPE_FLEX_ALGO, fa); - return; - } -} - /** * Check SR Algorithm is Flex-Algo * according to RFC9350 section 4 @@ -140,3 +168,24 @@ char *flex_algo_metric_type_print(char *type_str, size_t sz, } return type_str; } + +bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm) +{ + struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm); + + if (!fa) + return false; + + return fa->state; +} + +void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm, + bool state) +{ + struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm); + + if (!fa) + return; + + fa->state = state; +} diff --git a/lib/flex_algo.h b/lib/flex_algo.h index e012f46862..e617e7cae8 100644 --- a/lib/flex_algo.h +++ b/lib/flex_algo.h @@ -83,6 +83,11 @@ struct flex_algo { #define FLEX_ALGO_IP 0x04 uint8_t dataplanes; + /* True if the Algorithm is locally enabled (ie. a definition has been + * found and is supported). + */ + bool state; + /* * This property can be freely extended among different routing * protocols. Since Flex-Algo is an IGP protocol agnostic, both IS-IS @@ -107,6 +112,7 @@ struct flex_algos { */ struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator, flex_algo_releaser_t releaser); +void flex_algos_free(struct flex_algos *flex_algos); struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, uint8_t algorithm, void *arg); struct flex_algo *flex_algo_lookup(struct flex_algos *flex_algos, @@ -118,4 +124,8 @@ bool flex_algo_id_valid(uint16_t algorithm); char *flex_algo_metric_type_print(char *type_str, size_t sz, enum flex_algo_metric_type metric_type); +bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm); + +void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm, + bool state); #endif /* _FRR_FLEX_ALGO_H */ diff --git a/lib/link_state.c b/lib/link_state.c index 752030cd47..58727a568b 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -497,7 +497,6 @@ void ls_vertex_del(struct ls_ted *ted, struct ls_vertex *vertex) /* Then remove Vertex from Link State Data Base and free memory */ vertices_del(&ted->vertices, vertex); XFREE(MTYPE_LS_DB, vertex); - vertex = NULL; } void ls_vertex_del_all(struct ls_ted *ted, struct ls_vertex *vertex) @@ -956,7 +955,10 @@ struct ls_subnet *ls_find_subnet(struct ls_ted *ted, { struct ls_subnet subnet = {}; - subnet.key = *prefix; + if (!prefix) + return NULL; + + prefix_copy(&subnet.key, prefix); return subnets_find(&ted->subnets, &subnet); } @@ -1779,9 +1781,10 @@ struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg, case LS_MSG_EVENT_DELETE: vertex = ls_find_vertex_by_id(ted, node->adv); if (vertex) { - if (delete) + if (delete) { ls_vertex_del_all(ted, vertex); - else + vertex = NULL; + } else vertex->status = DELETE; } break; @@ -1858,9 +1861,10 @@ struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg, case LS_MSG_EVENT_DELETE: subnet = ls_find_subnet(ted, &pref->pref); if (subnet) { - if (delete) + if (delete) { ls_subnet_del_all(ted, subnet); - else + subnet = NULL; + } else subnet->status = DELETE; } break; diff --git a/lib/log_vty.c b/lib/log_vty.c index fc28ffc6fa..26e608d16b 100644 --- a/lib/log_vty.c +++ b/lib/log_vty.c @@ -34,18 +34,23 @@ static int log_cmdline_syslog_lvl = ZLOG_DISABLED; static struct zlog_cfg_file zt_file_cmdline = { .prio_min = ZLOG_DISABLED, + .ts_subsec = LOG_TIMESTAMP_PRECISION, }; static struct zlog_cfg_file zt_file = { .prio_min = ZLOG_DISABLED, + .ts_subsec = LOG_TIMESTAMP_PRECISION, }; static struct zlog_cfg_filterfile zt_filterfile = { - .parent = { - .prio_min = ZLOG_DISABLED, - }, + .parent = + { + .prio_min = ZLOG_DISABLED, + .ts_subsec = LOG_TIMESTAMP_PRECISION, + }, }; static struct zlog_cfg_file zt_stdout_file = { .prio_min = ZLOG_DISABLED, + .ts_subsec = LOG_TIMESTAMP_PRECISION, }; static struct zlog_cfg_5424 zt_stdout_journald = { .prio_min = ZLOG_DISABLED, diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index 7437eedfc7..9427f7cf3d 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -6,29 +6,25 @@ */ #include <zebra.h> +#include "debug.h" #include "libfrr.h" #include "mgmtd/mgmt.h" #include "mgmt_be_client.h" #include "mgmt_msg.h" #include "mgmt_pb.h" #include "network.h" +#include "northbound.h" #include "stream.h" #include "sockopt.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ +#include "lib/mgmt_be_client_clippy.c" + #define MGMTD_BE_CLIENT_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_be_client) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) + DEBUGD(&mgmt_dbg_be_client, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_BE_CLIENT_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ +#define MGMTD_DBG_BE_CLIENT_CHECK() \ + DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_ALL) DEFINE_MTYPE_STATIC(LIB, MGMTD_BE_BATCH, "MGMTD backend transaction batch data"); @@ -118,8 +114,6 @@ struct mgmt_be_client_ctx { struct nb_config *candidate_config; struct nb_config *running_config; - unsigned long num_batch_find; - unsigned long avg_batch_find_tm; unsigned long num_edit_nb_cfg; unsigned long avg_edit_nb_cfg_tm; unsigned long num_prep_nb_cfg; @@ -136,7 +130,7 @@ struct mgmt_be_client_ctx { #define FOREACH_BE_TXN_IN_LIST(client_ctx, txn) \ frr_each_safe (mgmt_be_txns, &(client_ctx)->txn_head, (txn)) -static bool mgmt_debug_be_client; +struct debug mgmt_dbg_be_client = {0, "Management backend client operations"}; static struct mgmt_be_client_ctx mgmt_be_client_ctx = { .conn_fd = -1, @@ -479,7 +473,6 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) bool error; char err_buf[BUFSIZ]; size_t num_processed; - bool debug_be = mgmt_debug_be_client; int err; assert(txn && txn->client_ctx); @@ -499,8 +492,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) * interested in validating it. */ error = false; - if (debug_be) - gettimeofday(&edit_nb_cfg_start, NULL); + + gettimeofday(&edit_nb_cfg_start, NULL); nb_candidate_edit_config_changes( client_ctx->candidate_config, txn_req->req.set_cfg.cfg_changes, @@ -516,16 +509,14 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) err_buf); return -1; } - if (debug_be) { - gettimeofday(&edit_nb_cfg_end, NULL); - edit_nb_cfg_tm = timeval_elapsed( - edit_nb_cfg_end, edit_nb_cfg_start); - client_ctx->avg_edit_nb_cfg_tm = - ((client_ctx->avg_edit_nb_cfg_tm - * client_ctx->num_edit_nb_cfg) - + edit_nb_cfg_tm) - / (client_ctx->num_edit_nb_cfg + 1); - } + gettimeofday(&edit_nb_cfg_end, NULL); + edit_nb_cfg_tm = timeval_elapsed(edit_nb_cfg_end, + edit_nb_cfg_start); + client_ctx->avg_edit_nb_cfg_tm = + ((client_ctx->avg_edit_nb_cfg_tm * + client_ctx->num_edit_nb_cfg) + + edit_nb_cfg_tm) / + (client_ctx->num_edit_nb_cfg + 1); client_ctx->num_edit_nb_cfg++; } @@ -540,8 +531,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) */ nb_ctx.client = NB_CLIENT_CLI; nb_ctx.user = (void *)client_ctx->client_params.user_data; - if (debug_be) - gettimeofday(&prep_nb_cfg_start, NULL); + + gettimeofday(&prep_nb_cfg_start, NULL); err = nb_candidate_commit_prepare(nb_ctx, client_ctx->candidate_config, "MGMTD Backend Txn", &txn->nb_txn, #ifdef MGMTD_LOCAL_VALIDATIONS_ENABLED @@ -569,16 +560,13 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) "Prepared configs for Txn %llx, %u Batches! successfully!", (unsigned long long)txn->txn_id, (uint32_t)num_processed); - if (debug_be) { - gettimeofday(&prep_nb_cfg_end, NULL); - prep_nb_cfg_tm = - timeval_elapsed(prep_nb_cfg_end, prep_nb_cfg_start); - client_ctx->avg_prep_nb_cfg_tm = - ((client_ctx->avg_prep_nb_cfg_tm - * client_ctx->num_prep_nb_cfg) - + prep_nb_cfg_tm) - / (client_ctx->num_prep_nb_cfg + 1); - } + + gettimeofday(&prep_nb_cfg_end, NULL); + prep_nb_cfg_tm = timeval_elapsed(prep_nb_cfg_end, prep_nb_cfg_start); + client_ctx->avg_prep_nb_cfg_tm = ((client_ctx->avg_prep_nb_cfg_tm * + client_ctx->num_prep_nb_cfg) + + prep_nb_cfg_tm) / + (client_ctx->num_prep_nb_cfg + 1); client_ctx->num_prep_nb_cfg++; FOREACH_BE_TXN_BATCH_IN_LIST (txn, batch) { @@ -593,12 +581,10 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) } } - if (debug_be) - MGMTD_BE_CLIENT_DBG( - "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u", - client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm, - client_ctx->avg_prep_nb_cfg_tm, - (uint32_t)num_processed); + MGMTD_BE_CLIENT_DBG( + "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u", + client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm, + client_ctx->avg_prep_nb_cfg_tm, (uint32_t)num_processed); if (error) mgmt_be_txn_cfg_abort(txn); @@ -736,7 +722,6 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn) char err_buf[BUFSIZ]; size_t num_processed; static uint64_t batch_ids[MGMTD_BE_MAX_BATCH_IDS_IN_REQ]; - bool debug_be = mgmt_debug_be_client; assert(txn && txn->client_ctx); client_ctx = txn->client_ctx; @@ -747,20 +732,16 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn) /* * Now apply all the batches we have applied in one go. */ - if (debug_be) - gettimeofday(&apply_nb_cfg_start, NULL); + gettimeofday(&apply_nb_cfg_start, NULL); (void)nb_candidate_commit_apply(txn->nb_txn, true, &txn->nb_txn_id, err_buf, sizeof(err_buf) - 1); - if (debug_be) { - gettimeofday(&apply_nb_cfg_end, NULL); - apply_nb_cfg_tm = - timeval_elapsed(apply_nb_cfg_end, apply_nb_cfg_start); - client_ctx->avg_apply_nb_cfg_tm = - ((client_ctx->avg_apply_nb_cfg_tm - * client_ctx->num_apply_nb_cfg) - + apply_nb_cfg_tm) - / (client_ctx->num_apply_nb_cfg + 1); - } + gettimeofday(&apply_nb_cfg_end, NULL); + + apply_nb_cfg_tm = timeval_elapsed(apply_nb_cfg_end, apply_nb_cfg_start); + client_ctx->avg_apply_nb_cfg_tm = ((client_ctx->avg_apply_nb_cfg_tm * + client_ctx->num_apply_nb_cfg) + + apply_nb_cfg_tm) / + (client_ctx->num_apply_nb_cfg + 1); client_ctx->num_apply_nb_cfg++; txn->nb_txn = NULL; @@ -789,10 +770,8 @@ static int mgmt_be_txn_proc_cfgapply(struct mgmt_be_txn_ctx *txn) mgmt_be_send_apply_reply(client_ctx, txn->txn_id, batch_ids, num_processed, true, NULL); - if (debug_be) - MGMTD_BE_CLIENT_DBG("Nb-apply-duration %lu (avg: %lu) uSec", - apply_nb_cfg_tm, - client_ctx->avg_apply_nb_cfg_tm); + MGMTD_BE_CLIENT_DBG("Nb-apply-duration %lu (avg: %lu) uSec", + apply_nb_cfg_tm, client_ctx->avg_apply_nb_cfg_tm); return 0; } @@ -903,7 +882,7 @@ static void mgmt_be_client_proc_msgbufs(struct event *thread) struct mgmt_be_client_ctx *client_ctx = EVENT_ARG(thread); if (mgmt_msg_procbufs(&client_ctx->mstate, mgmt_be_client_process_msg, - client_ctx, mgmt_debug_be_client)) + client_ctx, MGMTD_DBG_BE_CLIENT_CHECK())) mgmt_be_client_register_event(client_ctx, MGMTD_BE_PROC_MSG); } @@ -913,7 +892,7 @@ static void mgmt_be_client_read(struct event *thread) enum mgmt_msg_rsched rv; rv = mgmt_msg_read(&client_ctx->mstate, client_ctx->conn_fd, - mgmt_debug_be_client); + MGMTD_DBG_BE_CLIENT_CHECK()); if (rv == MSR_DISCONNECT) { mgmt_be_server_disconnect(client_ctx, true); return; @@ -958,7 +937,7 @@ static int mgmt_be_client_send_msg(struct mgmt_be_client_ctx *client_ctx, &client_ctx->mstate, be_msg, mgmtd__be_message__get_packed_size(be_msg), (size_t(*)(void *, void *))mgmtd__be_message__pack, - mgmt_debug_be_client); + MGMTD_DBG_BE_CLIENT_CHECK()); mgmt_be_client_sched_msg_write(client_ctx); return rv; } @@ -969,7 +948,7 @@ static void mgmt_be_client_write(struct event *thread) enum mgmt_msg_wsched rv; rv = mgmt_msg_write(&client_ctx->mstate, client_ctx->conn_fd, - mgmt_debug_be_client); + MGMTD_DBG_BE_CLIENT_CHECK()); if (rv == MSW_SCHED_STREAM) mgmt_be_client_register_event(client_ctx, MGMTD_BE_CONN_WRITE); else if (rv == MSW_DISCONNECT) @@ -1017,7 +996,7 @@ static int mgmt_be_send_subscr_req(struct mgmt_be_client_ctx *client_ctx, static void mgmt_be_server_connect(struct mgmt_be_client_ctx *client_ctx) { - const char *dbgtag = mgmt_debug_be_client ? "BE-client" : NULL; + const char *dbgtag = MGMTD_DBG_BE_CLIENT_CHECK() ? "BE-client" : NULL; assert(client_ctx->conn_fd == -1); client_ctx->conn_fd = mgmt_msg_connect( @@ -1097,7 +1076,47 @@ mgmt_be_client_schedule_conn_retry(struct mgmt_be_client_ctx *client_ctx, &client_ctx->conn_retry_tmr); } -extern struct nb_config *running_config; +DEFPY(debug_mgmt_client_be, debug_mgmt_client_be_cmd, + "[no] debug mgmt client backend", + NO_STR DEBUG_STR MGMTD_STR + "client\n" + "backend\n") +{ + uint32_t mode = DEBUG_NODE2MODE(vty->node); + + DEBUG_MODE_SET(&mgmt_dbg_be_client, mode, !no); + + return CMD_SUCCESS; +} + +static void mgmt_debug_client_be_set_all(uint32_t flags, bool set) +{ + DEBUG_FLAGS_SET(&mgmt_dbg_be_client, flags, set); +} + +static int mgmt_debug_be_client_config_write(struct vty *vty) +{ + if (DEBUG_MODE_CHECK(&mgmt_dbg_be_client, DEBUG_MODE_CONF)) + vty_out(vty, "debug mgmt client frontend\n"); + + return 1; +} + +void mgmt_debug_be_client_show_debug(struct vty *vty) +{ + if (MGMTD_DBG_BE_CLIENT_CHECK()) + vty_out(vty, "debug mgmt client backend\n"); +} + +static struct debug_callbacks mgmt_dbg_be_client_cbs = { + .debug_set_all = mgmt_debug_client_be_set_all}; + +static struct cmd_node mgmt_dbg_node = { + .name = "mgmt backend client", + .node = DEBUG_NODE, + .prompt = "", + .config_write = mgmt_debug_be_client_config_write, +}; /* * Initialize library and try connecting with MGMTD. @@ -1134,6 +1153,16 @@ uintptr_t mgmt_be_client_lib_init(struct mgmt_be_client_params *params, return (uintptr_t)&mgmt_be_client_ctx; } + +void mgmt_be_client_lib_vty_init(void) +{ + debug_init(&mgmt_dbg_be_client_cbs); + install_node(&mgmt_dbg_node); + install_element(ENABLE_NODE, &debug_mgmt_client_be_cmd); + install_element(CONFIG_NODE, &debug_mgmt_client_be_cmd); +} + + /* * Subscribe with MGMTD for one or more YANG subtree(s). */ diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h index db427457a4..d4f2d86fdf 100644 --- a/lib/mgmt_be_client.h +++ b/lib/mgmt_be_client.h @@ -192,6 +192,20 @@ extern uintptr_t mgmt_be_client_lib_init(struct mgmt_be_client_params *params, struct event_loop *master_thread); /* + * Initialize library vty (adds debug support). + * + * This call should be added to your component when enabling other vty code to + * enable mgmtd client debugs. When adding, one needs to also add a their + * component in `xref2vtysh.py` as well. + */ +extern void mgmt_be_client_lib_vty_init(void); + +/* + * Print enabled debugging commands. + */ +extern void mgmt_debug_be_client_show_debug(struct vty *vty); + +/* * Subscribe with MGMTD for one or more YANG subtree(s). * * lib_hndl diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index 7cb9aa3def..b8266bfa82 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -6,6 +6,7 @@ */ #include <zebra.h> +#include "debug.h" #include "memory.h" #include "libfrr.h" #include "mgmt_fe_client.h" @@ -15,20 +16,14 @@ #include "stream.h" #include "sockopt.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_FE_CLIENT_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_FE_CLIENT_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_FE_CLIENT_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_fe_client) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) -#define MGMTD_FE_CLIENT_ERR(fmt, ...) \ +#include "lib/mgmt_fe_client_clippy.c" + +#define MGMTD_FE_CLIENT_DBG(fmt, ...) \ + DEBUGD(&mgmt_dbg_fe_client, "%s:" fmt, __func__, ##__VA_ARGS__) +#define MGMTD_FE_CLIENT_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ +#define MGMTD_DBG_FE_CLIENT_CHECK() \ + DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_ALL) struct mgmt_fe_client_ctx; @@ -69,7 +64,7 @@ struct mgmt_fe_client_ctx { #define FOREACH_SESSION_IN_LIST(client_ctx, session) \ frr_each_safe (mgmt_sessions, &(client_ctx)->client_sessions, (session)) -static bool mgmt_debug_fe_client; +struct debug mgmt_dbg_fe_client = {0, "Management frontend client operations"}; static struct mgmt_fe_client_ctx mgmt_fe_client_ctx = { .conn_fd = -1, @@ -169,7 +164,7 @@ static int mgmt_fe_client_send_msg(struct mgmt_fe_client_ctx *client_ctx, &client_ctx->mstate, fe_msg, mgmtd__fe_message__get_packed_size(fe_msg), (size_t(*)(void *, void *))mgmtd__fe_message__pack, - mgmt_debug_fe_client); + MGMTD_DBG_FE_CLIENT_CHECK()); mgmt_fe_client_sched_msg_write(client_ctx); return rv; } @@ -181,7 +176,7 @@ static void mgmt_fe_client_write(struct event *thread) client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread); rv = mgmt_msg_write(&client_ctx->mstate, client_ctx->conn_fd, - mgmt_debug_fe_client); + MGMTD_DBG_FE_CLIENT_CHECK()); if (rv == MSW_SCHED_STREAM) mgmt_fe_client_register_event(client_ctx, MGMTD_FE_CONN_WRITE); else if (rv == MSW_DISCONNECT) @@ -679,7 +674,7 @@ static void mgmt_fe_client_proc_msgbufs(struct event *thread) client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread); if (mgmt_msg_procbufs(&client_ctx->mstate, mgmt_fe_client_process_msg, - client_ctx, mgmt_debug_fe_client)) + client_ctx, MGMTD_DBG_FE_CLIENT_CHECK())) mgmt_fe_client_register_event(client_ctx, MGMTD_FE_PROC_MSG); } @@ -691,7 +686,7 @@ static void mgmt_fe_client_read(struct event *thread) client_ctx = (struct mgmt_fe_client_ctx *)EVENT_ARG(thread); rv = mgmt_msg_read(&client_ctx->mstate, client_ctx->conn_fd, - mgmt_debug_fe_client); + MGMTD_DBG_FE_CLIENT_CHECK()); if (rv == MSR_DISCONNECT) { mgmt_fe_server_disconnect(client_ctx, true); return; @@ -703,7 +698,7 @@ static void mgmt_fe_client_read(struct event *thread) static void mgmt_fe_server_connect(struct mgmt_fe_client_ctx *client_ctx) { - const char *dbgtag = mgmt_debug_fe_client ? "FE-client" : NULL; + const char *dbgtag = MGMTD_DBG_FE_CLIENT_CHECK() ? "FE-client" : NULL; assert(client_ctx->conn_fd == -1); client_ctx->conn_fd = mgmt_msg_connect( @@ -779,6 +774,48 @@ static void mgmt_fe_client_schedule_conn_retry( &client_ctx->conn_retry_tmr); } +DEFPY(debug_mgmt_client_fe, debug_mgmt_client_fe_cmd, + "[no] debug mgmt client frontend", + NO_STR DEBUG_STR MGMTD_STR + "client\n" + "frontend\n") +{ + uint32_t mode = DEBUG_NODE2MODE(vty->node); + + DEBUG_MODE_SET(&mgmt_dbg_fe_client, mode, !no); + + return CMD_SUCCESS; +} + +static void mgmt_debug_client_fe_set_all(uint32_t flags, bool set) +{ + DEBUG_FLAGS_SET(&mgmt_dbg_fe_client, flags, set); +} + +static int mgmt_debug_fe_client_config_write(struct vty *vty) +{ + if (DEBUG_MODE_CHECK(&mgmt_dbg_fe_client, DEBUG_MODE_CONF)) + vty_out(vty, "debug mgmt client frontend\n"); + + return CMD_SUCCESS; +} + +void mgmt_debug_fe_client_show_debug(struct vty *vty) +{ + if (MGMTD_DBG_FE_CLIENT_CHECK()) + vty_out(vty, "debug mgmt client frontend\n"); +} + +static struct debug_callbacks mgmt_dbg_fe_client_cbs = { + .debug_set_all = mgmt_debug_client_fe_set_all}; + +static struct cmd_node mgmt_dbg_node = { + .name = "mgmt client frontend", + .node = DEBUG_NODE, + .prompt = "", + .config_write = mgmt_debug_fe_client_config_write, +}; + /* * Initialize library and try connecting with MGMTD. */ @@ -809,6 +846,14 @@ uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params, return (uintptr_t)&mgmt_fe_client_ctx; } +void mgmt_fe_client_lib_vty_init(void) +{ + debug_init(&mgmt_dbg_fe_client_cbs); + install_node(&mgmt_dbg_node); + install_element(ENABLE_NODE, &debug_mgmt_client_fe_cmd); + install_element(CONFIG_NODE, &debug_mgmt_client_fe_cmd); +} + /* * Create a new Session for a Frontend Client connection. */ diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h index aa3371f03c..94867787d9 100644 --- a/lib/mgmt_fe_client.h +++ b/lib/mgmt_fe_client.h @@ -134,6 +134,20 @@ extern uintptr_t mgmt_fe_client_lib_init(struct mgmt_fe_client_params *params, struct event_loop *master_thread); /* + * Initialize library vty (adds debug support). + * + * This call should be added to your component when enabling other vty code to + * enable mgmtd client debugs. When adding, one needs to also add a their + * component in `xref2vtysh.py` as well. + */ +extern void mgmt_fe_client_lib_vty_init(void); + +/* + * Print enabled debugging commands. + */ +extern void mgmt_debug_fe_client_show_debug(struct vty *vty); + +/* * Create a new Session for a Frontend Client connection. * * lib_hndl diff --git a/lib/subdir.am b/lib/subdir.am index 7ae82d5a69..c046c3c43c 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -179,6 +179,8 @@ clippy_scan += \ lib/filter_cli.c \ lib/if_rmap.c \ lib/log_vty.c \ + lib/mgmt_be_client.c \ + lib/mgmt_fe_client.c \ lib/nexthop_group.c \ lib/northbound_cli.c \ lib/plist.c \ @@ -125,8 +125,8 @@ static int no_password_check = 0; /* Integrated configuration file path */ static char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; -static bool do_log_commands; -static bool do_log_commands_perm; +bool vty_log_commands; +static bool vty_log_commands_perm; void vty_mgmt_resume_response(struct vty *vty, bool success) { @@ -508,7 +508,7 @@ static int vty_command(struct vty *vty, char *buf) /* * Log non empty command lines */ - if (do_log_commands && + if (vty_log_commands && strncmp(buf, "echo PING", strlen("echo PING")) != 0) cp = buf; if (cp != NULL) { @@ -3160,15 +3160,15 @@ DEFPY (log_commands, "Log all commands\n") { if (no) { - if (do_log_commands_perm) { + if (vty_log_commands_perm) { vty_out(vty, "Daemon started with permanent logging turned on for commands, ignoring\n"); return CMD_WARNING; } - do_log_commands = false; + vty_log_commands = false; } else - do_log_commands = true; + vty_log_commands = true; return CMD_SUCCESS; } @@ -3196,7 +3196,7 @@ static int vty_config_write(struct vty *vty) vty_endframe(vty, "exit\n"); - if (do_log_commands) + if (vty_log_commands) vty_out(vty, "log commands\n"); vty_out(vty, "!\n"); @@ -3677,8 +3677,8 @@ void vty_init(struct event_loop *master_thread, bool do_command_logging) install_element(CONFIG_NODE, &log_commands_cmd); if (do_command_logging) { - do_log_commands = true; - do_log_commands_perm = true; + vty_log_commands = true; + vty_log_commands_perm = true; } install_element(ENABLE_NODE, &terminal_monitor_cmd); @@ -335,6 +335,7 @@ struct vty_arg { #endif extern struct nb_config *vty_mgmt_candidate_config; +extern bool vty_log_commands; /* Prototypes. */ extern void vty_init(struct event_loop *m, bool do_command_logging); diff --git a/mgmtd/mgmt.c b/mgmtd/mgmt.c index a5c0eb34a3..7a65a19f55 100644 --- a/mgmtd/mgmt.c +++ b/mgmtd/mgmt.c @@ -7,6 +7,7 @@ */ #include <zebra.h> +#include "debug.h" #include "mgmtd/mgmt.h" #include "mgmtd/mgmt_be_server.h" #include "mgmtd/mgmt_be_adapter.h" @@ -16,10 +17,10 @@ #include "mgmtd/mgmt_history.h" #include "mgmtd/mgmt_memory.h" -bool mgmt_debug_be; -bool mgmt_debug_fe; -bool mgmt_debug_ds; -bool mgmt_debug_txn; +struct debug mgmt_debug_be = {.desc = "Management backend adapater"}; +struct debug mgmt_debug_ds = {.desc = "Management datastore"}; +struct debug mgmt_debug_fe = {.desc = "Management frontend adapater"}; +struct debug mgmt_debug_txn = {.desc = "Management transaction"}; /* MGMTD process wide configuration. */ static struct mgmt_master mgmt_master; diff --git a/mgmtd/mgmt.h b/mgmtd/mgmt.h index 9579b02230..603296bb38 100644 --- a/mgmtd/mgmt.h +++ b/mgmtd/mgmt.h @@ -9,6 +9,7 @@ #ifndef _FRR_MGMTD_H #define _FRR_MGMTD_H +#include "debug.h" #include "vrf.h" #include "defaults.h" #include "stream.h" @@ -23,10 +24,15 @@ #define MGMTD_SOCKET_BUF_SIZE 65535 #define MGMTD_MAX_COMMIT_LIST 10 -extern bool mgmt_debug_be; -extern bool mgmt_debug_fe; -extern bool mgmt_debug_ds; -extern bool mgmt_debug_txn; +extern struct debug mgmt_debug_be; +extern struct debug mgmt_debug_ds; +extern struct debug mgmt_debug_fe; +extern struct debug mgmt_debug_txn; + +#define MGMT_DEBUG_BE_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL) +#define MGMT_DEBUG_DS_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_ds, DEBUG_MODE_ALL) +#define MGMT_DEBUG_FE_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_fe, DEBUG_MODE_ALL) +#define MGMT_DEBUG_TXN_CHECK() DEBUG_MODE_CHECK(&mgmt_debug_tx, DEBUG_MODE_ALL) struct mgmt_txn_ctx; @@ -102,16 +108,4 @@ extern void mgmt_master_init(struct event_loop *master, const int buffer_size); extern void mgmt_init(void); extern void mgmt_vty_init(void); -static inline char *mgmt_realtime_to_string(struct timeval *tv, char *buf, - size_t sz) -{ - struct tm tm; - size_t n; - - localtime_r((const time_t *)&tv->tv_sec, &tm); - n = strftime(buf, sz, "%Y-%m-%dT%H:%M:%S", &tm); - snprintf(&buf[n], sz - n, ",%06u000", (unsigned int)tv->tv_usec); - return buf; -} - #endif /* _FRR_MGMTD_H */ diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index cf7d705943..9d210b8716 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -18,20 +18,10 @@ #include "mgmt_be_client.h" #include "mgmtd/mgmt_be_adapter.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_BE_ADAPTER_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_be) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) +#define MGMTD_BE_ADAPTER_DBG(fmt, ...) \ + DEBUGD(&mgmt_debug_be, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_BE_ADAPTER_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ #define FOREACH_ADAPTER_IN_LIST(adapter) \ frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter)) @@ -521,7 +511,7 @@ static int mgmt_be_adapter_send_msg(struct mgmt_be_client_adapter *adapter, &adapter->mstate, be_msg, mgmtd__be_message__get_packed_size(be_msg), (size_t(*)(void *, void *))mgmtd__be_message__pack, - mgmt_debug_be); + MGMT_DEBUG_BE_CHECK()); mgmt_be_adapter_sched_msg_write(adapter); return rv; } @@ -619,7 +609,7 @@ static void mgmt_be_adapter_proc_msgbufs(struct event *thread) struct mgmt_be_client_adapter *adapter = EVENT_ARG(thread); if (mgmt_msg_procbufs(&adapter->mstate, mgmt_be_adapter_process_msg, - adapter, mgmt_debug_be)) + adapter, MGMT_DEBUG_BE_CHECK())) mgmt_be_adapter_register_event(adapter, MGMTD_BE_PROC_MSG); } @@ -630,7 +620,8 @@ static void mgmt_be_adapter_read(struct event *thread) adapter = (struct mgmt_be_client_adapter *)EVENT_ARG(thread); - rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, mgmt_debug_be); + rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, + MGMT_DEBUG_BE_CHECK()); if (rv == MSR_DISCONNECT) { mgmt_be_adapter_disconnect(adapter); return; @@ -645,7 +636,8 @@ static void mgmt_be_adapter_write(struct event *thread) struct mgmt_be_client_adapter *adapter = EVENT_ARG(thread); enum mgmt_msg_wsched rv; - rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, mgmt_debug_be); + rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, + MGMT_DEBUG_BE_CHECK()); if (rv == MSW_SCHED_STREAM) mgmt_be_adapter_register_event(adapter, MGMTD_BE_CONN_WRITE); else if (rv == MSW_DISCONNECT) diff --git a/mgmtd/mgmt_be_server.c b/mgmtd/mgmt_be_server.c index aa77464524..029e032feb 100644 --- a/mgmtd/mgmt_be_server.c +++ b/mgmtd/mgmt_be_server.c @@ -13,20 +13,10 @@ #include "mgmtd/mgmt_be_server.h" #include "mgmtd/mgmt_be_adapter.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_BE_SRVR_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_BE_SRVR_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ #define MGMTD_BE_SRVR_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_be) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) + DEBUGD(&mgmt_debug_be, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_BE_SRVR_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ static int mgmt_be_listen_fd = -1; static struct event_loop *mgmt_be_listen_tm; diff --git a/mgmtd/mgmt_ds.c b/mgmtd/mgmt_ds.c index 05a67a89cd..b5eaf7bff6 100644 --- a/mgmtd/mgmt_ds.c +++ b/mgmtd/mgmt_ds.c @@ -15,20 +15,10 @@ #include "mgmtd/mgmt_txn.h" #include "libyang/libyang.h" -#ifdef REDIRECT_DEBUG_TO_STDERR #define MGMTD_DS_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_DS_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_DS_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_ds) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) + DEBUGD(&mgmt_debug_ds, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_DS_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ struct mgmt_ds_ctx { Mgmtd__DatastoreId ds_id; diff --git a/mgmtd/mgmt_ds.h b/mgmtd/mgmt_ds.h index 8d01f3d5b1..2a32eb641a 100644 --- a/mgmtd/mgmt_ds.h +++ b/mgmtd/mgmt_ds.h @@ -28,12 +28,9 @@ for ((id) = MGMTD_DS_NONE; (id) < MGMTD_DS_MAX_ID; (id)++) #define MGMTD_MAX_COMMIT_LIST 10 -#define MGMTD_MD5_HASH_LEN 16 -#define MGMTD_MD5_HASH_STR_HEX_LEN 33 #define MGMTD_COMMIT_FILE_PATH DAEMON_DB_DIR "/commit-%s.json" #define MGMTD_COMMIT_INDEX_FILE_NAME DAEMON_DB_DIR "/commit-index.dat" -#define MGMTD_COMMIT_TIME_STR_LEN 100 extern struct nb_config *running_config; diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index 90e6870fd4..262741b665 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -19,20 +19,10 @@ #include "mgmtd/mgmt_memory.h" #include "mgmtd/mgmt_fe_adapter.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_FE_ADAPTER_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_fe) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) +#define MGMTD_FE_ADAPTER_DBG(fmt, ...) \ + DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_FE_ADAPTER_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ #define FOREACH_ADAPTER_IN_LIST(adapter) \ frr_each_safe (mgmt_fe_adapters, &mgmt_fe_adapters, (adapter)) @@ -399,7 +389,7 @@ mgmt_fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter, &adapter->mstate, fe_msg, mgmtd__fe_message__get_packed_size(fe_msg), (size_t(*)(void *, void *))mgmtd__fe_message__pack, - mgmt_debug_fe); + MGMT_DEBUG_FE_CHECK()); mgmt_fe_adapter_sched_msg_write(adapter); return rv; } @@ -1439,7 +1429,7 @@ static void mgmt_fe_adapter_proc_msgbufs(struct event *thread) struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread); if (mgmt_msg_procbufs(&adapter->mstate, mgmt_fe_adapter_process_msg, - adapter, mgmt_debug_fe)) + adapter, MGMT_DEBUG_FE_CHECK())) mgmt_fe_adapter_register_event(adapter, MGMTD_FE_PROC_MSG); } @@ -1448,7 +1438,8 @@ static void mgmt_fe_adapter_read(struct event *thread) struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread); enum mgmt_msg_rsched rv; - rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, mgmt_debug_fe); + rv = mgmt_msg_read(&adapter->mstate, adapter->conn_fd, + MGMT_DEBUG_FE_CHECK()); if (rv == MSR_DISCONNECT) { mgmt_fe_adapter_disconnect(adapter); return; @@ -1463,7 +1454,8 @@ static void mgmt_fe_adapter_write(struct event *thread) struct mgmt_fe_client_adapter *adapter = EVENT_ARG(thread); enum mgmt_msg_wsched rv; - rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, mgmt_debug_fe); + rv = mgmt_msg_write(&adapter->mstate, adapter->conn_fd, + MGMT_DEBUG_FE_CHECK()); if (rv == MSW_SCHED_STREAM) mgmt_fe_adapter_register_event(adapter, MGMTD_FE_CONN_WRITE); else if (rv == MSW_DISCONNECT) @@ -1722,7 +1714,7 @@ static void mgmt_fe_adapter_cmt_stats_write(struct vty *vty, struct mgmt_fe_client_adapter *adapter) { - char buf[100] = {0}; + char buf[MGMT_LONG_TIME_MAX_LEN]; if (!mm->perf_stats_en) return; @@ -1803,7 +1795,7 @@ static void mgmt_fe_adapter_setcfg_stats_write(struct vty *vty, struct mgmt_fe_client_adapter *adapter) { - char buf[100] = {0}; + char buf[MGMT_LONG_TIME_MAX_LEN]; if (!mm->perf_stats_en) return; diff --git a/mgmtd/mgmt_fe_server.c b/mgmtd/mgmt_fe_server.c index e8bbe139bb..e737e00352 100644 --- a/mgmtd/mgmt_fe_server.c +++ b/mgmtd/mgmt_fe_server.c @@ -13,20 +13,10 @@ #include "mgmtd/mgmt_fe_server.h" #include "mgmtd/mgmt_fe_adapter.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_FE_SRVR_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_FE_SRVR_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ #define MGMTD_FE_SRVR_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_fe) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) + DEBUGD(&mgmt_debug_fe, "%s:" fmt, __func__, ##__VA_ARGS__) #define MGMTD_FE_SRVR_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ static int mgmt_fe_listen_fd = -1; static struct event_loop *mgmt_fe_listen_tm; diff --git a/mgmtd/mgmt_history.c b/mgmtd/mgmt_history.c index 2251c49f1c..a49718a490 100644 --- a/mgmtd/mgmt_history.c +++ b/mgmtd/mgmt_history.c @@ -18,8 +18,8 @@ struct mgmt_cmt_info_t { struct mgmt_cmt_infos_item cmts; - char cmtid_str[MGMTD_MD5_HASH_STR_HEX_LEN]; - char time_str[MGMTD_COMMIT_TIME_STR_LEN]; + char cmtid_str[MGMT_SHORT_TIME_MAX_LEN]; + char time_str[MGMT_LONG_TIME_MAX_LEN]; char cmt_json_file[PATH_MAX]; }; @@ -54,36 +54,30 @@ static void mgmt_history_remove_file(char *name) zlog_err("Old commit info deletion failed"); } -static void mgmt_history_hash(const char *input_str, char *hash) +static struct mgmt_cmt_info_t *mgmt_history_new_cmt_info(void) { - int i; - unsigned char digest[MGMTD_MD5_HASH_LEN]; - MD5_CTX ctx; - - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, input_str, strlen(input_str)); - MD5Final(digest, &ctx); - - for (i = 0; i < MGMTD_MD5_HASH_LEN; i++) - snprintf(&hash[i * 2], MGMTD_MD5_HASH_STR_HEX_LEN, "%02x", - (unsigned int)digest[i]); + struct mgmt_cmt_info_t *new; + struct timespec tv; + struct tm tm; + + new = XCALLOC(MTYPE_MGMTD_CMT_INFO, sizeof(struct mgmt_cmt_info_t)); + + clock_gettime(CLOCK_REALTIME, &tv); + localtime_r(&tv.tv_sec, &tm); + + mgmt_time_to_string(&tv, true, new->time_str, sizeof(new->time_str)); + mgmt_time_to_string(&tv, false, new->cmtid_str, sizeof(new->cmtid_str)); + snprintf(new->cmt_json_file, sizeof(new->cmt_json_file), + MGMTD_COMMIT_FILE_PATH, new->cmtid_str); + + return new; } static struct mgmt_cmt_info_t *mgmt_history_create_cmt_rec(void) { - struct mgmt_cmt_info_t *new; + struct mgmt_cmt_info_t *new = mgmt_history_new_cmt_info(); struct mgmt_cmt_info_t *cmt_info; struct mgmt_cmt_info_t *last_cmt_info = NULL; - struct timeval cmt_recd_tv; - - new = XCALLOC(MTYPE_MGMTD_CMT_INFO, sizeof(struct mgmt_cmt_info_t)); - gettimeofday(&cmt_recd_tv, NULL); - mgmt_realtime_to_string(&cmt_recd_tv, new->time_str, - sizeof(new->time_str)); - mgmt_history_hash(new->time_str, new->cmtid_str); - snprintf(new->cmt_json_file, sizeof(new->cmt_json_file) - 1, - MGMTD_COMMIT_FILE_PATH, new->cmtid_str); if (mgmt_cmt_infos_count(&mm->cmts) == MGMTD_MAX_COMMIT_LIST) { FOREACH_CMT_REC (mm, cmt_info) @@ -106,8 +100,7 @@ mgmt_history_find_cmt_record(const char *cmtid_str) struct mgmt_cmt_info_t *cmt_info; FOREACH_CMT_REC (mm, cmt_info) { - if (strncmp(cmt_info->cmtid_str, cmtid_str, - MGMTD_MD5_HASH_STR_HEX_LEN) == 0) + if (strcmp(cmt_info->cmtid_str, cmtid_str) == 0) return cmt_info; } @@ -282,8 +275,7 @@ int mgmt_history_rollback_by_id(struct vty *vty, const char *cmtid_str) } FOREACH_CMT_REC (mm, cmt_info) { - if (strncmp(cmt_info->cmtid_str, cmtid_str, - MGMTD_MD5_HASH_STR_HEX_LEN) == 0) { + if (strcmp(cmt_info->cmtid_str, cmtid_str) == 0) { ret = mgmt_history_rollback_to_cmt(vty, cmt_info, false); return ret; @@ -349,9 +341,9 @@ void show_mgmt_cmt_history(struct vty *vty) int slno = 0; vty_out(vty, "Last 10 commit history:\n"); - vty_out(vty, " Sl.No\tCommit-ID(HEX)\t\t\t Commit-Record-Time\n"); + vty_out(vty, "Slot Commit-ID Commit-Record-Time\n"); FOREACH_CMT_REC (mm, cmt_info) { - vty_out(vty, " %d\t%s %s\n", slno, cmt_info->cmtid_str, + vty_out(vty, "%4d %23s %s\n", slno, cmt_info->cmtid_str, cmt_info->time_str); slno++; } diff --git a/mgmtd/mgmt_history.h b/mgmtd/mgmt_history.h index 5f96cf90e1..d3f7958952 100644 --- a/mgmtd/mgmt_history.h +++ b/mgmtd/mgmt_history.h @@ -54,4 +54,42 @@ extern void mgmt_history_new_record(struct mgmt_ds_ctx *ds_ctx); extern void mgmt_history_destroy(void); extern void mgmt_history_init(void); +/* + * 012345678901234567890123456789 + * 2023-12-31T12:12:12,012345678 + * 20231231121212012345678 + */ +#define MGMT_LONG_TIME_FMT "%Y-%m-%dT%H:%M:%S" +#define MGMT_LONG_TIME_MAX_LEN 30 +#define MGMT_SHORT_TIME_FMT "%Y%m%d%H%M%S" +#define MGMT_SHORT_TIME_MAX_LEN 24 + +static inline const char * +mgmt_time_to_string(struct timespec *tv, bool long_fmt, char *buffer, size_t sz) +{ + struct tm tm; + size_t n; + + localtime_r(&tv->tv_sec, &tm); + + if (long_fmt) { + n = strftime(buffer, sz, MGMT_LONG_TIME_FMT, &tm); + snprintf(&buffer[n], sz - n, ",%09lu", tv->tv_nsec); + } else { + n = strftime(buffer, sz, MGMT_SHORT_TIME_FMT, &tm); + snprintf(&buffer[n], sz - n, "%09lu", tv->tv_nsec); + } + + return buffer; +} + +static inline const char *mgmt_realtime_to_string(struct timeval *tv, char *buf, + size_t sz) +{ + struct timespec ts = {.tv_sec = tv->tv_sec, + .tv_nsec = tv->tv_usec * 1000}; + + return mgmt_time_to_string(&ts, true, buf, sz); +} + #endif /* _FRR_MGMTD_HISTORY_H_ */ diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index 05844653ce..ad4a4e31f4 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -14,20 +14,10 @@ #include "mgmtd/mgmt_memory.h" #include "mgmtd/mgmt_txn.h" -#ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_TXN_DBG(fmt, ...) \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_TXN_ERR(fmt, ...) \ - fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) -#else /* REDIRECT_DEBUG_TO_STDERR */ #define MGMTD_TXN_DBG(fmt, ...) \ - do { \ - if (mgmt_debug_txn) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ - } while (0) -#define MGMTD_TXN_ERR(fmt, ...) \ + DEBUGD(&mgmt_debug_txn, "%s:" fmt, __func__, ##__VA_ARGS__) +#define MGMTD_TXN_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) -#endif /* REDIRECT_DEBUG_TO_STDERR */ #define MGMTD_TXN_LOCK(txn) mgmt_txn_lock(txn, __FILE__, __LINE__) #define MGMTD_TXN_UNLOCK(txn) mgmt_txn_unlock(txn, __FILE__, __LINE__) diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index fa34d90c75..7d133d522f 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -380,7 +380,7 @@ DEFPY(mgmt_rollback, return CMD_SUCCESS; } -static int config_write_mgmt_debug(struct vty *vty); +int config_write_mgmt_debug(struct vty *vty); static struct cmd_node debug_node = { .name = "debug", .node = DEBUG_NODE, @@ -388,27 +388,25 @@ static struct cmd_node debug_node = { .config_write = config_write_mgmt_debug, }; -static int config_write_mgmt_debug_helper(struct vty *vty, bool config) +static int write_mgmt_debug_helper(struct vty *vty, bool config) { - int n = mgmt_debug_be + mgmt_debug_fe + mgmt_debug_ds + mgmt_debug_txn; + uint32_t mode = config ? DEBUG_MODE_CONF : DEBUG_MODE_ALL; + bool be = DEBUG_MODE_CHECK(&mgmt_debug_be, mode); + bool ds = DEBUG_MODE_CHECK(&mgmt_debug_ds, mode); + bool fe = DEBUG_MODE_CHECK(&mgmt_debug_fe, mode); + bool txn = DEBUG_MODE_CHECK(&mgmt_debug_txn, mode); - if (!n) + if (!(be || ds || fe || txn)) return 0; - if (config && mgmt_debug_be && mgmt_debug_fe && mgmt_debug_ds && - mgmt_debug_txn) { - vty_out(vty, "debug mgmt all\n"); - return 0; - } - vty_out(vty, "debug mgmt"); - if (mgmt_debug_be) + if (be) vty_out(vty, " backend"); - if (mgmt_debug_ds) + if (ds) vty_out(vty, " datastore"); - if (mgmt_debug_fe) + if (fe) vty_out(vty, " frontend"); - if (mgmt_debug_txn) + if (txn) vty_out(vty, " transaction"); vty_out(vty, "\n"); @@ -416,17 +414,17 @@ static int config_write_mgmt_debug_helper(struct vty *vty, bool config) return 0; } -static int config_write_mgmt_debug(struct vty *vty) +int config_write_mgmt_debug(struct vty *vty) { - return config_write_mgmt_debug_helper(vty, true); + return write_mgmt_debug_helper(vty, true); } -DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd, +DEFPY_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd, "show debugging [mgmt]", SHOW_STR DEBUG_STR "MGMT Information\n") { vty_out(vty, "MGMT debugging status:\n"); - config_write_mgmt_debug_helper(vty, false); + write_mgmt_debug_helper(vty, false); cmd_show_lib_debugs(vty); @@ -434,27 +432,23 @@ DEFUN_NOSH(show_debugging_mgmt, show_debugging_mgmt_cmd, } DEFPY(debug_mgmt, debug_mgmt_cmd, - "[no$no] debug mgmt <all$all|{backend$be|datastore$ds|frontend$fe|transaction$txn}>", + "[no$no] debug mgmt {backend$be|datastore$ds|frontend$fe|transaction$txn}", NO_STR DEBUG_STR MGMTD_STR - "All debug\n" - "Back-end debug\n" + "Backend debug\n" "Datastore debug\n" - "Front-end debug\n" + "Frontend debug\n" "Transaction debug\n") { - bool set = !no; - - if (all) - be = fe = ds = txn = set ? all : NULL; + uint32_t mode = DEBUG_NODE2MODE(vty->node); if (be) - mgmt_debug_be = set; + DEBUG_MODE_SET(&mgmt_debug_be, mode, !no); if (ds) - mgmt_debug_ds = set; + DEBUG_MODE_SET(&mgmt_debug_ds, mode, !no); if (fe) - mgmt_debug_fe = set; + DEBUG_MODE_SET(&mgmt_debug_fe, mode, !no); if (txn) - mgmt_debug_txn = set; + DEBUG_MODE_SET(&mgmt_debug_txn, mode, !no); return CMD_SUCCESS; } @@ -530,6 +524,7 @@ void mgmt_vty_init(void) install_element(ENABLE_NODE, &show_debugging_mgmt_cmd); + mgmt_fe_client_lib_vty_init(); /* * TODO: Register and handlers for auto-completion here. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 09dd0081eb..1b4d26ef3d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3996,16 +3996,15 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, /* Interface name is specified. */ ifp = if_lookup_by_name(intf_name, ospf->vrf_id); if (ifp == NULL) { - if (use_json) + if (use_json) { json_object_boolean_true_add(json_vrf, "noSuchIface"); - else + json_object_free(json_interface); + } else vty_out(vty, "No such interface name\n"); } else { - if (use_json) { + if (use_json) json_interface_sub = json_object_new_object(); - json_interface = json_object_new_object(); - } show_ip_ospf_interface_sub( vty, ospf, ifp, json_interface_sub, use_json); diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c index 5eedfb7dca..aa39be63db 100644 --- a/pimd/pim6_mld.c +++ b/pimd/pim6_mld.c @@ -344,7 +344,8 @@ static const char *const gm_states[] = { }; /* clang-format on */ -CPP_NOTICE("TODO: S,G entries in EXCLUDE (i.e. prune) unsupported"); +/* TODO: S,G entries in EXCLUDE (i.e. prune) unsupported" */ + /* tib_sg_gm_prune() below is an "un-join", it doesn't prune S,G when *,G is * joined. Whether we actually want/need to support this is a separate * question - it is almost never used. In fact this is exactly what RFC5790 @@ -645,7 +646,7 @@ static void gm_handle_v2_pass1(struct gm_packet_state *pkt, */ gm_packet_sg_drop(old_grp); gm_sg_update(grp, false); - CPP_NOTICE("need S,G PRUNE => NO_INFO transition here"); +/* TODO "need S,G PRUNE => NO_INFO transition here" */ } break; @@ -793,7 +794,8 @@ static void gm_handle_v2_pass2_excl(struct gm_packet_state *pkt, size_t offs) gm_sg_update(sg_grp, false); } -CPP_NOTICE("TODO: QRV/QQIC are not copied from queries to local state"); +/* TODO: QRV/QQIC are not copied from queries to local state" */ + /* on receiving a query, we need to update our robustness/query interval to * match, so we correctly process group/source specific queries after last * member leaves @@ -949,7 +951,8 @@ static void gm_handle_v1_report(struct gm_if *gm_ifp, item = gm_packet_sg_setup(pkt, grp, true, false); item->n_exclude = 0; - CPP_NOTICE("set v1-seen timer on grp here"); + +/* TODO "set v1-seen timer on grp here" */ /* } */ @@ -1012,7 +1015,9 @@ static void gm_handle_v1_leave(struct gm_if *gm_ifp, if (old_grp) { gm_packet_sg_drop(old_grp); gm_sg_update(grp, false); - CPP_NOTICE("need S,G PRUNE => NO_INFO transition here"); + +/* TODO "need S,G PRUNE => NO_INFO transition here" */ + } } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 4d5da31827..b64fcdeb87 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -46,7 +46,7 @@ int pim_mroute_set(struct pim_instance *pim, int enable) /* * We need to create the VRF table for the pim mroute_socket */ - if (pim->vrf->vrf_id != VRF_DEFAULT) { + if (enable && pim->vrf->vrf_id != VRF_DEFAULT) { frr_with_privs (&pimd_privs) { data = pim->vrf->data.l.table_id; diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 3d0ecb1bf4..1cd7cce086 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -29,6 +29,7 @@ #include "pim_jp_agg.h" #include "pim_bfd.h" #include "pim_register.h" +#include "pim_oil.h" static void dr_election_by_addr(struct interface *ifp) { @@ -123,9 +124,10 @@ int pim_if_dr_election(struct interface *ifp) pim_if_update_could_assert(ifp); pim_if_update_assert_tracking_desired(ifp); - if (PIM_I_am_DR(pim_ifp)) + if (PIM_I_am_DR(pim_ifp)) { pim_ifp->am_i_dr = true; - else { + pim_clear_nocache_state(pim_ifp); + } else { if (pim_ifp->am_i_dr == true) { pim_reg_del_on_couldreg_fail(ifp); pim_ifp->am_i_dr = false; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 63ddb85d00..e1ec9b34a1 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -149,6 +149,31 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, return c_oil; } + +/* + * Clean up mroute and channel oil created for dropping pkts from directly + * connected source when the interface was non DR. + */ +void pim_clear_nocache_state(struct pim_interface *pim_ifp) +{ + struct channel_oil *c_oil; + + frr_each_safe (rb_pim_oil, &pim_ifp->pim->channel_oil_head, c_oil) { + + if ((!c_oil->up) || + !(PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(c_oil->up->flags))) + continue; + + if (*oil_parent(c_oil) != pim_ifp->mroute_vif_index) + continue; + + EVENT_OFF(c_oil->up->t_ka_timer); + PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(c_oil->up->flags); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(c_oil->up->flags); + pim_upstream_del(pim_ifp->pim, c_oil->up, __func__); + } +} + struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil, const char *name) { diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 45b337cc72..dc66eaace4 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -182,6 +182,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim, pim_sgaddr *sg); struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, pim_sgaddr *sg, const char *name); +void pim_clear_nocache_state(struct pim_interface *pim_ifp); struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil, const char *name); diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py index c325979d24..6dd5c8866e 100644 --- a/python/xref2vtysh.py +++ b/python/xref2vtysh.py @@ -37,6 +37,8 @@ daemon_flags = { "lib/filter_cli.c": "VTYSH_ACL", "lib/if.c": "VTYSH_INTERFACE", "lib/keychain.c": "VTYSH_RIPD|VTYSH_EIGRPD|VTYSH_OSPF6D", + "lib/mgmt_be_client.c": "VTYSH_STATICD", + "lib/mgmt_fe_client.c": "VTYSH_MGMTD", "lib/lib_vty.c": "VTYSH_ALL", "lib/log_vty.c": "VTYSH_ALL", "lib/nexthop_group.c": "VTYSH_NH_GROUP", diff --git a/ripd/rip_bfd.c b/ripd/rip_bfd.c index ac5035f547..b59db11a30 100644 --- a/ripd/rip_bfd.c +++ b/ripd/rip_bfd.c @@ -13,6 +13,8 @@ #include "ripd/rip_bfd.h" #include "ripd/rip_debug.h" +DEFINE_MTYPE(RIPD, RIP_BFD_PROFILE, "RIP BFD profile name"); + extern struct zclient *zclient; static const char *rip_bfd_interface_profile(struct rip_interface *ri) diff --git a/ripd/rip_bfd.h b/ripd/rip_bfd.h index d49ca15153..7621498b15 100644 --- a/ripd/rip_bfd.h +++ b/ripd/rip_bfd.h @@ -9,6 +9,8 @@ #include "frrevent.h" +DECLARE_MTYPE(RIP_BFD_PROFILE); + struct rip; struct rip_interface; struct rip_peer; diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index b383be042a..b58015a67d 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -25,6 +25,7 @@ #include "zebra/connected.h" #include "ripd/ripd.h" +#include "ripd/rip_bfd.h" #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" @@ -457,7 +458,7 @@ static void rip_interface_reset(struct rip_interface *ri) ri->sent_updates = 0; ri->passive = 0; - XFREE(MTYPE_TMP, ri->bfd.profile); + XFREE(MTYPE_RIP_BFD_PROFILE, ri->bfd.profile); rip_interface_clean(ri); } @@ -1110,9 +1111,10 @@ void rip_interface_sync(struct interface *ifp) struct rip_interface *ri; ri = ifp->info; - ri->ifp = ifp; - if (ri) + if (ri) { ri->rip = ifp->vrf->info; + ri->ifp = ifp; + } } /* Called when interface structure allocated. */ diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c index 8fe34705ca..5c7bd0fb86 100644 --- a/ripd/rip_nb_config.c +++ b/ripd/rip_nb_config.c @@ -25,8 +25,6 @@ #include "ripd/rip_interface.h" #include "ripd/rip_bfd.h" -DEFINE_MTYPE_STATIC(RIPD, RIP_BFD_PROFILE, "RIP BFD profile name"); - /* * XPath: /frr-ripd:ripd/instance */ diff --git a/ripd/ripd.c b/ripd/ripd.c index 48f266a94c..cb8dd4945d 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1171,6 +1171,12 @@ static void rip_response_process(struct rip_packet *packet, int size, continue; } + if (packet->version == RIPv1 && rte->tag != 0) { + zlog_warn("RIPv1 reserved field is nonzero: %d", + ntohs(rte->tag)); + continue; + } + /* - is the destination address valid (e.g., unicast; not net 0 or 127) */ if (!rip_destination_check(rte->prefix)) { diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 386b255a85..3e58a44aa7 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -13,6 +13,7 @@ #include "nexthop.h" #include "table.h" #include "srcdest_table.h" +#include "mgmt_be_client.h" #include "mpls.h" #include "northbound.h" #include "libfrr.h" @@ -1553,4 +1554,6 @@ void static_vty_init(void) install_element(ENABLE_NODE, &debug_staticd_cmd); install_element(CONFIG_NODE, &debug_staticd_cmd); + + mgmt_be_client_lib_vty_init(); } diff --git a/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf b/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf index 2071c256da..e855f75c20 100644 --- a/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf +++ b/tests/topotests/bgp_bfd_down_cease_notification/r1/bgpd.conf @@ -2,7 +2,9 @@ router bgp 65001 no bgp ebgp-requires-policy neighbor 192.168.255.2 remote-as external neighbor 192.168.255.2 timers 3 10 + neighbor 192.168.255.2 timers connect 1 neighbor 192.168.255.2 bfd + neighbor 192.168.255.2 passive address-family ipv4 redistribute connected exit-address-family diff --git a/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf b/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf index 3279804e6e..faf2c6b39b 100644 --- a/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf +++ b/tests/topotests/bgp_bfd_down_cease_notification/r2/bgpd.conf @@ -2,6 +2,7 @@ router bgp 65002 no bgp ebgp-requires-policy neighbor 192.168.255.1 remote-as external neighbor 192.168.255.1 timers 3 10 + neighbor 192.168.255.1 timers connect 1 neighbor 192.168.255.1 bfd address-family ipv4 redistribute connected diff --git a/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py b/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py index 0bc0306d7d..00142981c5 100644 --- a/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py +++ b/tests/topotests/bgp_bfd_down_cease_notification/test_bgp_bfd_down_cease_notification.py @@ -88,13 +88,14 @@ def test_bgp_bfd_down_notification(): expected = { "192.168.255.1": { "lastNotificationReason": "Cease/BFD Down", + "lastNotificationHardReset": True, } } 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) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assert result is None, "Failed to see BGP convergence on R2" step("Kill bfdd on R2") @@ -102,7 +103,7 @@ def test_bgp_bfd_down_notification(): step("Check if we received Cease/BFD Down notification message") test_func = functools.partial(_bgp_bfd_down_notification) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assert result is None, "Failed to see BGP Cease/BFD Down notification message on R2" diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf new file mode 100644 index 0000000000..3459796629 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce1 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json new file mode 100644 index 0000000000..d19e315772 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:1::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:1::/64": [ + { + "prefix": "2001:1::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf new file mode 100644 index 0000000000..bb5f93fe52 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce1/zebra.conf @@ -0,0 +1,16 @@ +log file zebra.log +! +hostname ce1 +! +interface eth0 + ipv6 address 2001:1::2/64 + ip address 192.168.1.2/24 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:1::1 +ip route 0.0.0.0/0 192.168.1.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf new file mode 100644 index 0000000000..8ed9978749 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce2 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json new file mode 100644 index 0000000000..35ff14efad --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:2::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:2::/64": [ + { + "prefix": "2001:2::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf new file mode 100644 index 0000000000..a52b83f2dc --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce2/zebra.conf @@ -0,0 +1,16 @@ +log file zebra.log +! +hostname ce2 +! +interface eth0 + ipv6 address 2001:2::2/64 + ip address 192.168.2.2/24 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:2::1 +ip route 0.0.0.0/0 192.168.2.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf new file mode 100644 index 0000000000..a85d9701c7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce3 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json new file mode 100644 index 0000000000..2f2931f80f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:3::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:3::/64": [ + { + "prefix": "2001:3::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf new file mode 100644 index 0000000000..beca0b1211 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce3/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce3 +! +interface eth0 + ipv6 address 2001:3::2/64 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:3::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf new file mode 100644 index 0000000000..93fb32fd1b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce4 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json new file mode 100644 index 0000000000..8a98768e0d --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:4::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:4::/64": [ + { + "prefix": "2001:4::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf new file mode 100644 index 0000000000..7b21074df0 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce4/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce4 +! +interface eth0 + ipv6 address 2001:4::2/64 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:4::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf new file mode 100644 index 0000000000..2ab6f2d2a7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce5 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json new file mode 100644 index 0000000000..80ff52ad6e --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:5::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:5::/64": [ + { + "prefix": "2001:5::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf new file mode 100644 index 0000000000..b5ad48e709 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce5/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce5 +! +interface eth0 + ipv6 address 2001:5::2/64 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:5::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf new file mode 100644 index 0000000000..e0b6540514 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/bgpd.conf @@ -0,0 +1,8 @@ +frr defaults traditional +! +hostname ce6 +password zebra +! +log stdout notifications +log commands +log file bgpd.log diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json new file mode 100644 index 0000000000..ace6136f06 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/ipv6_rib.json @@ -0,0 +1,58 @@ +{ + "::/0": [ + { + "prefix": "::/0", + "protocol": "static", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 1, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 73, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "ip": "2001:6::1", + "afi": "ipv6", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "2001:6::/64": [ + { + "prefix": "2001:6::/64", + "protocol": "connected", + "vrfId": 0, + "vrfName": "default", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 254, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf new file mode 100644 index 0000000000..7d19d9880b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/ce6/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce6 +! +interface eth0 + ipv6 address 2001:6::2/64 +! +ip forwarding +ipv6 forwarding +! +ipv6 route ::/0 2001:6::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf new file mode 100644 index 0000000000..bfc9db960a --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf @@ -0,0 +1,79 @@ +frr defaults traditional +! +hostname r1 +password zebra +! +log stdout notifications +log monitor notifications +log commands +! +!debug bgp neighbor-events +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 1 + bgp router-id 192.0.2.1 + no bgp ebgp-requires-policy + no bgp default ipv4-unicast + neighbor 2001::2 remote-as 2 + neighbor 2001::2 timers 3 10 + neighbor 2001::2 timers connect 1 + neighbor 2001::2 update-source 2001::1 + neighbor 2001::2 capability extended-nexthop + ! + address-family ipv4 vpn + neighbor 2001::2 activate + exit-address-family + ! + address-family ipv6 vpn + neighbor 2001::2 activate + exit-address-family + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 1 vrf vrf10 + bgp router-id 192.0.2.1 + no bgp ebgp-requires-policy + ! + address-family ipv6 unicast + sid vpn export auto + rd vpn export 1:10 + rt vpn both 99:99 + import vpn + export vpn + redistribute connected + exit-address-family +! + address-family ipv4 unicast + network 192.168.1.0/24 + sid vpn export auto + rd vpn export 11:10 + rt vpn both 77:77 + import vpn + export vpn + redistribute connected + exit-address-family +! +router bgp 1 vrf vrf20 + bgp router-id 192.0.2.1 + no bgp ebgp-requires-policy + no bgp default ipv4-unicast + ! + address-family ipv6 unicast + sid vpn export auto + rd vpn export 1:20 + rt vpn both 88:88 + import vpn + export vpn + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json new file mode 100644 index 0000000000..6fc43e194d --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json @@ -0,0 +1,169 @@ +{ + "vrfName": "default", + "tableVersion": 2, + "routerId": "192.0.2.1", + "defaultLocPrf": 100, + "localAS": 1, + "routes": { + "routeDistinguishers": { + "1:10": { + "2001:1::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:1::", + "prefixLen": 64, + "network": "2001:1::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ], + "2001:3::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:3::", + "prefixLen": 64, + "network": "2001:3::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "1:20": { + "2001:5::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:5::", + "prefixLen": 64, + "network": "2001:5::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "2001:2::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:2::", + "prefixLen": 64, + "network": "2001:2::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:20": { + "2001:4::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:4::", + "prefixLen": 64, + "network": "2001:4::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ], + "2001:6::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:6::", + "prefixLen": 64, + "network": "2001:6::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json new file mode 100644 index 0000000000..9783c7e0e6 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_no_sid_rib.json @@ -0,0 +1,23 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json new file mode 100644 index 0000000000..80c1acff8b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_auto_sid_rib.json @@ -0,0 +1,53 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "labels":[ + 16 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:1::" + } + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json new file mode 100644 index 0000000000..9783c7e0e6 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_no_sid_rib.json @@ -0,0 +1,23 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json new file mode 100644 index 0000000000..07ca64b45b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv4_manual_sid_rib.json @@ -0,0 +1,54 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"2001::2", + "afi":"ipv6", + "labels":[ + 128 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:8::" + } + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json new file mode 100644 index 0000000000..6ac8dac25f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_no_sid_rib.json @@ -0,0 +1,77 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json new file mode 100644 index 0000000000..fac3d1d5f3 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_auto_sid_rib.json @@ -0,0 +1,107 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "labels":[ + 32 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:2::" + } + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json new file mode 100644 index 0000000000..69ce312c4d --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_no_sid_rib.json @@ -0,0 +1,77 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json new file mode 100644 index 0000000000..04e230535e --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_afv6_manual_sid_rib.json @@ -0,0 +1,106 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "labels":[ + 128 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:8::" + } + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json new file mode 100644 index 0000000000..3cac156bb2 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_auto_sid_rib.json @@ -0,0 +1,54 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"2001::2", + "afi":"ipv6", + "labels":[ + 16 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:1::" + } + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json new file mode 100644 index 0000000000..163e9d626a --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf4_manual_sid_rib.json @@ -0,0 +1,53 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"2001::2", + "afi":"ipv6", + "labels":[ + 128 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:8::" + } + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json new file mode 100644 index 0000000000..1313f20c6c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_auto_sid_rib.json @@ -0,0 +1,106 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "labels":[ + 16 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:1::" + } + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json new file mode 100644 index 0000000000..51f249b184 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf6_manual_sid_rib.json @@ -0,0 +1,106 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "labels":[ + 128 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:8::" + } + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json new file mode 100644 index 0000000000..6ac8dac25f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_auto_no_sid_rib.json @@ -0,0 +1,77 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} + diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json new file mode 100644 index 0000000000..1c3dad089d --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_pervrf_manual_no_sid_rib.json @@ -0,0 +1,22 @@ +{ + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json new file mode 100644 index 0000000000..9579bb15de --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf10_rib.json @@ -0,0 +1,112 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 32 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:2::" + } + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json new file mode 100644 index 0000000000..25f146f4b7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vrf20_rib.json @@ -0,0 +1,106 @@ +{ + "2001:4::\/64":[ + { + "prefix":"2001:4::\/64", + "protocol":"bgp", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 48 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:3::" + } + } + ] + } + ], + "2001:5::\/64":[ + { + "prefix":"2001:5::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "2001:6::\/64":[ + { + "prefix":"2001:6::\/64", + "protocol":"bgp", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 48 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:2:2:3::" + } + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf new file mode 100644 index 0000000000..cf31a5c11b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/zebra.conf @@ -0,0 +1,43 @@ +log file zebra.log +! +hostname r1 +password zebra +! +log stdout notifications +log monitor notifications +log commands +! +!debug zebra packet +!debug zebra dplane +!debug zebra kernel +! +interface eth0 + ipv6 address 2001::1/64 +! +interface eth1 vrf vrf10 + ipv6 address 2001:1::1/64 + ip address 192.168.1.1/24 +! +interface eth2 vrf vrf10 + ipv6 address 2001:3::1/64 +! +interface eth3 vrf vrf20 + ipv6 address 2001:5::1/64 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:1:1::/64 block-len 40 node-len 24 func-bits 16 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:2:1::/64 2001::2 +ipv6 route 2001:db8:2:2::/64 2001::2 +ipv6 route 2001:db8:2:3::/64 2001::2 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf new file mode 100644 index 0000000000..892a9f73e5 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf @@ -0,0 +1,80 @@ +frr defaults traditional +! +hostname r2 +password zebra +! +log stdout notifications +log monitor notifications +log commands +! +!debug bgp neighbor-events +!debug bgp zebra +!debug bgp vnc verbose +!debug bgp update-groups +!debug bgp updates in +!debug bgp updates out +!debug bgp updates +!debug bgp vpn label +!debug bgp vpn leak-from-vrf +!debug bgp vpn leak-to-vrf +!debug bgp vpn rmap-event +! +router bgp 2 + bgp router-id 192.0.2.2 + no bgp ebgp-requires-policy + no bgp default ipv4-unicast + neighbor 2001::1 remote-as 1 + neighbor 2001::1 update-source 2001::2 + neighbor 2001::1 timers 3 10 + neighbor 2001::1 timers connect 1 + neighbor 2001::1 capability extended-nexthop + ! + address-family ipv4 vpn + neighbor 2001::1 activate + exit-address-family + ! + address-family ipv6 vpn + neighbor 2001::1 activate + exit-address-family + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 2 vrf vrf10 + bgp router-id 192.0.2.2 + no bgp ebgp-requires-policy + ! + address-family ipv6 unicast + sid vpn export auto + rd vpn export 2:10 + rt vpn both 99:99 + import vpn + export vpn + redistribute connected + exit-address-family +! + address-family ipv4 unicast + network 192.168.2.0/24 + sid vpn export auto + rd vpn export 22:10 + rt vpn both 77:77 + import vpn + export vpn + redistribute connected + exit-address-family +! +router bgp 2 vrf vrf20 + bgp router-id 192.0.2.2 + no bgp ebgp-requires-policy + no bgp default ipv4-unicast + ! + address-family ipv6 unicast + sid vpn export auto + rd vpn export 2:20 + rt vpn both 88:88 + import vpn + export vpn + redistribute connected + exit-address-family +!! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json new file mode 100644 index 0000000000..538e8955ef --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json @@ -0,0 +1,169 @@ +{ + "vrfName": "default", + "tableVersion": 2, + "routerId": "192.0.2.2", + "defaultLocPrf": 100, + "localAS": 2, + "routes": { + "routeDistinguishers": { + "1:10": { + "2001:1::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:1::", + "prefixLen": 64, + "network": "2001:1::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ], + "2001:3::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:3::", + "prefixLen": 64, + "network": "2001:3::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "1:20": { + "2001:5::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:5::", + "prefixLen": 64, + "network": "2001:5::/64", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "2001:2::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:2::", + "prefixLen": 64, + "network": "2001:2::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:20": { + "2001:4::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:4::", + "prefixLen": 64, + "network": "2001:4::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ], + "2001:6::/64": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "2001:6::", + "prefixLen": 64, + "network": "2001:6::/64", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "announceNexthopSelf": true, + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json new file mode 100644 index 0000000000..446bb8eb3c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf10_rib.json @@ -0,0 +1,106 @@ +{ + "2001:1::\/64":[ + { + "prefix":"2001:1::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 32 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:1:1:2::" + } + } + ] + } + ], + "2001:2::\/64":[ + { + "prefix":"2001:2::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "2001:3::\/64":[ + { + "prefix":"2001:3::\/64", + "protocol":"bgp", + "vrfName":"vrf10", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 32 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:1:1:2::" + } + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf10", + "distance":0, + "metric":0, + "installed":true, + "table":10, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json new file mode 100644 index 0000000000..8bc2fc23f1 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vrf20_rib.json @@ -0,0 +1,112 @@ +{ + "2001:4::\/64":[ + { + "prefix":"2001:4::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "2001:5::\/64":[ + { + "prefix":"2001:5::\/64", + "protocol":"bgp", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "afi":"ipv6", + "vrf":"default", + "active":true, + "labels":[ + 48 + ], + "weight":1, + "seg6local":{ + "action":"unspec" + }, + "seg6":{ + "segs":"2001:db8:1:1:3::" + } + } + ] + } + ], + "2001:6::\/64":[ + { + "prefix":"2001:6::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ], + "fe80::\/64":[ + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + }, + { + "prefix":"fe80::\/64", + "protocol":"connected", + "vrfName":"vrf20", + "distance":0, + "metric":0, + "installed":true, + "table":20, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf new file mode 100644 index 0000000000..9771ee1cd7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/zebra.conf @@ -0,0 +1,43 @@ +log file zebra.log +! +hostname r2 +password zebra +! +log stdout notifications +log monitor notifications +log commands +! +!debug zebra packet +!debug zebra dplane +!debug zebra kernel +! +interface eth0 + ipv6 address 2001::2/64 +! +interface eth1 vrf vrf10 + ipv6 address 2001:2::1/64 + ip address 192.168.2.1/24 +! +interface eth2 vrf vrf20 + ipv6 address 2001:4::1/64 +! +interface eth3 vrf vrf20 + ipv6 address 2001:6::1/64 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:2:2::/64 block-len 40 node-len 24 func-bits 16 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:1:1::/64 2001::1 +ipv6 route 2001:db8:1:2::/64 2001::1 +ipv6 route 2001:db8:1:3::/64 2001::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py new file mode 100755 index 0000000000..cddcf6a9a1 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py @@ -0,0 +1,453 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC +# +# Copyright 2023 6WIND S.A. +# Authored by Dmytro Shytyi <dmytro.shytyi@6wind.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +import os +import re +import sys +import json +import functools +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from lib.common_config import required_linux_kernel_version + + +def build_topo(tgen): + """ + CE1 CE3 CE5 + (eth0) (eth0) (eth0) + :2 :2 :2 + | | | + 192.168.1.0 | | + /24 | | + 2001: 2001: 2001: + 1::/64 3::/64 5::/64 + | | | + :1 :1 :1 + +-(eth1)--(eth2)---(eth3)-+ + | \ / | | + | (vrf10) (vrf20) | + | R1 | + +----------(eth0)---------+ + :1 + | + 2001::/64 + | + :2 + (eth0) + +----------(eth0)--------------+ + | R2 | + | (vrf10) (vrf20) | + | / / \ | + +-(eth1)-----(eth2)-----(eth3)-+ + :1 :1 :1 + | | | + +------+ +------+ +------+ + / 2001: \ / 2001: \ / 2001: \ + / 2::/64 \ 4::/64 / \ 6::/64 / + /192.168.2.0| / \ / + \ /24 / \ | | | + +------+ +------+ +------+ + | | | + :2 :2 :2 + (eth0) (eth0) (eth0) + CE2 CE4 CE6 + """ + + tgen.add_router("r1") + tgen.add_router("r2") + tgen.add_router("ce1") + tgen.add_router("ce2") + tgen.add_router("ce3") + tgen.add_router("ce4") + tgen.add_router("ce5") + tgen.add_router("ce6") + + tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0") + tgen.add_link(tgen.gears["ce1"], tgen.gears["r1"], "eth0", "eth1") + tgen.add_link(tgen.gears["ce2"], tgen.gears["r2"], "eth0", "eth1") + tgen.add_link(tgen.gears["ce3"], tgen.gears["r1"], "eth0", "eth2") + tgen.add_link(tgen.gears["ce4"], tgen.gears["r2"], "eth0", "eth2") + tgen.add_link(tgen.gears["ce5"], tgen.gears["r1"], "eth0", "eth3") + tgen.add_link(tgen.gears["ce6"], tgen.gears["r2"], "eth0", "eth3") + + +def setup_module(mod): + result = required_linux_kernel_version("5.11") + if result is not True: + pytest.skip("Kernel requirements are not met") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + router_list = tgen.routers() + for i, (rname, router) in enumerate(tgen.routers().items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.gears["r1"].run("modprobe vrf") + tgen.gears["r1"].run("ip link add vrf10 type vrf table 10") + tgen.gears["r1"].run("ip link set vrf10 up") + tgen.gears["r1"].run("ip link add vrf20 type vrf table 20") + tgen.gears["r1"].run("ip link set vrf20 up") + tgen.gears["r1"].run("ip link set eth1 master vrf10") + tgen.gears["r1"].run("ip link set eth2 master vrf10") + tgen.gears["r1"].run("ip link set eth3 master vrf20") + tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1") + tgen.gears["r1"].run("sysctl net.ipv4.conf.default.rp_filter=0") + tgen.gears["r1"].run("sysctl net.ipv4.conf.all.rp_filter=0") + tgen.gears["r1"].run("sysctl net.ipv4.conf.lo.rp_filter=0") + tgen.gears["r1"].run("sysctl net.ipv4.conf.eth0.rp_filter=0") + tgen.gears["r1"].run("sysctl net.ipv4.conf.eth1.rp_filter=0") + tgen.gears["r1"].run("sysctl net.ipv4.conf.vrf10.rp_filter=0") + + tgen.gears["r2"].run("modprobe vrf") + tgen.gears["r2"].run("ip link add vrf10 type vrf table 10") + tgen.gears["r2"].run("ip link set vrf10 up") + tgen.gears["r2"].run("ip link add vrf20 type vrf table 20") + tgen.gears["r2"].run("ip link set vrf20 up") + tgen.gears["r2"].run("ip link set eth1 master vrf10") + tgen.gears["r2"].run("ip link set eth2 master vrf20") + tgen.gears["r2"].run("ip link set eth3 master vrf20") + tgen.gears["r2"].run("sysctl net.vrf.strict_mode=1") + tgen.gears["r2"].run("sysctl net.ipv4.conf.default.rp_filter=0") + tgen.gears["r2"].run("sysctl net.ipv4.conf.all.rp_filter=0") + tgen.gears["r2"].run("sysctl net.ipv4.conf.lo.rp_filter=0") + tgen.gears["r2"].run("sysctl net.ipv4.conf.eth0.rp_filter=0") + tgen.gears["r2"].run("sysctl net.ipv4.conf.eth1.rp_filter=0") + tgen.gears["r2"].run("sysctl net.ipv4.conf.vrf10.rp_filter=0") + tgen.start_router() + + # FOR DEVELOPER: + # If you want to stop some specific line and start interactive shell, + # please use tgen.mininet_cli() to start it. + # Example: + # tgen=get_topogen() + # tgen.mininet_cli() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def open_json_file(filename): + try: + with open(filename, "r") as f: + return json.load(f) + except IOError: + assert False, "Could not read file {}".format(filename) + + +def check_ping(name, dest_addr, expect_connected): + def _check(name, dest_addr, match): + tgen = get_topogen() + output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr)) + logger.info(output) + if match not in output: + return True + + match = ", {} packet loss".format("0%" if expect_connected else "100%") + logger.info("[+] check {} {} {}".format(name, dest_addr, match)) + tgen = get_topogen() + func = functools.partial(_check, name, dest_addr, match) + success, result = topotest.run_and_expect(func, None, count=10, wait=0.5) + assert result is None, "Failed" + + +def check_rib(name, cmd, expected_file): + def _check(name, cmd, expected_file): + logger.info("polling") + tgen = get_topogen() + router = tgen.gears[name] + output = json.loads(router.vtysh_cmd(cmd)) + expected = open_json_file("{}/{}".format(CWD, expected_file)) + return topotest.json_cmp(output, expected) + + logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file)) + tgen = get_topogen() + func = functools.partial(_check, name, cmd, expected_file) + success, result = topotest.run_and_expect(func, None, count=10, wait=0.5) + assert result is None, "Failed" + + +def test_rib(): + check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib.json") + check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib.json") + check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_rib.json") + check_rib("r1", "show ipv6 route vrf vrf20 json", "r1/vrf20_rib.json") + check_rib("r2", "show ipv6 route vrf vrf10 json", "r2/vrf10_rib.json") + check_rib("r2", "show ipv6 route vrf vrf20 json", "r2/vrf20_rib.json") + check_rib("ce1", "show ipv6 route json", "ce1/ipv6_rib.json") + check_rib("ce2", "show ipv6 route json", "ce2/ipv6_rib.json") + check_rib("ce3", "show ipv6 route json", "ce3/ipv6_rib.json") + check_rib("ce4", "show ipv6 route json", "ce4/ipv6_rib.json") + check_rib("ce5", "show ipv6 route json", "ce5/ipv6_rib.json") + check_rib("ce6", "show ipv6 route json", "ce6/ipv6_rib.json") + + +def test_ping(): + check_ping("ce1", "2001:2::2", True) + check_ping("ce1", "2001:3::2", True) + check_ping("ce1", "2001:4::2", False) + check_ping("ce1", "2001:5::2", False) + check_ping("ce1", "2001:6::2", False) + check_ping("ce4", "2001:1::2", False) + check_ping("ce4", "2001:2::2", False) + check_ping("ce4", "2001:3::2", False) + check_ping("ce4", "2001:5::2", True) + check_ping("ce4", "2001:6::2", True) + + +def test_sid_per_afv6_auto(): + check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json") + check_ping("ce1", "2001:2::2", True) + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv6 unicast + no sid vpn export auto + """ + ) + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv6 unicast + sid vpn export auto + """ + ) + check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json") + check_ping("ce1", "2001:2::2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv6 unicast + no sid vpn export auto + """ + ) + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + + +def test_sid_per_afv6_manual(): + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv6 unicast + sid vpn export 8 + """ + ) + + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv6 unicast + no sid vpn export 8 + """ + ) + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + + +def test_sid_per_afv4_auto(): + check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json") + check_ping("ce1", "192.168.2.2", True) + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv4 unicast + no sid vpn export auto + """ + ) + + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", False) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv4 unicast + sid vpn export auto + """ + ) + + check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json") + check_ping("ce1", "192.168.2.2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv4 unicast + no sid vpn export auto + """ + ) + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", False) + + +def test_sid_per_afv4_manual(): + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", False) + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv4 unicast + sid vpn export 8 + """ + ) + + check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_sid_rib.json") + check_ping("ce1", "192.168.2.2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + address-family ipv4 unicast + no sid vpn export 8 + """ + ) + check_ping("ce1", "192.168.2.2", False) + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json" + ) + + +def test_sid_per_vrf_auto(): + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + sid vpn per-vrf export auto + """ + ) + + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_auto_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", True) + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_auto_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + no sid vpn per-vrf export auto + """ + ) + + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", False) + + +def test_sid_per_vrf_manual(): + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", False) + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + sid vpn per-vrf export 8 + """ + ) + + check_rib( + "r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_manual_sid_rib.json" + ) + check_ping("ce1", "2001:2::2", True) + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_manual_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", True) + + get_topogen().gears["r2"].vtysh_cmd( + """ + configure terminal + router bgp 2 vrf vrf10 + no sid vpn per-vrf export 8 + """ + ) + + check_rib( + "r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json" + ) + check_ping("ce1", "192.168.2.2", False) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf index 4ab5b98c12..8700f12d63 100644 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/r2/bgpd.conf @@ -1,6 +1,6 @@ frr defaults traditional ! -!bgp send-extra-data zebra +bgp send-extra-data zebra ! hostname r2 password zebra diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 3583ce17ed..2d6138990e 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -236,7 +236,6 @@ class Topogen(object): self.add_topology_from_dict(topodef) def add_topology_from_dict(self, topodef): - keylist = ( topodef.keys() if isinstance(topodef, OrderedDict) @@ -869,7 +868,7 @@ class TopoRouter(TopoGear): "conf t", "log file {}.log debug".format(daemon), "log commands", - "log timestamp precision 3", + "log timestamp precision 6", ] ), daemon=daemon, @@ -919,7 +918,7 @@ class TopoRouter(TopoGear): "conf t", "log file {}.log debug".format(daemon), "log commands", - "log timestamp precision 3", + "log timestamp precision 6", ] ), daemon=daemon, @@ -1204,6 +1203,7 @@ class TopoExaBGP(TopoHost): # Diagnostic function # + # Disable linter branch warning. It is expected to have these here. # pylint: disable=R0912 def diagnose_env_linux(rundir): diff --git a/tests/topotests/ospf_basic_functionality/ospf_lan.json b/tests/topotests/ospf_basic_functionality/ospf_lan.json index 126934c344..54863382b2 100644 --- a/tests/topotests/ospf_basic_functionality/ospf_lan.json +++ b/tests/topotests/ospf_basic_functionality/ospf_lan.json @@ -18,7 +18,7 @@ "ospf": { "area": "0.0.0.3", "hello_interval": 1, - "dead_interval": 4, + "dead_interval": 10, "priority": 98 } }, @@ -27,7 +27,7 @@ "ospf": { "area": "0.0.0.3", "hello_interval": 1, - "dead_interval": 4, + "dead_interval": 10, "priority": 99 } }, @@ -36,7 +36,7 @@ "ospf": { "area": "0.0.0.3", "hello_interval": 1, - "dead_interval": 4, + "dead_interval": 10, "priority": 0 } }, @@ -45,7 +45,7 @@ "ospf": { "area": "0.0.0.3", "hello_interval": 1, - "dead_interval": 4, + "dead_interval": 10, "priority": 0 } } @@ -135,4 +135,4 @@ } } } -}
\ No newline at end of file +} diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py index e4a032018c..1358027f21 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py @@ -196,8 +196,10 @@ def test_ospf_lan_tc1_p0(request): result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - 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": { @@ -233,8 +235,10 @@ def test_ospf_lan_tc1_p0(request): result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True) assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) - step("Configure DR priority 150 on R0 and clear ospf neighbors " - "on all the routers.") + step( + "Configure DR priority 150 on R0 and clear ospf neighbors " + "on all the routers." + ) input_dict = { "r0": { @@ -489,7 +493,7 @@ def test_ospf_lan_tc2_p0(request): "s1": { "ospf": { "priority": 98, - "timerDeadSecs": 4, + "timerDeadSecs": 10, "area": "0.0.0.3", "mcastMemberOspfDesignatedRouters": True, "mcastMemberOspfAllRouters": True, diff --git a/tests/topotests/ospf_metric_propagation/r1/frr.conf b/tests/topotests/ospf_metric_propagation/r1/frr.conf index 9f388dbd0f..85230494dd 100644 --- a/tests/topotests/ospf_metric_propagation/r1/frr.conf +++ b/tests/topotests/ospf_metric_propagation/r1/frr.conf @@ -8,18 +8,18 @@ interface r1-eth0 ip address 10.0.1.1/24 ip ospf cost 100 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r1-eth1 vrf blue ip address 10.0.10.1/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! ! interface r1-eth2 vrf green ip address 10.0.91.1/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! ! router ospf diff --git a/tests/topotests/ospf_metric_propagation/r2/frr.conf b/tests/topotests/ospf_metric_propagation/r2/frr.conf index 469ae5da88..e67a374ff5 100644 --- a/tests/topotests/ospf_metric_propagation/r2/frr.conf +++ b/tests/topotests/ospf_metric_propagation/r2/frr.conf @@ -8,18 +8,18 @@ interface r2-eth0 ip address 10.0.1.2/24 ip ospf cost 100 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r2-eth1 vrf blue ip address 10.0.20.2/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r2-eth2 vrf green ip address 10.0.70.2/24 ip ospf cost 1000 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.2 diff --git a/tests/topotests/ospf_metric_propagation/r3/frr.conf b/tests/topotests/ospf_metric_propagation/r3/frr.conf index 8dbbaf0fc4..175851d427 100644 --- a/tests/topotests/ospf_metric_propagation/r3/frr.conf +++ b/tests/topotests/ospf_metric_propagation/r3/frr.conf @@ -8,18 +8,18 @@ interface r3-eth0 ip address 10.0.3.3/24 ip ospf cost 100 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r3-eth1 vrf blue ip address 10.0.30.3/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r3-eth2 vrf green ip address 10.0.80.3/24 ip ospf cost 1000 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.3 diff --git a/tests/topotests/ospf_metric_propagation/r4/frr.conf b/tests/topotests/ospf_metric_propagation/r4/frr.conf index af1005063b..70a47e34fa 100644 --- a/tests/topotests/ospf_metric_propagation/r4/frr.conf +++ b/tests/topotests/ospf_metric_propagation/r4/frr.conf @@ -8,17 +8,17 @@ interface r4-eth0 ip address 10.0.3.4/24 ip ospf cost 100 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r4-eth1 vrf blue ip address 10.0.40.4/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface r4-eth2 vrf green ip address 10.0.94.4/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.4 diff --git a/tests/topotests/ospf_metric_propagation/ra/frr.conf b/tests/topotests/ospf_metric_propagation/ra/frr.conf index 0bc2ec5679..7be9e5c33e 100644 --- a/tests/topotests/ospf_metric_propagation/ra/frr.conf +++ b/tests/topotests/ospf_metric_propagation/ra/frr.conf @@ -7,17 +7,17 @@ ip forwarding interface ra-eth0 ip address 10.0.50.5/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface ra-eth1 ip address 10.0.10.5/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface ra-eth2 ip address 10.0.20.5/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.5 diff --git a/tests/topotests/ospf_metric_propagation/rb/frr.conf b/tests/topotests/ospf_metric_propagation/rb/frr.conf index 6f540d125e..a7dbf82278 100644 --- a/tests/topotests/ospf_metric_propagation/rb/frr.conf +++ b/tests/topotests/ospf_metric_propagation/rb/frr.conf @@ -7,17 +7,17 @@ ip forwarding interface rb-eth0 ip address 10.0.50.6/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface rb-eth1 ip address 10.0.30.6/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface rb-eth2 ip address 10.0.40.6/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.6 diff --git a/tests/topotests/ospf_metric_propagation/rc/frr.conf b/tests/topotests/ospf_metric_propagation/rc/frr.conf index 9fc0ef718f..f5a2ed7c4f 100644 --- a/tests/topotests/ospf_metric_propagation/rc/frr.conf +++ b/tests/topotests/ospf_metric_propagation/rc/frr.conf @@ -7,12 +7,12 @@ ip forwarding interface rc-eth0 ip address 10.0.70.7/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! interface rc-eth1 ip address 10.0.80.7/24 ip ospf hello-interval 1 - ip ospf dead-interval 3 + ip ospf dead-interval 30 ! router ospf ospf router-id 10.0.255.7 diff --git a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py index 709e07649b..4d78bd2372 100644 --- a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py +++ b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py @@ -71,7 +71,6 @@ def build_topo(tgen): tgen.add_router("h1") tgen.add_router("h2") - # Interconect router 1, 2 switch = tgen.add_switch("s1-2") switch.add_link(tgen.gears["r1"]) @@ -127,6 +126,7 @@ def build_topo(tgen): switch.add_link(tgen.gears["r3"]) switch.add_link(tgen.gears["rc"]) + def setup_module(mod): logger.info("OSPF Metric Propagation:\n {}".format(TOPOLOGY)) @@ -148,8 +148,12 @@ def setup_module(mod): for cmd in vrf_setup_cmds: tgen.net["r{}".format(routern)].cmd(cmd) for routern in range(1, 5): - tgen.net["r{}".format(routern)].cmd("ip link set dev r{}-eth1 vrf blue up".format(routern)) - tgen.net["r{}".format(routern)].cmd("ip link set dev r{}-eth2 vrf green up".format(routern)) + tgen.net["r{}".format(routern)].cmd( + "ip link set dev r{}-eth1 vrf blue up".format(routern) + ) + tgen.net["r{}".format(routern)].cmd( + "ip link set dev r{}-eth2 vrf green up".format(routern) + ) for rname, router in router_list.items(): logger.info("Loading router %s" % rname) @@ -181,7 +185,7 @@ def test_all_links_up(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=40, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg @@ -202,7 +206,7 @@ def test_link_1_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg @@ -216,6 +220,10 @@ def test_link_1_2_down(): pytest.skip("skipped because of router(s) failure") tgen.net["r2"].cmd("ip link set dev r2-eth1 down") + tgen.net["r2"].cmd("ip link set dev r2-eth2 down") + # ospf dead-interval is set to 30 seconds, wait 35 seconds to clear the neighbor + sleep(35) + tgen.net["r2"].cmd("ip link set dev r2-eth2 up") r1 = tgen.gears["r1"] json_file = "{}/r1/show_ip_route-3.json".format(CWD) @@ -223,7 +231,7 @@ def test_link_1_2_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg @@ -238,8 +246,8 @@ def test_link_1_2_3_down(): tgen.net["r3"].cmd("ip link set dev r3-eth0 down") tgen.net["r3"].cmd("ip link set dev r3-eth1 down") - # ospf dead-interval is set to 3 seconds, wait 5 seconds to clear the neighbor - sleep(5) + # ospf dead-interval is set to 30 seconds, wait 35 seconds to clear the neighbor + sleep(35) tgen.net["r3"].cmd("ip link set dev r3-eth0 up") r1 = tgen.gears["r1"] @@ -248,11 +256,12 @@ def test_link_1_2_3_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg + def test_link_1_2_3_4_down(): "Test path R1 -> R2 -> Rc -> R3 -> R4" tgen = get_topogen() @@ -268,11 +277,12 @@ def test_link_1_2_3_4_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg + def test_link_1_2_4_down(): "Test path R1 -> R2 -> Rc -> R3 -> R4" tgen = get_topogen() @@ -289,11 +299,12 @@ def test_link_1_2_4_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg + def test_link_1_4_down(): "Test path R1 -> R2 -> Ra -> Rb -> R3 -> R4" tgen = get_topogen() @@ -310,7 +321,7 @@ def test_link_1_4_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg @@ -332,7 +343,7 @@ def test_link_4_down(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg @@ -354,7 +365,7 @@ def test_link_1_2_3_4_up(): test_func = partial( topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) assertmsg = "r1 JSON output mismatches" assert result is None, assertmsg diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 3a325df06c..fcb692b715 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -2323,8 +2323,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) zlog_debug("RTM_DELLINK for %s(%u)", name, ifp->ifindex); - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - if (IS_ZEBRA_IF_BOND(ifp)) zebra_l2if_update_bond(ifp, false); if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) diff --git a/zebra/interface.c b/zebra/interface.c index 496a85e676..231ddc51db 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -800,6 +800,8 @@ void if_delete_update(struct interface **pifp) if (ifp->vrf->vrf_id && !vrf_is_backend_netns()) if_handle_vrf_change(ifp, VRF_DEFAULT); + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + /* Reset some zebra interface params to default values. */ zif = ifp->info; if (zif) { @@ -840,6 +842,9 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id) /* This is to issue an UPDATE or a DELETE, as appropriate. */ zebra_interface_vrf_update_del(ifp, vrf_id); + if (if_is_vrf(ifp)) + return; + /* update VRF */ if_update_to_new_vrf(ifp, vrf_id); diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index bf488ca316..49120c2877 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -3157,6 +3157,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty, json_array_string_add(json_flags, "local"); if (es->flags & ZEBRA_EVPNES_REMOTE) json_array_string_add(json_flags, "remote"); + if (es->flags & ZEBRA_EVPNES_LOCAL && + !(es->flags & ZEBRA_EVPNES_NON_DF)) + json_array_string_add(json_flags, "df"); if (es->flags & ZEBRA_EVPNES_NON_DF) json_array_string_add(json_flags, "nonDF"); if (es->flags & ZEBRA_EVPNES_BYPASS) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 3bbcd38d1c..28b83ce8b6 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1532,11 +1532,15 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, seg6local_context2str(buf, sizeof(buf), &nexthop->nh_srv6->seg6local_ctx, nexthop->nh_srv6->seg6local_action); - vty_out(vty, ", seg6local %s %s", - seg6local_action2str( - nexthop->nh_srv6->seg6local_action), - buf); - vty_out(vty, ", seg6 %pI6", &nexthop->nh_srv6->seg6_segs); + if (nexthop->nh_srv6->seg6local_action != + ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) + vty_out(vty, ", seg6local %s %s", + seg6local_action2str( + nexthop->nh_srv6->seg6local_action), + buf); + if (IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs, &in6addr_any)) + vty_out(vty, ", seg6 %pI6", + &nexthop->nh_srv6->seg6_segs); } if (nexthop->weight) |
