summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--babeld/message.c20
-rw-r--r--bfdd/ptm_adapter.c2
-rw-r--r--bgpd/bgp_route.c7
-rw-r--r--bgpd/rfapi/rfapi_import.c18
-rw-r--r--bgpd/rfapi/rfapi_rib.c2
-rw-r--r--doc/developer/cspf.rst196
-rw-r--r--doc/developer/workflow.rst4
-rw-r--r--doc/user/pim.rst1
-rw-r--r--doc/user/sharp.rst11
-rw-r--r--include/linux/seg6_local.h1
-rw-r--r--isisd/isis_te.c1
-rw-r--r--isisd/isis_tlvs.c70
-rw-r--r--isisd/isis_tlvs.h1
-rw-r--r--lib/cspf.c646
-rw-r--r--lib/cspf.h211
-rw-r--r--lib/filter_nb.c2
-rw-r--r--lib/if.c12
-rw-r--r--lib/prefix.h3
-rw-r--r--lib/subdir.am2
-rw-r--r--ospfd/ospf_asbr.c9
-rw-r--r--ospfd/ospf_lsa.c409
-rw-r--r--ospfd/ospf_lsa.h8
-rw-r--r--ospfd/ospf_lsdb.c6
-rw-r--r--ospfd/ospf_snmp.c8
-rw-r--r--ospfd/ospf_vty.c55
-rw-r--r--pimd/pim_addr.c8
-rw-r--r--pimd/pim_addr.h73
-rw-r--r--pimd/pim_assert.c6
-rw-r--r--pimd/pim_br.c9
-rw-r--r--pimd/pim_bsm.c8
-rw-r--r--pimd/pim_cmd.c313
-rw-r--r--pimd/pim_iface.c16
-rw-r--r--pimd/pim_ifchannel.c125
-rw-r--r--pimd/pim_igmp_mtrace.c4
-rw-r--r--pimd/pim_igmpv3.c4
-rw-r--r--pimd/pim_join.c58
-rw-r--r--pimd/pim_jp_agg.c18
-rw-r--r--pimd/pim_macro.c2
-rw-r--r--pimd/pim_mlag.c37
-rw-r--r--pimd/pim_mroute.c62
-rw-r--r--pimd/pim_msdp.c38
-rw-r--r--pimd/pim_msdp_packet.c4
-rw-r--r--pimd/pim_msg.c4
-rw-r--r--pimd/pim_nht.c10
-rw-r--r--pimd/pim_oil.c11
-rw-r--r--pimd/pim_register.c23
-rw-r--r--pimd/pim_rp.c20
-rw-r--r--pimd/pim_rpf.c2
-rw-r--r--pimd/pim_str.c10
-rw-r--r--pimd/pim_str.h22
-rw-r--r--pimd/pim_upstream.c65
-rw-r--r--pimd/pim_vty.c3
-rw-r--r--pimd/pim_vxlan.c8
-rw-r--r--pimd/pim_vxlan.h8
-rw-r--r--pimd/pim_zebra.c85
-rw-r--r--pimd/pim_zlookup.c12
-rw-r--r--pimd/pimd.h2
-rw-r--r--sharpd/sharp_vty.c111
-rw-r--r--sharpd/sharp_zebra.c4
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin245481 -> 222652 bytes
-rw-r--r--tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py2
-rw-r--r--tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity/customize.py2
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce1/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce2/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce3/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce4/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce5/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/bgpd.conf8
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/ip_rib.json58
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/ce6/zebra.conf14
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/bgpd.conf66
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vpnv4_rib.json167
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf10_rib.json86
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/vrf20_rib.json92
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r1/zebra.conf41
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/bgpd.conf66
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vpnv4_rib.json167
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf10_rib.json92
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/vrf20_rib.json86
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/r2/zebra.conf40
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py171
-rw-r--r--tests/topotests/cspf_topo1/r1/isisd.conf33
-rw-r--r--tests/topotests/cspf_topo1/r1/sharpd.conf3
-rw-r--r--tests/topotests/cspf_topo1/r1/zebra.conf27
-rw-r--r--tests/topotests/cspf_topo1/r2/isisd.conf46
-rw-r--r--tests/topotests/cspf_topo1/r2/zebra.conf45
-rw-r--r--tests/topotests/cspf_topo1/r3/isisd.conf34
-rw-r--r--tests/topotests/cspf_topo1/r3/zebra.conf27
-rw-r--r--tests/topotests/cspf_topo1/r4/isisd.conf40
-rw-r--r--tests/topotests/cspf_topo1/r4/zebra.conf26
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-failed-dst.txt1
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-failed-same.txt1
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-failed-src.txt1
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-failed.txt1
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv4-delay.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv4-metric.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv4-te-metric.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv6-delay.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv6-metric.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/cspf-ipv6-te-metric.txt3
-rw-r--r--tests/topotests/cspf_topo1/reference/sharp-ted.json860
-rw-r--r--tests/topotests/cspf_topo1/test_cspf_topo1.py253
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step1.json11
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step2.json7
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step3.json8
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step4.json8
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step5.json12
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step6.json12
-rw-r--r--tests/topotests/ldp_oc_acl_topo1/test_ldp_oc_acl_topo1.py2
-rw-r--r--tests/topotests/ldp_oc_topo1/test_ldp_oc_topo1.py2
-rw-r--r--tests/topotests/ldp_topo1/test_ldp_topo1.py2
-rw-r--r--tests/topotests/ospf6_topo1/test_ospf6_topo1.py2
-rwxr-xr-xtests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py2
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py150
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step1.json6
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step2.json4
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step3.json4
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step4.json4
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step5.json6
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step6.json6
-rw-r--r--tests/topotests/ospf_te_topo1/reference/ted_step7.json5
-rw-r--r--zebra/rt_netlink.c26
-rw-r--r--zebra/zebra_nhg.c2
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);
diff --git a/lib/if.c b/lib/if.c
index 158303a38..a2918b6d7 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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
index accc906bf..20b1dc33f 100644
--- a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
Binary files differ
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);