diff options
136 files changed, 5271 insertions, 880 deletions
diff --git a/babeld/message.c b/babeld/message.c index 3a29b6a60..559b8c4e4 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -140,12 +140,12 @@ parse_update_subtlv(const unsigned char *a, int alen, continue; } - if(i + 1 > alen) { + if(i + 1 >= alen) { flog_err(EC_BABEL_PACKET, "Received truncated attributes."); return; } len = a[i + 1]; - if(i + len > alen) { + if(i + len + 2 > alen) { flog_err(EC_BABEL_PACKET, "Received truncated attributes."); return; } @@ -182,19 +182,19 @@ parse_hello_subtlv(const unsigned char *a, int alen, int type, len, i = 0, ret = 0; while(i < alen) { - type = a[0]; + type = a[i]; if(type == SUBTLV_PAD1) { i++; continue; } - if(i + 1 > alen) { + if(i + 1 >= alen) { flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Hello message."); return -1; } len = a[i + 1]; - if(i + len > alen) { + if(i + len + 2 > alen) { flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Hello message."); return -1; @@ -228,19 +228,19 @@ parse_ihu_subtlv(const unsigned char *a, int alen, int type, len, i = 0, ret = 0; while(i < alen) { - type = a[0]; + type = a[i]; if(type == SUBTLV_PAD1) { i++; continue; } - if(i + 1 > alen) { + if(i + 1 >= alen) { flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on IHU message."); return -1; } len = a[i + 1]; - if(i + len > alen) { + if(i + len + 2 > alen) { flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on IHU message."); return -1; @@ -307,12 +307,12 @@ babel_packet_examin(const unsigned char *packet, int packetlen) i++; continue; } - if(i + 1 > bodylen) { + if(i + 2 > bodylen) { debugf(BABEL_DEBUG_COMMON,"Received truncated message."); return 1; } len = message[1]; - if(i + len > bodylen) { + if(i + len + 2 > bodylen) { debugf(BABEL_DEBUG_COMMON,"Received truncated message."); return 1; } diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index b0eb85e5f..0e5f701fc 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -457,7 +457,7 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, } /* Sanity check: peer and local address must match IP types. */ - if (bpc->bpc_local.sa_sin.sin_family != 0 + if (bpc->bpc_local.sa_sin.sin_family != AF_UNSPEC && (bpc->bpc_local.sa_sin.sin_family != bpc->bpc_peer.sa_sin.sin_family)) { zlog_warn("ptm-read: peer family doesn't match local type"); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f353abead..e390ba5c7 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2200,10 +2200,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, if (ret == RMAP_DENYMATCH) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] %pFX is filtered by route-map", - peer->host, p); + "%s [Update:SEND] %pFX is filtered by route-map '%s'", + peer->host, p, + ROUTE_MAP_OUT_NAME(filter)); - bgp_attr_flush(attr); + bgp_attr_flush(&dummy_attr); return false; } } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 07aed045c..4b50b4656 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -388,7 +388,7 @@ int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p) return 0; /* MPLS carries UN address in next hop */ rfapiNexthop2Prefix(attr, p); - if (p->family != 0) + if (p->family != AF_UNSPEC) return 0; return ENOENT; @@ -457,7 +457,7 @@ int rfapiGetUnAddrOfVpnBi(struct bgp_path_info *bpi, struct prefix *p) return 0; default: if (p) - p->family = 0; + p->family = AF_UNSPEC; #ifdef DEBUG_ENCAP_MONITOR vnc_zlog_debug_verbose( "%s: bpi->extra->vnc.import.un_family is 0, no UN addr", @@ -1155,7 +1155,7 @@ static int rfapiVpnBiSamePtUn(struct bgp_path_info *bpi1, bpi1->extra->vnc.import.un.addr6; break; default: - pfx_un1.family = 0; + pfx_un1.family = AF_UNSPEC; break; } } @@ -1174,13 +1174,13 @@ static int rfapiVpnBiSamePtUn(struct bgp_path_info *bpi1, bpi2->extra->vnc.import.un.addr6; break; default: - pfx_un2.family = 0; + pfx_un2.family = AF_UNSPEC; break; } } } - if (pfx_un1.family == 0 || pfx_un2.family == 0) + if (pfx_un1.family == AF_UNSPEC || pfx_un2.family == AF_UNSPEC) return 0; if (pfx_un1.family != pfx_un2.family) @@ -1358,7 +1358,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, struct prefix p; /* MPLS carries UN address in next hop */ rfapiNexthop2Prefix(bpi->attr, &p); - if (p.family != 0) { + if (p.family != AF_UNSPEC) { rfapiQprefix2Raddr(&p, &new->un_address); have_vnc_tunnel_un = 1; } @@ -2609,7 +2609,7 @@ static void rfapiCopyUnEncap2VPN(struct bgp_path_info *encap_bpi, default: zlog_warn("%s: invalid encap nexthop length: %d", __func__, encap_bpi->attr->mp_nexthop_len); - vpn_bpi->extra->vnc.import.un_family = 0; + vpn_bpi->extra->vnc.import.un_family = AF_UNSPEC; break; } } @@ -2634,7 +2634,7 @@ rfapiWithdrawEncapUpdateCachedUn(struct rfapi_import_table *import_table, __func__); return 1; } - vpn_bpi->extra->vnc.import.un_family = 0; + vpn_bpi->extra->vnc.import.un_family = AF_UNSPEC; memset(&vpn_bpi->extra->vnc.import.un, 0, sizeof(vpn_bpi->extra->vnc.import.un)); if (CHECK_FLAG(vpn_bpi->flags, BGP_PATH_VALID)) { @@ -3626,7 +3626,7 @@ void rfapiBgpInfoFilteredImportVPN( /* Not a big deal, just means VPN route got here first */ vnc_zlog_debug_verbose("%s: no encap route for vn addr %pFX", __func__, &vn_prefix); - info_new->extra->vnc.import.un_family = 0; + info_new->extra->vnc.import.un_family = AF_UNSPEC; } if (rn) { diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index d1f335f54..6b9a8fb4a 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -1950,7 +1950,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, && RFAPI_HOST_PREFIX(&rk.aux_prefix)) { /* mark as "none" if nhp->prefix is 0/32 or * 0/128 */ - rk.aux_prefix.family = 0; + rk.aux_prefix.family = AF_UNSPEC; } } diff --git a/doc/developer/cspf.rst b/doc/developer/cspf.rst new file mode 100644 index 000000000..426553ff0 --- /dev/null +++ b/doc/developer/cspf.rst @@ -0,0 +1,196 @@ +Path Computation Algorithms +=========================== + +Introduction +------------ + +Both RSVP-TE and Segment Routing Flex Algo need to compute end to end path +with other constraints as the standard IGP metric. Based on Shortest Path First +(SPF) algorithms, a new class of Constrained SPF (CSPF) is provided by the FRR +library. + +Supported constraints are as follow: +- Standard IGP metric (here, CSPF provides the same result as a normal SPF) +- Traffic Engineering (TE) IGP metric +- Delay from the IGP Extended Metrics +- Bandwidth for a given Class of Service (CoS) for bandwidth reservation + +Algorithm +--------- + +The CSPF algorithm is based on a Priority Queue which store the on-going +possible path sorted by their respective weights. This weight corresponds +to the cost of the cuurent path from the source up to the current node. + +The algorithm is as followed: + +``` + cost = MAX_COST; + Priority_Queue.empty(); + Visited_Node.empty(); + Processed_Path.empty(); + src = new_path(source_address); + src.cost = 0; + dst = new_destinatio(destination_address); + dst.cost = MAX_COST; + Processed_Path.add(src); + Processed_Path.add(dst); + while (Priority_Queue.count != 0) { + current_path = Priority_Queue.pop(); + current_node = next_path.destination; + Visited_Node.add(current_node); + for (current_node.edges: edge) { + if (prune_edge(current_path, edge) + continue; + if (relax(current_path) && cost > current_path.cost) { + optim_path = current_path; + cost = current_path.cost; + } + } + } + + prune_edge(path, edge) { + // check that path + edge meet constraints e.g. + if (current_path.cost + edge.cost > constrained_cost) + return false; + else + return true; + } + + relax_edge(current_path, edge) { + next_node = edge.destination; + if (Visited_Node.get(next_node)) + return false; + next_path = Processed_Path.get(edge.destination); + if (!next_path) { + next_path = new path(edge.destination); + Processed_Path.add(next_path); + } + total_cost = current_path.cost + edge.cost; + if (total_cost < next_path.cost) { + next_path = current_path; + next_path.add_edge(edge); + next_path.cost = total_cost; + Priority_Queue.add(next_path); + } + return (next_path.destination == destination); + } + +``` + +Definition +---------- + +.. c:struct:: constraints + +This is the constraints structure that contains: + +- cost: the total cost that the path must respect +- ctype: type of constraints: + + - CSPF_METRIC for standard metric + - CSPF_TE_METRIC for TE metric + - CSPF_DELAY for delay metric + +- bw: bandwidth that the path must respect +- cos: Class of Service (COS) for the bandwidth +- family: AF_INET or AF_INET6 +- type: RSVP_TE, SR_TE or SRV6_TE + +.. c:struct:: c_path + +This is the Constraint Path structure that contains: + +- edges: List of Edges that compose the path +- status: FAILED, IN_PROGRESS, SUCCESS, NO_SOURCE, NO_DESTINATION, SAME_SRC_DST +- weight: the cost from source to the destination of the path +- dst: key of the destination vertex + +.. c:struct:: cspf + +This is the main structure for path computation. Even if it is public, you +don't need to set manually the internal field of the structure. Instead, use +the following functions: + +.. c:function:: struct cspf *cspf_new(void); + +Function to create an empty cspf for future call of path computation + +.. c:function:: struct cspf *cspf_init(struct cspf *algo, const struct ls_vertex *src, const struct ls_vertex *dst, struct constraints *csts); + +This function initialize the cspf with source and destination vertex and +constraints and return pointer to the cspf structure. If input cspf structure +is NULL, a new cspf structure is allocated and initialize. + +.. c:function:: struct cspf *cspf_init_v4(struct cspf *algo, struct ls_ted *ted, const struct in_addr src, const struct in_addr dst, struct constraints *csts); + +Same as cspf_init, but here, source and destination vertex are extract from +the TED data base based on respective IPv4 source and destination addresses. + +.. c:function:: struct cspf *cspf_init_v6(struct cspf *algo, struct ls_ted *ted, const struct in6_addr src, const struct in6_addr dst, struct constraints *csts); + +Same as cspf_init_v4 but with IPv6 source and destination addresses. + +.. c:function:: void cspf_clean(struct cspf *algo); + +Clean internal structure of cspf in order to reuse it for another path +computation. + +.. c:function:: void cspf_del(struct cspf *algo); + +Delete cspf structure. A call to cspf_clean() function is perform prior to +free allocated memeory. + +.. c:function:: struct c_path *compute_p2p_path(struct ls_ted *ted, struct cspf *algo); + +Compute point to point path from the ted and cspf. +The function always return a constraints path. The status of the path gives +indication about the success or failure of the algorithm. If cspf structure has +not been initialize with a call to `cspf_init() or cspf_init_XX()`, the +algorithm returns a constraints path with status set to FAILED. +Note that a call to `cspf_clean()` is performed at the end of this function, +thus it is mandatory to initialize the cspf structure again prior to call again +the path computation algorithm. + + +Usage +----- + +Of course, CSPF algorithm needs a network topology that contains the +various metrics. Link State provides such Traffic Engineering Database. + +To perform a Path Computation with given constraints, proceed as follow: + +.. code-block:: c + struct cspf *algo; + struct ls_ted *ted; + struct in_addr src; + struct in_addr dst; + struct constraints csts; + struct c_path *path; + + // Create a new CSPF structure + algo = cspf_new(); + + // Initialize constraints + csts.cost = 100; + csts.ctype = CSPF_TE_METRIC; + csts.family = AF_INET; + csts.type = SR_TE; + csts.bw = 1000000; + csts.cos = 3; + + // Then, initialise th CSPF with source, destination and constraints + cspf_init_v4(algo, ted, src, dst, &csts); + + // Finally, got the Computed Path; + path = compute_p2p_path(ted, algo); + + if (path.status == SUCCESS) + zlog_info("Got a valid constraints path"); + else + zlog_info("Unable to compute constraints path. Got %d status", path->status); + + +If you would compute another path, you must call `cspf_init()` prior to +`compute_p2p_path()` to change source, destination and/or constraints. diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index 5911fdb58..6ae3d2939 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -124,11 +124,11 @@ March/July/November. Walking backwards from this date: % git push upstream dev/8.2 % git checkout master % sed -i 's/8.2-dev/8.3-dev/' configure.ac - % git tag -a frr-8.3-dev -m "frr-8.3-dev" - % git push upstream frr-8.3-dev % git add configure.ac % git commit -s -m "build: FRR 8.3 development version" + % git tag -a frr-8.3-dev -m "frr-8.3-dev" % git push upstream master + % git push upstream frr-8.3-dev In this step, we also have to update package versions to reflect the development version. Versions need to be updated using diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 1b418a434..306feec0f 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -452,6 +452,7 @@ cause great confusion. .. clicmd:: show ip pim assert Display information about asserts in the PIM system for S,G mroutes. + This command does not show S,G Channel states that in a NOINFO state. .. clicmd:: show ip pim assert-internal diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index e088c2f75..e9d4e2763 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -139,7 +139,7 @@ keyword. At present, no sharp commands will be preserved in the config. .. clicmd:: sharp import-te - Import Traffic Engineering Database produce by OSPF or IS-IS. + Import Traffic Engineering Database produced by OSPF or IS-IS. .. clicmd:: show sharp ted [verbose|json] @@ -147,6 +147,15 @@ keyword. At present, no sharp commands will be preserved in the config. Show imported Traffic Engineering Data Base +.. clicmd:: show sharp cspf source <A.B.C.D|X:X:X:X> destination <A.B.C.D|X:X:X:X> <metric|te-metric|delay> (0-16777215) [rsv-bw (0-7) BANDWIDTH] + + Show the result of a call to the Constraint Shortest Path First (CSPF) + algorithm that allows to compute a path between a source and a + destination under various constraints. Standard Metric, TE Metric, Delay + and Bandwidth are supported constraints. Prior to use this function, it is + necessary to import a Traffic Engineering Database with `sharp import-te` + command (see above). + .. clicmd:: sharp install seg6-routes [vrf NAME] <A.B.C.D|X:X::X:X> nexthop-seg6 X:X::X:X encap X:X::X:X (1-1000000) This command installs a route for SRv6 Transit behavior (on Linux it is diff --git a/include/linux/seg6_local.h b/include/linux/seg6_local.h index 5312de80b..bb5c8ddfc 100644 --- a/include/linux/seg6_local.h +++ b/include/linux/seg6_local.h @@ -26,6 +26,7 @@ enum { SEG6_LOCAL_IIF, SEG6_LOCAL_OIF, SEG6_LOCAL_BPF, + SEG6_LOCAL_VRFTABLE, __SEG6_LOCAL_MAX, }; #define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1) diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 118bcf780..95fbca17a 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -756,6 +756,7 @@ static int lsp_to_edge_cb(const uint8_t *id, uint32_t metric, bool old_metric, return LSP_ITER_CONTINUE; attr->metric = metric; + SET_FLAG(attr->flags, LS_ATTR_METRIC); /* Get corresponding Edge from Link State Data Base */ edge = get_edge(args->ted, attr); diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index 9a442e037..f1aae7caf 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -3007,28 +3007,55 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, type = stream_getc(s); length = stream_getc(s); + + if (length > STREAM_READABLE(s) || length > subtlv_len - 2) { + sbuf_push( + log, indent, + "WARNING: Router Capability subTLV length too large compared to expected size\n"); + stream_forward_getp(s, STREAM_READABLE(s)); + + return 0; + } + switch (type) { case ISIS_SUBTLV_SID_LABEL_RANGE: /* Check that SRGB is correctly formated */ if (length < SUBTLV_RANGE_LABEL_SIZE || length > SUBTLV_RANGE_INDEX_SIZE) { stream_forward_getp(s, length); - continue; + break; } /* Only one SRGB is supported. Skip subsequent one */ if (rcap->srgb.range_size != 0) { stream_forward_getp(s, length); - continue; + break; } rcap->srgb.flags = stream_getc(s); rcap->srgb.range_size = stream_get3(s); /* Skip Type and get Length of SID Label */ stream_getc(s); size = stream_getc(s); - if (size == ISIS_SUBTLV_SID_LABEL_SIZE) + + if (size == ISIS_SUBTLV_SID_LABEL_SIZE + && length != SUBTLV_RANGE_LABEL_SIZE) { + stream_forward_getp(s, length - 6); + break; + } + + if (size == ISIS_SUBTLV_SID_INDEX_SIZE + && length != SUBTLV_RANGE_INDEX_SIZE) { + stream_forward_getp(s, length - 6); + break; + } + + if (size == ISIS_SUBTLV_SID_LABEL_SIZE) { rcap->srgb.lower_bound = stream_get3(s); - else + } else if (size == ISIS_SUBTLV_SID_INDEX_SIZE) { rcap->srgb.lower_bound = stream_getl(s); + } else { + stream_forward_getp(s, length - 6); + break; + } /* SRGB sanity checks. */ if (rcap->srgb.range_size == 0 @@ -3042,9 +3069,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, /* Only one range is supported. Skip subsequent one */ size = length - (size + SUBTLV_SR_BLOCK_SIZE); if (size > 0) - stream_forward_getp(s, length); + stream_forward_getp(s, size); + break; case ISIS_SUBTLV_ALGORITHM: + if (length == 0) + break; /* Only 2 algorithms are supported: SPF & Strict SPF */ stream_get(&rcap->algo, s, length > SR_ALGORITHM_COUNT @@ -3059,12 +3089,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, if (length < SUBTLV_RANGE_LABEL_SIZE || length > SUBTLV_RANGE_INDEX_SIZE) { stream_forward_getp(s, length); - continue; + break; } /* RFC 8667 section #3.3: Only one SRLB is authorized */ if (rcap->srlb.range_size != 0) { stream_forward_getp(s, length); - continue; + break; } /* Ignore Flags which are not defined */ stream_getc(s); @@ -3072,10 +3102,27 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, /* Skip Type and get Length of SID Label */ stream_getc(s); size = stream_getc(s); - if (size == ISIS_SUBTLV_SID_LABEL_SIZE) + + if (size == ISIS_SUBTLV_SID_LABEL_SIZE + && length != SUBTLV_RANGE_LABEL_SIZE) { + stream_forward_getp(s, length - 6); + break; + } + + if (size == ISIS_SUBTLV_SID_INDEX_SIZE + && length != SUBTLV_RANGE_INDEX_SIZE) { + stream_forward_getp(s, length - 6); + break; + } + + if (size == ISIS_SUBTLV_SID_LABEL_SIZE) { rcap->srlb.lower_bound = stream_get3(s); - else + } else if (size == ISIS_SUBTLV_SID_INDEX_SIZE) { rcap->srlb.lower_bound = stream_getl(s); + } else { + stream_forward_getp(s, length - 6); + break; + } /* SRLB sanity checks. */ if (rcap->srlb.range_size == 0 @@ -3089,13 +3136,14 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, /* Only one range is supported. Skip subsequent one */ size = length - (size + SUBTLV_SR_BLOCK_SIZE); if (size > 0) - stream_forward_getp(s, length); + stream_forward_getp(s, size); + break; case ISIS_SUBTLV_NODE_MSD: /* Check that MSD is correctly formated */ if (length < MSD_TLV_SIZE) { stream_forward_getp(s, length); - continue; + break; } msd_type = stream_getc(s); rcap->msd = stream_getc(s); diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index 38470ef85..0c6ed11cb 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -447,6 +447,7 @@ enum ext_subtlv_size { /* RFC 8667 sections #2 & #3 */ ISIS_SUBTLV_SID_LABEL_SIZE = 3, + ISIS_SUBTLV_SID_INDEX_SIZE = 4, ISIS_SUBTLV_SID_LABEL_RANGE_SIZE = 9, ISIS_SUBTLV_ALGORITHM_SIZE = 4, ISIS_SUBTLV_ADJ_SID_SIZE = 5, diff --git a/lib/cspf.c b/lib/cspf.c new file mode 100644 index 000000000..ef3e7c2fa --- /dev/null +++ b/lib/cspf.c @@ -0,0 +1,646 @@ +/* + * Constraints Shortest Path First algorithms - cspf.c + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2022 Orange http://www.orange.com + * + * This file is part of Free Range Routing (FRR). + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "if.h" +#include "linklist.h" +#include "log.h" +#include "hash.h" +#include "memory.h" +#include "prefix.h" +#include "table.h" +#include "stream.h" +#include "printfrr.h" +#include "link_state.h" +#include "cspf.h" + +/* Link State Memory allocation */ +DEFINE_MTYPE_STATIC(LIB, PCA, "Path Computation Algorithms"); + +/** + * Create new Constrained Path. Memory is dynamically allocated. + * + * @param key Vertex key of the destination of this path + * + * @return Pointer to a new Constrained Path structure + */ +static struct c_path *cpath_new(uint64_t key) +{ + struct c_path *path; + + /* Sanity Check */ + if (key == 0) + return NULL; + + path = XCALLOC(MTYPE_PCA, sizeof(struct c_path)); + path->dst = key; + path->status = IN_PROGRESS; + path->edges = list_new(); + path->weight = MAX_COST; + + return path; +} + +/** + * Copy src Constrained Path into dst Constrained Path. A new Constrained Path + * structure is dynamically allocated if dst is NULL. If src is NULL, the + * function return the dst disregarding if it is NULL or not. + * + * @param dest Destination Constrained Path structure + * @param src Source Constrained Path structure + * + * @return Pointer to the destination Constrained Path structure + */ +static struct c_path *cpath_copy(struct c_path *dest, const struct c_path *src) +{ + struct c_path *new_path; + + if (!src) + return dest; + + if (!dest) { + new_path = XCALLOC(MTYPE_PCA, sizeof(struct c_path)); + } else { + new_path = dest; + if (dest->edges) + list_delete(&new_path->edges); + } + + new_path->dst = src->dst; + new_path->weight = src->weight; + new_path->edges = list_dup(src->edges); + new_path->status = src->status; + + return new_path; +} + +/** + * Delete Constrained Path structure. Previous allocated memory is freed. + * + * @param path Constrained Path structure to be deleted + */ +static void cpath_del(struct c_path *path) +{ + if (!path) + return; + + if (path->edges) + list_delete(&path->edges); + + XFREE(MTYPE_PCA, path); + path = NULL; +} + +/** + * Replace the list of edges in the next Constrained Path by the list of edges + * in the current Constrained Path. + * + * @param next_path next Constrained Path structure + * @param cur_path current Constrained Path structure + */ +static void cpath_replace(struct c_path *next_path, struct c_path *cur_path) +{ + + if (next_path->edges) + list_delete(&next_path->edges); + + next_path->edges = list_dup(cur_path->edges); +} + +/** + * Create a new Visited Node structure from the provided Vertex. Structure is + * dynamically allocated. + * + * @param vertex Vertex structure + * + * @return Pointer to the new Visited Node structure + */ +static struct v_node *vnode_new(struct ls_vertex *vertex) +{ + struct v_node *vnode; + + if (!vertex) + return NULL; + + vnode = XCALLOC(MTYPE_PCA, sizeof(struct v_node)); + vnode->vertex = vertex; + vnode->key = vertex->key; + + return vnode; +} + +/** + * Delete Visited Node structure. Previous allocated memory is freed. + * + * @param vnode Visited Node structure to be deleted + */ +static void vnode_del(struct v_node *vnode) +{ + if (!vnode) + return; + + XFREE(MTYPE_PCA, vnode); + vnode = NULL; +} + +/** + * Search Vertex in TED by IPv4 address. The function search vertex by browsing + * the subnets table. It allows to find not only vertex by router ID, but also + * vertex by interface IPv4 address. + * + * @param ted Traffic Engineering Database + * @param ipv4 IPv4 address + * + * @return Vertex if found, NULL otherwise + */ +static struct ls_vertex *get_vertex_by_ipv4(struct ls_ted *ted, + struct in_addr ipv4) +{ + struct ls_subnet *subnet; + struct prefix p; + + p.family = AF_INET; + p.u.prefix4 = ipv4; + + frr_each (subnets, &ted->subnets, subnet) { + if (subnet->key.family != AF_INET) + continue; + p.prefixlen = subnet->key.prefixlen; + if (prefix_same(&subnet->key, &p)) + return subnet->vertex; + } + + return NULL; +} + +/** + * Search Vertex in TED by IPv6 address. The function search vertex by browsing + * the subnets table. It allows to find not only vertex by router ID, but also + * vertex by interface IPv6 address. + * + * @param ted Traffic Engineering Database + * @param ipv6 IPv6 address + * + * @return Vertex if found, NULL otherwise + */ +static struct ls_vertex *get_vertex_by_ipv6(struct ls_ted *ted, + struct in6_addr ipv6) +{ + struct ls_subnet *subnet; + struct prefix p; + + p.family = AF_INET6; + p.u.prefix6 = ipv6; + + frr_each (subnets, &ted->subnets, subnet) { + if (subnet->key.family != AF_INET6) + continue; + p.prefixlen = subnet->key.prefixlen; + if (prefix_cmp(&subnet->key, &p) == 0) + return subnet->vertex; + } + + return NULL; +} + +struct cspf *cspf_new(void) +{ + struct cspf *algo; + + /* Allocate New CSPF structure */ + algo = XCALLOC(MTYPE_PCA, sizeof(struct cspf)); + + /* Initialize RB-Trees */ + processed_init(&algo->processed); + visited_init(&algo->visited); + pqueue_init(&algo->pqueue); + + algo->path = NULL; + algo->pdst = NULL; + + return algo; +} + +struct cspf *cspf_init(struct cspf *algo, const struct ls_vertex *src, + const struct ls_vertex *dst, struct constraints *csts) +{ + struct cspf *new_algo; + struct c_path *psrc; + + if (!csts) + return NULL; + + if (!algo) + new_algo = cspf_new(); + else + new_algo = algo; + + /* Initialize Processed Path and Priority Queue with Src & Dst */ + if (src) { + psrc = cpath_new(src->key); + psrc->weight = 0; + processed_add(&new_algo->processed, psrc); + pqueue_add(&new_algo->pqueue, psrc); + new_algo->path = psrc; + } + if (dst) { + new_algo->pdst = cpath_new(dst->key); + processed_add(&new_algo->processed, new_algo->pdst); + } + + memcpy(&new_algo->csts, csts, sizeof(struct constraints)); + + return new_algo; +} + +struct cspf *cspf_init_v4(struct cspf *algo, struct ls_ted *ted, + const struct in_addr src, const struct in_addr dst, + struct constraints *csts) +{ + struct ls_vertex *vsrc; + struct ls_vertex *vdst; + struct cspf *new_algo; + + /* Sanity Check */ + if (!ted) + return algo; + + if (!algo) + new_algo = cspf_new(); + else + new_algo = algo; + + /* Got Source and Destination Vertex from TED */ + vsrc = get_vertex_by_ipv4(ted, src); + vdst = get_vertex_by_ipv4(ted, dst); + csts->family = AF_INET; + + return cspf_init(new_algo, vsrc, vdst, csts); +} + +struct cspf *cspf_init_v6(struct cspf *algo, struct ls_ted *ted, + const struct in6_addr src, const struct in6_addr dst, + struct constraints *csts) +{ + struct ls_vertex *vsrc; + struct ls_vertex *vdst; + struct cspf *new_algo; + + /* Sanity Check */ + if (!ted) + return algo; + + if (!algo) + new_algo = cspf_new(); + else + new_algo = algo; + + /* Got Source and Destination Vertex from TED */ + vsrc = get_vertex_by_ipv6(ted, src); + vdst = get_vertex_by_ipv6(ted, dst); + csts->family = AF_INET6; + + return cspf_init(new_algo, vsrc, vdst, csts); +} + +void cspf_clean(struct cspf *algo) +{ + struct c_path *path; + struct v_node *vnode; + + if (!algo) + return; + + /* Normally, Priority Queue is empty. Clean it in case of. */ + if (pqueue_count(&algo->pqueue)) { + frr_each_safe (pqueue, &algo->pqueue, path) { + pqueue_del(&algo->pqueue, path); + } + } + + /* Empty Processed Path tree and associated Path */ + if (processed_count(&algo->processed)) { + frr_each_safe (processed, &algo->processed, path) { + processed_del(&algo->processed, path); + cpath_del(path); + } + } + + /* Empty visited Vertex tree and associated Node */ + if (visited_count(&algo->visited)) { + frr_each_safe (visited, &algo->visited, vnode) { + visited_del(&algo->visited, vnode); + vnode_del(vnode); + } + } + + memset(&algo->csts, 0, sizeof(struct constraints)); + algo->path = NULL; + algo->pdst = NULL; +} + +void cspf_del(struct cspf *algo) +{ + if (!algo) + return; + + /* Empty Priority Queue and Processes Path */ + cspf_clean(algo); + + /* Then, reset Priority Queue, Processed Path and Visited RB-Tree */ + pqueue_fini(&algo->pqueue); + processed_fini(&algo->processed); + visited_fini(&algo->visited); + + XFREE(MTYPE_PCA, algo); + algo = NULL; +} + +/** + * Prune Edge if constraints are not met by testing Edge Attributes against + * given constraints and cumulative cost of the given constrained path. + * + * @param path On-going Computed Path with cumulative cost constraints + * @param edge Edge to be validate against Constraints + * @param csts Constraints for this path + * + * @return True if Edge should be prune, false if Edge is valid + */ +static bool prune_edge(const struct c_path *path, const struct ls_edge *edge, + const struct constraints *csts) +{ + struct ls_vertex *dst; + struct ls_attributes *attr; + + /* Check that Path, Edge and Constraints are valid */ + if (!path || !edge || !csts) + return true; + + /* Check that Edge has a valid destination */ + if (!edge->destination) + return true; + dst = edge->destination; + + /* Check that Edge has valid attributes */ + if (!edge->attributes) + return true; + attr = edge->attributes; + + /* Check that Edge belongs to the requested Address Family and type */ + if (csts->family == AF_INET) { + if (IPV4_NET0(attr->standard.local.s_addr)) + return true; + if (csts->type == SR_TE) + if (!CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID) || + !CHECK_FLAG(dst->node->flags, LS_NODE_SR)) + return true; + } + if (csts->family == AF_INET6) { + if (IN6_IS_ADDR_UNSPECIFIED(&attr->standard.local6)) + return true; + if (csts->type == SR_TE) + if (!CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6) || + !CHECK_FLAG(dst->node->flags, LS_NODE_SR)) + return true; + } + + /* + * Check that total cost, up to this edge, respects the initial + * constraints + */ + switch (csts->ctype) { + case CSPF_METRIC: + if (!CHECK_FLAG(attr->flags, LS_ATTR_METRIC)) + return true; + if ((attr->metric + path->weight) > csts->cost) + return true; + break; + + case CSPF_TE_METRIC: + if (!CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC)) + return true; + if ((attr->standard.te_metric + path->weight) > csts->cost) + return true; + break; + + case CSPF_DELAY: + if (!CHECK_FLAG(attr->flags, LS_ATTR_DELAY)) + return true; + if ((attr->extended.delay + path->weight) > csts->cost) + return true; + break; + } + + /* If specified, check that Edge meet Bandwidth constraint */ + if (csts->bw > 0.0) { + if (attr->standard.max_bw < csts->bw || + attr->standard.max_rsv_bw < csts->bw || + attr->standard.unrsv_bw[csts->cos] < csts->bw) + return true; + } + + /* All is fine. We can consider this Edge valid, so not to be prune */ + return false; +} + +/** + * Relax constraints of the current path up to the destination vertex of the + * provided Edge. This function progress in the network topology by validating + * the next vertex on the computed path. If Vertex has not already been visited, + * list of edges of the current path is augmented with this edge if the new cost + * is lower than prior path up to this vertex. Current path is re-inserted in + * the Priority Queue with its new cost i.e. current cost + edge cost. + * + * @param algo CSPF structure + * @param edge Next Edge to be added to the current computed path + * + * @return True if current path reach destination, false otherwise + */ +static bool relax_constraints(struct cspf *algo, struct ls_edge *edge) +{ + + struct c_path pkey = {}; + struct c_path *next_path; + struct v_node vnode = {}; + uint32_t total_cost = MAX_COST; + + /* Verify that we have a current computed path */ + if (!algo->path) + return false; + + /* Verify if we have not visited the next Vertex to avoid loop */ + vnode.key = edge->destination->key; + if (visited_member(&algo->visited, &vnode)) { + return false; + } + + /* + * Get Next Computed Path from next vertex key + * or create a new one if it has not yet computed. + */ + pkey.dst = edge->destination->key; + next_path = processed_find(&algo->processed, &pkey); + if (!next_path) { + next_path = cpath_new(pkey.dst); + processed_add(&algo->processed, next_path); + } + + /* + * Add or update the Computed Path in the Priority Queue if total cost + * is lower than cost associated to this next Vertex. This could occurs + * if we process a Vertex that as not yet been visited in the Graph + * or if we found a shortest path up to this Vertex. + */ + switch (algo->csts.ctype) { + case CSPF_METRIC: + total_cost = edge->attributes->metric + algo->path->weight; + break; + case CSPF_TE_METRIC: + total_cost = edge->attributes->standard.te_metric + + algo->path->weight; + break; + case CSPF_DELAY: + total_cost = + edge->attributes->extended.delay + algo->path->weight; + break; + default: + break; + } + if (total_cost < next_path->weight) { + /* + * It is not possible to directly update the q_path in the + * Priority Queue. Indeed, if we modify the path weight, the + * Priority Queue must be re-ordered. So, we need fist to remove + * the q_path if it is present in the Priority Queue, then, + * update the Path, in particular the Weight, and finally + * (re-)insert it in the Priority Queue. + */ + struct c_path *path; + frr_each_safe (pqueue, &algo->pqueue, path) { + if (path->dst == pkey.dst) { + pqueue_del(&algo->pqueue, path); + break; + } + } + next_path->weight = total_cost; + cpath_replace(next_path, algo->path); + listnode_add(next_path->edges, edge); + pqueue_add(&algo->pqueue, next_path); + } + + /* Return True if we reach the destination */ + return (next_path->dst == algo->pdst->dst); +} + +struct c_path *compute_p2p_path(struct cspf *algo, struct ls_ted *ted) +{ + struct listnode *node; + struct ls_vertex *vertex; + struct ls_edge *edge; + struct c_path *optim_path; + struct v_node *vnode; + uint32_t cur_cost; + + optim_path = cpath_new(0xFFFFFFFFFFFFFFFF); + optim_path->status = FAILED; + + /* Check that all is correctly initialized */ + if (!algo) + return optim_path; + + if (!algo->csts.ctype) + return optim_path; + + if (!algo->pdst) { + optim_path->status = NO_DESTINATION; + return optim_path; + } + + if (!algo->path) { + optim_path->status = NO_SOURCE; + return optim_path; + } + + if (algo->pdst->dst == algo->path->dst) { + optim_path->status = SAME_SRC_DST; + return optim_path; + } + + optim_path->dst = algo->pdst->dst; + optim_path->status = IN_PROGRESS; + + /* + * Process all Connected Vertex until priority queue becomes empty. + * Connected Vertices are added into the priority queue when + * processing the next Connected Vertex: see relax_constraints() + */ + cur_cost = MAX_COST; + while (pqueue_count(&algo->pqueue) != 0) { + /* Got shortest current Path from the Priority Queue */ + algo->path = pqueue_pop(&algo->pqueue); + + /* Add destination Vertex of this path to the visited RB Tree */ + vertex = ls_find_vertex_by_key(ted, algo->path->dst); + if (!vertex) + continue; + vnode = vnode_new(vertex); + visited_add(&algo->visited, vnode); + + /* Process all outgoing links from this Vertex */ + for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) { + /* + * Skip Connected Edges that must be prune i.e. + * Edges that not satisfy the given constraints, + * in particular the Bandwidth, TE Metric and Delay. + */ + if (prune_edge(algo->path, edge, &algo->csts)) + continue; + + /* + * Relax constraints and check if we got a shorter + * candidate path + */ + if (relax_constraints(algo, edge) && + algo->pdst->weight < cur_cost) { + cur_cost = algo->pdst->weight; + cpath_copy(optim_path, algo->pdst); + optim_path->status = SUCCESS; + } + } + } + + /* + * The priority queue is empty => all the possible (vertex, path) + * elements have been explored. The optim_path contains the optimal + * path if it exists. Otherwise an empty path with status failed is + * returned. + */ + if (optim_path->status == IN_PROGRESS || + listcount(optim_path->edges) == 0) + optim_path->status = FAILED; + cspf_clean(algo); + + return optim_path; +} diff --git a/lib/cspf.h b/lib/cspf.h new file mode 100644 index 000000000..6466ddb25 --- /dev/null +++ b/lib/cspf.h @@ -0,0 +1,211 @@ +/* + * Constraints Shortest Path First algorithms definition - cspf.h + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2022 Orange http://www.orange.com + * + * This file is part of Free Range Routing (FRR). + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_CSPF_H_ +#define _FRR_CSPF_H_ + +#include "typesafe.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This file defines the different structure used for Path Computation with + * various constrained. Up to now, standard metric, TE metric, delay and + * bandwidth constraints are supported. + * All proposed algorithms used the same principle: + * - A pruning function that keeps only links that meet constraints + * - A priority Queue that keeps the shortest on-going computed path + * - A main loop over all vertices to find the shortest path + */ + +#define MAX_COST 0xFFFFFFFF + +/* Status of the path */ +enum path_status { + FAILED = 0, + NO_SOURCE, + NO_DESTINATION, + SAME_SRC_DST, + IN_PROGRESS, + SUCCESS +}; +enum path_type {RSVP_TE = 1, SR_TE, SRV6_TE}; +enum metric_type {CSPF_METRIC = 1, CSPF_TE_METRIC, CSPF_DELAY}; + +/* Constrained metrics structure */ +struct constraints { + uint32_t cost; /* total cost (metric) of the path */ + enum metric_type ctype; /* Metric Type: standard, TE or Delay */ + float bw; /* bandwidth of the path */ + uint8_t cos; /* Class of Service of the path */ + enum path_type type; /* RSVP-TE or SR-TE path */ + uint8_t family; /* AF_INET or AF_INET6 address family */ +}; + +/* Priority Queue for Constrained Path Computation */ +PREDECL_RBTREE_NONUNIQ(pqueue); + +/* Processed Path for Constrained Path Computation */ +PREDECL_RBTREE_UNIQ(processed); + +/* Constrained Path structure */ +struct c_path { + struct pqueue_item q_itm; /* entry in the Priority Queue */ + uint32_t weight; /* Weight to sort path in Priority Queue */ + struct processed_item p_itm; /* entry in the Processed RB Tree */ + uint64_t dst; /* Destination vertex key of this path */ + struct list *edges; /* List of Edges that compose this path */ + enum path_status status; /* status of the computed path */ +}; + +macro_inline int q_cmp(const struct c_path *p1, const struct c_path *p2) +{ + return numcmp(p1->weight, p2->weight); +} +DECLARE_RBTREE_NONUNIQ(pqueue, struct c_path, q_itm, q_cmp); + +macro_inline int p_cmp(const struct c_path *p1, const struct c_path *p2) +{ + return numcmp(p1->dst, p2->dst); +} +DECLARE_RBTREE_UNIQ(processed, struct c_path, p_itm, p_cmp); + +/* List of visited node */ +PREDECL_RBTREE_UNIQ(visited); +struct v_node { + struct visited_item item; /* entry in the Processed RB Tree */ + uint64_t key; + struct ls_vertex *vertex; +}; + +macro_inline int v_cmp(const struct v_node *p1, const struct v_node *p2) +{ + return numcmp(p1->key, p2->key); +} +DECLARE_RBTREE_UNIQ(visited, struct v_node, item, v_cmp); + +/* Path Computation algorithms structure */ +struct cspf { + struct pqueue_head pqueue; /* Priority Queue */ + struct processed_head processed; /* Paths that have been processed */ + struct visited_head visited; /* Vertices that have been visited */ + struct constraints csts; /* Constraints of the path */ + struct c_path *path; /* Current Computed Path */ + struct c_path *pdst; /* Computed Path to the destination */ +}; + +/** + * Create a new CSPF structure. Memory is dynamically allocated. + * + * @return pointer to the new cspf structure + */ +extern struct cspf *cspf_new(void); + +/** + * Initialize CSPF structure prior to compute a constrained path. If CSPF + * structure is NULL, a new CSPF is dynamically allocated prior to the + * configuration itself. + * + * @param algo CSPF structure, may be null if a new CSPF must be created + * @param src Source vertex of the requested path + * @param dst Destination vertex of the requested path + * @param csts Constraints of the requested path + * + * @return pointer to the initialized CSPF structure + */ +extern struct cspf *cspf_init(struct cspf *algo, const struct ls_vertex *src, + const struct ls_vertex *dst, + struct constraints *csts); + +/** + * Initialize CSPF structure prior to compute a constrained path. If CSPF + * structure is NULL, a new CSPF is dynamically allocated prior to the + * configuration itself. This function starts by searching source and + * destination vertices from the IPv4 addresses in the provided TED. + * + * @param algo CSPF structure, may be null if a new CSPF must be created + * @param ted Traffic Engineering Database + * @param src Source IPv4 address of the requested path + * @param dst Destination IPv4 address of the requested path + * @param csts Constraints of the requested path + * + * @return pointer to the initialized CSPF structure + */ +extern struct cspf *cspf_init_v4(struct cspf *algo, struct ls_ted *ted, + const struct in_addr src, + const struct in_addr dst, + struct constraints *csts); + +/** + * Initialize CSPF structure prior to compute a constrained path. If CSPF + * structure is NULL, a new CSPF is dynamically allocated prior to the + * configuration itself. This function starts by searching source and + * destination vertices from the IPv6 addresses in the provided TED. + * + * @param algo CSPF structure, may be null if a new CSPF must be created + * @param ted Traffic Engineering Database + * @param src Source IPv6 address of the requested path + * @param dst Destination IPv6 address of the requested path + * @param csts Constraints of the requested path + * + * @return pointer to the initialized CSPF structure + */ +extern struct cspf *cspf_init_v6(struct cspf *algo, struct ls_ted *ted, + const struct in6_addr src, + const struct in6_addr dst, + struct constraints *csts); + +/** + * Clean CSPF structure. Reset all internal list and priority queue for latter + * initialization of the CSPF structure and new path computation. + * + * @param algo CSPF structure + */ +extern void cspf_clean(struct cspf *algo); + +/** + * Delete CSPF structure, internal list and priority queue. + * + * @param algo CSPF structure + */ +extern void cspf_del(struct cspf *algo); + +/** + * Compute point-to-point constrained path. cspf_init() function must be call + * prior to call this function. + * + * @param algo CSPF structure + * @param ted Traffic Engineering Database + * + * @return Constrained Path with status to indicate computation success + */ +extern struct c_path *compute_p2p_path(struct cspf *algo, struct ls_ted *ted); + +#ifdef __cplusplus +} +#endif + +#endif /* _FRR_CSPF_H_ */ diff --git a/lib/filter_nb.c b/lib/filter_nb.c index 80ea7a57c..35b97a9bd 100644 --- a/lib/filter_nb.c +++ b/lib/filter_nb.c @@ -1135,7 +1135,7 @@ static int lib_access_list_entry_any_destroy(struct nb_cb_destroy_args *args) f = nb_running_get_entry(args->dnode, NULL, true); fz = &f->u.zfilter; - fz->prefix.family = 0; + fz->prefix.family = AF_UNSPEC; acl_notify_route_map(f->acl, RMAP_EVENT_FILTER_DELETED); @@ -1090,9 +1090,6 @@ struct if_link_params *if_link_params_get(struct interface *ifp) struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params)); - /* Set TE metric equal to standard metric */ - iflp->te_metric = ifp->metric; - /* Compute default bandwidth based on interface */ iflp->default_bw = ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) @@ -1105,8 +1102,13 @@ struct if_link_params *if_link_params_get(struct interface *ifp) iflp->unrsv_bw[i] = iflp->default_bw; /* Update Link parameters status */ - iflp->lp_status = - LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; + iflp->lp_status = LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; + + /* Set TE metric equal to standard metric only if it is set */ + if (ifp->metric != 0) { + iflp->te_metric = ifp->metric; + iflp->lp_status |= LP_TE_METRIC; + } /* Finally attach newly created Link Parameters */ ifp->link_params = iflp; diff --git a/lib/prefix.h b/lib/prefix.h index f2773240d..b3545a72b 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -341,9 +341,6 @@ union prefixconstptr { prefixtype(prefixconstptr, const struct prefix_rd, rd) } TRANSPARENT_UNION; -#undef prefixtype -#undef TRANSPARENT_UNION - #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif /* INET_ADDRSTRLEN */ diff --git a/lib/subdir.am b/lib/subdir.am index bb10d71ed..2cd329c8a 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -16,6 +16,7 @@ lib_libfrr_la_SOURCES = \ lib/command_lex.l \ lib/command_match.c \ lib/command_parse.y \ + lib/cspf.c \ lib/csv.c \ lib/debug.c \ lib/defaults.c \ @@ -182,6 +183,7 @@ pkginclude_HEADERS += \ lib/command_graph.h \ lib/command_match.h \ lib/compiler.h \ + lib/cspf.h \ lib/csv.h \ lib/db.h \ lib/debug.h \ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 8cb85b462..f44e1dde8 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -223,8 +223,15 @@ struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf, id.s_addr = p->prefix.s_addr | (~mask.s_addr); lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, id, ospf->router_id); - if (lsa) + if (lsa) { + if (p->prefixlen == IPV4_MAX_BITLEN) { + al = (struct as_external_lsa *)lsa->data; + + if (mask.s_addr != al->mask.s_addr) + return NULL; + } return lsa; + } lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, p->prefix, ospf->router_id); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index c169996e0..e3ba1f1dd 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -53,6 +53,29 @@ #include "ospfd/ospf_abr.h" #include "ospfd/ospf_errors.h" +static struct ospf_lsa *ospf_handle_summarylsa_lsId_chg(struct ospf *ospf, + struct prefix_ipv4 *p, + uint8_t type, + uint32_t metric, + struct in_addr old_id); +static struct ospf_lsa * +ospf_summary_lsa_prepare_and_flood(struct prefix_ipv4 *p, uint32_t metric, + struct ospf_area *area, struct in_addr id); +static struct ospf_lsa *ospf_summary_lsa_refresh(struct ospf *ospf, + struct ospf_lsa *lsa); +static struct ospf_lsa * +ospf_asbr_summary_lsa_prepare_and_flood(struct prefix_ipv4 *p, uint32_t metric, + struct ospf_area *area, + struct in_addr id); +static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf, + struct ospf_lsa *lsa); +static struct ospf_lsa *ospf_handle_exnl_lsa_lsId_chg(struct ospf *ospf, + struct external_info *ei, + struct in_addr id); +static struct ospf_lsa * +ospf_exnl_lsa_prepare_and_flood(struct ospf *ospf, struct external_info *ei, + struct in_addr id); + uint32_t get_metric(uint8_t *metric) { uint32_t m; @@ -1221,31 +1244,11 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area, } /* Originate Summary-LSA. */ -struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, - uint32_t metric, - struct ospf_area *area) +static struct ospf_lsa * +ospf_summary_lsa_prepare_and_flood(struct prefix_ipv4 *p, uint32_t metric, + struct ospf_area *area, struct in_addr id) { struct ospf_lsa *new; - struct in_addr id; - - if (area->ospf->gr_info.restart_in_progress) { - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type%d]: Graceful Restart in progress, don't originate", - OSPF_SUMMARY_LSA); - return NULL; - } - - id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); - - if (id.s_addr == 0xffffffff) { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type%d]: Link ID not available, can't originate", - OSPF_SUMMARY_LSA); - return NULL; - } /* Create new summary-LSA instance. */ if (!(new = ospf_summary_lsa_new(area, (struct prefix *)p, metric, id))) @@ -1270,6 +1273,97 @@ struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, return new; } +static struct ospf_lsa *ospf_handle_summarylsa_lsId_chg(struct ospf *ospf, + struct prefix_ipv4 *p, + uint8_t type, + uint32_t metric, + struct in_addr old_id) +{ + struct ospf_lsa *lsa = NULL; + struct ospf_lsa *new = NULL; + struct summary_lsa *sl = NULL; + struct ospf_area *old_area = NULL; + struct prefix_ipv4 old_prefix; + uint32_t old_metric; + struct in_addr mask; + uint32_t metric_val; + char *metric_buf; + + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, p->prefix, + ospf->router_id); + + if (!lsa) { + flog_warn(EC_OSPF_LSA_NULL, "(%s): LSA not found", __func__); + return NULL; + } + + sl = (struct summary_lsa *)lsa->data; + + old_area = lsa->area; + old_metric = GET_METRIC(sl->metric); + old_prefix.prefix = sl->header.id; + old_prefix.prefixlen = ip_masklen(sl->mask); + old_prefix.family = AF_INET; + + + /* change the mask */ + masklen2ip(p->prefixlen, &mask); + sl->mask.s_addr = mask.s_addr; + + /* Copy the metric*/ + metric_val = htonl(metric); + metric_buf = (char *)&metric_val; + memcpy(sl->metric, metric_buf, sizeof(metric_val)); + + if (type == OSPF_SUMMARY_LSA) { + /*Refresh the LSA with new LSA*/ + ospf_summary_lsa_refresh(ospf, lsa); + + new = ospf_summary_lsa_prepare_and_flood( + &old_prefix, old_metric, old_area, old_id); + } else { + /*Refresh the LSA with new LSA*/ + ospf_summary_asbr_lsa_refresh(ospf, lsa); + + new = ospf_asbr_summary_lsa_prepare_and_flood( + &old_prefix, old_metric, old_area, old_id); + } + + return new; +} + +/* Originate Summary-LSA. */ +struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, + uint32_t metric, + struct ospf_area *area) +{ + struct in_addr id; + enum lsid_status status; + struct ospf_lsa *new = NULL; + + status = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p, + &id); + + if (status == LSID_CHANGE) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("Link ID has to be changed."); + + new = ospf_handle_summarylsa_lsId_chg( + area->ospf, p, OSPF_SUMMARY_LSA, metric, id); + return new; + } else if (status == LSID_NOT_AVAILABLE) { + /* Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: Link ID not available, can't originate"); + + return NULL; + } + + new = ospf_summary_lsa_prepare_and_flood(p, metric, area, id); + return new; +} + static struct ospf_lsa *ospf_summary_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) { @@ -1370,32 +1464,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area, } /* Originate summary-ASBR-LSA. */ -struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, - uint32_t metric, - struct ospf_area *area) +static struct ospf_lsa * +ospf_asbr_summary_lsa_prepare_and_flood(struct prefix_ipv4 *p, uint32_t metric, + struct ospf_area *area, + struct in_addr id) { struct ospf_lsa *new; - struct in_addr id; - - if (area->ospf->gr_info.restart_in_progress) { - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type%d]: Graceful Restart in progress, don't originate", - OSPF_ASBR_SUMMARY_LSA); - return NULL; - } - - id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, - p); - - if (id.s_addr == 0xffffffff) { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type%d]: Link ID not available, can't originate", - OSPF_ASBR_SUMMARY_LSA); - return NULL; - } /* Create new summary-LSA instance. */ new = ospf_summary_asbr_lsa_new(area, (struct prefix *)p, metric, id); @@ -1421,6 +1495,37 @@ struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, return new; } +struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, + uint32_t metric, + struct ospf_area *area) +{ + struct ospf_lsa *new; + struct in_addr id; + enum lsid_status status; + + status = ospf_lsa_unique_id(area->ospf, area->lsdb, + OSPF_ASBR_SUMMARY_LSA, p, &id); + + if (status == LSID_CHANGE) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("Link ID has to be changed."); + + new = ospf_handle_summarylsa_lsId_chg( + area->ospf, p, OSPF_ASBR_SUMMARY_LSA, metric, id); + return new; + } else if (status == LSID_NOT_AVAILABLE) { + /* Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: Link ID not available, can't originate"); + + return NULL; + } + + new = ospf_asbr_summary_lsa_prepare_and_flood(p, metric, area, id); + return new; +} + static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) { @@ -1612,42 +1717,15 @@ static void ospf_external_lsa_body_set(struct stream *s, } /* Create new external-LSA. */ -static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, - struct external_info *ei, - struct in_addr *old_id) +static struct ospf_lsa * +ospf_exnl_lsa_prepare_and_flood(struct ospf *ospf, struct external_info *ei, + struct in_addr id) { struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new; - struct in_addr id; int length; - if (ei == NULL) { - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type5]: External info is NULL, can't originate"); - return NULL; - } - - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug("LSA[Type5]: Originate AS-external-LSA instance"); - - /* If old Link State ID is specified, refresh LSA with same ID. */ - if (old_id) - id = *old_id; - /* Get Link State with unique ID. */ - else { - id = ospf_lsa_unique_id(ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, - &ei->p); - if (id.s_addr == 0xffffffff) { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) - zlog_debug( - "LSA[Type5]: Link ID not available, can't originate"); - return NULL; - } - } - /* Create new stream for LSA. */ s = stream_new(OSPF_MAX_LSA_SIZE); lsah = (struct lsa_header *)STREAM_DATA(s); @@ -1677,6 +1755,99 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, return new; } +static struct ospf_lsa *ospf_handle_exnl_lsa_lsId_chg(struct ospf *ospf, + struct external_info *ei, + struct in_addr id) +{ + struct ospf_lsa *lsa; + struct as_external_lsa *al; + struct in_addr mask; + struct ospf_lsa *new; + struct external_info ei_summary; + struct external_info *ei_old; + + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, + ei->p.prefix, ospf->router_id); + + if (!lsa) { + flog_warn(EC_OSPF_LSA_NULL, "(%s): LSA not found", __func__); + return NULL; + } + + ei_old = ospf_external_info_check(ospf, lsa); + + al = (struct as_external_lsa *)lsa->data; + + if (!ei_old) { + /* eii_old pointer of LSA is NULL, this + * must be external aggregate route. + */ + ei_summary.p.family = AF_INET; + ei_summary.p.prefix = al->header.id; + ei_summary.p.prefixlen = ip_masklen(al->mask); + ei_summary.tag = (unsigned long)ntohl(al->e[0].route_tag); + ei_old = &ei_summary; + } + + /* change the mask */ + masklen2ip(ei->p.prefixlen, &mask); + al->mask.s_addr = mask.s_addr; + + /*Refresh the LSA with new LSA*/ + ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE, 0); + + /*Originate the old LSA with changed LSID*/ + new = ospf_exnl_lsa_prepare_and_flood(ospf, ei_old, id); + + return new; +} + +static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, + struct external_info *ei, + struct in_addr *old_id) +{ + struct ospf_lsa *new; + struct in_addr id; + enum lsid_status status; + + if (ei == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: External info is NULL, can't originate"); + return NULL; + } + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type5]: Originate AS-external-LSA instance"); + + /* If old Link State ID is specified, refresh LSA with same ID. */ + if (old_id) + id = *old_id; + /* Get Link State with unique ID. */ + else { + status = ospf_lsa_unique_id(ospf, ospf->lsdb, + OSPF_AS_EXTERNAL_LSA, &ei->p, &id); + + if (status == LSID_CHANGE) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("Link ID has to be changed."); + + new = ospf_handle_exnl_lsa_lsId_chg(ospf, ei, id); + return new; + } else if (status == LSID_NOT_AVAILABLE) { + /* Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: Link ID not available, can't originate"); + return NULL; + } + } + + new = ospf_exnl_lsa_prepare_and_flood(ospf, ei, id); + + return new; +} + /* As Type-7 */ static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa, struct external_info *ei) @@ -2983,7 +3154,7 @@ void ospf_lsa_maxage_delete(struct ospf *ospf, struct ospf_lsa *lsa) struct prefix lsa_prefix; memset(&lsa_prefix, 0, sizeof(struct prefix)); - lsa_prefix.family = 0; + lsa_prefix.family = AF_UNSPEC; lsa_prefix.prefixlen = sizeof(lsa_prefix.u.ptr) * CHAR_BIT; lsa_prefix.u.ptr = (uintptr_t)lsa; @@ -3024,7 +3195,7 @@ void ospf_lsa_maxage(struct ospf *ospf, struct ospf_lsa *lsa) } memset(&lsa_prefix, 0, sizeof(struct prefix)); - lsa_prefix.family = 0; + lsa_prefix.family = AF_UNSPEC; lsa_prefix.prefixlen = sizeof(lsa_prefix.u.ptr) * CHAR_BIT; lsa_prefix.u.ptr = (uintptr_t)lsa; @@ -3509,49 +3680,87 @@ int ospf_lsa_is_self_originated(struct ospf *ospf, struct ospf_lsa *lsa) } /* Get unique Link State ID. */ -struct in_addr ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, - uint8_t type, struct prefix_ipv4 *p) +enum lsid_status ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, + uint8_t type, struct prefix_ipv4 *p, + struct in_addr *id) { struct ospf_lsa *lsa; - struct in_addr mask, id; + struct in_addr mask; - id = p->prefix; + *id = p->prefix; /* Check existence of LSA instance. */ - lsa = ospf_lsdb_lookup_by_id(lsdb, type, id, ospf->router_id); + lsa = ospf_lsdb_lookup_by_id(lsdb, type, *id, ospf->router_id); if (lsa) { struct as_external_lsa *al = (struct as_external_lsa *)lsa->data; + /* Ref rfc2328,Appendex E.1 + * If router already originated the external lsa with lsid + * as the current prefix, and the masklens are same then + * terminate the LSID algorithem. + */ if (ip_masklen(al->mask) == p->prefixlen) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "ospf_lsa_unique_id(): Can't get Link State ID for %pFX", - p); + "%s: Can't get Link State ID for %pFX", + __func__, p); /* id.s_addr = 0; */ - id.s_addr = 0xffffffff; - return id; - } - /* Masklen differs, then apply wildcard mask to Link State ID. - */ - else { + id->s_addr = 0xffffffff; + return LSID_NOT_AVAILABLE; + } else if (ip_masklen(al->mask) < p->prefixlen) { + /* Ref rfc2328,Appendex E.2 + * the current prefix masklen is greater than the + * existing LSA, then generate the Link state ID, + * by setting all host bits in prefix addressa and + * originate. + * + * Eg: 1st Route : 10.0.0.0/16 - LSID:10.0.0.0 + * 2nd Route : 10.0.0.0/24 - LSID:10.0.0.255 + */ masklen2ip(p->prefixlen, &mask); - id.s_addr = p->prefix.s_addr | (~mask.s_addr); - lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, id, + id->s_addr = p->prefix.s_addr | (~mask.s_addr); + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, *id, ospf->router_id); if (lsa) { if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) zlog_debug( - "ospf_lsa_unique_id(): Can't get Link State ID for %pFX", - p); - /* id.s_addr = 0; */ - id.s_addr = 0xffffffff; - return id; + "%s: Can't get Link State ID for %pFX", + __func__, p); + id->s_addr = 0xffffffff; + return LSID_NOT_AVAILABLE; + } + } else { + /* Ref rfc2328,Appendex E.3 + * the current prefix masklen is lesser than the + * existing LSA,then the originated LSA has to be + * refreshed by modifying masklen, cost and tag. + * Originate the old route info with new LSID by + * setting the host bits in prefix address. + * + * Eg: 1st Route : 10.0.0.0/24 - LSID:10.0.0.0 + * 2nd Route : 10.0.0.0/16 - ? + * Since 2nd route mask len is less than firstone + * LSID has to be changed. + * 1st route LSID:10.0.0.255 + * 2nd route LSID:10.0.0.0 + */ + id->s_addr = lsa->data->id.s_addr | (~al->mask.s_addr); + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, *id, + ospf->router_id); + if (lsa && (ip_masklen(al->mask) != IPV4_MAX_BITLEN)) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "%s: Can't get Link State ID for %pFX", + __func__, p); + id->s_addr = 0xffffffff; + return LSID_NOT_AVAILABLE; } + return LSID_CHANGE; } } - return id; + return LSID_AVAILABLE; } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index a97957371..d04d11841 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -208,6 +208,8 @@ struct as_external_lsa { } e[1]; }; +enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE }; + #include "ospfd/ospf_opaque.h" /* Macros. */ @@ -317,8 +319,10 @@ extern struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *, struct ospf_lsa *, struct external_info *, int, bool aggr); -extern struct in_addr ospf_lsa_unique_id(struct ospf *, struct ospf_lsdb *, - uint8_t, struct prefix_ipv4 *); +extern enum lsid_status ospf_lsa_unique_id(struct ospf *ospf, + struct ospf_lsdb *lsdb, + uint8_t type, struct prefix_ipv4 *p, + struct in_addr *addr); extern void ospf_schedule_lsa_flood_area(struct ospf_area *, struct ospf_lsa *); extern void ospf_schedule_lsa_flush_area(struct ospf_area *, struct ospf_lsa *); diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index 86eb14131..b0881c098 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -70,7 +70,7 @@ void ospf_lsdb_cleanup(struct ospf_lsdb *lsdb) void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa) { if (lp && lsa && lsa->data) { - lp->family = 0; + lp->family = AF_UNSPEC; lp->prefixlen = 64; lp->id = lsa->data->id; lp->adv_router = lsa->data->adv_router; @@ -199,7 +199,7 @@ struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, uint8_t type, table = lsdb->type[type].db; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = id; lp.adv_router = adv_router; @@ -226,7 +226,7 @@ struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb, table = lsdb->type[type].db; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = id; lp.adv_router = adv_router; diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 7ec3db789..bf3755686 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -1779,7 +1779,7 @@ static int ospf_snmp_vl_add(struct ospf_vl_data *vl_data) struct route_node *rn; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = vl_data->vl_area_id; lp.adv_router = vl_data->vl_peer; @@ -1798,7 +1798,7 @@ static int ospf_snmp_vl_delete(struct ospf_vl_data *vl_data) struct route_node *rn; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = vl_data->vl_area_id; lp.adv_router = vl_data->vl_peer; @@ -1820,7 +1820,7 @@ static struct ospf_vl_data *ospf_snmp_vl_lookup(struct in_addr *area_id, struct ospf_vl_data *vl_data; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = *area_id; lp.adv_router = *neighbor; @@ -1843,7 +1843,7 @@ static struct ospf_vl_data *ospf_snmp_vl_lookup_next(struct in_addr *area_id, struct ospf_vl_data *vl_data; memset(&lp, 0, sizeof(struct prefix_ls)); - lp.family = 0; + lp.family = AF_UNSPEC; lp.prefixlen = 64; lp.id = *area_id; lp.adv_router = *neighbor; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index c82c8cb42..32d87b9a9 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -652,20 +652,22 @@ DEFUN (ospf_area_range, DEFUN (ospf_area_range_cost, ospf_area_range_cost_cmd, - "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M cost (0-16777215)", + "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M {cost (0-16777215)|substitute A.B.C.D/M}", "OSPF area parameters\n" "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n" "Summarize routes matching address/mask (border routers only)\n" "Area range prefix\n" "User specified metric for this range\n" - "Advertised metric for this range\n") + "Advertised metric for this range\n" + "Announce area range as another prefix\n" + "Network prefix to be announced instead of range\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); int idx_ipv4_number = 1; int idx_ipv4_prefixlen = 3; - int idx_cost = 5; - struct prefix_ipv4 p; + int idx = 4; + struct prefix_ipv4 p, s; struct in_addr area_id; int format; uint32_t cost; @@ -677,8 +679,16 @@ DEFUN (ospf_area_range_cost, ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), format); - cost = strtoul(argv[idx_cost]->arg, NULL, 10); - ospf_area_range_cost_set(ospf, area_id, &p, cost); + if (argv_find(argv, argc, "cost", &idx)) { + cost = strtoul(argv[idx + 1]->arg, NULL, 10); + ospf_area_range_cost_set(ospf, area_id, &p, cost); + } + + idx = 4; + if (argv_find(argv, argc, "substitute", &idx)) { + str2prefix_ipv4(argv[idx + 1]->arg, &s); + ospf_area_range_substitute_set(ospf, area_id, &p, &s); + } return CMD_SUCCESS; } @@ -742,36 +752,6 @@ DEFUN (no_ospf_area_range, return CMD_SUCCESS; } -DEFUN (ospf_area_range_substitute, - ospf_area_range_substitute_cmd, - "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M substitute A.B.C.D/M", - "OSPF area parameters\n" - "OSPF area ID in IP address format\n" - "OSPF area ID as a decimal value\n" - "Summarize routes matching address/mask (border routers only)\n" - "Area range prefix\n" - "Announce area range as another prefix\n" - "Network prefix to be announced instead of range\n") -{ - VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4_prefixlen = 3; - int idx_ipv4_prefixlen_2 = 5; - struct prefix_ipv4 p, s; - struct in_addr area_id; - int format; - - VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); - - ospf_area_range_substitute_set(ospf, area_id, &p, &s); - ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), - format); - - return CMD_SUCCESS; -} - DEFUN (no_ospf_area_range_substitute, no_ospf_area_range_substitute_cmd, "no area <A.B.C.D|(0-4294967295)> range A.B.C.D/M substitute A.B.C.D/M", @@ -6578,7 +6558,7 @@ static void show_lsa_prefix_set(struct vty *vty, struct prefix_ls *lp, struct in_addr *id, struct in_addr *adv_router) { memset(lp, 0, sizeof(struct prefix_ls)); - lp->family = 0; + lp->family = AF_UNSPEC; if (id == NULL) lp->prefixlen = 0; else if (adv_router == NULL) { @@ -12792,7 +12772,6 @@ void ospf_vty_init(void) install_element(OSPF_NODE, &ospf_area_range_cost_cmd); install_element(OSPF_NODE, &ospf_area_range_not_advertise_cmd); install_element(OSPF_NODE, &no_ospf_area_range_cmd); - install_element(OSPF_NODE, &ospf_area_range_substitute_cmd); install_element(OSPF_NODE, &no_ospf_area_range_substitute_cmd); /* "area virtual-link" commands. */ diff --git a/pimd/pim_addr.c b/pimd/pim_addr.c index 8d89b5714..2a6b4fe20 100644 --- a/pimd/pim_addr.c +++ b/pimd/pim_addr.c @@ -39,12 +39,8 @@ static ssize_t printfrr_pimaddr(struct fbuf *buf, struct printfrr_eargs *ea, if (!addr) return bputs(buf, "(null)"); - if (use_star) { - pim_addr zero = {}; - - if (memcmp(addr, &zero, sizeof(zero)) == 0) - return bputch(buf, '*'); - } + if (use_star && pim_addr_is_any(*addr)) + return bputch(buf, '*'); #if PIM_IPV == 4 return bprintfrr(buf, "%pI4", addr); diff --git a/pimd/pim_addr.h b/pimd/pim_addr.h index a1a8b55a5..3c4b5a84d 100644 --- a/pimd/pim_addr.h +++ b/pimd/pim_addr.h @@ -21,6 +21,9 @@ #define _PIMD_PIM_ADDR_H #include "jhash.h" +#include "prefix.h" + +/* clang-format off */ /* temporarily disable IPv6 types to keep code compiling. * Defining PIM_V6_TEMP_BREAK will show a lot of compile errors - they are @@ -28,12 +31,78 @@ */ #if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK) typedef struct in_addr pim_addr; -#define PIM_ADDRSTRLEN INET_ADDRSTRLEN + +#define PIM_ADDRSTRLEN INET_ADDRSTRLEN +#define PIM_AF AF_INET +#define PIM_AFI AFI_IP +#define PIM_MAX_BITLEN IPV4_MAX_BITLEN + +union pimprefixptr { + prefixtype(pimprefixptr, struct prefix, p) + prefixtype(pimprefixptr, struct prefix_ipv4, p4) +} TRANSPARENT_UNION; + +union pimprefixconstptr { + prefixtype(pimprefixconstptr, const struct prefix, p) + prefixtype(pimprefixconstptr, const struct prefix_ipv4, p4) +} TRANSPARENT_UNION; + #else typedef struct in6_addr pim_addr; -#define PIM_ADDRSTRLEN INET6_ADDRSTRLEN + +#define PIM_ADDRSTRLEN INET6_ADDRSTRLEN +#define PIM_AF AF_INET6 +#define PIM_AFI AFI_IP6 +#define PIM_MAX_BITLEN IPV6_MAX_BITLEN + +union pimprefixptr { + prefixtype(pimprefixptr, struct prefix, p) + prefixtype(pimprefixptr, struct prefix_ipv6, p6) +} TRANSPARENT_UNION; + +union pimprefixconstptr { + prefixtype(pimprefixconstptr, const struct prefix, p) + prefixtype(pimprefixconstptr, const struct prefix_ipv6, p6) +} TRANSPARENT_UNION; #endif +/* for assignment/initialization (C99 compound literal) + * named PIMADDR_ANY (not PIM_ADDR_ANY) to match INADDR_ANY + */ +#define PIMADDR_ANY (pim_addr){ } + +/* clang-format on */ + +static inline bool pim_addr_is_any(pim_addr addr) +{ + pim_addr zero = {}; + + return memcmp(&addr, &zero, sizeof(zero)) == 0; +} + +static inline int pim_addr_cmp(pim_addr a, pim_addr b) +{ + return memcmp(&a, &b, sizeof(a)); +} + +static inline void pim_addr_to_prefix(union pimprefixptr out, pim_addr in) +{ + out.p->family = PIM_AF; + out.p->prefixlen = PIM_MAX_BITLEN; + memcpy(out.p->u.val, &in, sizeof(in)); +} + +static inline pim_addr pim_addr_from_prefix(union pimprefixconstptr in) +{ + pim_addr ret; + + if (in.p->family != PIM_AF) + return PIMADDR_ANY; + + memcpy(&ret, in.p->u.val, sizeof(ret)); + return ret; +} + /* don't use this struct directly, use the pim_sgaddr typedef */ struct _pim_sgaddr { pim_addr grp; diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 79b46994a..3c38ebd76 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -287,15 +287,13 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, if (PIM_DEBUG_PIM_TRACE) { char neigh_str[INET_ADDRSTRLEN]; char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("<neigh?>", src_addr, neigh_str, sizeof(neigh_str)); pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); - pim_inet4_dump("<grp?>", sg.grp, group_str, sizeof(group_str)); zlog_debug( - "%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", - __func__, neigh_str, ifp->name, source_str, group_str, + "%s: from %s on %s: (S,G)=(%s,%pPAs) pref=%u metric=%u rpt_bit=%u", + __func__, neigh_str, ifp->name, source_str, &sg.grp, msg_metric.metric_preference, msg_metric.route_metric, PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); } diff --git a/pimd/pim_br.c b/pimd/pim_br.c index b3fc8969b..3e64296de 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -43,8 +43,7 @@ struct in_addr pim_br_get_pmbr(pim_sgaddr *sg) struct pim_br *pim_br; for (ALL_LIST_ELEMENTS_RO(pim_br_list, node, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr - && sg->grp.s_addr == pim_br->sg.grp.s_addr) + if (!pim_sgaddr_cmp(*sg, pim_br->sg)) return pim_br->pmbr; } @@ -57,8 +56,7 @@ void pim_br_set_pmbr(pim_sgaddr *sg, struct in_addr br) struct pim_br *pim_br; for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr - && sg->grp.s_addr == pim_br->sg.grp.s_addr) + if (!pim_sgaddr_cmp(*sg, pim_br->sg)) break; } @@ -81,8 +79,7 @@ void pim_br_clear_pmbr(pim_sgaddr *sg) struct pim_br *pim_br; for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr - && sg->grp.s_addr == pim_br->sg.grp.s_addr) + if (!pim_sgaddr_cmp(*sg, pim_br->sg)) break; } diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 238c19d2c..421479047 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -557,8 +557,7 @@ static void pim_bsm_update(struct pim_instance *pim, struct in_addr bsr, uint32_t bsr_prio) { if (bsr.s_addr != pim->global_scope.current_bsr.s_addr) { - if (pim->global_scope.current_bsr.s_addr) - pim_nht_bsr_del(pim, pim->global_scope.current_bsr); + pim_nht_bsr_del(pim, pim->global_scope.current_bsr); pim_nht_bsr_add(pim, bsr); pim->global_scope.current_bsr = bsr; @@ -582,8 +581,7 @@ void pim_bsm_clear(struct pim_instance *pim) struct rp_info *rp_info; bool upstream_updated = false; - if (pim->global_scope.current_bsr.s_addr) - pim_nht_bsr_del(pim, pim->global_scope.current_bsr); + pim_nht_bsr_del(pim, pim->global_scope.current_bsr); /* Reset scope zone data */ pim->global_scope.accept_nofwd_bsm = false; @@ -663,7 +661,7 @@ void pim_bsm_clear(struct pim_instance *pim) /* Find the upstream (*, G) whose upstream address is same as * the RP */ - if (up->sg.src.s_addr != INADDR_ANY) + if (!pim_addr_is_any(up->sg.src)) continue; struct prefix grp; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 01cb35177..2baaca1c9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -79,6 +79,14 @@ static struct cmd_node debug_node = { .config_write = pim_debug_config_write, }; +static inline bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match) +{ + return (pim_addr_is_any(match.grp) || + !pim_addr_cmp(match.grp, item.grp)) && + (pim_addr_is_any(match.src) || + !pim_addr_cmp(match.src, item.src)); +} + static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[], const int argc, int *idx) { @@ -100,8 +108,6 @@ static void pim_show_assert_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch, time_t now) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; char winner_str[INET_ADDRSTRLEN]; struct in_addr ifaddr; char uptime[10]; @@ -110,18 +116,16 @@ static void pim_show_assert_helper(struct vty *vty, ifaddr = pim_ifp->primary_address; - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("<assrt_win?>", ch->ifassert_winner, winner_str, sizeof(winner_str)); pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); pim_time_timer_to_mmss(timer, sizeof(timer), ch->t_ifassert_timer); - vty_out(vty, "%-16s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-6s %-15s %-8s %-5s\n", ch->interface->name, - inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), ch_src_str, - ch_grp_str, pim_ifchannel_ifassert_name(ch->ifassert_state), + inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), &ch->sg.src, + &ch->sg.grp, pim_ifchannel_ifassert_name(ch->ifassert_state), winner_str, uptime, timer); } @@ -143,6 +147,9 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty) continue; RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { + if (ch->ifassert_state == PIM_IFASSERT_NOINFO) + continue; + pim_show_assert_helper(vty, pim_ifp, ch, now); } /* scan interface channels */ } @@ -152,19 +159,15 @@ static void pim_show_assert_internal_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; struct in_addr ifaddr; char buf[PREFIX_STRLEN]; ifaddr = pim_ifp->primary_address; - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); - vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-3s %-3s %-3s %-4s\n", ch->interface->name, - inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), - ch_src_str, ch_grp_str, + inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), &ch->sg.src, + &ch->sg.grp, PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" @@ -201,8 +204,6 @@ static void pim_show_assert_metric_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN]; struct pim_assert_metric am; struct in_addr ifaddr; @@ -213,14 +214,12 @@ static void pim_show_assert_metric_helper(struct vty *vty, am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("<addr?>", am.ip_address, addr_str, sizeof(addr_str)); - vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-3s %4u %6u %-15s\n", ch->interface->name, - inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), - ch_src_str, ch_grp_str, am.rpt_bit_flag ? "yes" : "no", + inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), &ch->sg.src, + &ch->sg.grp, am.rpt_bit_flag ? "yes" : "no", am.metric_preference, am.route_metric, addr_str); } @@ -248,8 +247,6 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; char addr_str[INET_ADDRSTRLEN]; struct pim_assert_metric *am; struct in_addr ifaddr; @@ -261,8 +258,6 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty, am = &ch->ifassert_winner_metric; - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); pim_inet4_dump("<addr?>", am->ip_address, addr_str, sizeof(addr_str)); if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) @@ -276,11 +271,11 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty, else snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); - vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-3s %-4s %-6s %-15s\n", ch->interface->name, - inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), ch_src_str, - ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str, metr_str, - addr_str); + inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), &ch->sg.src, + &ch->sg.grp, am->rpt_bit_flag ? "yes" : "no", pref_str, + metr_str, addr_str); } static void pim_show_assert_winner_metric(struct pim_instance *pim, @@ -340,14 +335,10 @@ static void pim_show_membership_helper(struct vty *vty, struct pim_ifchannel *ch, struct json_object *json) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; + char ch_grp_str[PIM_ADDRSTRLEN]; json_object *json_iface = NULL; json_object *json_row = NULL; - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); - json_object_object_get_ex(json, ch->interface->name, &json_iface); if (!json_iface) { json_iface = json_object_new_object(); @@ -355,8 +346,10 @@ static void pim_show_membership_helper(struct vty *vty, json_object_object_add(json, ch->interface->name, json_iface); } + snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", &ch->sg.grp); + json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); + json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src); json_object_string_add(json_row, "group", ch_grp_str); json_object_string_add(json_row, "localMembership", ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO @@ -364,6 +357,7 @@ static void pim_show_membership_helper(struct vty *vty, : "INCLUDE"); json_object_object_add(json_iface, ch_grp_str, json_row); } + static void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj) { @@ -1045,10 +1039,10 @@ static void pim_show_interfaces_single(struct pim_instance *pim, json_fhr_sources = json_object_new_object(); - pim_inet4_dump("<src?>", up->sg.src, src_str, - sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, - sizeof(grp_str)); + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &up->sg.src); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); @@ -1222,15 +1216,11 @@ static void pim_show_interfaces_single(struct pim_instance *pim, print_header = 0; } - pim_inet4_dump("<src?>", up->sg.src, src_str, - sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, - sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); vty_out(vty, - "%s : %s is a source, uptime is %s\n", - grp_str, src_str, uptime); + "%pPAs : %pPAs is a source, uptime is %s\n", + &up->sg.grp, &up->sg.src, uptime); } if (!print_header) { @@ -1650,8 +1640,6 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, struct pim_ifchannel *ch, json_object *json, time_t now, bool uj) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; json_object *json_iface = NULL; json_object *json_row = NULL; json_object *json_grp = NULL; @@ -1663,9 +1651,6 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, ifaddr = pim_ifp->primary_address; - pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str)); - pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); pim_time_timer_to_mmss(expire, sizeof(expire), ch->t_ifjoin_expiry_timer); @@ -1673,6 +1658,14 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, ch->t_ifjoin_prune_pending_timer); if (uj) { + char ch_grp_str[PIM_ADDRSTRLEN]; + char ch_src_str[PIM_ADDRSTRLEN]; + + snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs", + &ch->sg.grp); + snprintfrr(ch_src_str, sizeof(ch_src_str), "%pPAs", + &ch->sg.src); + json_object_object_get_ex(json, ch->interface->name, &json_iface); @@ -1707,10 +1700,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, } else json_object_object_add(json_grp, ch_src_str, json_row); } else { - vty_out(vty, "%-16s %-15s %-15s %-15s %-10s %8s %-6s %5s\n", + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n", ch->interface->name, inet_ntop(AF_INET, &ifaddr, buf, sizeof(buf)), - ch_src_str, ch_grp_str, + &ch->sg.src, &ch->sg.grp, pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), uptime, expire, prune); } @@ -1739,11 +1732,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, continue; RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { - if (sg->grp.s_addr != INADDR_ANY - && sg->grp.s_addr != ch->sg.grp.s_addr) - continue; - if (sg->src.s_addr != INADDR_ANY - && sg->src.s_addr != ch->sg.src.s_addr) + if (!pim_sgaddr_match(ch->sg, *sg)) continue; pim_show_join_helper(vty, pim_ifp, ch, json, now, uj); } /* scan interface channels */ @@ -2416,8 +2405,6 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char uptime[10]; char join_timer[10]; char rs_timer[10]; @@ -2425,15 +2412,9 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, char msdp_reg_timer[10]; char state_str[PIM_REG_STATE_STR_LEN]; - if (sg->grp.s_addr != INADDR_ANY - && sg->grp.s_addr != up->sg.grp.s_addr) - continue; - if (sg->src.s_addr != INADDR_ANY - && sg->src.s_addr != up->sg.src.s_addr) + if (!pim_sgaddr_match(up->sg, *sg)) continue; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), @@ -2474,6 +2455,14 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, } if (uj) { + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -2497,8 +2486,8 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, * we are the FHR, else we just put * the RP as the rpfAddress */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR - || up->sg.src.s_addr == INADDR_ANY) { + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR || + pim_addr_is_any(up->sg.src)) { char rpf[PREFIX_STRLEN]; struct pim_rpf *rpg; @@ -2537,12 +2526,12 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, json_object_object_add(json_group, src_str, json_row); } else { vty_out(vty, - "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", + "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : "Unknown", - src_str, grp_str, state_str, uptime, join_timer, - rs_timer, ka_timer, up->ref_count); + &up->sg.src, &up->sg.grp, state_str, uptime, + join_timer, rs_timer, ka_timer, up->ref_count); } } @@ -2558,14 +2547,15 @@ static void pim_show_channel_helper(struct pim_instance *pim, { struct pim_upstream *up = ch->upstream; json_object *json_group = NULL; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json_row = NULL; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - if (uj) { + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -2596,8 +2586,8 @@ static void pim_show_channel_helper(struct pim_instance *pim, json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", - ch->interface->name, src_str, grp_str, + vty_out(vty, "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n", + ch->interface->name, &up->sg.src, &up->sg.grp, pim_macro_ch_lost_assert(ch) ? "yes" : "no", pim_macro_chisin_joins(ch) ? "yes" : "no", pim_macro_chisin_pim_include(ch) ? "yes" : "no", @@ -2648,14 +2638,15 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, json_object *json, bool uj) { json_object *json_group = NULL; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json_row = NULL; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); - if (uj) { + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -2675,8 +2666,8 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-6s\n", - src_str, grp_str, + vty_out(vty, "%-15pPAs %-15pPAs %-6s\n", + &up->sg.src, &up->sg.grp, pim_upstream_evaluate_join_desired(pim, up) ? "yes" : "no"); } @@ -2720,8 +2711,6 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, "Source Group RpfIface RibNextHop RpfAddress \n"); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char rpf_nexthop_str[PREFIX_STRLEN]; char rpf_addr_str[PREFIX_STRLEN]; struct pim_rpf *rpf; @@ -2729,8 +2718,6 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, rpf = &up->rpf; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); pim_addr_dump("<nexthop?>", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); @@ -2740,6 +2727,14 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; if (uj) { + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -2760,9 +2755,9 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, rpf_addr_str); json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str, - grp_str, rpf_ifname, rpf_nexthop_str, - rpf_addr_str); + vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s\n", + &up->sg.src, &up->sg.grp, rpf_ifname, + rpf_nexthop_str, rpf_addr_str); } } @@ -2854,15 +2849,11 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) } frr_each (rb_pim_upstream, &pim->upstream_head, up) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; char rib_nexthop_str[PREFIX_STRLEN]; const char *rpf_ifname; struct pim_rpf *rpf = &up->rpf; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); pim_addr_dump("<nexthop?>", @@ -2872,6 +2863,14 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>"; if (uj) { + char grp_str[PIM_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -2898,9 +2897,9 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-16s %-15s %-15s %6d %4d\n", - src_str, grp_str, rpf_ifname, rpf_addr_str, - rib_nexthop_str, + vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15s %-15s %6d %4d\n", + &up->sg.src, &up->sg.grp, rpf_ifname, + rpf_addr_str, rib_nexthop_str, rpf->source_nexthop.mrib_route_metric, rpf->source_nexthop.mrib_metric_preference); } @@ -4603,18 +4602,13 @@ static void pim_show_jp_agg_helper(struct vty *vty, struct pim_upstream *up, int is_join) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char rpf_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); /* pius->address.s_addr */ pim_inet4_dump("<rpf?>", neigh->source_addr, rpf_str, sizeof(rpf_str)); - vty_out(vty, "%-16s %-15s %-15s %-15s %5s\n", - ifp->name, rpf_str, src_str, - grp_str, is_join?"J":"P"); + vty_out(vty, "%-16s %-15s %-15pPAs %-15pPAs %5s\n", ifp->name, rpf_str, + &up->sg.src, &up->sg.grp, is_join ? "J" : "P"); } static void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty) @@ -4772,8 +4766,8 @@ static void pim_show_mlag_up_detail(struct vrf *vrf, struct vty *vty, const char *src_or_group, const char *group, bool uj) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; struct pim_upstream *up; struct pim_instance *pim = vrf->info; json_object *json = NULL; @@ -4790,8 +4784,9 @@ static void pim_show_mlag_up_detail(struct vrf *vrf, && !pim_up_mlag_is_local(up)) continue; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src); + /* XXX: strcmps are clearly inefficient. we should do uint comps * here instead. */ @@ -4817,8 +4812,6 @@ static void pim_show_mlag_up_vrf(struct vrf *vrf, struct vty *vty, bool uj) json_object *json = NULL; json_object *json_row; struct pim_upstream *up; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; struct pim_instance *pim = vrf->info; json_object *json_group = NULL; @@ -4834,11 +4827,16 @@ static void pim_show_mlag_up_vrf(struct vrf *vrf, struct vty *vty, bool uj) && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE) && !pim_up_mlag_is_local(up)) continue; - pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str)); if (uj) { + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; json_object *own_list = NULL; + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &up->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &up->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { json_group = json_object_new_object(); @@ -4885,8 +4883,8 @@ static void pim_show_mlag_up_vrf(struct vrf *vrf, struct vty *vty, bool uj) if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)) strlcat(own_str, "I", sizeof(own_str)); vty_out(vty, - "%-15s %-15s %-6s %-11u %-10u %2s\n", - src_str, grp_str, own_str, + "%-15pPAs %-15pPAs %-6s %-11u %-10u %2s\n", + &up->sg.src, &up->sg.grp, own_str, pim_up_mlag_local_cost(up), pim_up_mlag_peer_cost(up), PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags) @@ -5851,11 +5849,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, if (!c_oil->installed) continue; - if (sg->grp.s_addr != INADDR_ANY - && sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) + if (!pim_addr_is_any(sg->grp) && + pim_addr_cmp(sg->grp, c_oil->oil.mfcc_mcastgrp)) continue; - if (sg->src.s_addr != INADDR_ANY - && sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr) + if (!pim_addr_is_any(sg->src) && + pim_addr_cmp(sg->src, c_oil->oil.mfcc_origin)) continue; pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str, @@ -8230,13 +8228,12 @@ DEFPY_HIDDEN (pim_test_sg_keepalive, up = pim_upstream_find(pim, &sg); if (!up) { - vty_out(vty, "%% Unable to find %s specified\n", - pim_str_sg_dump(&sg)); + vty_out(vty, "%% Unable to find %pSG specified\n", &sg); return CMD_WARNING; } - vty_out(vty, "Setting %s to current keep alive time: %d\n", - pim_str_sg_dump(&sg), pim->keep_alive_time); + vty_out(vty, "Setting %pSG to current keep alive time: %d\n", &sg, + pim->keep_alive_time); pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time); return CMD_SUCCESS; @@ -10146,8 +10143,6 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) { struct listnode *sanode; struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char rp_str[INET_ADDRSTRLEN]; char timebuf[PIM_MSDP_UPTIME_STRLEN]; char spt_str[8]; @@ -10167,8 +10162,6 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { now = pim_time_monotonic_sec(); pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); if (sa->flags & PIM_MSDP_SAF_PEER) { pim_inet4_dump("<rp?>", sa->rp, rp_str, sizeof(rp_str)); if (sa->up) { @@ -10186,6 +10179,14 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) strlcpy(local_str, "no", sizeof(local_str)); } if (uj) { + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &sa->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &sa->sg.src); + json_object_object_get_ex(json, grp_str, &json_group); if (!json_group) { @@ -10203,8 +10204,8 @@ static void ip_msdp_show_sa(struct pim_instance *pim, struct vty *vty, bool uj) json_object_string_add(json_row, "upTime", timebuf); json_object_object_add(json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n", - src_str, grp_str, rp_str, local_str[0], + vty_out(vty, "%-15pPAs %15pPAs %15s %5c %3c %8s\n", + &sa->sg.src, &sa->sg.grp, rp_str, local_str[0], spt_str[0], timebuf); } } @@ -10284,8 +10285,6 @@ static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty, { struct listnode *sanode; struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json = NULL; if (uj) { @@ -10293,8 +10292,12 @@ static void ip_msdp_show_sa_detail(struct pim_instance *pim, struct vty *vty, } for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &sa->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &sa->sg.src); + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); } @@ -10364,8 +10367,6 @@ static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty, { struct listnode *sanode; struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json = NULL; if (uj) { @@ -10373,8 +10374,12 @@ static void ip_msdp_show_sa_addr(struct pim_instance *pim, struct vty *vty, } for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &sa->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &sa->sg.src); + if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); @@ -10390,8 +10395,6 @@ static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty, { struct listnode *sanode; struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json = NULL; if (uj) { @@ -10399,8 +10402,12 @@ static void ip_msdp_show_sa_sg(struct pim_instance *pim, struct vty *vty, } for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { - pim_inet4_dump("<src?>", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", sa->sg.grp, grp_str, sizeof(grp_str)); + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &sa->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", &sa->sg.src); + if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); @@ -10509,8 +10516,6 @@ static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg, { struct vty *vty = cwd->vty; json_object *json = cwd->json; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; json_object *json_row; bool installed = (vxlan_sg->up) ? true : false; const char *iif_name = vxlan_sg->iif?vxlan_sg->iif->name:"-"; @@ -10521,13 +10526,19 @@ static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg, else oif_name = vxlan_sg->term_oif?vxlan_sg->term_oif->name:""; - if (cwd->addr_match && (vxlan_sg->sg.src.s_addr != cwd->addr.s_addr) && - (vxlan_sg->sg.grp.s_addr != cwd->addr.s_addr)) { + if (cwd->addr_match && pim_addr_cmp(vxlan_sg->sg.src, cwd->addr) && + pim_addr_cmp(vxlan_sg->sg.grp, cwd->addr)) { return; } - pim_inet4_dump("<src?>", vxlan_sg->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", vxlan_sg->sg.grp, grp_str, sizeof(grp_str)); if (json) { + char src_str[PIM_ADDRSTRLEN]; + char grp_str[PIM_ADDRSTRLEN]; + + snprintfrr(grp_str, sizeof(grp_str), "%pPAs", + &vxlan_sg->sg.grp); + snprintfrr(src_str, sizeof(src_str), "%pPAs", + &vxlan_sg->sg.src); + json_object_object_get_ex(json, grp_str, &cwd->json_group); if (!cwd->json_group) { @@ -10547,9 +10558,9 @@ static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg, json_object_boolean_false_add(json_row, "installed"); json_object_object_add(cwd->json_group, src_str, json_row); } else { - vty_out(vty, "%-15s %-15s %-15s %-15s %-5s\n", - src_str, grp_str, iif_name, oif_name, - installed?"I":""); + vty_out(vty, "%-15pPAs %-15pPAs %-15s %-15s %-5s\n", + &vxlan_sg->sg.src, &vxlan_sg->sg.grp, iif_name, + oif_name, installed ? "I" : ""); } } diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 72e04460d..3f138e22e 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -403,7 +403,7 @@ static int pim_sec_addr_update(struct interface *ifp) for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { struct prefix *p = ifc->address; - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + if (p->u.prefix4.s_addr == INADDR_ANY) { continue; } @@ -598,7 +598,7 @@ void pim_if_addr_add(struct connected *ifc) if (PIM_IF_TEST_PIM(pim_ifp->options)) { - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + if (!pim_addr_is_any(pim_ifp->primary_address)) { /* Interface has a valid socket ? */ if (pim_ifp->pim_sock_fd < 0) { @@ -684,7 +684,7 @@ static void pim_if_addr_del_pim(struct connected *ifc) return; } - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + if (!pim_addr_is_any(pim_ifp->primary_address)) { /* Interface keeps a valid primary address */ return; } @@ -752,7 +752,7 @@ void pim_if_addr_add_all(struct interface *ifp) if (PIM_IF_TEST_PIM(pim_ifp->options)) { /* Interface has a valid primary address ? */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + if (!pim_addr_is_any(pim_ifp->primary_address)) { /* Interface has a valid socket ? */ if (pim_ifp->pim_sock_fd < 0) { @@ -836,7 +836,7 @@ struct in_addr pim_find_primary_addr(struct interface *ifp) int v6_addrs = 0; struct pim_interface *pim_ifp = ifp->info; - if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source)) { return pim_ifp->update_source; } @@ -848,7 +848,7 @@ struct in_addr pim_find_primary_addr(struct interface *ifp) continue; } - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + if (p->u.prefix4.s_addr == INADDR_ANY) { zlog_warn( "%s: null IPv4 address connected to interface %s", __func__, ifp->name); @@ -916,7 +916,7 @@ static int pim_iface_next_vif_index(struct interface *ifp) int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term) { struct pim_interface *pim_ifp = ifp->info; - struct in_addr ifaddr; + pim_addr ifaddr; unsigned char flags = 0; assert(pim_ifp); @@ -935,7 +935,7 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term) } ifaddr = pim_ifp->primary_address; - if (!ispimreg && !is_vxlan_term && PIM_INADDR_IS_ANY(ifaddr)) { + if (!ispimreg && !is_vxlan_term && pim_addr_is_any(ifaddr)) { zlog_warn( "%s: could not get address for interface %s ifindex=%d", __func__, ifp->name, ifp->ifindex); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index c0d693071..924817772 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -62,19 +62,7 @@ int pim_ifchannel_compare(const struct pim_ifchannel *ch1, if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) return 1; - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; - - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; - - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; - - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; - - return 0; + return pim_sgaddr_cmp(ch1->sg, ch2->sg); } /* @@ -107,18 +95,15 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch) struct pim_ifchannel *child; // Basic Sanity that we are not being silly - if ((ch->sg.src.s_addr != INADDR_ANY) - && (ch->sg.grp.s_addr != INADDR_ANY)) + if (!pim_addr_is_any(ch->sg.src) && !pim_addr_is_any(ch->sg.grp)) return; - if ((ch->sg.src.s_addr == INADDR_ANY) - && (ch->sg.grp.s_addr == INADDR_ANY)) + if (pim_addr_is_any(ch->sg.src) && pim_addr_is_any(ch->sg.grp)) return; RB_FOREACH (child, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { - if ((ch->sg.grp.s_addr != INADDR_ANY) - && (child->sg.grp.s_addr == ch->sg.grp.s_addr) - && (child != ch)) { + if (!pim_addr_is_any(ch->sg.grp) && + !pim_addr_cmp(child->sg.grp, ch->sg.grp) && (child != ch)) { child->parent = ch; listnode_add_sort(ch->sources, child); } @@ -162,9 +147,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) * being inherited. So let's figure out what * needs to be done here */ - if ((ch->sg.src.s_addr != INADDR_ANY) && - pim_upstream_evaluate_join_desired_interface( - ch->upstream, ch, ch->parent)) + if (!pim_addr_is_any(ch->sg.src) && + pim_upstream_evaluate_join_desired_interface( + ch->upstream, ch, ch->parent)) pim_channel_add_oif(ch->upstream->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR, @@ -293,7 +278,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, ch->ifjoin_state = new_state; - if (ch->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(ch->sg.src)) { struct pim_upstream *up = ch->upstream; struct pim_upstream *child; struct listnode *up_node; @@ -455,8 +440,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, pim_sgaddr *sg) pim_ifp = ifp->info; if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __func__, pim_str_sg_dump(sg), ifp->name); + zlog_warn("%s: (S,G)=%pSG: multicast not enabled on interface %s", + __func__, sg, ifp->name); return NULL; } @@ -527,9 +512,9 @@ static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch) struct pim_ifchannel *parent = NULL; // (S,G) - if ((parent_sg.src.s_addr != INADDR_ANY) - && (parent_sg.grp.s_addr != INADDR_ANY)) { - parent_sg.src.s_addr = INADDR_ANY; + if (!pim_addr_is_any(parent_sg.src) && + !pim_addr_is_any(parent_sg.grp)) { + parent_sg.src = PIMADDR_ANY; parent = pim_ifchannel_find(ch->interface, &parent_sg); if (parent) @@ -558,8 +543,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg, if (ch->upstream) ch->upstream->flags |= up_flags; else if (PIM_DEBUG_EVENTS) - zlog_debug("%s:%s No Upstream found", __func__, - pim_str_sg_dump(sg)); + zlog_debug("%s:%pSG No Upstream found", __func__, sg); return ch; } @@ -575,9 +559,9 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg, ch->interface = ifp; ch->sg = *sg; - pim_str_sg_set(sg, ch->sg_str); + snprintfrr(ch->sg_str, sizeof(ch->sg_str), "%pSG", sg); ch->parent = pim_ifchannel_find_parent(ch); - if (ch->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(ch->sg.src)) { ch->sources = list_new(); ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; @@ -688,10 +672,9 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch = THREAD_ARG(t); if (PIM_DEBUG_PIM_TRACE) - zlog_debug( - "%s: IFCHANNEL%s %s Prune Pending Timer Popped", - __func__, pim_str_sg_dump(&ch->sg), - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); + zlog_debug("%s: IFCHANNEL%pSG %s Prune Pending Timer Popped", + __func__, &ch->sg, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { ifp = ch->interface; @@ -832,9 +815,9 @@ static int nonlocal_upstream(int is_join, struct interface *recv_ifp, if (PIM_DEBUG_PIM_TRACE_DETAIL) { char up_str[INET_ADDRSTRLEN]; pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); - zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", + zlog_warn("%s: recv %s (S,G)=%pSG to non-local upstream=%s on %s", __func__, is_join ? "join" : "prune", - pim_str_sg_dump(sg), up_str, recv_ifp->name); + sg, up_str, recv_ifp->name); } /* @@ -994,8 +977,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, THREAD_OFF(ch->t_ifjoin_prune_pending_timer); /* Check if SGRpt join Received */ - if ((source_flags & PIM_ENCODE_RPT_BIT) - && (sg->src.s_addr != INADDR_ANY)) { + if ((source_flags & PIM_ENCODE_RPT_BIT) && + !pim_addr_is_any(sg->src)) { /* * Transitions from Prune-Pending State (Rcv SGRpt Join) * RFC 7761 Sec 4.5.3: @@ -1049,10 +1032,9 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, ch = pim_ifchannel_find(ifp, sg); if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) { if (PIM_DEBUG_PIM_TRACE) - zlog_debug( - "%s: Received prune with no relevant ifchannel %s%s state: %d", - __func__, ifp->name, pim_str_sg_dump(sg), - source_flags); + zlog_debug("%s: Received prune with no relevant ifchannel %s%pSG state: %d", + __func__, ifp->name, sg, + source_flags); return; } @@ -1182,28 +1164,26 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, pim_sgaddr *sg, pim_ifp = ifp->info; if (!pim_ifp) { if (PIM_DEBUG_EVENTS) - zlog_debug("%s:%s Expected pim interface setup for %s", - __func__, pim_str_sg_dump(sg), ifp->name); + zlog_debug("%s:%pSG Expected pim interface setup for %s", + __func__, sg, ifp->name); return 0; } if (!PIM_IF_TEST_PIM(pim_ifp->options)) { if (PIM_DEBUG_EVENTS) - zlog_debug( - "%s:%s PIM is not configured on this interface %s", - __func__, pim_str_sg_dump(sg), ifp->name); + zlog_debug("%s:%pSG PIM is not configured on this interface %s", + __func__, sg, ifp->name); return 0; } pim = pim_ifp->pim; /* skip (*,G) ch creation if G is of type SSM */ - if (sg->src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg->src)) { if (pim_is_grp_ssm(pim, sg->grp)) { if (PIM_DEBUG_PIM_EVENTS) - zlog_debug( - "%s: local membership (S,G)=%s ignored as group is SSM", - __func__, pim_str_sg_dump(sg)); + zlog_debug("%s: local membership (S,G)=%pSG ignored as group is SSM", + __func__, sg); return 1; } } @@ -1217,7 +1197,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, pim_sgaddr *sg, ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - if (sg->src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg->src)) { struct pim_upstream *up = pim_upstream_find(pim, sg); struct pim_upstream *child; struct listnode *up_node; @@ -1293,7 +1273,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, pim_sgaddr *sg) return; ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - if (sg->src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg->src)) { struct pim_upstream *up = pim_upstream_find(pim_ifp->pim, sg); struct pim_upstream *child; struct listnode *up_node, *up_nnode; @@ -1351,15 +1331,11 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) if (new_couldassert == old_couldassert) return; - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", - __func__, src_str, grp_str, ch->interface->name, - old_couldassert, new_couldassert); - } + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug("%s: CouldAssert(%pPAs,%pPAs,%s) changed from %d to %d", + __func__, &ch->sg.src, &ch->sg.grp, + ch->interface->name, old_couldassert, + new_couldassert); if (new_couldassert) { /* CouldAssert(S,G,I) switched from false to true */ @@ -1393,19 +1369,15 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) return; if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; char old_addr_str[INET_ADDRSTRLEN]; char new_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); pim_inet4_dump("<new_addr?>", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); zlog_debug( - "%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", - __func__, src_str, grp_str, ch->interface->name, + "%s: my_assert_metric(%pPAs,%pPAs,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", + __func__, &ch->sg.src, &ch->sg.grp, ch->interface->name, ch->ifassert_my_metric.rpt_bit_flag, ch->ifassert_my_metric.metric_preference, ch->ifassert_my_metric.route_metric, old_addr_str, @@ -1432,16 +1404,11 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) if (new_atd == old_atd) return; - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str)); + if (PIM_DEBUG_PIM_EVENTS) zlog_debug( - "%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", - __func__, src_str, grp_str, ch->interface->name, + "%s: AssertTrackingDesired(%pPAs,%pPAs,%s) changed from %d to %d", + __func__, &ch->sg.src, &ch->sg.grp, ch->interface->name, old_atd, new_atd); - } if (new_atd) { /* AssertTrackingDesired(S,G,I) switched from false to true */ diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c index 1518ef232..d8210168e 100644 --- a/pimd/pim_igmp_mtrace.c +++ b/pimd/pim_igmp_mtrace.c @@ -119,7 +119,7 @@ static bool mtrace_fwd_info(struct pim_instance *pim, up = pim_upstream_find(pim, &sg); if (!up) { - sg.src.s_addr = INADDR_ANY; + sg.src = PIMADDR_ANY; up = pim_upstream_find(pim, &sg); } @@ -154,7 +154,7 @@ static bool mtrace_fwd_info(struct pim_instance *pim, rspp->rtg_proto = MTRACE_RTG_PROTO_PIM; /* 6.2.2. 4. Fill in ... S, and Src Mask */ - if (sg.src.s_addr != INADDR_ANY) { + if (!pim_addr_is_any(sg.src)) { rspp->s = 1; rspp->src_mask = MTRACE_SRC_MASK_SOURCE; } else { diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 492af5f2d..fafca5a14 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -1675,7 +1675,7 @@ void igmp_v3_send_query(struct gm_group *group, int fd, const char *ifname, */ if (!s_flag) { /* general query? */ - if (PIM_INADDR_IS_ANY(group_addr)) { + if (group_addr.s_addr == INADDR_ANY) { char dst_str[INET_ADDRSTRLEN]; char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("<dst?>", dst_addr, dst_str, @@ -1762,7 +1762,7 @@ void igmp_v3_recv_query(struct gm_sock *igmp, const char *from_str, if (!s_flag) { /* s_flag is clear */ - if (PIM_INADDR_IS_ANY(group_addr)) { + if (group_addr.s_addr == INADDR_ANY) { /* this is a general query */ /* log that general query should have the s_flag set */ zlog_warn( diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 5e96d39e8..fa2d8d462 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -65,12 +65,11 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_debug( - "%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __func__, pim_str_sg_dump(sg), - !!(source_flags & PIM_RPT_BIT_MASK), - !!(source_flags & PIM_WILDCARD_BIT_MASK), up_str, - holdtime, neigh_str, ifp->name); + zlog_debug("%s: join (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __func__, sg, + !!(source_flags & PIM_RPT_BIT_MASK), + !!(source_flags & PIM_WILDCARD_BIT_MASK), up_str, + holdtime, neigh_str, ifp->name); } pim_ifp = ifp->info; @@ -96,26 +95,23 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, * our RP for the group, drop the message */ if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) { - char received_rp[INET_ADDRSTRLEN]; char local_rp[INET_ADDRSTRLEN]; - pim_inet4_dump("<received?>", sg->src, received_rp, - sizeof(received_rp)); pim_inet4_dump("<local?>", rp->rpf_addr.u.prefix4, local_rp, sizeof(local_rp)); zlog_warn( - "%s: Specified RP(%s) in join is different than our configured RP(%s)", - __func__, received_rp, local_rp); + "%s: Specified RP(%pPAs) in join is different than our configured RP(%s)", + __func__, &sg->src, local_rp); return; } if (pim_is_grp_ssm(pim_ifp->pim, sg->grp)) { zlog_warn( - "%s: Specified Group(%pI4) in join is now in SSM, not allowed to create PIM state", + "%s: Specified Group(%pPA) in join is now in SSM, not allowed to create PIM state", __func__, &sg->grp); return; } - sg->src.s_addr = INADDR_ANY; + sg->src = PIMADDR_ANY; } /* Restart join expiry timer */ @@ -135,12 +131,12 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str)); pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_debug( - "%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __func__, pim_str_sg_dump(sg), - source_flags & PIM_RPT_BIT_MASK, - source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, - neigh_str, ifp->name); + zlog_debug("%s: prune (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __func__, sg, + source_flags & PIM_RPT_BIT_MASK, + source_flags & PIM_WILDCARD_BIT_MASK, up_str, + holdtime, + neigh_str, ifp->name); } pim_ifp = ifp->info; @@ -155,16 +151,11 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, * Received Prune(*,G) messages are processed even if the * RP in the message does not match RP(G). */ - if (PIM_DEBUG_PIM_TRACE) { - char received_rp[INET_ADDRSTRLEN]; - - pim_inet4_dump("<received?>", sg->src, received_rp, - sizeof(received_rp)); - zlog_debug("%s: Prune received with RP(%s) for %pSG", - __func__, received_rp, sg); - } + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: Prune received with RP(%pPAs) for %pSG", + __func__, &sg->src, sg); - sg->src.s_addr = INADDR_ANY; + sg->src = PIMADDR_ANY; } pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); @@ -281,16 +272,13 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, if (PIM_DEBUG_PIM_J_P) { char src_str[INET_ADDRSTRLEN]; char upstream_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4, upstream_str, sizeof(upstream_str)); - pim_inet4_dump("<grp?>", sg.grp, group_str, - sizeof(group_str)); zlog_debug( - "%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", - __func__, upstream_str, group_str, + "%s: join/prune upstream=%s group=%pPA/32 join_src=%d prune_src=%d from %s on %s", + __func__, upstream_str, &sg.grp, msg_num_joined_sources, msg_num_pruned_sources, src_str, ifp->name); } @@ -316,7 +304,7 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); - if (sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg.src)) { starg_ch = pim_ifchannel_find(ifp, &sg); if (starg_ch) pim_ifchannel_set_star_g_join_state( @@ -489,7 +477,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups) return -1; } - if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) { + if (rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY) { if (PIM_DEBUG_PIM_J_P) { char dst_str[INET_ADDRSTRLEN]; pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 5c6f55e99..feeef15f8 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -80,13 +80,7 @@ static int pim_jp_agg_src_cmp(void *arg1, void *arg2) if (!js1->is_join && js2->is_join) return 1; - if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) - return -1; - - if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) - return 1; - - return 0; + return pim_addr_cmp(js1->up->sg.src, js2->up->sg.src); } /* @@ -156,7 +150,7 @@ void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up, struct pim_jp_sources *js = NULL; for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { - if (jag->group.s_addr == up->sg.grp.s_addr) + if (!pim_addr_cmp(jag->group, up->sg.grp)) break; } @@ -202,7 +196,7 @@ int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up) struct pim_jp_sources *js = NULL; for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { - if (jag->group.s_addr == up->sg.grp.s_addr) + if (!pim_addr_cmp(jag->group, up->sg.grp)) break; } @@ -276,14 +270,14 @@ void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, struct pim_jp_sources *js = NULL; for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { - if (jag->group.s_addr == up->sg.grp.s_addr) + if (!pim_addr_cmp(jag->group, up->sg.grp)) break; } if (!jag) { jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof(struct pim_jp_agg_group)); - jag->group.s_addr = up->sg.grp.s_addr; + jag->group = up->sg.grp; jag->sources = list_new(); jag->sources->cmp = pim_jp_agg_src_cmp; jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; @@ -378,7 +372,7 @@ void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, listnode_add(&groups, &jag); listnode_add(jag.sources, &js); - jag.group.s_addr = up->sg.grp.s_addr; + jag.group = up->sg.grp; js.up = up; js.is_join = is_join; diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 81ef6962d..aa41033ce 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -128,7 +128,7 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) return 0; /* false */ } - if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) + if (pim_addr_is_any(ch->ifassert_winner)) return 0; /* false */ /* AssertWinner(S,G,I) == me ? */ diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c index 1f38b1c93..f4ddc1bf6 100644 --- a/pimd/pim_mlag.c +++ b/pimd/pim_mlag.c @@ -174,8 +174,8 @@ bool pim_mlag_up_df_role_update(struct pim_instance *pim, /* If DF role changed on a (*,G) termination mroute update the * associated DF role on the inherited (S,G) entries */ - if ((up->sg.src.s_addr == INADDR_ANY) && - PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags)) + if (pim_addr_is_any(up->sg.src) && + PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags)) pim_vxlan_inherit_mlag_flags(pim, up, true /* inherit */); return true; @@ -255,17 +255,14 @@ static void pim_mlag_up_peer_add(struct mlag_mroute_add *msg) int flags = 0; pim_sgaddr sg; struct vrf *vrf; - char sg_str[PIM_SG_LEN]; memset(&sg, 0, sizeof(sg)); sg.src.s_addr = htonl(msg->source_ip); sg.grp.s_addr = htonl(msg->group_ip); - if (PIM_DEBUG_MLAG) - pim_str_sg_set(&sg, sg_str); if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute add %s:%s cost %d", - msg->vrf_name, sg_str, msg->cost_to_rp); + zlog_debug("peer MLAG mroute add %s:%pSG cost %d", + msg->vrf_name, &sg, msg->cost_to_rp); /* XXX - this is not correct. we MUST cache updates to avoid losing * an entry because of race conditions with the peer switch. @@ -273,8 +270,9 @@ static void pim_mlag_up_peer_add(struct mlag_mroute_add *msg) vrf = vrf_lookup_by_name(msg->vrf_name); if (!vrf) { if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute add failed %s:%s; no vrf", - msg->vrf_name, sg_str); + zlog_debug( + "peer MLAG mroute add failed %s:%pSG; no vrf", + msg->vrf_name, &sg); return; } pim = vrf->info; @@ -294,8 +292,9 @@ static void pim_mlag_up_peer_add(struct mlag_mroute_add *msg) if (!up) { if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute add failed %s:%s", - vrf->name, sg_str); + zlog_debug( + "peer MLAG mroute add failed %s:%pSG", + vrf->name, &sg); return; } } @@ -329,23 +328,20 @@ static void pim_mlag_up_peer_del(struct mlag_mroute_del *msg) struct pim_instance *pim; pim_sgaddr sg; struct vrf *vrf; - char sg_str[PIM_SG_LEN]; memset(&sg, 0, sizeof(sg)); sg.src.s_addr = htonl(msg->source_ip); sg.grp.s_addr = htonl(msg->group_ip); - if (PIM_DEBUG_MLAG) - pim_str_sg_set(&sg, sg_str); if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute del %s:%s", msg->vrf_name, - sg_str); + zlog_debug("peer MLAG mroute del %s:%pSG", msg->vrf_name, &sg); vrf = vrf_lookup_by_name(msg->vrf_name); if (!vrf) { if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute del skipped %s:%s; no vrf", - msg->vrf_name, sg_str); + zlog_debug( + "peer MLAG mroute del skipped %s:%pSG; no vrf", + msg->vrf_name, &sg); return; } pim = vrf->info; @@ -353,8 +349,9 @@ static void pim_mlag_up_peer_del(struct mlag_mroute_del *msg) up = pim_upstream_find(pim, &sg); if (!up) { if (PIM_DEBUG_MLAG) - zlog_debug("peer MLAG mroute del skipped %s:%s; no up", - vrf->name, sg_str); + zlog_debug( + "peer MLAG mroute del skipped %s:%pSG; no up", + vrf->name, &sg); return; } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a01256dfb..91b997f44 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -189,9 +189,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, if (!(PIM_I_am_DR(pim_ifp))) { if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug( - "%s: Interface is not the DR blackholing incoming traffic for %s", - __func__, pim_str_sg_dump(&sg)); + zlog_debug("%s: Interface is not the DR blackholing incoming traffic for %pSG", + __func__, &sg); /* * We are not the DR, but we are still receiving packets @@ -258,7 +257,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, up = pim_upstream_find(pim_ifp->pim, &sg); if (!up) { pim_sgaddr star = sg; - star.src.s_addr = INADDR_ANY; + star.src = PIMADDR_ANY; up = pim_upstream_find(pim_ifp->pim, &star); @@ -268,9 +267,8 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, __func__, NULL); if (!up) { if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: Unable to create upstream information for %s", - __func__, pim_str_sg_dump(&sg)); + zlog_debug("%s: Unable to create upstream information for %pSG", + __func__, &sg); return 0; } pim_upstream_keep_alive_timer_start( @@ -284,9 +282,8 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, return 0; } if (PIM_DEBUG_MROUTE_DETAIL) { - zlog_debug( - "%s: Unable to find upstream channel WHOLEPKT%s", - __func__, pim_str_sg_dump(&sg)); + zlog_debug("%s: Unable to find upstream channel WHOLEPKT%pSG", + __func__, &sg); } return 0; } @@ -316,9 +313,8 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, if (!up->t_rs_timer) { if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) { if (PIM_DEBUG_PIM_REG) - zlog_debug( - "%s register forward skipped as group is SSM", - pim_str_sg_dump(&sg)); + zlog_debug("%pSG register forward skipped as group is SSM", + &sg); return 0; } @@ -361,18 +357,16 @@ static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, if (!ifp) { if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", - __func__, pim_str_sg_dump(&sg), msg->im_vif); + zlog_debug("%s: WRONGVIF (S,G)=%pSG could not find input interface for input_vif_index=%d", + __func__, &sg, msg->im_vif); return -1; } pim_ifp = ifp->info; if (!pim_ifp) { if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", - __func__, pim_str_sg_dump(&sg), ifp->name); + zlog_debug("%s: WRONGVIF (S,G)=%pSG multicast not enabled on interface %s", + __func__, &sg, ifp->name); return -2; } @@ -380,18 +374,16 @@ static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, if (!ch) { pim_sgaddr star_g = sg; if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: WRONGVIF (S,G)=%s could not find channel on interface %s", - __func__, pim_str_sg_dump(&sg), ifp->name); + zlog_debug("%s: WRONGVIF (S,G)=%pSG could not find channel on interface %s", + __func__, &sg, ifp->name); - star_g.src.s_addr = INADDR_ANY; + star_g.src = PIMADDR_ANY; ch = pim_ifchannel_find(ifp, &star_g); if (!ch) { if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: WRONGVIF (*,G)=%s could not find channel on interface %s", - __func__, pim_str_sg_dump(&star_g), - ifp->name); + zlog_debug("%s: WRONGVIF (*,G)=%pSG could not find channel on interface %s", + __func__, &star_g, + ifp->name); return -3; } } @@ -467,7 +459,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, } star_g = sg; - star_g.src.s_addr = INADDR_ANY; + star_g.src = PIMADDR_ANY; pim = pim_ifp->pim; /* @@ -558,9 +550,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, NULL); if (!up) { if (PIM_DEBUG_MROUTE) - zlog_debug( - "%s: WRONGVIF%s unable to create upstream on interface", - pim_str_sg_dump(&sg), ifp->name); + zlog_debug("%pSG: WRONGVIF%s unable to create upstream on interface", + &sg, ifp->name); return -2; } PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); @@ -1218,9 +1209,8 @@ void pim_mroute_update_counters(struct channel_oil *c_oil) sg.src = c_oil->oil.mfcc_origin; sg.grp = c_oil->oil.mfcc_mcastgrp; - zlog_debug( - "Channel%s is not installed no need to collect data from kernel", - pim_str_sg_dump(&sg)); + zlog_debug("Channel%pSG is not installed no need to collect data from kernel", + &sg); } return; } @@ -1236,8 +1226,8 @@ void pim_mroute_update_counters(struct channel_oil *c_oil) sg.src = c_oil->oil.mfcc_origin; sg.grp = c_oil->oil.mfcc_mcastgrp; - zlog_warn("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%s: errno=%d: %s", - (unsigned long)SIOCGETSGCNT, pim_str_sg_dump(&sg), + zlog_warn("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%pSG: errno=%d: %s", + (unsigned long)SIOCGETSGCNT, &sg, errno, safe_strerror(errno)); return; } diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 673347b4f..eb89040d4 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -244,7 +244,7 @@ static struct pim_msdp_sa *pim_msdp_sa_new(struct pim_instance *pim, sa->pim = pim; sa->sg = *sg; - pim_str_sg_set(sg, sa->sg_str); + snprintfrr(sa->sg_str, sizeof(sa->sg_str), "%pSG", sg); sa->rp = rp; sa->uptime = pim_time_monotonic_sec(); @@ -314,7 +314,7 @@ static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, } /* any time the peer ip changes also update the rp address */ - if (PIM_INADDR_ISNOT_ANY(sa->peer)) { + if (sa->peer.s_addr != INADDR_ANY) { old_mp = pim_msdp_peer_find(sa->pim, sa->peer); if (old_mp && old_mp->sa_cnt) { --old_mp->sa_cnt; @@ -624,15 +624,14 @@ void pim_msdp_up_join_state_changed(struct pim_instance *pim, } /* If this is not really an XG entry just move on */ - if ((xg_up->sg.src.s_addr != INADDR_ANY) - || (xg_up->sg.grp.s_addr == INADDR_ANY)) { + if (!pim_addr_is_any(xg_up->sg.src) || pim_addr_is_any(xg_up->sg.grp)) { return; } /* XXX: Need to maintain SAs per-group to avoid all this unnecessary * walking */ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { + if (pim_addr_cmp(sa->sg.grp, xg_up->sg.grp)) { continue; } pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); @@ -645,18 +644,18 @@ static void pim_msdp_up_xg_del(struct pim_instance *pim, pim_sgaddr *sg) struct pim_msdp_sa *sa; if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); + zlog_debug("MSDP %pSG del", sg); } /* If this is not really an XG entry just move on */ - if ((sg->src.s_addr != INADDR_ANY) || (sg->grp.s_addr == INADDR_ANY)) { + if (!pim_addr_is_any(sg->src) || pim_addr_is_any(sg->grp)) { return; } /* XXX: Need to maintain SAs per-group to avoid all this unnecessary * walking */ for (ALL_LIST_ELEMENTS_RO(pim->msdp.sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != sg->grp.s_addr) { + if (pim_addr_cmp(sa->sg.grp, sg->grp)) { continue; } pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); @@ -666,9 +665,9 @@ static void pim_msdp_up_xg_del(struct pim_instance *pim, pim_sgaddr *sg) void pim_msdp_up_del(struct pim_instance *pim, pim_sgaddr *sg) { if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); + zlog_debug("MSDP up %pSG del", sg); } - if (sg->src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg->src)) { pim_msdp_up_xg_del(pim, sg); } else { pim_msdp_sa_local_del_on_up_del(pim, sg); @@ -680,7 +679,7 @@ static unsigned int pim_msdp_sa_hash_key_make(const void *p) { const struct pim_msdp_sa *sa = p; - return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); + return pim_sgaddr_hash(sa->sg, 0); } static bool pim_msdp_sa_hash_eq(const void *p1, const void *p2) @@ -688,8 +687,7 @@ static bool pim_msdp_sa_hash_eq(const void *p1, const void *p2) const struct pim_msdp_sa *sa1 = p1; const struct pim_msdp_sa *sa2 = p2; - return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) - && (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); + return !pim_sgaddr_cmp(sa1->sg, sa2->sg); } static int pim_msdp_sa_comp(const void *p1, const void *p2) @@ -697,19 +695,7 @@ static int pim_msdp_sa_comp(const void *p1, const void *p2) const struct pim_msdp_sa *sa1 = p1; const struct pim_msdp_sa *sa2 = p2; - if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) - return -1; - - if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) - return 1; - - if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) - return -1; - - if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) - return 1; - - return 0; + return pim_sgaddr_cmp(sa1->sg, sa2->sg); } /* RFC-3618:Sec-10.1.3 - Peer-RPF forwarding */ diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 64fdbaa89..395bbf6f2 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -77,7 +77,7 @@ static void pim_msdp_pkt_sa_dump_one(struct stream *s) sg.grp.s_addr = stream_get_ipv4(s); sg.src.s_addr = stream_get_ipv4(s); - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + zlog_debug(" sg %pSG", &sg); } static void pim_msdp_pkt_sa_dump(struct stream *s) @@ -513,7 +513,7 @@ static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) return; } if (PIM_DEBUG_MSDP_PACKETS) { - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + zlog_debug(" sg %pSG", &sg); } pim_msdp_sa_ref(mp->pim, mp, &sg, rp); diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 65b6405c8..c493ded0c 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -115,7 +115,7 @@ size_t pim_msg_get_jp_group_size(struct list *sources) size += sizeof(struct pim_encoded_source_ipv4) * sources->count; js = listgetdata(listhead(sources)); - if (js && js->up->sg.src.s_addr == INADDR_ANY && js->is_join) { + if (js && pim_addr_is_any(js->up->sg.src) && js->is_join) { struct pim_upstream *child, *up; struct listnode *up_node; @@ -193,7 +193,7 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, else grp->prunes++; - if (source->up->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(source->up->sg.src)) { struct pim_instance *pim = source->up->channel_oil->pim; struct pim_rpf *rpf = pim_rp_g(pim, source->up->sg.grp); bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index cd6f4c45f..26ca48543 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -234,7 +234,7 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, struct prefix grp; struct rp_info *trp_info; - if (upstream->sg.src.s_addr != INADDR_ANY) + if (!pim_addr_is_any(upstream->sg.src)) continue; grp.family = AF_INET; @@ -259,6 +259,14 @@ void pim_nht_bsr_del(struct pim_instance *pim, struct in_addr addr) struct pim_nexthop_cache *pnc = NULL; struct pim_nexthop_cache lookup; + /* + * Nothing to do here if the address to unregister + * is 0.0.0.0 as that the BSR has not been registered + * for tracking yet. + */ + if (addr.s_addr == INADDR_ANY) + return; + lookup.rpf.rpf_addr.family = AF_INET; lookup.rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; lookup.rpf.rpf_addr.u.prefix4 = addr; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index c094e99a7..b17f821dd 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -45,8 +45,8 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size) sg.src = c_oil->oil.mfcc_origin; sg.grp = c_oil->oil.mfcc_mcastgrp; ifp = pim_if_find_by_vif_index(c_oil->pim, c_oil->oil.mfcc_parent); - snprintf(buf, size, "%s IIF: %s, OIFS: ", pim_str_sg_dump(&sg), - ifp ? ifp->name : "(?)"); + snprintfrr(buf, size, "%pSG IIF: %s, OIFS: ", &sg, + ifp ? ifp->name : "(?)"); out = buf + strlen(buf); for (i = 0; i < MAXVIFS; i++) { @@ -163,8 +163,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, rb_pim_oil_add(&pim->channel_oil_head, c_oil); if (PIM_DEBUG_MROUTE) - zlog_debug("%s(%s): c_oil %s add", - __func__, name, pim_str_sg_dump(sg)); + zlog_debug("%s(%s): c_oil %pSG add", __func__, name, sg); return c_oil; } @@ -327,8 +326,8 @@ void pim_channel_del_inherited_oif(struct channel_oil *c_oil, /* if an inherited OIF is being removed join-desired can change * if the inherited OIL is now empty and KAT is running */ - if (up && up->sg.src.s_addr != INADDR_ANY && - pim_upstream_empty_inherited_olist(up)) + if (up && !pim_addr_is_any(up->sg.src) && + pim_upstream_empty_inherited_olist(up)) pim_upstream_update_join_desired(up->pim, up); } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index e7bbeb4f6..855d91256 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -75,9 +75,8 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, struct prefix p; if (PIM_DEBUG_PIM_REG) { - zlog_debug("Sending Register stop for %s to %pI4 on %s", - pim_str_sg_dump(sg), &originator, - ifp->name); + zlog_debug("Sending Register stop for %pSG to %pI4 on %s", sg, + &originator, ifp->name); } memset(buffer, 0, 10000); @@ -377,14 +376,14 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); - zlog_debug("Received Register message%s from %s on %s, rp: %d", - pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp); + zlog_debug("Received Register message%pSG from %s on %s, rp: %d", + &sg, src_str, ifp->name, i_am_rp); } if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) { - if (sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(sg.src)) { zlog_warn( - "%s: Received Register message for Group(%pI4) is now in SSM, dropping the packet", + "%s: Received Register message for Group(%pPA) is now in SSM, dropping the packet", __func__, &sg.grp); /* Drop Packet Silently */ return 0; @@ -515,13 +514,11 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, } else { if (PIM_DEBUG_PIM_REG) { if (!i_am_rp) - zlog_debug( - "Received Register packet for %s, Rejecting packet because I am not the RP configured for group", - pim_str_sg_dump(&sg)); + zlog_debug("Received Register packet for %pSG, Rejecting packet because I am not the RP configured for group", + &sg); else - zlog_debug( - "Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", - pim_str_sg_dump(&sg)); + zlog_debug("Received Register packet for %pSG, Rejecting packet because the dst ip address is not the actual RP", + &sg); } pim_register_stop_send(ifp, &sg, dest_addr, src_addr); } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index d356aff9f..f35adb0ce 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -536,8 +536,8 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, /* Find (*, G) upstream whose RP is not * configured yet */ - if ((up->upstream_addr.s_addr == INADDR_ANY) - && (up->sg.src.s_addr == INADDR_ANY)) { + if ((up->upstream_addr.s_addr == INADDR_ANY) && + pim_addr_is_any(up->sg.src)) { struct prefix grp; struct rp_info *trp_info; @@ -628,7 +628,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, route_node_get_lock_count(rn)); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - if (up->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(up->sg.src)) { struct prefix grp; struct rp_info *trp_info; @@ -778,9 +778,9 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, /* Find the upstream (*, G) whose upstream address is * same as the deleted RP */ - if ((up->upstream_addr.s_addr - == rp_info->rp.rpf_addr.u.prefix4.s_addr) - && (up->sg.src.s_addr == INADDR_ANY)) { + if ((up->upstream_addr.s_addr == + rp_info->rp.rpf_addr.u.prefix4.s_addr) && + pim_addr_is_any(up->sg.src)) { struct prefix grp; grp.family = AF_INET; grp.prefixlen = IPV4_MAX_BITLEN; @@ -826,9 +826,9 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, /* Find the upstream (*, G) whose upstream address is same as * the deleted RP */ - if ((up->upstream_addr.s_addr - == rp_info->rp.rpf_addr.u.prefix4.s_addr) - && (up->sg.src.s_addr == INADDR_ANY)) { + if ((up->upstream_addr.s_addr == + rp_info->rp.rpf_addr.u.prefix4.s_addr) && + pim_addr_is_any(up->sg.src)) { struct prefix grp; grp.family = AF_INET; @@ -914,7 +914,7 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, listnode_add_sort(pim->rp_list, rp_info); frr_each (rb_pim_upstream, &pim->upstream_head, up) { - if (up->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(up->sg.src)) { struct prefix grp; struct rp_info *trp_info; diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index aa89431d3..1e865a395 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -259,7 +259,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, grp.prefixlen = IPV4_MAX_BITLEN; grp.u.prefix4 = up->sg.grp; - if ((up->sg.src.s_addr == INADDR_ANY && I_am_RP(pim, up->sg.grp)) || + if ((pim_addr_is_any(up->sg.src) && I_am_RP(pim, up->sg.grp)) || PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) neigh_needed = false; pim_find_or_track_nexthop(pim, &nht_p, up, NULL, NULL); diff --git a/pimd/pim_str.c b/pimd/pim_str.c index 180ed69fd..8744d62d1 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -41,13 +41,3 @@ void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, errno = save_errno; } - -char *pim_str_sg_dump(const pim_sgaddr *sg) -{ - static char sg_str[PIM_SG_LEN]; - - pim_str_sg_set(sg, sg_str); - - return sg_str; -} - diff --git a/pimd/pim_str.h b/pimd/pim_str.h index f6d209b79..be8b6a9f4 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -39,31 +39,9 @@ #define PIM_SG_LEN PREFIX_SG_STR_LEN #define pim_inet4_dump prefix_mcast_inet4_dump -static inline const char *pim_str_sg_set(const pim_sgaddr *sg, char *str) -{ - snprintfrr(str, PREFIX_SG_STR_LEN, "%pSG", sg); - return str; -} - -static inline void pim_addr_copy(pim_addr *dest, pim_addr *source) -{ - dest->s_addr = source->s_addr; -} - -static inline int pim_is_addr_any(pim_addr addr) -{ - return (addr.s_addr == INADDR_ANY); -} - -static inline int pim_addr_cmp(pim_addr addr1, pim_addr addr2) -{ - return IPV4_ADDR_CMP(&addr1, &addr2); -} - void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, int buf_size); void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); -char *pim_str_sg_dump(const pim_sgaddr *sg); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index ef356213e..800ec9c45 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -101,18 +101,15 @@ static void pim_upstream_find_new_children(struct pim_instance *pim, { struct pim_upstream *child; - if ((up->sg.src.s_addr != INADDR_ANY) - && (up->sg.grp.s_addr != INADDR_ANY)) + if (!pim_addr_is_any(up->sg.src) && !pim_addr_is_any(up->sg.grp)) return; - if ((up->sg.src.s_addr == INADDR_ANY) - && (up->sg.grp.s_addr == INADDR_ANY)) + if (pim_addr_is_any(up->sg.src) && pim_addr_is_any(up->sg.grp)) return; frr_each (rb_pim_upstream, &pim->upstream_head, child) { - if ((up->sg.grp.s_addr != INADDR_ANY) - && (child->sg.grp.s_addr == up->sg.grp.s_addr) - && (child != up)) { + if (!pim_addr_is_any(up->sg.grp) && + !pim_addr_cmp(child->sg.grp, up->sg.grp) && (child != up)) { child->parent = up; listnode_add_sort(up->sources, child); if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags)) @@ -135,9 +132,9 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim, struct pim_upstream *up = NULL; // (S,G) - if ((child->sg.src.s_addr != INADDR_ANY) - && (child->sg.grp.s_addr != INADDR_ANY)) { - any.src.s_addr = INADDR_ANY; + if (!pim_addr_is_any(child->sg.src) && + !pim_addr_is_any(child->sg.grp)) { + any.src = PIMADDR_ANY; up = pim_upstream_find(pim, &any); if (up) @@ -217,7 +214,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, if (up->join_state == PIM_UPSTREAM_JOINED) { pim_jp_agg_single_upstream_send(&up->rpf, up, 0); - if (up->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(up->sg.src)) { /* if a (*, G) entry in the joined state is being * deleted we * need to notify MSDP */ @@ -229,7 +226,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, pim_jp_agg_upstream_verification(up, false); up->rpf.source_nexthop.interface = NULL; - if (up->sg.src.s_addr != INADDR_ANY) { + if (!pim_addr_is_any(up->sg.src)) { if (pim->upstream_sg_wheel) wheel_remove_item(pim->upstream_sg_wheel, up); notify_msdp = true; @@ -656,7 +653,7 @@ void pim_upstream_update_use_rpt(struct pim_upstream *up, bool old_use_rpt; bool new_use_rpt; - if (up->sg.src.s_addr == INADDR_ANY) + if (pim_addr_is_any(up->sg.src)) return; old_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags); @@ -704,7 +701,7 @@ void pim_upstream_reeval_use_rpt(struct pim_instance *pim) struct pim_upstream *up; frr_each (rb_pim_upstream, &pim->upstream_head, up) { - if (up->sg.src.s_addr == INADDR_ANY) + if (pim_addr_is_any(up->sg.src)) continue; pim_upstream_update_use_rpt(up, true /*update_mroute*/); @@ -775,7 +772,7 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, * RFC 4601 Sec 4.5.7: * JoinDesired(S,G) -> False, set SPTbit to false. */ - if (up->sg.src.s_addr != INADDR_ANY) + if (!pim_addr_is_any(up->sg.src)) up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; if (old_state == PIM_UPSTREAM_JOINED) @@ -827,19 +824,7 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, int pim_upstream_compare(const struct pim_upstream *up1, const struct pim_upstream *up2) { - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) - return -1; - - if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) - return 1; - - if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) - return -1; - - if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) - return 1; - - return 0; + return pim_sgaddr_cmp(up1->sg, up2->sg); } void pim_upstream_fill_static_iif(struct pim_upstream *up, @@ -873,7 +858,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->pim = pim; up->sg = *sg; - pim_str_sg_set(sg, up->sg_str); + snprintfrr(up->sg_str, sizeof(up->sg_str), "%pSG", sg); if (ch) ch->upstream = up; @@ -889,7 +874,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, } up->parent = pim_upstream_find_parent(pim, up); - if (up->sg.src.s_addr == INADDR_ANY) { + if (pim_addr_is_any(up->sg.src)) { up->sources = list_new(); up->sources->cmp = (int (*)(void *, void *))pim_upstream_compare; @@ -923,7 +908,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->ifchannels = list_new(); up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - if (up->sg.src.s_addr != INADDR_ANY) { + if (!pim_addr_is_any(up->sg.src)) { wheel_add_item(pim->upstream_sg_wheel, up); /* Inherit the DF role from the parent (*, G) entry for @@ -1092,8 +1077,8 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim, pim_sgaddr *sg, up->rpf.source_nexthop.interface->name : "Unknown" , found, up->ref_count); else - zlog_debug("%s(%s): (%s) failure to create", __func__, - name, pim_str_sg_dump(sg)); + zlog_debug("%s(%s): (%pSG) failure to create", __func__, + name, sg); } return up; @@ -1225,7 +1210,7 @@ bool pim_upstream_evaluate_join_desired(struct pim_instance *pim, empty_imm_oil = pim_upstream_empty_immediate_olist(pim, up); /* (*,G) */ - if (up->sg.src.s_addr == INADDR_ANY) + if (pim_addr_is_any(up->sg.src)) return !empty_imm_oil; /* (S,G) */ @@ -1961,7 +1946,7 @@ unsigned int pim_upstream_hash_key(const void *arg) { const struct pim_upstream *up = arg; - return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0); + return pim_sgaddr_hash(up->sg, 0); } void pim_upstream_terminate(struct pim_instance *pim) @@ -1984,11 +1969,7 @@ bool pim_upstream_equal(const void *arg1, const void *arg2) const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) - && (up1->sg.src.s_addr == up2->sg.src.s_addr)) - return true; - - return false; + return !pim_sgaddr_cmp(up1->sg, up2->sg); } /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines @@ -2131,7 +2112,7 @@ void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim) struct pim_upstream *up; frr_each (rb_pim_upstream, &pim->upstream_head, up) { - if (up->sg.src.s_addr != INADDR_ANY) + if (!pim_addr_is_any(up->sg.src)) continue; if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)) @@ -2178,7 +2159,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, g.prefixlen = IPV4_MAX_BITLEN; frr_each (rb_pim_upstream, &pim->upstream_head, up) { - if (up->sg.src.s_addr != INADDR_ANY) + if (!pim_addr_is_any(up->sg.src)) continue; if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)) diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 8c0132a9a..c543c63ee 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -340,8 +340,7 @@ int pim_interface_config_write(struct vty *vty) } /* update source */ - if (PIM_INADDR_ISNOT_ANY( - pim_ifp->update_source)) { + if (!pim_addr_is_any(pim_ifp->update_source)) { char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<src?>", pim_ifp->update_source, diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index 3aa8bacb8..c1e7be587 100644 --- a/pimd/pim_vxlan.c +++ b/pimd/pim_vxlan.c @@ -720,8 +720,7 @@ static unsigned int pim_vxlan_sg_hash_key_make(const void *p) { const struct pim_vxlan_sg *vxlan_sg = p; - return (jhash_2words(vxlan_sg->sg.src.s_addr, - vxlan_sg->sg.grp.s_addr, 0)); + return pim_sgaddr_hash(vxlan_sg->sg, 0); } static bool pim_vxlan_sg_hash_eq(const void *p1, const void *p2) @@ -729,8 +728,7 @@ static bool pim_vxlan_sg_hash_eq(const void *p1, const void *p2) const struct pim_vxlan_sg *sg1 = p1; const struct pim_vxlan_sg *sg2 = p2; - return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr) - && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr)); + return !pim_sgaddr_cmp(sg1->sg, sg2->sg); } static struct pim_vxlan_sg *pim_vxlan_sg_new(struct pim_instance *pim, @@ -742,7 +740,7 @@ static struct pim_vxlan_sg *pim_vxlan_sg_new(struct pim_instance *pim, vxlan_sg->pim = pim; vxlan_sg->sg = *sg; - pim_str_sg_set(sg, vxlan_sg->sg_str); + snprintfrr(vxlan_sg->sg_str, sizeof(vxlan_sg->sg_str), "%pSG", sg); if (PIM_DEBUG_VXLAN) zlog_debug("vxlan SG %s alloc", vxlan_sg->sg_str); diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h index cd3de23e6..96882918a 100644 --- a/pimd/pim_vxlan.h +++ b/pimd/pim_vxlan.h @@ -109,14 +109,14 @@ struct pim_vxlan { */ static inline bool pim_vxlan_is_orig_mroute(struct pim_vxlan_sg *vxlan_sg) { - return (vxlan_sg->sg.src.s_addr != INADDR_ANY); + return !pim_addr_is_any(vxlan_sg->sg.src); } static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up) { - return (up->sg.src.s_addr != INADDR_ANY) && - up->rpf.source_nexthop.interface && - if_is_loopback(up->rpf.source_nexthop.interface); + return !pim_addr_is_any(up->sg.src) && + up->rpf.source_nexthop.interface && + if_is_loopback(up->rpf.source_nexthop.interface); } static inline bool pim_vxlan_is_term_dev_cfg(struct pim_instance *pim, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 05b6f23ed..2efafd4b9 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -340,14 +340,9 @@ static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS) stream_get(&sg.src.s_addr, s, prefixlen); stream_get(&sg.grp.s_addr, s, prefixlen); - if (PIM_DEBUG_ZEBRA) { - char sg_str[PIM_SG_LEN]; - - pim_str_sg_set(&sg, sg_str); - zlog_debug("%u:recv SG %s %s", vrf_id, - (cmd == ZEBRA_VXLAN_SG_ADD)?"add":"del", - sg_str); - } + if (PIM_DEBUG_ZEBRA) + zlog_debug("%u:recv SG %s %pSG", vrf_id, + (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", &sg); if (cmd == ZEBRA_VXLAN_SG_ADD) pim_vxlan_sg_add(pim, &sg); @@ -520,9 +515,8 @@ static void igmp_source_forward_reevaluate_one(struct pim_instance *pim, if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { if (PIM_DEBUG_PIM_EVENTS) - zlog_debug( - "local membership del for %s as G is now SSM", - pim_str_sg_dump(&sg)); + zlog_debug("local membership del for %pSG as G is now SSM", + &sg); pim_ifchannel_local_membership_del(group->interface, &sg); } @@ -531,9 +525,8 @@ static void igmp_source_forward_reevaluate_one(struct pim_instance *pim, if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { if (PIM_DEBUG_PIM_EVENTS) - zlog_debug( - "local membership add for %s as G is now ASM", - pim_str_sg_dump(&sg)); + zlog_debug("local membership add for %pSG as G is now ASM", + &sg); pim_ifchannel_local_membership_add( group->interface, &sg, false /*is_vxlan*/); } @@ -569,7 +562,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_temp) { if (pim_is_grp_ssm(pim, ch->sg.grp)) { - if (ch->sg.src.s_addr == INADDR_ANY) + if (pim_addr_is_any(ch->sg.src)) pim_ifchannel_delete(ch); } } @@ -590,8 +583,7 @@ void igmp_source_forward_start(struct pim_instance *pim, sg.grp = source->source_group->group_addr; if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s oif=%s fwd=%d", __func__, - pim_str_sg_dump(&sg), + zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, source->source_group->interface->name, IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); } @@ -655,10 +647,9 @@ void igmp_source_forward_start(struct pim_instance *pim, pim_inet4_dump("<source?>", vif_source, buf2, sizeof(buf2)); - zlog_debug( - "%s: NHT %s vif_source %s vif_index:%d ", - __func__, pim_str_sg_dump(&sg), buf2, - input_iface_vif_index); + zlog_debug("%s: NHT %pSG vif_source %s vif_index:%d ", + __func__, &sg, buf2, + input_iface_vif_index); } if (input_iface_vif_index < 1) { @@ -689,13 +680,12 @@ void igmp_source_forward_start(struct pim_instance *pim, /* ignore request for looped MFC entry */ if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s: ignoring request for looped MFC entry (S,G)=%s: oif=%s vif_index=%d", - __func__, - pim_str_sg_dump(&sg), - source->source_group - ->interface->name, - input_iface_vif_index); + zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d", + __func__, + &sg, + source->source_group + ->interface->name, + input_iface_vif_index); } return; } @@ -704,10 +694,9 @@ void igmp_source_forward_start(struct pim_instance *pim, pim_channel_oil_add(pim, &sg, __func__); if (!source->source_channel_oil) { if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __func__, - pim_str_sg_dump(&sg)); + zlog_debug("%s %s: could not create OIL for channel (S,G)=%pSG", + __FILE__, __func__, + &sg); } return; } @@ -728,10 +717,9 @@ void igmp_source_forward_start(struct pim_instance *pim, } } else { if (PIM_DEBUG_IGMP_TRACE) - zlog_debug( - "%s: %s was received on %s interface but we are not DR for that interface", - __func__, pim_str_sg_dump(&sg), - group->interface->name); + zlog_debug("%s: %pSG was received on %s interface but we are not DR for that interface", + __func__, &sg, + group->interface->name); return; } @@ -742,8 +730,8 @@ void igmp_source_forward_start(struct pim_instance *pim, if (!pim_ifchannel_local_membership_add(group->interface, &sg, false /*is_vxlan*/)) { if (PIM_DEBUG_MROUTE) - zlog_warn("%s: Failure to add local membership for %s", - __func__, pim_str_sg_dump(&sg)); + zlog_warn("%s: Failure to add local membership for %pSG", + __func__, &sg); pim_channel_del_oif(source->source_channel_oil, group->interface, PIM_OIF_FLAG_PROTO_IGMP, @@ -769,8 +757,7 @@ void igmp_source_forward_stop(struct gm_source *source) sg.grp = source->source_group->group_addr; if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s oif=%s fwd=%d", __func__, - pim_str_sg_dump(&sg), + zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, source->source_group->interface->name, IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); } @@ -819,21 +806,9 @@ void pim_forward_start(struct pim_ifchannel *ch) struct pim_upstream *up = ch->upstream; uint32_t mask = 0; - if (PIM_DEBUG_PIM_TRACE) { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - char upstream_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("<source?>", ch->sg.src, source_str, - sizeof(source_str)); - pim_inet4_dump("<group?>", ch->sg.grp, group_str, - sizeof(group_str)); - pim_inet4_dump("<upstream?>", up->upstream_addr, upstream_str, - sizeof(upstream_str)); - zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%pI4)", __func__, - source_str, group_str, ch->interface->name, - &up->upstream_addr); - } + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: (S,G)=%pSG oif=%s (%pI4)", __func__, &ch->sg, + ch->interface->name, &up->upstream_addr); if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) mask = PIM_OIF_FLAG_PROTO_IGMP; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 755b9b132..5997cc25a 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -535,10 +535,9 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil) more.src = c_oil->oil.mfcc_origin; more.grp = c_oil->oil.mfcc_mcastgrp; - zlog_debug( - "Sending Request for New Channel Oil Information%s VIIF %d(%s)", - pim_str_sg_dump(&more), c_oil->oil.mfcc_parent, - c_oil->pim->vrf->name); + zlog_debug("Sending Request for New Channel Oil Information%pSG VIIF %d(%s)", + &more, c_oil->oil.mfcc_parent, + c_oil->pim->vrf->name); } if (!ifp) @@ -593,9 +592,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil) more.grp = c_oil->oil.mfcc_mcastgrp; flog_err( EC_LIB_ZAPI_MISSMATCH, - "%s: Received wrong %s(%s) information requested", - __func__, pim_str_sg_dump(&more), - c_oil->pim->vrf->name); + "%s: Received wrong %pSG(%s) information requested", + __func__, &more, c_oil->pim->vrf->name); } zclient_lookup_failed(zlookup); return -3; diff --git a/pimd/pimd.h b/pimd/pimd.h index 5ba29f9c4..7732dc5b7 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -83,8 +83,6 @@ #define PIM_FORCE_BOOLEAN(expr) ((expr) != 0) #define PIM_NET_INADDR_ANY (htonl(INADDR_ANY)) -#define PIM_INADDR_IS_ANY(addr) (addr).s_addr == PIM_NET_INADDR_ANY -#define PIM_INADDR_ISNOT_ANY(addr) ((addr).s_addr != PIM_NET_INADDR_ANY) /* struct in_addr addr */ #define PIM_MASK_PIM_EVENTS (1 << 0) #define PIM_MASK_PIM_EVENTS_DETAIL (1 << 1) diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 0a323f744..ceed9cf73 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -29,7 +29,9 @@ #include "vrf.h" #include "zclient.h" #include "nexthop_group.h" +#include "linklist.h" #include "link_state.h" +#include "cspf.h" #include "sharpd/sharp_globals.h" #include "sharpd/sharp_zebra.h" @@ -425,7 +427,8 @@ DEFPY (install_seg6local_routes, End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\ End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\ End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\ - End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table>\ + End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\ + End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table>\ (1-1000000)$routes [repeat (2-1000)$rpt]", "Sharp routing Protocol\n" "install some routes\n" @@ -444,6 +447,8 @@ DEFPY (install_seg6local_routes, "V4 Nexthop address to use\n" "SRv6 End.DT6 function to use\n" "Redirect table id to use\n" + "SRv6 End.DT4 function to use\n" + "Redirect table id to use\n" "How many to create\n" "Should we repeat this command\n" "How many times to repeat this command\n") @@ -494,6 +499,9 @@ DEFPY (install_seg6local_routes, } else if (seg6l_enddt6) { action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6; ctx.table = seg6l_enddt6_table; + } else if (seg6l_enddt4) { + action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4; + ctx.table = seg6l_enddt4_table; } else { action = ZEBRA_SEG6_LOCAL_ACTION_END; } @@ -1150,6 +1158,106 @@ DEFPY (show_sharp_segment_routing_srv6, return CMD_SUCCESS; } +DEFPY (show_sharp_cspf, + show_sharp_cspf_cmd, + "show sharp cspf source <A.B.C.D$src4|X:X::X:X$src6> \ + destination <A.B.C.D$dst4|X:X::X:X$dst6> \ + <metric|te-metric|delay> (0-16777215)$cost \ + [rsv-bw (0-7)$cos BANDWIDTH$bw]", + SHOW_STR + SHARP_STR + "Constraint Shortest Path First path computation\n" + "Source of the path\n" + "IPv4 Source address in dot decimal A.B.C.D\n" + "IPv6 Source address as X:X:X:X\n" + "Destination of the path\n" + "IPv4 Destination address in dot decimal A.B.C.D\n" + "IPv6 Destination address as X:X:X:X\n" + "Maximum Metric\n" + "Maximum TE Metric\n" + "Maxim Delay\n" + "Value of Maximum cost\n" + "Reserved Bandwidth of this path\n" + "Class of Service or Priority level\n" + "Bytes/second (IEEE floating point format)\n") +{ + + struct cspf *algo; + struct constraints csts; + struct c_path *path; + struct listnode *node; + struct ls_edge *edge; + int idx; + + if (sg.ted == NULL) { + vty_out(vty, "MPLS-TE import is not enabled\n"); + return CMD_WARNING; + } + + if ((src4.s_addr != INADDR_ANY && dst4.s_addr == INADDR_ANY) || + (src4.s_addr == INADDR_ANY && dst4.s_addr != INADDR_ANY)) { + vty_out(vty, "Don't mix IPv4 and IPv6 addresses\n"); + return CMD_WARNING; + } + + idx = 6; + memset(&csts, 0, sizeof(struct constraints)); + if (argv_find(argv, argc, "metric", &idx)) { + csts.ctype = CSPF_METRIC; + csts.cost = cost; + } + idx = 6; + if (argv_find(argv, argc, "te-metric", &idx)) { + csts.ctype = CSPF_TE_METRIC; + csts.cost = cost; + } + idx = 6; + if (argv_find(argv, argc, "delay", &idx)) { + csts.ctype = CSPF_DELAY; + csts.cost = cost; + } + if (argc > 9) { + if (sscanf(bw, "%g", &csts.bw) != 1) { + vty_out(vty, "Bandwidth constraints: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + csts.cos = cos; + } + + /* Initialize and call point-to-point Path computation */ + if (src4.s_addr != INADDR_ANY) + algo = cspf_init_v4(NULL, sg.ted, src4, dst4, &csts); + else + algo = cspf_init_v6(NULL, sg.ted, src6, dst6, &csts); + path = compute_p2p_path(algo, sg.ted); + cspf_del(algo); + + if (!path) { + vty_out(vty, "Path computation failed without error\n"); + return CMD_SUCCESS; + } + if (path->status != SUCCESS) { + vty_out(vty, "Path computation failed: %d\n", path->status); + return CMD_SUCCESS; + } + + vty_out(vty, "Path computation success\n"); + vty_out(vty, "\tCost: %d\n", path->weight); + vty_out(vty, "\tEdges:"); + for (ALL_LIST_ELEMENTS_RO(path->edges, node, edge)) { + if (src4.s_addr != INADDR_ANY) + vty_out(vty, " %pI4", + &edge->attributes->standard.remote); + else + vty_out(vty, " %pI6", + &edge->attributes->standard.remote6); + } + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + void sharp_vty_init(void) { install_element(ENABLE_NODE, &install_routes_data_dump_cmd); @@ -1175,6 +1283,7 @@ void sharp_vty_init(void) install_element(ENABLE_NODE, &show_debugging_sharpd_cmd); install_element(ENABLE_NODE, &show_sharp_ted_cmd); + install_element(ENABLE_NODE, &show_sharp_cspf_cmd); install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd); install_element(ENABLE_NODE, diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 8c9f0c278..313febd9b 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -799,10 +799,12 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS) if (info.type == LINK_STATE_UPDATE) { lse = ls_stream2ted(sg.ted, s, false); - if (lse) + if (lse) { zlog_debug(" |- Got %s %s from Link State Database", status2txt[lse->status], type2txt[lse->type]); + lse->status = SYNC; + } else zlog_debug( "%s: Error to convert Stream into Link State", diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz Binary files differindex accc906bf..20b1dc33f 100644 --- a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz +++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz diff --git a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py index 138512bc6..8a7192be2 100644 --- a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py +++ b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py @@ -18,7 +18,7 @@ # OF THIS SOFTWARE. # -""" +r""" Reference: https://www.cmand.org/communityexploration --y2-- diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py index 7d7a4bd15..36bfdfe06 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py @@ -21,7 +21,7 @@ # OF THIS SOFTWARE. # -""" +r""" customize.py: Simple FRR MPLS L3VPN test topology | diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py index fce8e708f..5161d8471 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py @@ -21,7 +21,7 @@ # OF THIS SOFTWARE. # -""" +r""" customize.py: Simple FRR MPLS L3VPN test topology | diff --git a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py index 9c13c1c07..9f4399d6d 100644 --- a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py +++ b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py @@ -22,7 +22,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_bgp_multiview_topo1.py: Simple FRR Route-Server Test +----------+ +----------+ +----------+ +----------+ +----------+ diff --git a/tests/topotests/bgp_rfapi_basic_sanity/customize.py b/tests/topotests/bgp_rfapi_basic_sanity/customize.py index 1a86746e3..c82fe8321 100644 --- a/tests/topotests/bgp_rfapi_basic_sanity/customize.py +++ b/tests/topotests/bgp_rfapi_basic_sanity/customize.py @@ -22,7 +22,7 @@ # OF THIS SOFTWARE. # -""" +r""" customize.py: Simple FRR MPLS L3VPN test topology +---------+ diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/bgpd.conf new file mode 100644 index 000000000..345979662 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce1/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/ip_rib.json new file mode 100644 index 000000000..1d33fee71 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.1.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "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_to_bgp_vrf2/ce1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/zebra.conf new file mode 100644 index 000000000..447d1b40c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce1 +! +interface eth0 + ip address 192.168.1.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.1.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/bgpd.conf new file mode 100644 index 000000000..8ed997874 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce2/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/ip_rib.json new file mode 100644 index 000000000..a21f4a11b --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.2.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "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_to_bgp_vrf2/ce2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/zebra.conf new file mode 100644 index 000000000..11652252a --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce2 +! +interface eth0 + ip address 192.168.2.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.2.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/bgpd.conf new file mode 100644 index 000000000..a85d9701c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce3/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/ip_rib.json new file mode 100644 index 000000000..38a7807df --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.3.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.3.0/24": [ + { + "prefix": "192.168.3.0/24", + "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_to_bgp_vrf2/ce3/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/zebra.conf new file mode 100644 index 000000000..299c6597c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce3 +! +interface eth0 + ip address 192.168.3.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.3.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/bgpd.conf new file mode 100644 index 000000000..93fb32fd1 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce4/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/ip_rib.json new file mode 100644 index 000000000..a0be78e98 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.4.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.4.0/24": [ + { + "prefix": "192.168.4.0/24", + "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_to_bgp_vrf2/ce4/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/zebra.conf new file mode 100644 index 000000000..30f3736fe --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce4 +! +interface eth0 + ip address 192.168.4.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.4.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/bgpd.conf new file mode 100644 index 000000000..2ab6f2d2a --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce5/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/ip_rib.json new file mode 100644 index 000000000..dc338d5de --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.5.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.5.0/24": [ + { + "prefix": "192.168.5.0/24", + "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_to_bgp_vrf2/ce5/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/zebra.conf new file mode 100644 index 000000000..208dcb1a7 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce5 +! +interface eth0 + ip address 192.168.5.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.5.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/bgpd.conf new file mode 100644 index 000000000..e0b654051 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/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_to_bgp_vrf2/ce6/ip_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/ip_rib.json new file mode 100644 index 000000000..4a603a55c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/ip_rib.json @@ -0,0 +1,58 @@ +{ + "0.0.0.0/0": [ + { + "prefix": "0.0.0.0/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": "192.168.6.1", + "afi": "ipv4", + "interfaceName": "eth0", + "active": true, + "weight": 1 + } + ] + } + ], + "192.168.6.0/24": [ + { + "prefix": "192.168.6.0/24", + "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_to_bgp_vrf2/ce6/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/zebra.conf new file mode 100644 index 000000000..d68a008e3 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/zebra.conf @@ -0,0 +1,14 @@ +log file zebra.log +! +hostname ce6 +! +interface eth0 + ip address 192.168.6.2/24 +! +ip forwarding +ipv6 forwarding +! +ip route 0.0.0.0/0 192.168.6.1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/bgpd.conf new file mode 100644 index 000000000..c06175193 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/bgpd.conf @@ -0,0 +1,66 @@ +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 1.1.1.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 capability extended-nexthop + ! + address-family ipv4 vpn + neighbor 2001::2 activate + exit-address-family + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 1 vrf vrf10 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + ! + address-family ipv4 unicast + sid vpn export auto + nexthop vpn export 2001::1 + rd vpn export 1:10 + rt vpn both 99:99 + import vpn + export vpn + redistribute connected + ! + exit-address-family +! +router bgp 1 vrf vrf20 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + ! + address-family ipv4 unicast + sid vpn export auto + nexthop vpn export 2001::1 + 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_to_bgp_vrf2/r1/vpnv4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vpnv4_rib.json new file mode 100644 index 000000000..3cc2fddcf --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vpnv4_rib.json @@ -0,0 +1,167 @@ +{ + "vrfId": 0, + "vrfName": "default", + "tableVersion": 2, + "routerId": "1.1.1.1", + "defaultLocPrf": 100, + "localAS": 1, + "routes": { + "routeDistinguishers": { + "1:10": { + "192.168.1.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.1.0", + "prefixLen": 24, + "network": "192.168.1.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ], + "192.168.3.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.3.0", + "prefixLen": 24, + "network": "192.168.3.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "1:20": { + "192.168.5.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.5.0", + "prefixLen": 24, + "network": "192.168.5.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "192.168.2.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.2.0", + "prefixLen": 24, + "network": "192.168.2.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:20": { + "192.168.4.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.4.0", + "prefixLen": 24, + "network": "192.168.4.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::2", + "path": "2", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ], + "192.168.6.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.6.0", + "prefixLen": 24, + "network": "192.168.6.0/24", + "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_to_bgp_vrf2/r1/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf10_rib.json new file mode 100644 index 000000000..8daa9b155 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf10_rib.json @@ -0,0 +1,86 @@ +{ + "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, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth1", + "active": 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, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:2:2:100::" + } + } + ], + "asPath": "2" + } + ], + "192.168.3.0/24": [ + { + "prefix": "192.168.3.0/24", + "protocol": "connected", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth2", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf20_rib.json new file mode 100644 index 000000000..6f123cf4f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf20_rib.json @@ -0,0 +1,92 @@ +{ + "192.168.4.0/24": [ + { + "prefix": "192.168.4.0/24", + "protocol": "bgp", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:2:2:200::" + } + } + ], + "asPath": "2" + } + ], + "192.168.5.0/24": [ + { + "prefix": "192.168.5.0/24", + "protocol": "connected", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth3", + "active": true + } + ] + } + ], + "192.168.6.0/24": [ + { + "prefix": "192.168.6.0/24", + "protocol": "bgp", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:2:2:200::" + } + } + ], + "asPath": "2" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf new file mode 100644 index 000000000..a43cec20e --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf @@ -0,0 +1,41 @@ +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 + ip address 192.168.1.1/24 + ipv6 address 2001:1::1/64 +! +interface eth2 vrf vrf10 + ip address 192.168.3.1/24 +! +interface eth3 vrf vrf20 + ip address 192.168.5.1/24 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:1:1::/64 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:2:2::/64 2001::2 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/bgpd.conf new file mode 100644 index 000000000..05170572a --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/bgpd.conf @@ -0,0 +1,66 @@ +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 2.2.2.2 + no bgp ebgp-requires-policy + no bgp default ipv4-unicast + neighbor 2001::1 remote-as 1 + 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 + ! + segment-routing srv6 + locator loc1 + ! +! +router bgp 2 vrf vrf10 + bgp router-id 2.2.2.2 + no bgp ebgp-requires-policy + ! + address-family ipv4 unicast + sid vpn export auto + nexthop vpn export 2001::2 + rd vpn export 2:10 + rt vpn both 99:99 + import vpn + export vpn + redistribute connected + exit-address-family +! +router bgp 2 vrf vrf20 + bgp router-id 2.2.2.2 + no bgp ebgp-requires-policy + ! + address-family ipv4 unicast + sid vpn export auto + nexthop vpn export 2001::2 + 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_to_bgp_vrf2/r2/vpnv4_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vpnv4_rib.json new file mode 100644 index 000000000..95570541c --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vpnv4_rib.json @@ -0,0 +1,167 @@ +{ + "vrfId": 0, + "vrfName": "default", + "tableVersion": 2, + "routerId": "2.2.2.2", + "defaultLocPrf": 100, + "localAS": 2, + "routes": { + "routeDistinguishers": { + "1:10": { + "192.168.1.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.1.0", + "prefixLen": 24, + "network": "192.168.1.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ], + "192.168.3.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.3.0", + "prefixLen": 24, + "network": "192.168.3.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "1:20": { + "192.168.5.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.5.0", + "prefixLen": 24, + "network": "192.168.5.0/24", + "metric": 0, + "weight": 0, + "peerId": "2001::1", + "path": "1", + "origin": "incomplete", + "nexthops": [ + { + "ip": "2001::1", + "hostname": "r1", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:10": { + "192.168.2.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.2.0", + "prefixLen": 24, + "network": "192.168.2.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf10", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + }, + "2:20": { + "192.168.4.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.4.0", + "prefixLen": 24, + "network": "192.168.4.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ], + "192.168.6.0/24": [ + { + "valid": true, + "bestpath": true, + "selectionReason": "First path received", + "pathFrom": "external", + "prefix": "192.168.6.0", + "prefixLen": 24, + "network": "192.168.6.0/24", + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "path": "", + "origin": "incomplete", + "nhVrfName": "vrf20", + "nexthops": [ + { + "ip": "2001::2", + "hostname": "r2", + "afi": "ipv6", + "used": true + } + ] + } + ] + } + } + } +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf10_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf10_rib.json new file mode 100644 index 000000000..626803187 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf10_rib.json @@ -0,0 +1,92 @@ +{ + "192.168.1.0/24": [ + { + "prefix": "192.168.1.0/24", + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:1:1:100::" + } + } + ], + "asPath": "1" + } + ], + "192.168.2.0/24": [ + { + "prefix": "192.168.2.0/24", + "protocol": "connected", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth1", + "active": true + } + ] + } + ], + "192.168.3.0/24": [ + { + "prefix": "192.168.3.0/24", + "protocol": "bgp", + "vrfName": "vrf10", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 10, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:1:1:100::" + } + } + ], + "asPath": "1" + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf20_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf20_rib.json new file mode 100644 index 000000000..ffe2e07c8 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf20_rib.json @@ -0,0 +1,86 @@ +{ + "192.168.4.0/24": [ + { + "prefix": "192.168.4.0/24", + "protocol": "connected", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth2", + "active": true + } + ] + } + ], + "192.168.5.0/24": [ + { + "prefix": "192.168.5.0/24", + "protocol": "bgp", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 20, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "afi": "ipv6", + "interfaceName": "eth0", + "vrf": "default", + "active": true, + "weight": 1, + "seg6": { + "segs": "2001:db8:1:1:200::" + } + } + ], + "asPath": "1" + } + ], + "192.168.6.0/24": [ + { + "prefix": "192.168.6.0/24", + "protocol": "connected", + "vrfName": "vrf20", + "selected": true, + "destSelected": true, + "distance": 0, + "metric": 0, + "installed": true, + "table": 20, + "internalStatus": 16, + "internalFlags": 8, + "internalNextHopNum": 1, + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "flags": 3, + "fib": true, + "directlyConnected": true, + "interfaceName": "eth3", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf new file mode 100644 index 000000000..71ddedf6f --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf @@ -0,0 +1,40 @@ +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 + ip address 192.168.2.1/24 +! +interface eth2 vrf vrf20 + ip address 192.168.4.1/24 +! +interface eth3 vrf vrf20 + ip address 192.168.6.1/24 +! +segment-routing + srv6 + locators + locator loc1 + prefix 2001:db8:2:2::/64 + ! + ! +! +ip forwarding +ipv6 forwarding +! +ipv6 route 2001:db8:1:1::/64 2001::1 +! +line vty +! diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py new file mode 100755 index 000000000..af66a5a79 --- /dev/null +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +# +# Part of NetDEF Topology Tests +# +# Copyright (c) 2018, LabN Consulting, L.L.C. +# Authored by Lou Berger <lberger@labn.net> +# +# 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 + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + 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.15") + if result is not True: + pytest.skip("Kernel requirements are not met") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + for rname, router in tgen.routers().items(): + router.run("/bin/bash {}/{}/setup.sh".format(CWD, rname)) + router.load_config(TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname))) + router.load_config(TopoRouter.RD_BGP, + os.path.join(CWD, '{}/bgpd.conf'.format(rname))) + + tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1") + 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["r2"].run("sysctl net.vrf.strict_mode=1") + 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.start_router() + + +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) + assert match in output, "ping fail" + + 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, dest_addr, match): + 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 ipv4 vpn json", "r1/vpnv4_rib.json") + check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib.json") + check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_rib.json") + check_rib("r1", "show ip route vrf vrf20 json", "r1/vrf20_rib.json") + check_rib("r2", "show ip route vrf vrf10 json", "r2/vrf10_rib.json") + check_rib("r2", "show ip route vrf vrf20 json", "r2/vrf20_rib.json") + check_rib("ce1", "show ip route json", "ce1/ip_rib.json") + check_rib("ce2", "show ip route json", "ce2/ip_rib.json") + check_rib("ce3", "show ip route json", "ce3/ip_rib.json") + check_rib("ce4", "show ip route json", "ce4/ip_rib.json") + check_rib("ce5", "show ip route json", "ce5/ip_rib.json") + check_rib("ce6", "show ip route json", "ce6/ip_rib.json") + + +def test_ping(): + check_ping("ce1", "192.168.2.2", " 0% packet loss") + check_ping("ce1", "192.168.3.2", " 0% packet loss") + check_ping("ce1", "192.168.4.2", " 100% packet loss") + check_ping("ce1", "192.168.5.2", " 100% packet loss") + check_ping("ce1", "192.168.6.2", " 100% packet loss") + check_ping("ce4", "192.168.1.2", " 100% packet loss") + check_ping("ce4", "192.168.2.2", " 100% packet loss") + check_ping("ce4", "192.168.3.2", " 100% packet loss") + check_ping("ce4", "192.168.5.2", " 0% packet loss") + check_ping("ce4", "192.168.6.2", " 0% packet loss") + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/cspf_topo1/r1/isisd.conf b/tests/topotests/cspf_topo1/r1/isisd.conf new file mode 100644 index 000000000..788ac5b7a --- /dev/null +++ b/tests/topotests/cspf_topo1/r1/isisd.conf @@ -0,0 +1,33 @@ +! +hostname r1 +! +interface lo + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis passive +! +interface r1-eth0 + ip router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r1-eth1 + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +router isis TE + net 49.0000.0000.0000.0001.00 + is-type level-2-only + topology ipv6-unicast + lsp-timers gen-interval 2 refresh-interval 10 max-lifetime 350 + mpls-te on + mpls-te router-address 10.0.255.1 + mpls-te router-address ipv6 2001:db8::1 + mpls-te export +! + diff --git a/tests/topotests/cspf_topo1/r1/sharpd.conf b/tests/topotests/cspf_topo1/r1/sharpd.conf new file mode 100644 index 000000000..272eac944 --- /dev/null +++ b/tests/topotests/cspf_topo1/r1/sharpd.conf @@ -0,0 +1,3 @@ +! +import-te +! diff --git a/tests/topotests/cspf_topo1/r1/zebra.conf b/tests/topotests/cspf_topo1/r1/zebra.conf new file mode 100644 index 000000000..3aa0cad43 --- /dev/null +++ b/tests/topotests/cspf_topo1/r1/zebra.conf @@ -0,0 +1,27 @@ +! +hostname r1 +! +interface lo + ip address 10.0.255.1/32 + ipv6 address 2001:db8::1/128 +! +interface r1-eth0 + ip address 10.0.0.1/24 + link-params + metric 20 + delay 10000 + ava-bw 1.25e+08 + enable + exit-link-params +! +interface r1-eth1 + ip address 10.0.1.1/24 + ipv6 address 2001:db8:1::1:1/64 + link-params + metric 10 + delay 20000 + enable + exit-link-params +! +ip forwarding +! diff --git a/tests/topotests/cspf_topo1/r2/isisd.conf b/tests/topotests/cspf_topo1/r2/isisd.conf new file mode 100644 index 000000000..04df685e9 --- /dev/null +++ b/tests/topotests/cspf_topo1/r2/isisd.conf @@ -0,0 +1,46 @@ +! +hostname r2 +! +! debug isis te-events +! +interface lo + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis passive +! +interface r2-eth0 + ip router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r2-eth1 + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r2-eth2 + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r2-eth3 + ip router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +router isis TE + net 49.0000.0000.0000.0002.00 + is-type level-2-only + topology ipv6-unicast + lsp-timers gen-interval 2 refresh-interval 10 max-lifetime 350 + mpls-te on + mpls-te router-address 10.0.255.2 + mpls-te router-address ipv6 2001:db8::2 +! diff --git a/tests/topotests/cspf_topo1/r2/zebra.conf b/tests/topotests/cspf_topo1/r2/zebra.conf new file mode 100644 index 000000000..1cc37ba12 --- /dev/null +++ b/tests/topotests/cspf_topo1/r2/zebra.conf @@ -0,0 +1,45 @@ +! +hostname r2 +! +interface lo + ip address 10.0.255.2/32 + ipv6 address 2001:db8::2/128 +! +interface r2-eth0 + ip address 10.0.0.2/24 + link-params + metric 20 + delay 10000 + enable + exit-link-params +! +interface r2-eth1 + ip address 10.0.1.2/24 + ipv6 address 2001:db8:1::1:2/64 + link-params + metric 10 + delay 20000 + enable + exit-link-params +! +interface r2-eth2 + ip address 10.0.3.2/24 + ipv6 address 2001:db8:3::3:2/64 + link-params + metric 40 + delay 40000 + enable + exit-link-params +! +interface r2-eth3 + ip address 10.0.4.2/24 + ipv6 address 2001:db8:4::4:2/64 + link-params + metric 25 + delay 25000 + use-bw 1.25e+8 + enable + exit-link-params +! +ip forwarding +! diff --git a/tests/topotests/cspf_topo1/r3/isisd.conf b/tests/topotests/cspf_topo1/r3/isisd.conf new file mode 100644 index 000000000..9db82c7b2 --- /dev/null +++ b/tests/topotests/cspf_topo1/r3/isisd.conf @@ -0,0 +1,34 @@ +! +hostname r3 +! +! debug isis te-events +! +interface lo + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis passive +! +interface r3-eth0 + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r3-eth1 + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +! +router isis TE + net 49.0000.0000.0000.0003.00 + is-type level-2-only + topology ipv6-unicast + lsp-timers gen-interval 2 refresh-interval 10 max-lifetime 350 + mpls-te on + mpls-te router-address 10.0.255.3 + mpls-te router-address ipv6 2001:db8::3 +! diff --git a/tests/topotests/cspf_topo1/r3/zebra.conf b/tests/topotests/cspf_topo1/r3/zebra.conf new file mode 100644 index 000000000..29a4c515f --- /dev/null +++ b/tests/topotests/cspf_topo1/r3/zebra.conf @@ -0,0 +1,27 @@ +! +hostname r3 +! +interface lo + ip address 10.0.255.3/32 + ipv6 address 2001:db8::3/128 +! +interface r3-eth0 + ip address 10.0.3.3/24 + ipv6 address 2001:db8:3::3:3/64 + link-params + metric 25 + delay 25000 + enable + admin-grp 0x20 + exit-link-params +! +interface r3-eth1 + ipv6 address 2001:db8:5::4:3/64 + link-params + enable + metric 10 + delay 10000 + exit-link-params +! +ip forwarding +! diff --git a/tests/topotests/cspf_topo1/r4/isisd.conf b/tests/topotests/cspf_topo1/r4/isisd.conf new file mode 100644 index 000000000..c5c4d4e05 --- /dev/null +++ b/tests/topotests/cspf_topo1/r4/isisd.conf @@ -0,0 +1,40 @@ +! +hostname r4 +! +! debug isis te-events +! debug isis sr-events +! debug isis lsp-gen +! +interface lo + ip router isis TE + ipv6 router isis TE + isis circuit-type level-2-only + isis passive +! +interface r4-eth0 + ip router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +interface r4-eth1 + ipv6 router isis TE + isis circuit-type level-2-only + isis network point-to-point + isis hello-multiplier 3 +! +! +router isis TE + net 49.0000.0000.0000.0004.00 + is-type level-2-only + topology ipv6-unicast + lsp-timers gen-interval 2 refresh-interval 10 max-lifetime 350 + mpls-te on + mpls-te router-address 10.0.255.4 + mpls-te router-address ipv6 2001:db8::4 + segment-routing on + segment-routing global-block 10000 19999 local-block 5000 5999 + segment-routing node-msd 12 + segment-routing prefix 10.0.255.4/32 index 400 no-php-flag + segment-routing prefix 2001:db8:ffff::4/128 index 1400 no-php-flag +! diff --git a/tests/topotests/cspf_topo1/r4/zebra.conf b/tests/topotests/cspf_topo1/r4/zebra.conf new file mode 100644 index 000000000..bf5306d0e --- /dev/null +++ b/tests/topotests/cspf_topo1/r4/zebra.conf @@ -0,0 +1,26 @@ +! +hostname r4 +! +interface lo + ip address 10.0.255.4/32 + ipv6 address 2001:db8::4/128 +! +interface r4-eth0 + ip address 10.0.4.4/24 + ipv6 address 2001:db8:4::2:4/64 + link-params + metric 40 + delay 40000 + enable + exit-link-params +! +interface r4-eth1 + ipv6 address 2001:db8:5::3:4/64 + link-params + metric 10 + delay 10000 + enable + exit-link-params +! +ip forwarding +! diff --git a/tests/topotests/cspf_topo1/reference/cspf-failed-dst.txt b/tests/topotests/cspf_topo1/reference/cspf-failed-dst.txt new file mode 100644 index 000000000..df792cef9 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-failed-dst.txt @@ -0,0 +1 @@ +Path computation failed: 2 diff --git a/tests/topotests/cspf_topo1/reference/cspf-failed-same.txt b/tests/topotests/cspf_topo1/reference/cspf-failed-same.txt new file mode 100644 index 000000000..48f6fd9b6 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-failed-same.txt @@ -0,0 +1 @@ +Path computation failed: 3 diff --git a/tests/topotests/cspf_topo1/reference/cspf-failed-src.txt b/tests/topotests/cspf_topo1/reference/cspf-failed-src.txt new file mode 100644 index 000000000..62d00ccab --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-failed-src.txt @@ -0,0 +1 @@ +Path computation failed: 1 diff --git a/tests/topotests/cspf_topo1/reference/cspf-failed.txt b/tests/topotests/cspf_topo1/reference/cspf-failed.txt new file mode 100644 index 000000000..de53a9382 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-failed.txt @@ -0,0 +1 @@ +Path computation failed: 0 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv4-delay.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv4-delay.txt new file mode 100644 index 000000000..2cc042842 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv4-delay.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 35000 + Edges: 10.0.0.2 10.0.4.4 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv4-metric.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv4-metric.txt new file mode 100644 index 000000000..060a39c9e --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv4-metric.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 20 + Edges: 10.0.0.2 10.0.4.4 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv4-te-metric.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv4-te-metric.txt new file mode 100644 index 000000000..6d983067e --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv4-te-metric.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 35 + Edges: 10.0.1.2 10.0.4.4 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv6-delay.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv6-delay.txt new file mode 100644 index 000000000..b65869bcf --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv6-delay.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 70000 + Edges: 2001:db8:1::1:2 2001:db8:3::3:3 2001:db8:5::3:4 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv6-metric.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv6-metric.txt new file mode 100644 index 000000000..5acbb74d2 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv6-metric.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 30 + Edges: 2001:db8:1::1:2 2001:db8:3::3:3 2001:db8:5::3:4 diff --git a/tests/topotests/cspf_topo1/reference/cspf-ipv6-te-metric.txt b/tests/topotests/cspf_topo1/reference/cspf-ipv6-te-metric.txt new file mode 100644 index 000000000..2290a04a8 --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/cspf-ipv6-te-metric.txt @@ -0,0 +1,3 @@ +Path computation success + Cost: 60 + Edges: 2001:db8:1::1:2 2001:db8:3::3:3 2001:db8:5::3:4 diff --git a/tests/topotests/cspf_topo1/reference/sharp-ted.json b/tests/topotests/cspf_topo1/reference/sharp-ted.json new file mode 100644 index 000000000..db50260ac --- /dev/null +++ b/tests/topotests/cspf_topo1/reference/sharp-ted.json @@ -0,0 +1,860 @@ +{ + "ted":{ + "name":"Sharp", + "key":1, + "verticesCount":4, + "edgesCount":14, + "subnetsCount":22, + "vertices":[ + { + "vertex-id":1, + "status":"Sync", + "origin":"ISIS_L2", + "name":"r1", + "router-id":"10.0.255.1", + "router-id-v6":"2001:db8::1" + }, + { + "vertex-id":2, + "status":"Sync", + "origin":"ISIS_L2", + "name":"r2", + "router-id":"10.0.255.2", + "router-id-v6":"2001:db8::2" + }, + { + "vertex-id":3, + "status":"Sync", + "origin":"ISIS_L2", + "name":"r3", + "router-id":"10.0.255.3", + "router-id-v6":"2001:db8::3" + }, + { + "vertex-id":4, + "status":"Sync", + "origin":"ISIS_L2", + "name":"r4", + "router-id":"10.0.255.4", + "router-id-v6":"2001:db8::4", + "segment-routing":{ + "srgb-size":10000, + "srgb-lower":10000, + "algorithms":[ + { + "0":"SPF" + } + ], + "srlb-size":1000, + "srlb-lower":5000, + "msd":12 + } + } + ], + "edges":[ + { + "edge-id":65537, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "local-vertex-id":1, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address-v6":"2001:db8:1::1:1", + "remote-address-v6":"2001:db8:1::1:2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":20000 + } + }, + { + "edge-id":65538, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":1, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address-v6":"2001:db8:1::1:2", + "remote-address-v6":"2001:db8:1::1:1", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":20000 + } + }, + { + "edge-id":196610, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":3, + "metric":10, + "edge-attributes":{ + "te-metric":40, + "local-address-v6":"2001:db8:3::3:2", + "remote-address-v6":"2001:db8:3::3:3", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":40000 + } + }, + { + "edge-id":196611, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "local-vertex-id":3, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":25, + "admin-group":32, + "local-address-v6":"2001:db8:3::3:3", + "remote-address-v6":"2001:db8:3::3:2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":25000 + } + }, + { + "edge-id":196612, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "local-vertex-id":4, + "remote-vertex-id":3, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address-v6":"2001:db8:5::3:4", + "remote-address-v6":"2001:db8:5::4:3", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":10000 + }, + "segment-routing":[ + { + "adj-sid":5001, + "flags":"0xb0", + "weight":0 + } + ] + }, + { + "edge-id":262147, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "local-vertex-id":3, + "remote-vertex-id":4, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address-v6":"2001:db8:5::4:3", + "remote-address-v6":"2001:db8:5::3:4", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":10000 + } + }, + { + "edge-id":167772161, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "local-vertex-id":1, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":20, + "local-address":"10.0.0.1", + "remote-address":"10.0.0.2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":10000, + "available-bandwidth":125000000.0 + } + }, + { + "edge-id":167772162, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":1, + "metric":10, + "edge-attributes":{ + "te-metric":20, + "local-address":"10.0.0.2", + "remote-address":"10.0.0.1", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":10000 + } + }, + { + "edge-id":167772417, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "local-vertex-id":1, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address":"10.0.1.1", + "remote-address":"10.0.1.2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":20000 + } + }, + { + "edge-id":167772418, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":1, + "metric":10, + "edge-attributes":{ + "te-metric":10, + "local-address":"10.0.1.2", + "remote-address":"10.0.1.1", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":20000 + } + }, + { + "edge-id":167772930, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":3, + "metric":10, + "edge-attributes":{ + "te-metric":40, + "local-address":"10.0.3.2", + "remote-address":"10.0.3.3", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":40000 + } + }, + { + "edge-id":167772931, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "local-vertex-id":3, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":25, + "admin-group":32, + "local-address":"10.0.3.3", + "remote-address":"10.0.3.2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":25000 + } + }, + { + "edge-id":167773186, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "local-vertex-id":2, + "remote-vertex-id":4, + "metric":10, + "edge-attributes":{ + "te-metric":25, + "local-address":"10.0.4.2", + "remote-address":"10.0.4.4", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":25000, + "utilized-bandwidth":125000000.0 + } + }, + { + "edge-id":167773188, + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "local-vertex-id":4, + "remote-vertex-id":2, + "metric":10, + "edge-attributes":{ + "te-metric":40, + "local-address":"10.0.4.4", + "remote-address":"10.0.4.2", + "max-link-bandwidth":176258176.0, + "max-resv-link-bandwidth":176258176.0, + "unreserved-bandwidth":[ + { + "class-type-0":176258176.0 + }, + { + "class-type-1":176258176.0 + }, + { + "class-type-2":176258176.0 + }, + { + "class-type-3":176258176.0 + }, + { + "class-type-4":176258176.0 + }, + { + "class-type-5":176258176.0 + }, + { + "class-type-6":176258176.0 + }, + { + "class-type-7":176258176.0 + } + ], + "delay":40000 + }, + "segment-routing":[ + { + "adj-sid":5000, + "flags":"0x30", + "weight":0 + } + ] + } + ], + "subnets":[ + { + "subnet-id":"10.0.0.1/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "vertex-id":1, + "metric":10 + }, + { + "subnet-id":"10.0.0.2/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"10.0.1.1/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "vertex-id":1, + "metric":10 + }, + { + "subnet-id":"10.0.1.2/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"10.0.3.2/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"10.0.3.3/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "vertex-id":3, + "metric":10 + }, + { + "subnet-id":"10.0.4.2/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"10.0.4.4/24", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "vertex-id":4, + "metric":10 + }, + { + "subnet-id":"10.0.255.1/32", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "vertex-id":1, + "metric":10 + }, + { + "subnet-id":"10.0.255.2/32", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"10.0.255.3/32", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "vertex-id":3, + "metric":10 + }, + { + "subnet-id":"10.0.255.4/32", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "vertex-id":4, + "metric":10, + "segment-routing":{ + "pref-sid":400, + "algo":0, + "flags":"0x60" + } + }, + { + "subnet-id":"2001:db8:1::1:1/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "vertex-id":1, + "metric":10 + }, + { + "subnet-id":"2001:db8:1::1:2/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"2001:db8:3::3:2/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"2001:db8:3::3:3/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "vertex-id":3, + "metric":10 + }, + { + "subnet-id":"2001:db8:5::3:4/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "vertex-id":4, + "metric":10 + }, + { + "subnet-id":"2001:db8:5::4:3/64", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "vertex-id":3, + "metric":10 + }, + { + "subnet-id":"2001:db8::1/128", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0001", + "vertex-id":1, + "metric":10 + }, + { + "subnet-id":"2001:db8::2/128", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0002", + "vertex-id":2, + "metric":10 + }, + { + "subnet-id":"2001:db8::3/128", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0003", + "vertex-id":3, + "metric":10 + }, + { + "subnet-id":"2001:db8::4/128", + "status":"Sync", + "origin":"ISIS_L2", + "advertised-router":"0000.0000.0004", + "vertex-id":4, + "metric":10 + } + ] + } +} diff --git a/tests/topotests/cspf_topo1/test_cspf_topo1.py b/tests/topotests/cspf_topo1/test_cspf_topo1.py new file mode 100644 index 000000000..1b71ac3a1 --- /dev/null +++ b/tests/topotests/cspf_topo1/test_cspf_topo1.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python + +# +# test_cspf_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2022 by Orange +# Author: Olivier Dugeon <olivier.dugeon@orange.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_cspf_topo1.py: Test the FRR Constraint Shortest Path First algorithm. + + +------------+ + | | + | R1 | + | 10.0.225.1 | + | | + +------------+ + r1-eth0| |r1-eth1 + | | + 10.0.0.0/24| |10.0.1.0/24 + | |2001:db8:1:/64 + | | + r2-eth0| |r2-eth1 + +------------+ +------------+ + | | | | + | R2 |r2-eth2 r3-eth0| R3 | + | 10.0.255.2 +------------------+ 10.0.255.3 | + | | 10.0.3.0/24 | | + +------------+ 2001:db8:3:/64 +------+-----+ + r2-eth3| r3-eth1| + | | + 10.0.4.0/24| | + | | + | | + r4-eth0| 2001:db8:5:/64| + +------------+ | + | | | + | R4 |r4-eth1 | + | 10.0.255.4 +-------------------------+ + | | + +------------+ + +""" + +import os +import sys +import json +from functools import partial + +# Save the Current Working Directory to find configuration files. +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 + +# and Finally pytest +import pytest + +pytestmark = [pytest.mark.isisd] + + +def build_topo(tgen): + "Build function" + + # Create 4 routers + for routern in range(1, 5): + tgen.add_router("r{}".format(routern)) + + # Interconect router 1 and 2 with 2 links + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + # Interconect router 3 and 2 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r2"]) + + # Interconect router 4 and 2 + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r2"]) + + # Interconnect router 3 and 4 + switch = tgen.add_switch("s5") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + +def setup_module(mod): + "Sets up the pytest environment" + + logger.info("\n\n---- Starting CSPF tests ----\n") + + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) + ) + if rname == "r1": + router.load_config( + TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format("r1")) + ) + + # Initialize all routers. + tgen.start_router() + + +def teardown_module(): + "Teardown the pytest environment" + + tgen = get_topogen() + tgen.stop_topology() + + logger.info("\n\n---- CSPF tests End ----\n") + + +def compare_ted_json_output(tgen, rname, fileref): + "Compare TED JSON output" + + logger.info('Comparing router "%s" TED output', rname) + + filename = "{}/reference/{}".format(CWD, fileref) + expected = json.loads(open(filename).read()) + command = "show sharp ted json" + + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) + _, diff = topotest.run_and_expect(test_func, None, count=60, wait=2) + assertmsg = '"{}" TED JSON output mismatches the expected result'.format(rname) + assert diff is None, assertmsg + + +def compare_cspf_output(tgen, rname, fileref, src, dst, cost, bw=""): + "Compare CSPF output" + + logger.info('Comparing router "%s" CSPF output', rname) + + filename = "{}/reference/{}".format(CWD, fileref) + expected = open(filename).read() + command = "show sharp cspf source {} destination {} {} {}".format(src, dst, cost, bw) + + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial(topotest.router_output_cmp, tgen.gears[rname], command, expected) + result, diff = topotest.run_and_expect(test_func, "", count=2, wait=2) + assert result, "CSPF output mismatches the expected result on {}:\n{}".format(rname, diff) + + +def setup_testcase(msg): + "Setup test case" + + logger.info(msg) + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + return tgen + + +# Note that all routers must discover the same Network Topology, so the same TED. + + +def test_step1(): + "Step1: Check initial topology" + + tgen = setup_testcase("Step1: test initial IS-IS TE Data Base import") + tgen.net["r1"].cmd('vtysh -c "sharp import-te"') + + compare_ted_json_output(tgen, "r1", "sharp-ted.json") + + +def test_step2(): + "Step2: Test CSPF from r1 to r4 for IPv4 with various metric" + + tgen = setup_testcase("Step2: CSPF(r1, r4, IPv4)") + + compare_cspf_output(tgen, "r1", "cspf-ipv4-metric.txt", "10.0.0.1", "10.0.255.4", "metric 50") + compare_cspf_output(tgen, "r1", "cspf-ipv4-te-metric.txt", "10.0.255.1", "10.0.4.4", "te-metric 50") + compare_cspf_output(tgen, "r1", "cspf-ipv4-delay.txt", "10.0.255.1", "10.0.255.4", "delay 50000") + compare_cspf_output(tgen, "r1", "cspf-ipv4-delay.txt", "10.0.255.1", "10.0.255.4", "delay 50000", "rsv 7 100000000") + + +def test_step3(): + "Step3: Test CSPF from r1 to r4 for IPv6 with various metric" + + tgen = setup_testcase("Step2: CSPF(r1, r4, IPv6)") + + compare_cspf_output(tgen, "r1", "cspf-ipv6-metric.txt", "2001:db8:1::1:1", "2001:db8::4", "metric 50") + compare_cspf_output(tgen, "r1", "cspf-ipv6-te-metric.txt", "2001:db8::1", "2001:db8:5::3:4", "te-metric 80") + compare_cspf_output(tgen, "r1", "cspf-ipv6-delay.txt", "2001:db8::1", "2001:db8::4", "delay 80000") + compare_cspf_output(tgen, "r1", "cspf-ipv6-delay.txt", "2001:db8::1", "2001:db8::4", "delay 80000", "rsv 7 100000000") + + +def test_step4(): + "Step4: Test CSPF from r1 to r4 with no possible path" + + tgen = setup_testcase("Step2: CSPF(r1, r4, failure)") + + compare_cspf_output(tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "metric 10") + compare_cspf_output(tgen, "r1", "cspf-failed.txt", "2001:db8::1", "2001:db8::4", "te-metric 50") + compare_cspf_output(tgen, "r1", "cspf-failed.txt", "10.0.255.1", "10.0.255.4", "delay 5000") + compare_cspf_output(tgen, "r1", "cspf-failed.txt", "2001:db8::1", "2001:db8::4", "delay 80000", "rsv 7 1000000000") + compare_cspf_output(tgen, "r1", "cspf-failed-src.txt", "10.0.0.3", "10.0.255.4", "metric 10") + compare_cspf_output(tgen, "r1", "cspf-failed-dst.txt", "10.0.0.1", "10.0.4.40", "metric 10") + compare_cspf_output(tgen, "r1", "cspf-failed-same.txt", "10.0.0.1", "10.0.0.1", "metric 10") + + +def test_memory_leak(): + "Run the memory leak test and report results." + + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/isis_te_topo1/reference/ted_step1.json b/tests/topotests/isis_te_topo1/reference/ted_step1.json index 7a4773380..027dd806c 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step1.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step1.json @@ -58,7 +58,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:1", "remote-address-v6":"2001:db8:1::1:2", "max-link-bandwidth":176258176.0, @@ -100,7 +99,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:2", "remote-address-v6":"2001:db8:1::1:1", "max-link-bandwidth":176258176.0, @@ -142,7 +140,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -184,7 +181,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -227,7 +223,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -363,7 +358,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -405,7 +399,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -447,7 +440,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -489,7 +481,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -531,7 +522,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -618,7 +608,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/isis_te_topo1/reference/ted_step2.json b/tests/topotests/isis_te_topo1/reference/ted_step2.json index 8277e6d53..2e9a5ec84 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step2.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step2.json @@ -58,7 +58,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -100,7 +99,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -143,7 +141,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -279,7 +276,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -321,7 +317,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -363,7 +358,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -450,7 +444,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/isis_te_topo1/reference/ted_step3.json b/tests/topotests/isis_te_topo1/reference/ted_step3.json index 0ade39884..5c7ccdd6a 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step3.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step3.json @@ -102,7 +102,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8::2", "max-link-bandwidth":176258176.0, "max-resv-link-bandwidth":176258176.0, @@ -143,7 +142,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -185,7 +183,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -228,7 +225,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -364,7 +360,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -406,7 +401,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -448,7 +442,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -535,7 +528,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/isis_te_topo1/reference/ted_step4.json b/tests/topotests/isis_te_topo1/reference/ted_step4.json index 0ade39884..5c7ccdd6a 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step4.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step4.json @@ -102,7 +102,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8::2", "max-link-bandwidth":176258176.0, "max-resv-link-bandwidth":176258176.0, @@ -143,7 +142,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -185,7 +183,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -228,7 +225,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -364,7 +360,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -406,7 +401,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -448,7 +442,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -535,7 +528,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/isis_te_topo1/reference/ted_step5.json b/tests/topotests/isis_te_topo1/reference/ted_step5.json index ba9bdb01f..48d475c72 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step5.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step5.json @@ -102,7 +102,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8::2", "max-link-bandwidth":176258176.0, "max-resv-link-bandwidth":176258176.0, @@ -143,7 +142,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:1", "remote-address-v6":"2001:db8:1::1:2", "max-link-bandwidth":176258176.0, @@ -185,7 +183,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:2", "remote-address-v6":"2001:db8:1::1:1", "max-link-bandwidth":176258176.0, @@ -227,7 +224,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -269,7 +265,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -312,7 +307,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -448,7 +442,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -490,7 +483,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -532,7 +524,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -574,7 +565,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -616,7 +606,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -703,7 +692,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/isis_te_topo1/reference/ted_step6.json b/tests/topotests/isis_te_topo1/reference/ted_step6.json index 83bb27235..75443a42e 100644 --- a/tests/topotests/isis_te_topo1/reference/ted_step6.json +++ b/tests/topotests/isis_te_topo1/reference/ted_step6.json @@ -102,7 +102,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8::2", "max-link-bandwidth":176258176.0, "max-resv-link-bandwidth":176258176.0, @@ -143,7 +142,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:1", "remote-address-v6":"2001:db8:1::1:2", "max-link-bandwidth":176258176.0, @@ -185,7 +183,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:1::1:2", "remote-address-v6":"2001:db8:1::1:1", "max-link-bandwidth":176258176.0, @@ -227,7 +224,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:3::3:2", "remote-address-v6":"2001:db8:3::3:3", "max-link-bandwidth":176258176.0, @@ -269,7 +265,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address-v6":"2001:db8:3::3:3", "remote-address-v6":"2001:db8:3::3:2", @@ -312,7 +307,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address-v6":"2001:db8:5::3:4", "remote-address-v6":"2001:db8:5::4:3", "max-link-bandwidth":176258176.0, @@ -448,7 +442,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -490,7 +483,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -532,7 +524,6 @@ "remote-vertex-id":1, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -574,7 +565,6 @@ "remote-vertex-id":3, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.3", "max-link-bandwidth":176258176.0, @@ -616,7 +606,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.3", "remote-address":"10.0.3.2", @@ -702,7 +691,6 @@ "remote-vertex-id":2, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.4", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ldp_oc_acl_topo1/test_ldp_oc_acl_topo1.py b/tests/topotests/ldp_oc_acl_topo1/test_ldp_oc_acl_topo1.py index 3608c5a48..01f3fe182 100644 --- a/tests/topotests/ldp_oc_acl_topo1/test_ldp_oc_acl_topo1.py +++ b/tests/topotests/ldp_oc_acl_topo1/test_ldp_oc_acl_topo1.py @@ -21,7 +21,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_ldp_oc_acl_topo1.py: Simple FRR LDP Test +---------+ diff --git a/tests/topotests/ldp_oc_topo1/test_ldp_oc_topo1.py b/tests/topotests/ldp_oc_topo1/test_ldp_oc_topo1.py index 972692691..4faaf45c1 100644 --- a/tests/topotests/ldp_oc_topo1/test_ldp_oc_topo1.py +++ b/tests/topotests/ldp_oc_topo1/test_ldp_oc_topo1.py @@ -21,7 +21,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_ldp_oc_topo1.py: Simple FRR LDP Test +---------+ diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py index 4a33edb9d..8d6978723 100644 --- a/tests/topotests/ldp_topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py @@ -22,7 +22,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_ldp_topo1.py: Simple FRR LDP Test +---------+ diff --git a/tests/topotests/ospf6_topo1/test_ospf6_topo1.py b/tests/topotests/ospf6_topo1/test_ospf6_topo1.py index 99379354f..53d84e619 100644 --- a/tests/topotests/ospf6_topo1/test_ospf6_topo1.py +++ b/tests/topotests/ospf6_topo1/test_ospf6_topo1.py @@ -22,7 +22,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_ospf6_topo1.py: -----\ diff --git a/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py b/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py index ac4a23da9..f823d5aef 100755 --- a/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py +++ b/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py @@ -23,7 +23,7 @@ # OF THIS SOFTWARE. # -""" +r""" test_ospf6_topo1_vrf.py: -----\ diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py index fb96054db..88c87dcec 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py @@ -81,6 +81,8 @@ NETWORK = { "11.0.20.5/32", ] } + +NETWORK_APP_E = {"ipv4": ["12.0.0.0/24", "12.0.0.0/16", "12.0.0.0/8"]} TOPOOLOGY = """ Please view in a fixed-width font such as Courier. +---+ A1 +---+ @@ -557,6 +559,154 @@ def test_ospf_redistribution_tc8_p1(request): write_test_footer(tc_name) +def test_ospf_rfc2328_appendinxE_p0(request): + """ + Test OSPF appendinx E RFC2328. + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config.") + + reset_config_on_routers(tgen) + + step("Verify that OSPF neighbours are Full.") + # Api call verify whether OSPF is converged + ospf_covergence = verify_ospf_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + redistribute_ospf(tgen, topo, "r0", "static") + + step("Configure static route with prefix 24, 16, 8 to check ") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][0], + "no_of_ip": 1, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][1], + "no_of_ip": 1, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][2], + "no_of_ip": 1, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that ospf originates routes with mask 24, 16, 8") + ip_net = NETWORK_APP_E["ipv4"][0] + input_dict = {"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1}]}} + + dut = "r1" + result = verify_ospf_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + ip_net = NETWORK_APP_E["ipv4"][1] + input_dict = {"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1}]}} + + dut = "r1" + result = verify_ospf_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + ip_net = NETWORK_APP_E["ipv4"][2] + input_dict = {"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1}]}} + + dut = "r1" + result = verify_ospf_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Delete static route with prefix 24, 16, 8 to check ") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][0], + "no_of_ip": 1, + "next_hop": "Null0", + "delete": True, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][1], + "no_of_ip": 1, + "next_hop": "Null0", + "delete": True, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK_APP_E["ipv4"][2], + "no_of_ip": 1, + "next_hop": "Null0", + "delete": True, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + def test_ospf_cost_tc52_p0(request): """OSPF Cost - verifying ospf interface cost functionality""" tc_name = request.node.name diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step1.json b/tests/topotests/ospf_te_topo1/reference/ted_step1.json index 9624292cc..d6bfca63f 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step1.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step1.json @@ -109,7 +109,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -151,7 +150,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -193,7 +191,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -235,7 +232,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -278,7 +274,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -320,7 +315,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step2.json b/tests/topotests/ospf_te_topo1/reference/ted_step2.json index 623d1dc7e..ec30af603 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step2.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step2.json @@ -109,7 +109,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -151,7 +150,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -194,7 +192,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -236,7 +233,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step3.json b/tests/topotests/ospf_te_topo1/reference/ted_step3.json index 117011a43..853704b4f 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step3.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step3.json @@ -101,7 +101,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -143,7 +142,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -186,7 +184,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -228,7 +225,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step4.json b/tests/topotests/ospf_te_topo1/reference/ted_step4.json index 5c2dee1e4..0aa57713c 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step4.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step4.json @@ -136,7 +136,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -190,7 +189,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -233,7 +231,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -287,7 +284,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step5.json b/tests/topotests/ospf_te_topo1/reference/ted_step5.json index 47e747f3c..07637f304 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step5.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step5.json @@ -136,7 +136,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -190,7 +189,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -244,7 +242,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -298,7 +295,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -341,7 +337,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -395,7 +390,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step6.json b/tests/topotests/ospf_te_topo1/reference/ted_step6.json index 74bd83fbd..e9eee96ff 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step6.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step6.json @@ -136,7 +136,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -190,7 +189,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -244,7 +242,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -298,7 +295,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -341,7 +337,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, @@ -395,7 +390,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.4.1", "remote-address":"10.0.4.2", "max-link-bandwidth":176258176.0, diff --git a/tests/topotests/ospf_te_topo1/reference/ted_step7.json b/tests/topotests/ospf_te_topo1/reference/ted_step7.json index 1cea9f045..f912ae4a8 100644 --- a/tests/topotests/ospf_te_topo1/reference/ted_step7.json +++ b/tests/topotests/ospf_te_topo1/reference/ted_step7.json @@ -117,7 +117,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.0.2", "remote-address":"10.0.0.1", "max-link-bandwidth":176258176.0, @@ -171,7 +170,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.1", "remote-address":"10.0.1.2", "max-link-bandwidth":176258176.0, @@ -225,7 +223,6 @@ "remote-vertex-id":167837441, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.1.2", "remote-address":"10.0.1.1", "max-link-bandwidth":176258176.0, @@ -279,7 +276,6 @@ "remote-vertex-id":167837442, "metric":10, "edge-attributes":{ - "te-metric":0, "admin-group":32, "local-address":"10.0.3.1", "remote-address":"10.0.3.2", @@ -322,7 +318,6 @@ "remote-vertex-id":167837443, "metric":10, "edge-attributes":{ - "te-metric":0, "local-address":"10.0.3.2", "remote-address":"10.0.3.1", "max-link-bandwidth":176258176.0, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 2d12ad4c8..064c86b16 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -438,6 +438,10 @@ parse_encap_seg6local(struct rtattr *tb, if (tb_encap[SEG6_LOCAL_TABLE]) ctx->table = *(uint32_t *)RTA_DATA(tb_encap[SEG6_LOCAL_TABLE]); + if (tb_encap[SEG6_LOCAL_VRFTABLE]) + ctx->table = + *(uint32_t *)RTA_DATA(tb_encap[SEG6_LOCAL_VRFTABLE]); + return act; } @@ -1467,6 +1471,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p, ctx->table)) return false; break; + case ZEBRA_SEG6_LOCAL_ACTION_END_DT4: + if (!nl_attr_put32(nlmsg, req_size, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DT4)) + return false; + if (!nl_attr_put32(nlmsg, req_size, + SEG6_LOCAL_VRFTABLE, + ctx->table)) + return false; + break; default: zlog_err("%s: unsupport seg6local behaviour action=%u", __func__, @@ -2570,6 +2584,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, ctx->table)) return 0; break; + case SEG6_LOCAL_ACTION_END_DT4: + if (!nl_attr_put32( + &req->n, buflen, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DT4)) + return 0; + if (!nl_attr_put32( + &req->n, buflen, + SEG6_LOCAL_VRFTABLE, + ctx->table)) + return 0; + break; default: zlog_err("%s: unsupport seg6local behaviour action=%u", __func__, action); diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index fac312cf7..c1b104aec 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2369,7 +2369,7 @@ static unsigned nexthop_active_check(struct route_node *rn, else if (rn->p.family == AF_INET6) family = AFI_IP6; else - family = 0; + family = AF_UNSPEC; if (IS_ZEBRA_DEBUG_NHG_DETAIL) zlog_debug("%s: re %p, nexthop %pNHv", __func__, re, nexthop); |