summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_interface.c4
-rw-r--r--bfdd/bfd_packet.c4
-rw-r--r--bgpd/bgp_attr_evpn.c12
-rw-r--r--bgpd/bgp_attr_evpn.h9
-rw-r--r--bgpd/bgp_evpn.c36
-rw-r--r--bgpd/bgp_fsm.c31
-rw-r--r--bgpd/bgp_route.c73
-rw-r--r--bgpd/bgp_vty.c64
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/bgpd.c32
-rw-r--r--bgpd/bgpd.h13
-rw-r--r--doc/user/bgp.rst5
-rw-r--r--doc/user/isisd.rst28
-rw-r--r--isisd/isis_adjacency.c23
-rw-r--r--isisd/isis_adjacency.h12
-rw-r--r--isisd/isis_bfd.c11
-rw-r--r--isisd/isis_circuit.c14
-rw-r--r--isisd/isis_cli.c71
-rw-r--r--isisd/isis_lfa.c5
-rw-r--r--isisd/isis_lsp.c67
-rw-r--r--isisd/isis_mt.c11
-rw-r--r--isisd/isis_mt.h2
-rw-r--r--isisd/isis_nb.c15
-rw-r--r--isisd/isis_nb.h10
-rw-r--r--isisd/isis_nb_config.c94
-rw-r--r--isisd/isis_pdu.c5
-rw-r--r--isisd/isis_route.c4
-rw-r--r--isisd/isis_snmp.c8
-rw-r--r--isisd/isis_sr.c18
-rw-r--r--isisd/isis_te.c1370
-rw-r--r--isisd/isis_te.h21
-rw-r--r--isisd/isis_tlvs.c349
-rw-r--r--isisd/isis_tlvs.h8
-rw-r--r--isisd/isis_zebra.c28
-rw-r--r--isisd/isis_zebra.h1
-rw-r--r--isisd/isisd.c42
-rw-r--r--isisd/isisd.h9
-rw-r--r--lib/elf_py.c29
-rw-r--r--lib/if.c16
-rw-r--r--lib/if.h2
-rw-r--r--lib/ipaddr.h13
-rw-r--r--lib/lib_errors.c6
-rw-r--r--lib/lib_errors.h1
-rw-r--r--lib/link_state.c341
-rw-r--r--lib/link_state.h42
-rw-r--r--lib/route_opaque.h17
-rw-r--r--lib/thread.c20
-rw-r--r--lib/thread.h6
-rw-r--r--lib/workqueue.c5
-rw-r--r--lib/yang.c5
-rw-r--r--nhrpd/nhrp_vty.c4
-rw-r--r--ospf6d/ospf6_area.c20
-rw-r--r--ospf6d/ospf6_area.h1
-rw-r--r--ospf6d/ospf6_interface.c8
-rw-r--r--ospf6d/ospf6_route.h3
-rw-r--r--ospf6d/ospf6_top.c39
-rw-r--r--ospf6d/ospf6_top.h6
-rw-r--r--ospf6d/ospf6_zebra.c37
-rw-r--r--ospfd/ospf_lsa.c3
-rw-r--r--ospfd/ospf_route.c16
-rw-r--r--ospfd/ospf_route.h1
-rw-r--r--ospfd/ospf_vty.c109
-rw-r--r--ospfd/ospf_zebra.c36
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--ospfd/ospfd.h1
-rw-r--r--pbrd/pbr_vty.c8
-rw-r--r--pimd/pim6_main.c3
-rw-r--r--pimd/pim_bfd.c1
-rw-r--r--pimd/pim_cmd.c93
-rw-r--r--pimd/pim_iface.c30
-rw-r--r--pimd/pim_iface.h5
-rw-r--r--pimd/pim_main.c3
-rw-r--r--pimd/pim_msdp.c1
-rw-r--r--pimd/pim_vty.c15
-rw-r--r--redhat/frr.logrotate2
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin176859 -> 245481 bytes
-rw-r--r--tests/topotests/bgp_llgr/r0/bgpd.conf2
-rw-r--r--tests/topotests/bgp_llgr/r1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_llgr/r2/bgpd.conf9
-rw-r--r--tests/topotests/bgp_llgr/r2/zebra.conf3
-rw-r--r--tests/topotests/bgp_llgr/r3/bgpd.conf2
-rw-r--r--tests/topotests/bgp_llgr/r4/bgpd.conf13
-rw-r--r--tests/topotests/bgp_llgr/r4/zebra.conf7
-rw-r--r--tests/topotests/bgp_llgr/test_bgp_llgr.py34
-rwxr-xr-xtests/topotests/isis_te_topo1/__init__.py0
-rw-r--r--tests/topotests/isis_te_topo1/r1/isisd.conf31
-rw-r--r--tests/topotests/isis_te_topo1/r1/zebra.conf25
-rw-r--r--tests/topotests/isis_te_topo1/r2/isisd.conf45
-rw-r--r--tests/topotests/isis_te_topo1/r2/zebra.conf39
-rw-r--r--tests/topotests/isis_te_topo1/r3/isisd.conf34
-rw-r--r--tests/topotests/isis_te_topo1/r3/zebra.conf25
-rw-r--r--tests/topotests/isis_te_topo1/r4/isisd.conf39
-rw-r--r--tests/topotests/isis_te_topo1/r4/zebra.conf22
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step1.json851
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step2.json651
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step3.json752
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step4.json752
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step5.json952
-rw-r--r--tests/topotests/isis_te_topo1/reference/ted_step6.json953
-rw-r--r--tests/topotests/isis_te_topo1/test_isis_te_topo1.py265
-rwxr-xr-xtests/topotests/isis_topo1_vrf/r1/isisd.conf6
-rwxr-xr-xtests/topotests/isis_topo1_vrf/r2/isisd.conf6
-rwxr-xr-xtests/topotests/isis_topo1_vrf/r3/isisd.conf12
-rwxr-xr-xtests/topotests/isis_topo1_vrf/r4/isisd.conf12
-rwxr-xr-xtests/topotests/isis_topo1_vrf/r5/isisd.conf12
-rw-r--r--tests/topotests/lib/common_config.py10
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py32
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json33
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json17
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json25
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf2
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json13
-rw-r--r--tests/topotests/ospf_instance_redistribute/r1/zebra.conf2
-rw-r--r--tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py188
-rw-r--r--tests/topotests/zebra_opaque/r3/ospf6d.conf8
-rw-r--r--tests/topotests/zebra_opaque/r3/ospfd.conf8
-rw-r--r--tests/topotests/zebra_opaque/r3/zebra.conf5
-rw-r--r--tests/topotests/zebra_opaque/r4/ospf6d.conf8
-rw-r--r--tests/topotests/zebra_opaque/r4/ospfd.conf8
-rw-r--r--tests/topotests/zebra_opaque/r4/zebra.conf5
-rw-r--r--tests/topotests/zebra_opaque/test_zebra_opaque.py48
-rw-r--r--yang/frr-isisd.yang11
-rw-r--r--zebra/if_netlink.c16
-rw-r--r--zebra/interface.c16
-rw-r--r--zebra/kernel_netlink.c3
-rw-r--r--zebra/redistribute.c137
-rw-r--r--zebra/redistribute.h25
-rw-r--r--zebra/rib.h3
-rw-r--r--zebra/zapi_msg.c52
-rw-r--r--zebra/zapi_msg.h7
-rw-r--r--zebra/zebra_rib.c113
-rw-r--r--zebra/zebra_vty.c29
132 files changed, 9054 insertions, 787 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index e725fbffe9..98c5d21196 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -1308,7 +1308,7 @@ interface_config_write (struct vty *vty)
int write = 0;
FOR_ALL_INTERFACES (vrf, ifp) {
- vty_frame (vty, "interface %s\n",ifp->name);
+ if_vty_config_start(vty, ifp);
if (ifp->desc)
vty_out (vty, " description %s\n",ifp->desc);
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
@@ -1385,7 +1385,7 @@ interface_config_write (struct vty *vty)
write++;
}
}
- vty_endframe (vty, "exit\n!\n");
+ if_vty_config_end(vty);
write++;
}
return write;
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 652b914118..839f06329a 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -639,8 +639,6 @@ int bfd_recv_cb(struct thread *t)
return 0;
}
- bfd->stats.rx_ctrl_pkt++;
-
/*
* Multi hop: validate packet TTL.
* Single hop: set local address that received the packet.
@@ -656,6 +654,8 @@ int bfd_recv_cb(struct thread *t)
bfd->local_address = local;
}
+ bfd->stats.rx_ctrl_pkt++;
+
/*
* If no interface was detected, save the interface where the
* packet came in.
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 0e341a8c6b..add999bd44 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -304,15 +304,3 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
return -1;
return 0;
}
-
-extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
-{
- if (afi == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&gw_ip->ipv6))
- return true;
-
- if (afi == AF_INET && gw_ip->ipv4.s_addr == INADDR_ANY)
- return true;
-
- return false;
-}
-
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 102509fdd7..64f0e7c51a 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -25,11 +25,6 @@
struct attr;
-union gw_addr {
- struct in_addr ipv4;
- struct in6_addr ipv6;
-};
-
enum overlay_index_type {
OVERLAY_INDEX_TYPE_NONE,
OVERLAY_INDEX_GATEWAY_IP,
@@ -45,7 +40,7 @@ enum overlay_index_type {
struct bgp_route_evpn {
enum overlay_index_type type;
esi_t eth_s_id;
- union gw_addr gw_ip;
+ struct ipaddr gw_ip;
};
extern bool str2esi(const char *str, esi_t *id);
@@ -64,6 +59,4 @@ extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag,
bool *proxy);
extern uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg);
-extern bool is_zero_gw_ip(const union gw_addr *gw_ip, afi_t afi);
-
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index ea54c14222..ffa4aca3fb 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1335,7 +1335,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
if (src_attr &&
!IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) {
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
- memcpy(&attr.evpn_overlay.gw_ip.ipv6,
+ SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
&src_attr->mp_nexthop_global,
sizeof(struct in6_addr));
}
@@ -1344,7 +1345,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
if (src_attr && src_attr->nexthop.s_addr != 0) {
attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
- memcpy(&attr.evpn_overlay.gw_ip.ipv4,
+ SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
&src_attr->nexthop, sizeof(struct in_addr));
}
}
@@ -2470,11 +2472,11 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
if (afi == AFI_IP6) {
memcpy(&attr.mp_nexthop_global,
- &attr.evpn_overlay.gw_ip.ipv6,
+ &attr.evpn_overlay.gw_ip.ipaddr_v6,
sizeof(struct in6_addr));
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
} else {
- attr.nexthop = attr.evpn_overlay.gw_ip.ipv4;
+ attr.nexthop = attr.evpn_overlay.gw_ip.ipaddr_v4;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
}
}
@@ -4041,7 +4043,6 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
uint32_t eth_tag;
mpls_label_t label; /* holds the VNI as in the packet */
int ret;
- afi_t gw_afi;
bool is_valid_update = true;
/* Type-5 route should be 34 or 58 bytes:
@@ -4100,17 +4101,17 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
pfx += 4;
- memcpy(&evpn.gw_ip.ipv4, pfx, 4);
+ SET_IPADDR_V4(&evpn.gw_ip);
+ memcpy(&evpn.gw_ip.ipaddr_v4, pfx, 4);
pfx += 4;
- gw_afi = AF_INET;
} else {
SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx,
IPV6_MAX_BYTELEN);
pfx += IPV6_MAX_BYTELEN;
- memcpy(&evpn.gw_ip.ipv6, pfx, IPV6_MAX_BYTELEN);
+ SET_IPADDR_V6(&evpn.gw_ip);
+ memcpy(&evpn.gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN);
pfx += IPV6_MAX_BYTELEN;
- gw_afi = AF_INET6;
}
/* Get the VNI (in MPLS label field). Stored as bytes here. */
@@ -4127,20 +4128,20 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
* An update containing a non-zero gateway IP and a non-zero ESI
* at the same time is should be treated as withdraw
*/
- if (bgp_evpn_is_esi_valid(&evpn.eth_s_id)
- && !is_zero_gw_ip(&evpn.gw_ip, gw_afi)) {
+ if (bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
+ !ipaddr_is_zero(&evpn.gw_ip)) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
peer->host);
is_valid_update = false;
} else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
evpn.type = OVERLAY_INDEX_ESI;
- else if (!is_zero_gw_ip(&evpn.gw_ip, gw_afi))
+ else if (!ipaddr_is_zero(&evpn.gw_ip))
evpn.type = OVERLAY_INDEX_GATEWAY_IP;
if (attr) {
- if (is_zero_mac(&attr->rmac)
- && !bgp_evpn_is_esi_valid(&evpn.eth_s_id)
- && is_zero_gw_ip(&evpn.gw_ip, gw_afi) && label == 0) {
+ if (is_zero_mac(&attr->rmac) &&
+ !bgp_evpn_is_esi_valid(&evpn.eth_s_id) &&
+ ipaddr_is_zero(&evpn.gw_ip) && label == 0) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
peer->host);
@@ -4213,9 +4214,10 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
bgp_attr_get_evpn_overlay(attr);
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
- stream_put_ipv4(s, evpn_overlay->gw_ip.ipv4.s_addr);
+ stream_put_ipv4(s,
+ evpn_overlay->gw_ip.ipaddr_v4.s_addr);
else
- stream_put(s, &(evpn_overlay->gw_ip.ipv6), 16);
+ stream_put(s, &(evpn_overlay->gw_ip.ipaddr_v6), 16);
} else {
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
stream_put_ipv4(s, 0);
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 45e9aad1ba..672fa4512a 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -662,6 +662,15 @@ static void bgp_graceful_restart_timer_off(struct peer *peer)
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
BGP_TIMER_OFF(peer->t_gr_stale);
+
+ if (peer_dynamic_neighbor(peer) &&
+ !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s (dynamic neighbor) deleted (%s)",
+ peer->host, __func__);
+ peer_delete(peer);
+ }
+
bgp_timer_set(peer);
}
@@ -1380,10 +1389,11 @@ int bgp_stop(struct peer *peer)
&& peer->last_reset == PEER_DOWN_UPDATE_SOURCE_CHANGE)
bfd_sess_uninstall(peer->bfd_config->session);
- if (peer_dynamic_neighbor(peer)
- && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
+ if (peer_dynamic_neighbor_no_nsf(peer) &&
+ !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) {
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ zlog_debug("%s (dynamic neighbor) deleted (%s)",
+ peer->host, __func__);
peer_delete(peer);
return -1;
}
@@ -1602,9 +1612,10 @@ static int bgp_stop_with_error(struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
- if (peer_dynamic_neighbor(peer)) {
+ if (peer_dynamic_neighbor_no_nsf(peer)) {
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ zlog_debug("%s (dynamic neighbor) deleted (%s)",
+ peer->host, __func__);
peer_delete(peer);
return -1;
}
@@ -1620,9 +1631,10 @@ static int bgp_stop_with_notify(struct peer *peer, uint8_t code,
/* Send notify to remote peer */
bgp_notify_send(peer, code, sub_code);
- if (peer_dynamic_neighbor(peer)) {
+ if (peer_dynamic_neighbor_no_nsf(peer)) {
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ zlog_debug("%s (dynamic neighbor) deleted (%s)",
+ peer->host, __func__);
peer_delete(peer);
return -1;
}
@@ -1781,9 +1793,10 @@ static int bgp_connect_success_w_delayopen(struct peer *peer)
/* TCP connect fail */
static int bgp_connect_fail(struct peer *peer)
{
- if (peer_dynamic_neighbor(peer)) {
+ if (peer_dynamic_neighbor_no_nsf(peer)) {
if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s (dynamic neighbor) deleted", peer->host);
+ zlog_debug("%s (dynamic neighbor) deleted (%s)",
+ peer->host, __func__);
peer_delete(peer);
return -1;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f6231a3c7a..4956c7238d 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3582,30 +3582,6 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
return new;
}
-static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
- union gw_addr *gw_ip)
-{
- const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
- union gw_addr path_gw_ip, *path_gw_ip_remote;
- union {
- esi_t esi;
- union gw_addr ip;
- } temp;
-
- if (afi != AFI_L2VPN)
- return true;
-
- path_gw_ip = eo->gw_ip;
-
- if (gw_ip == NULL) {
- memset(&temp, 0, sizeof(temp));
- path_gw_ip_remote = &temp.ip;
- } else
- path_gw_ip_remote = gw_ip;
-
- return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
-}
-
/* Check if received nexthop is valid or not. */
bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
uint8_t type, uint8_t stype, struct attr *attr,
@@ -6107,7 +6083,6 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
mpls_label_t label = 0;
#endif
uint32_t num_labels = 0;
- union gw_addr add;
assert(bgp_static);
@@ -6130,12 +6105,17 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
}
}
if (afi == AFI_L2VPN) {
- if (bgp_static->gatewayIp.family == AF_INET)
- add.ipv4.s_addr =
- bgp_static->gatewayIp.u.prefix4.s_addr;
- else if (bgp_static->gatewayIp.family == AF_INET6)
- memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
- sizeof(struct in6_addr));
+ if (bgp_static->gatewayIp.family == AF_INET) {
+ SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
+ &bgp_static->gatewayIp.u.prefix4,
+ IPV4_MAX_BYTELEN);
+ } else if (bgp_static->gatewayIp.family == AF_INET6) {
+ SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
+ &bgp_static->gatewayIp.u.prefix6,
+ IPV6_MAX_BYTELEN);
+ }
memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
struct bgp_encap_type_vxlan bet;
@@ -6184,9 +6164,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
break;
if (pi) {
- memset(&add, 0, sizeof(union gw_addr));
if (attrhash_cmp(pi->attr, attr_new)
- && overlay_index_equal(afi, pi, &add)
&& !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
bgp_dest_unlock_node(dest);
bgp_attr_unintern(&attr_new);
@@ -9530,10 +9508,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
- if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
- inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
- else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
- inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
+ ipaddr2str(&eo->gw_ip, buf, BUFSIZ);
if (!json_path)
vty_out(vty, "/%s", buf);
@@ -9946,12 +9921,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
&& attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
char gwip_buf[INET6_ADDRSTRLEN];
- if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
- inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
- gwip_buf, sizeof(gwip_buf));
- else
- inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
- gwip_buf, sizeof(gwip_buf));
+ ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
+ sizeof(gwip_buf));
if (json_paths)
json_object_string_add(json_path, "gatewayIP",
@@ -10736,10 +10707,26 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
str, label2vni(&attr->label));
}
+ if (path->peer->t_gr_restart &&
+ CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
+ unsigned long gr_remaining =
+ thread_timer_remain_second(path->peer->t_gr_restart);
+
+ if (json_paths) {
+ json_object_int_add(json_path,
+ "gracefulRestartSecondsRemaining",
+ gr_remaining);
+ } else
+ vty_out(vty,
+ " Time until Graceful Restart stale route deleted: %lu\n",
+ gr_remaining);
+ }
+
if (path->peer->t_llgr_stale[afi][safi] && attr->community &&
community_include(attr->community, COMMUNITY_LLGR_STALE)) {
unsigned long llgr_remaining = thread_timer_remain_second(
path->peer->t_llgr_stale[afi][safi]);
+
if (json_paths) {
json_object_int_add(json_path, "llgrSecondsRemaining",
llgr_remaining);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 0072148823..5eae350102 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9431,7 +9431,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out>]",
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
CLEAR_STR
IP_STR
BGP_STR
@@ -9453,7 +9453,8 @@ DEFUN (clear_ip_bgp_all,
BGP_SOFT_OUT_STR
BGP_SOFT_IN_STR
"Push out prefix-list ORF and do inbound soft reconfig\n"
- BGP_SOFT_OUT_STR)
+ BGP_SOFT_OUT_STR
+ "Reset message statistics\n")
{
char *vrf = NULL;
@@ -9510,7 +9511,7 @@ DEFUN (clear_ip_bgp_all,
clr_sort = clear_external;
}
- /* [<soft [<in|out>]|in [prefix-filter]|out>] */
+ /* [<soft [<in|out>]|in [prefix-filter]|out|message-stats>] */
if (argv_find(argv, argc, "soft", &idx)) {
if (argv_find(argv, argc, "in", &idx)
|| argv_find(argv, argc, "out", &idx))
@@ -9525,6 +9526,8 @@ DEFUN (clear_ip_bgp_all,
: BGP_CLEAR_SOFT_IN;
} else if (argv_find(argv, argc, "out", &idx)) {
clr_type = BGP_CLEAR_SOFT_OUT;
+ } else if (argv_find(argv, argc, "message-stats", &idx)) {
+ clr_type = BGP_CLEAR_MESSAGE_STATS;
} else
clr_type = BGP_CLEAR_SOFT_NONE;
@@ -16548,17 +16551,14 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
/* capability extended-nexthop */
if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
- if (!peer->conf_if) {
- if (CHECK_FLAG(peer->flags_invert,
- PEER_FLAG_CAPABILITY_ENHE))
- vty_out(vty,
- " no neighbor %s capability extended-nexthop\n",
- addr);
- else
- vty_out(vty,
- " neighbor %s capability extended-nexthop\n",
- addr);
- }
+ if (CHECK_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE))
+ vty_out(vty,
+ " no neighbor %s capability extended-nexthop\n",
+ addr);
+ else if (!peer->conf_if)
+ vty_out(vty,
+ " neighbor %s capability extended-nexthop\n",
+ addr);
}
/* dont-capability-negotiation */
@@ -17496,7 +17496,20 @@ static struct cmd_node bgp_srv6_node = {
static void community_list_vty(void);
-static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
+static void bgp_ac_peergroup(vector comps, struct cmd_token *token)
+{
+ struct bgp *bgp;
+ struct peer_group *group;
+ struct listnode *lnbgp, *lnpeer;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
+ for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group))
+ vector_set(comps,
+ XSTRDUP(MTYPE_COMPLETION, group->name));
+ }
+}
+
+static void bgp_ac_peer(vector comps, struct cmd_token *token)
{
struct bgp *bgp;
struct peer *peer;
@@ -17526,25 +17539,20 @@ static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
}
}
+static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
+{
+ bgp_ac_peer(comps, token);
+
+ if (token->type == VARIABLE_TKN)
+ bgp_ac_peergroup(comps, token);
+}
+
static const struct cmd_variable_handler bgp_var_neighbor[] = {
{.varname = "neighbor", .completions = bgp_ac_neighbor},
{.varname = "neighbors", .completions = bgp_ac_neighbor},
{.varname = "peer", .completions = bgp_ac_neighbor},
{.completions = NULL}};
-static void bgp_ac_peergroup(vector comps, struct cmd_token *token)
-{
- struct bgp *bgp;
- struct peer_group *group;
- struct listnode *lnbgp, *lnpeer;
-
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) {
- for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group))
- vector_set(comps, XSTRDUP(MTYPE_COMPLETION,
- group->name));
- }
-}
-
static const struct cmd_variable_handler bgp_var_peergroup[] = {
{.tokenname = "PGNAME", .completions = bgp_ac_peergroup},
{.completions = NULL} };
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index de25aa30d9..21912d143e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -65,6 +65,8 @@
#include "bgpd/bgp_evpn_mh.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_trace.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_lcommunity.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 920660f9d9..bc7203fec6 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -7604,6 +7604,34 @@ int peer_ttl_security_hops_unset(struct peer *peer)
return ret;
}
+static void peer_reset_message_stats(struct peer *peer)
+{
+ if (peer) {
+ atomic_store_explicit(&peer->open_in, 0, memory_order_relaxed);
+ atomic_store_explicit(&peer->open_out, 0, memory_order_relaxed);
+ atomic_store_explicit(&peer->update_in, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->update_out, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->keepalive_in, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->keepalive_out, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->notify_in, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->notify_out, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->refresh_in, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->refresh_out, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->dynamic_cap_in, 0,
+ memory_order_relaxed);
+ atomic_store_explicit(&peer->dynamic_cap_out, 0,
+ memory_order_relaxed);
+ }
+}
+
/*
* If peer clear is invoked in a loop for all peers on the BGP instance,
* it may end up freeing the doppelganger, and if this was the next node
@@ -7716,6 +7744,10 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
}
}
+
+ if (stype == BGP_CLEAR_MESSAGE_STATS)
+ peer_reset_message_stats(peer);
+
return 0;
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 8d79b9fe09..ae6427b356 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1905,7 +1905,8 @@ enum bgp_clear_type {
BGP_CLEAR_SOFT_OUT,
BGP_CLEAR_SOFT_IN,
BGP_CLEAR_SOFT_BOTH,
- BGP_CLEAR_SOFT_IN_ORF_PREFIX
+ BGP_CLEAR_SOFT_IN_ORF_PREFIX,
+ BGP_CLEAR_MESSAGE_STATS
};
/* Macros. */
@@ -2387,9 +2388,15 @@ static inline bool peer_established(struct peer *peer)
return peer->status == Established;
}
-static inline int peer_dynamic_neighbor(struct peer *peer)
+static inline bool peer_dynamic_neighbor(struct peer *peer)
{
- return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0;
+ return CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
+}
+
+static inline bool peer_dynamic_neighbor_no_nsf(struct peer *peer)
+{
+ return (peer_dynamic_neighbor(peer) &&
+ !CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT));
}
static inline int peer_cap_enhe(struct peer *peer, afi_t afi, safi_t safi)
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 0fb5fa8482..004b1723ee 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -3392,6 +3392,11 @@ The following are available in the top level *enable* mode:
Clear peer using soft reconfiguration in this address-family and sub-address-family.
+.. clicmd:: clear bgp [ipv4|ipv6] [unicast] PEER|\* message-stats
+
+ Clear BGP message statistics for a specified peer or for all peers,
+ optionally filtered by activated address-family and sub-address-family.
+
The following are available in the ``router bgp`` mode:
.. clicmd:: write-quanta (1-64)
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index 4a711a8feb..5d53f60f93 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -318,6 +318,11 @@ Traffic Engineering
.. note::
+ IS-IS-TE supports RFC 5305 (base TE), RFC 6119 (IPv6) and RFC 7810 / 8570
+ (Extended Metric) with or without Multi-Topology. All Traffic Engineering
+ information are stored in a database formally named TED. However, best
+ acccuracy is provided without Multi-Topology due to inconsistency of Traffic
+ Engineering Advertisement of 3rd party commercial routers when MT is enabled.
At this time, FRR offers partial support for some of the routing protocol
extensions that can be used with MPLS-TE. FRR does not currently support a
complete RSVP-TE solution.
@@ -330,6 +335,15 @@ Traffic Engineering
Configure stable IP address for MPLS-TE.
+.. clicmd:: mpls-te router-address ipv6 <X:X::X:X>
+
+ Configure stable IPv6 address for MPLS-TE.
+
+.. clicmd:: mpls-te export
+
+ Export Traffic Engineering DataBase to other daemons through the ZAPI
+ Opaque Link State messages.
+
.. clicmd:: show isis mpls-te interface
.. clicmd:: show isis mpls-te interface INTERFACE
@@ -340,6 +354,16 @@ Traffic Engineering
Show Traffic Engineering router parameters.
+.. clicmd:: show isis [vrf <NAME|all>] mpls-te database [detail|json]
+
+.. clicmd:: show isis [vrf <NAME|all>] mpls-te database vertex [WORD] [detail|json]
+
+.. clicmd:: show isis [vrf <NAME|all>] mpls-te database edge [A.B.C.D|X:X::X:X] [detail|json]
+
+.. clicmd:: show isis [vrf <NAME|all>] mpls-te database subnet [A.B.C.D/M|X:X::X:X/M] [detail|json]
+
+ Show Traffic Engineering Database
+
.. seealso::
:ref:`ospf-traffic-engineering`
@@ -445,6 +469,10 @@ Debugging ISIS
Update related packets.
+.. clicmd:: debug isis te-events
+
+ IS-IS Traffic Engineering events
+
.. clicmd:: debug isis sr-events
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 9529adb09a..d75613f300 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -168,7 +168,7 @@ void isis_delete_adj(void *arg)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
- XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs);
adj_mt_finish(adj);
list_delete(&adj->adj_sids);
@@ -420,11 +420,11 @@ void isis_adj_print(struct isis_adjacency *adj)
zlog_debug("%pI4", &adj->ipv4_addresses[i]);
}
- if (adj->ipv6_address_count) {
+ if (adj->ll_ipv6_count) {
zlog_debug("IPv6 Address(es):");
- for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
char buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &adj->ipv6_addresses[i], buf,
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
sizeof(buf));
zlog_debug("%s", buf);
}
@@ -583,12 +583,21 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, " %pI4\n",
&adj->ipv4_addresses[i]);
}
- if (adj->ipv6_address_count) {
+ if (adj->ll_ipv6_count) {
vty_out(vty, " IPv6 Address(es):\n");
- for (unsigned int i = 0; i < adj->ipv6_address_count;
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i],
+ buf, sizeof(buf));
+ vty_out(vty, " %s\n", buf);
+ }
+ }
+ if (adj->global_ipv6_count) {
+ vty_out(vty, " Global IPv6 Address(es):\n");
+ for (unsigned int i = 0; i < adj->global_ipv6_count;
i++) {
char buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &adj->ipv6_addresses[i],
+ inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
buf, sizeof(buf));
vty_out(vty, " %s\n", buf);
}
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index 4aa553e303..af70775a87 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -88,8 +88,10 @@ struct isis_adjacency {
struct in_addr *ipv4_addresses;
unsigned int ipv4_address_count;
struct in_addr router_address;
- struct in6_addr *ipv6_addresses;
- unsigned int ipv6_address_count;
+ struct in6_addr *ll_ipv6_addrs; /* Link local IPv6 neighbor address */
+ unsigned int ll_ipv6_count;
+ struct in6_addr *global_ipv6_addrs; /* Global IPv6 neighbor address */
+ unsigned int global_ipv6_count;
struct in6_addr router_address6;
uint8_t prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
int circuit_t; /* from hello PDU hdr */
@@ -127,9 +129,11 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
enum isis_adj_usage adj_usage);
DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj));
DECLARE_HOOK(isis_adj_ip_enabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
DECLARE_HOOK(isis_adj_ip_disabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
void isis_log_adj_change(struct isis_adjacency *adj,
enum isis_adj_state old_state,
enum isis_adj_state new_state, const char *reason);
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index a7548e2f13..1f50fb9342 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -81,7 +81,7 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj)
*/
if (circuit->ipv6_router
&& (listcount(circuit->ipv6_link) == 0
- || adj->ipv6_address_count == 0)) {
+ || adj->ll_ipv6_count == 0)) {
if (IS_DEBUG_BFD)
zlog_debug(
"ISIS-BFD: skipping BFD initialization on adjacency with %s because IPv6 is enabled but not ready",
@@ -93,9 +93,9 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj)
* If IS-IS is enabled for both IPv4 and IPv6 on the circuit, prefer
* creating a BFD session over IPv6.
*/
- if (circuit->ipv6_router && adj->ipv6_address_count) {
+ if (circuit->ipv6_router && adj->ll_ipv6_count) {
family = AF_INET6;
- dst_ip.ipv6 = adj->ipv6_addresses[0];
+ dst_ip.ipv6 = adj->ll_ipv6_addrs[0];
local_ips = circuit->ipv6_link;
if (!local_ips || list_isempty(local_ips)) {
if (IS_DEBUG_BFD)
@@ -181,10 +181,11 @@ void isis_bfd_circuit_cmd(struct isis_circuit *circuit)
}
}
-static int bfd_handle_adj_ip_enabled(struct isis_adjacency *adj, int family)
+static int bfd_handle_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
- if (family != AF_INET6)
+ if (family != AF_INET6 || global)
return 0;
if (adj->bfd_session)
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index a91bbd0b95..1b0447226d 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -335,8 +335,16 @@ void isis_circuit_add_addr(struct isis_circuit *circuit,
if (IN6_IS_ADDR_LINKLOCAL(&ipv6->prefix))
listnode_add(circuit->ipv6_link, ipv6);
- else
+ else {
listnode_add(circuit->ipv6_non_link, ipv6);
+ /* Update Local IPv6 address param. if MPLS TE is on */
+ if (circuit->ext && circuit->area
+ && IS_MPLS_TE(circuit->area->mta)) {
+ IPV6_ADDR_COPY(&circuit->ext->local_addr6,
+ &ipv6->prefix);
+ SET_SUBTLV(circuit->ext, EXT_LOCAL_ADDR6);
+ }
+ }
if (circuit->area)
lsp_regenerate_schedule(circuit->area, circuit->is_type,
0);
@@ -1061,7 +1069,7 @@ static int isis_interface_config_write(struct vty *vty)
FOR_ALL_INTERFACES (vrf, ifp) {
/* IF name */
- vty_frame(vty, "interface %s\n", ifp->name);
+ if_vty_config_start(vty, ifp);
write++;
/* IF desc */
if (ifp->desc) {
@@ -1269,7 +1277,7 @@ static int isis_interface_config_write(struct vty *vty)
write += hook_call(isis_circuit_config_write,
circuit, vty);
} while (0);
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
return write;
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index 21162045ad..9feabfa012 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -1140,6 +1140,43 @@ void cli_show_isis_mpls_te_router_addr(struct vty *vty,
yang_dnode_get_string(dnode, NULL));
}
+/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/router-address-v6
+ */
+DEFPY_YANG(isis_mpls_te_router_addr_v6, isis_mpls_te_router_addr_v6_cmd,
+ "mpls-te router-address ipv6 X:X::X:X",
+ MPLS_TE_STR
+ "Stable IP address of the advertising router\n"
+ "IPv6 address\n"
+ "MPLS-TE router address in IPv6 address format\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_MODIFY,
+ ipv6_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_isis_mpls_te_router_addr_v6, no_isis_mpls_te_router_addr_v6_cmd,
+ "no mpls-te router-address ipv6 [X:X::X:X]",
+ NO_STR MPLS_TE_STR
+ "Delete IP address of the advertising router\n"
+ "IPv6 address\n"
+ "MPLS-TE router address in IPv6 address format\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_DESTROY,
+ NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_isis_mpls_te_router_addr_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " mpls-te router-address ipv6 %s\n",
+ yang_dnode_get_string(dnode, NULL));
+}
+
DEFPY_YANG(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd,
"[no] mpls-te inter-as [level-1|level-1-2|level-2-only]",
NO_STR MPLS_TE_STR
@@ -1153,6 +1190,36 @@ DEFPY_YANG(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd,
}
/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/export
+ */
+DEFPY_YANG(isis_mpls_te_export, isis_mpls_te_export_cmd, "mpls-te export",
+ MPLS_TE_STR "Enable export of MPLS-TE Link State information\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/export", NB_OP_MODIFY, "true");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_isis_mpls_te_export, no_isis_mpls_te_export_cmd,
+ "no mpls-te export",
+ NO_STR MPLS_TE_STR
+ "Disable export of MPLS-TE Link State information\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/export", NB_OP_MODIFY, "false");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_isis_mpls_te_export(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ if (!yang_dnode_get_bool(dnode, NULL))
+ vty_out(vty, " no");
+
+ vty_out(vty, " mpls-te export\n");
+}
+
+/*
* XPath: /frr-isisd:isis/instance/default-information-originate
*/
DEFPY_YANG(isis_default_originate, isis_default_originate_cmd,
@@ -3125,7 +3192,11 @@ void isis_cli_init(void)
install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd);
install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd);
install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_cmd);
+ install_element(ISIS_NODE, &isis_mpls_te_router_addr_v6_cmd);
+ install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_v6_cmd);
install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd);
+ install_element(ISIS_NODE, &isis_mpls_te_export_cmd);
+ install_element(ISIS_NODE, &no_isis_mpls_te_export_cmd);
install_element(ISIS_NODE, &isis_default_originate_cmd);
install_element(ISIS_NODE, &isis_redistribute_cmd);
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index e033c28fef..84aac24d52 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -1443,9 +1443,8 @@ static mpls_label_t rlfa_nexthop_label(struct isis_spftree *spftree,
}
break;
case AF_INET6:
- for (unsigned int j = 0; j < adj->ipv6_address_count;
- j++) {
- struct in6_addr addr = adj->ipv6_addresses[j];
+ for (unsigned int j = 0; j < adj->ll_ipv6_count; j++) {
+ struct in6_addr addr = adj->ll_ipv6_addrs[j];
if (!IPV6_ADDR_SAME(
&addr,
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index e3de6f08c0..92d329f035 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -124,6 +124,8 @@ static void lsp_destroy(struct isis_lsp *lsp)
ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags);
+ isis_te_lsp_event(lsp, LSP_DEL);
+
lsp_clear_data(lsp);
if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) {
@@ -335,6 +337,7 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
lsp_pack_pdu(lsp);
isis_spf_schedule(lsp->area, lsp->level);
+ isis_te_lsp_event(lsp, LSP_INC);
}
static void lsp_purge_add_poi(struct isis_lsp *lsp,
@@ -570,8 +573,10 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
lsp_link_fragment(lsp, lsp0);
}
- if (lsp->hdr.seqno)
+ if (lsp->hdr.seqno) {
isis_spf_schedule(lsp->area, lsp->level);
+ isis_te_lsp_event(lsp, LSP_UPD);
+ }
}
/* creation of LSP directly from what we received */
@@ -636,8 +641,10 @@ struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id,
void lsp_insert(struct lspdb_head *head, struct isis_lsp *lsp)
{
lspdb_add(head, lsp);
- if (lsp->hdr.seqno)
+ if (lsp->hdr.seqno) {
isis_spf_schedule(lsp->area, lsp->level);
+ isis_te_lsp_event(lsp, LSP_ADD);
+ }
}
/*
@@ -1030,6 +1037,10 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
cap.srlb.lower_bound = srdb->config.srlb_lower_bound;
/* And finally MSD */
cap.msd = srdb->config.msd;
+ } else {
+ /* Disable SR Algorithm */
+ cap.algo[0] = SR_ALGORITHM_UNSET;
+ cap.algo[1] = SR_ALGORITHM_UNSET;
}
isis_tlvs_set_router_capability(lsp->tlvs, &cap);
@@ -1067,6 +1078,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
area->area_tag);
}
+ if (IS_MPLS_TE(area->mta)
+ && !IN6_IS_ADDR_UNSPECIFIED(&area->mta->router_id_ipv6)) {
+ lsp_debug("ISIS (%s): Adding IPv6 TE Router ID tlv.",
+ area->area_tag);
+ isis_tlvs_set_te_router_id_ipv6(lsp->tlvs,
+ &area->mta->router_id_ipv6);
+ }
+
lsp_debug("ISIS (%s): Adding circuit specific information.",
area->area_tag);
@@ -1601,6 +1620,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
struct list *adj_list;
struct listnode *node;
struct isis_area *area = circuit->area;
+ uint16_t mtid;
lsp_clear_data(lsp);
lsp->tlvs = isis_alloc_tlvs();
@@ -1630,8 +1650,11 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
LSP_PSEUDO_ID(ne_id));
}
if (circuit->area->newmetric) {
- isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST,
- ne_id, 0, NULL);
+ if (area_is_mt(circuit->area))
+ mtid = ISIS_MT_IPV4_UNICAST;
+ else
+ mtid = ISIS_MT_DISABLE;
+ isis_tlvs_add_extended_reach(lsp->tlvs, mtid, ne_id, 0, NULL);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
area->area_tag, sysid_print(ne_id),
@@ -2000,6 +2023,7 @@ int lsp_tick(struct thread *thread)
/* 7.3.16.4 c) record the time to purge
* FIXME */
isis_spf_schedule(lsp->area, lsp->level);
+ isis_te_lsp_event(lsp, LSP_TICK);
}
if (lsp->age_out == 0) {
@@ -2154,7 +2178,7 @@ int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid,
if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0)
return LSP_ITER_CONTINUE;
- /* Parse main LSP. */
+ /* Parse LSP */
if (lsp->tlvs) {
if (!fabricd && !pseudo_lsp && family == AF_INET
&& mtid == ISIS_MT_IPV4_UNICAST) {
@@ -2224,13 +2248,17 @@ int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid,
}
}
- /* Parse LSP fragments. */
- for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
- if (!frag->tlvs)
- continue;
+ /* Parse LSP fragments if it is not a fragment itself */
+ if (!LSP_FRAGMENT(lsp->hdr.lsp_id))
+ for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ if (!frag->tlvs)
+ continue;
- isis_lsp_iterate_ip_reach(frag, family, mtid, cb, arg);
- }
+ if (isis_lsp_iterate_ip_reach(frag, family, mtid, cb,
+ arg)
+ == LSP_ITER_STOP)
+ return LSP_ITER_STOP;
+ }
return LSP_ITER_CONTINUE;
}
@@ -2251,7 +2279,7 @@ int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0)
return LSP_ITER_CONTINUE;
- /* Parse main LSP. */
+ /* Parse LSP */
if (lsp->tlvs) {
if (pseudo_lsp || mtid == ISIS_MT_IPV4_UNICAST) {
head = lsp->tlvs->oldstyle_reach.head;
@@ -2283,13 +2311,16 @@ int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
}
}
- /* Parse LSP fragments. */
- for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
- if (!frag->tlvs)
- continue;
+ /* Parse LSP fragments if it not a fragment itself. */
+ if (!LSP_FRAGMENT(lsp->hdr.lsp_id))
+ for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ if (!frag->tlvs)
+ continue;
- isis_lsp_iterate_is_reach(frag, mtid, cb, arg);
- }
+ if (isis_lsp_iterate_is_reach(frag, mtid, cb, arg)
+ == LSP_ITER_STOP)
+ return LSP_ITER_STOP;
+ }
return LSP_ITER_CONTINUE;
}
diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c
index c024549fcc..f937bdf55c 100644
--- a/isisd/isis_mt.c
+++ b/isisd/isis_mt.c
@@ -515,6 +515,17 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
uint8_t *id, uint32_t metric,
struct isis_ext_subtlvs *ext)
{
+ /* Check if MT is enable for this area */
+ if (!area_is_mt(area)) {
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as te-style neighbor (MT disable)",
+ area->area_tag, sysid_print(id), LSP_PSEUDO_ID(id));
+ isis_tlvs_add_extended_reach(tlvs, ISIS_MT_DISABLE, id, metric,
+ ext);
+ return;
+ }
+
+ /* Process Multi-Topology */
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
if (mt_set[i] == ISIS_MT_IPV4_UNICAST) {
diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h
index fd9ee133ca..2952a2f171 100644
--- a/isisd/isis_mt.h
+++ b/isisd/isis_mt.h
@@ -33,6 +33,8 @@
#define ISIS_MT_IPV6_MULTICAST 4
#define ISIS_MT_IPV6_MGMT 5
#define ISIS_MT_IPV6_DSTSRC 3996 /* FIXME: IANA */
+/* Use first Reserved Flag to indicate that there is no MT Topology active */
+#define ISIS_MT_DISABLE 4096
#define ISIS_MT_NAMES \
"<ipv4-unicast" \
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index f62a8d4813..20e4806525 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -567,6 +567,21 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-isisd:isis/instance/mpls-te/router-address-v6",
+ .cbs = {
+ .cli_show = cli_show_isis_mpls_te_router_addr_ipv6,
+ .destroy = isis_instance_mpls_te_router_address_ipv6_destroy,
+ .modify = isis_instance_mpls_te_router_address_ipv6_modify,
+ }
+ },
+ {
+ .xpath = "/frr-isisd:isis/instance/mpls-te/export",
+ .cbs = {
+ .cli_show = cli_show_isis_mpls_te_export,
+ .modify = isis_instance_mpls_te_export_modify,
+ },
+ },
+ {
.xpath = "/frr-isisd:isis/instance/segment-routing/enabled",
.cbs = {
.modify = isis_instance_segment_routing_enabled_modify,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index ee7904163c..96de64a68b 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -211,6 +211,11 @@ int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args);
int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args);
int isis_instance_mpls_te_router_address_destroy(
struct nb_cb_destroy_args *args);
+int isis_instance_mpls_te_router_address_ipv6_modify(
+ struct nb_cb_modify_args *args);
+int isis_instance_mpls_te_router_address_ipv6_destroy(
+ struct nb_cb_destroy_args *args);
+int isis_instance_mpls_te_export_modify(struct nb_cb_modify_args *args);
int lib_interface_isis_create(struct nb_cb_create_args *args);
int lib_interface_isis_destroy(struct nb_cb_destroy_args *args);
int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args);
@@ -463,6 +468,11 @@ void cli_show_isis_mpls_te(struct vty *vty, const struct lyd_node *dnode,
void cli_show_isis_mpls_te_router_addr(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
+void cli_show_isis_mpls_te_router_addr_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
+void cli_show_isis_mpls_te_export(struct vty *vty, const struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_def_origin_ipv4(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 3674d69376..019c26687b 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -33,6 +33,7 @@
#include "lib_errors.h"
#include "vrf.h"
#include "ldp_sync.h"
+#include "link_state.h"
#include "isisd/isisd.h"
#include "isisd/isis_nb.h"
@@ -51,6 +52,7 @@
#include "isisd/isis_redist.h"
#include "isisd/isis_ldp_sync.h"
#include "isisd/isis_dr.h"
+#include "isisd/isis_zebra.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters");
DEFINE_MTYPE_STATIC(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
@@ -1827,12 +1829,19 @@ int isis_instance_mpls_te_create(struct nb_cb_create_args *args)
new->inter_as = off;
new->interas_areaid.s_addr = 0;
new->router_id.s_addr = 0;
+ new->ted = ls_ted_new(1, "ISIS", 0);
+ if (!new->ted)
+ zlog_warn("Unable to create Link State Data Base");
area->mta = new;
} else {
area->mta->status = enable;
}
+ /* Initialize Link State Database */
+ if (area->mta->ted)
+ isis_te_init_ted(area);
+
/* Update Extended TLVs according to Interface link parameters */
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
isis_link_params_update(circuit, circuit->interface);
@@ -1858,6 +1867,9 @@ int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args)
else
return NB_OK;
+ /* Remove Link State Database */
+ ls_ted_del_all(area->mta->ted);
+
/* Flush LSP if circuit engage */
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
if (!IS_EXT_TE(circuit->ext))
@@ -1930,6 +1942,88 @@ int isis_instance_mpls_te_router_address_destroy(
}
/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/router-address-v6
+ */
+int isis_instance_mpls_te_router_address_ipv6_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct in6_addr value;
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ /* only proceed if MPLS-TE is enabled */
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ yang_dnode_get_ipv6(&value, args->dnode, NULL);
+ /* Update Area IPv6 Router ID if different */
+ if (!IPV6_ADDR_SAME(&area->mta->router_id_ipv6, &value)) {
+ IPV6_ADDR_COPY(&area->mta->router_id_ipv6, &value);
+
+ /* And re-schedule LSP update */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+ }
+
+ return NB_OK;
+}
+
+int isis_instance_mpls_te_router_address_ipv6_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ /* only proceed if MPLS-TE is enabled */
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ /* Reset Area Router ID */
+ IPV6_ADDR_COPY(&area->mta->router_id_ipv6, &in6addr_any);
+
+ /* And re-schedule LSP update */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/export
+ */
+int isis_instance_mpls_te_export_modify(struct nb_cb_modify_args *args)
+{
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ /* only proceed if MPLS-TE is enabled */
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ area->mta->export = yang_dnode_get_bool(args->dnode, NULL);
+ if (area->mta->export) {
+ if (IS_DEBUG_EVENTS)
+ zlog_debug("MPLS-TE: Enabled Link State export");
+ if (isis_zebra_ls_register(true) != 0)
+ zlog_warn("Unable to register Link State");
+ } else {
+ if (IS_DEBUG_EVENTS)
+ zlog_debug("MPLS-TE: Disable Link State export");
+ if (isis_zebra_ls_register(false) != 0)
+ zlog_warn("Unable to register Link State");
+ }
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-isisd:isis/instance/segment-routing/enabled
*/
int isis_instance_segment_routing_enabled_modify(
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 7256fcbbc7..0814f3eea0 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -1971,6 +1971,11 @@ int send_hello(struct isis_circuit *circuit, int level)
if (circuit->ipv6_router && circuit->ipv6_link)
isis_tlvs_add_ipv6_addresses(tlvs, circuit->ipv6_link);
+ /* RFC6119 section 4 define TLV 233 to provide Global IPv6 address */
+ if (circuit->ipv6_router && circuit->ipv6_non_link)
+ isis_tlvs_add_global_ipv6_addresses(tlvs,
+ circuit->ipv6_non_link);
+
if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer,
circuit->pad_hellos, false)) {
isis_free_tlvs(tlvs);
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index bf0079d814..764a0b0cd3 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -145,8 +145,8 @@ void adjinfo2nexthop(int family, struct list *nexthops,
}
break;
case AF_INET6:
- for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
- ip.ipv6 = adj->ipv6_addresses[i];
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ ip.ipv6 = adj->ll_ipv6_addrs[i];
if (!nexthoplookup(nexthops, AF_INET6, &ip,
adj->circuit->interface->ifindex)) {
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
index c530eb9169..3590044f85 100644
--- a/isisd/isis_snmp.c
+++ b/isisd/isis_snmp.c
@@ -37,6 +37,7 @@
#include "smux.h"
#include "libfrr.h"
#include "lib/version.h"
+#include "lib/zclient.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
@@ -1186,14 +1187,13 @@ static int isis_snmp_adj_helper(struct isis_adjacency *adj, int data_id,
break;
case ISIS_SNMP_ADJ_DATA_IP_ADDR:
- if (data_off
- >= (adj->ipv4_address_count + adj->ipv6_address_count))
+ if (data_off >= (adj->ipv4_address_count + adj->ll_ipv6_count))
return 0;
if (data_off >= adj->ipv4_address_count) {
- data = (uint8_t *)&adj->ipv6_addresses
+ data = (uint8_t *)&adj->ll_ipv6_addrs
[data_off - adj->ipv4_address_count];
- data_len = sizeof(adj->ipv6_addresses[0]);
+ data_len = sizeof(adj->ll_ipv6_addrs[0]);
} else {
data = (uint8_t *)&adj->ipv4_addresses[data_off];
data_len = sizeof(adj->ipv4_addresses[0]);
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 54e31f0040..18a727adde 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -661,10 +661,10 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup,
nexthop.ipv4 = adj->ipv4_addresses[0];
break;
case AF_INET6:
- if (!circuit->ipv6_router || !adj->ipv6_address_count)
+ if (!circuit->ipv6_router || !adj->ll_ipv6_count)
return;
- nexthop.ipv6 = adj->ipv6_addresses[0];
+ nexthop.ipv6 = adj->ll_ipv6_addrs[0];
break;
default:
flog_err(EC_LIB_DEVELOPMENT,
@@ -880,12 +880,14 @@ static int sr_adj_state_change(struct isis_adjacency *adj)
*
* @param adj IS-IS Adjacency
* @param family Inet Family (IPv4 or IPv6)
+ * @param global Indicate if it concerns the Local or Global IPv6 addresses
*
* @return 0
*/
-static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family)
+static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
- if (!adj->circuit->area->srdb.enabled)
+ if (!adj->circuit->area->srdb.enabled || global)
return 0;
sr_adj_sid_add(adj, family);
@@ -899,15 +901,17 @@ static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family)
*
* @param adj IS-IS Adjacency
* @param family Inet Family (IPv4 or IPv6)
+ * @param global Indicate if it concerns the Local or Global IPv6 addresses
*
* @return 0
*/
-static int sr_adj_ip_disabled(struct isis_adjacency *adj, int family)
+static int sr_adj_ip_disabled(struct isis_adjacency *adj, int family,
+ bool global)
{
struct sr_adjacency *sra;
struct listnode *node, *nnode;
- if (!adj->circuit->area->srdb.enabled)
+ if (!adj->circuit->area->srdb.enabled || global)
return 0;
for (ALL_LIST_ELEMENTS(adj->adj_sids, node, nnode, sra))
@@ -1148,7 +1152,7 @@ int isis_sr_start(struct isis_area *area)
for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
if (adj->ipv4_address_count > 0)
sr_adj_sid_add(adj, AF_INET);
- if (adj->ipv6_address_count > 0)
+ if (adj->ll_ipv6_count > 0)
sr_adj_sid_add(adj, AF_INET6);
}
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 8daa2b36bf..93be70036e 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -43,6 +43,8 @@
#include "sockunion.h"
#include "network.h"
#include "sbuf.h"
+#include "link_state.h"
+#include "lib/json.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
@@ -57,6 +59,8 @@
#include "isisd/isis_csm.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_spf.h"
+#include "isisd/isis_tlvs.h"
+#include "isisd/isis_mt.h"
#include "isisd/isis_te.h"
#include "isisd/isis_zebra.h"
@@ -82,14 +86,14 @@ void isis_link_params_update(struct isis_circuit *circuit,
if ((ifp == NULL) || (circuit->state != C_STATE_UP))
return;
- zlog_debug("TE(%s): Update circuit parameters for interface %s",
- circuit->area->area_tag, ifp->name);
+ te_debug("ISIS-TE(%s): Update circuit parameters for interface %s",
+ circuit->area->area_tag, ifp->name);
/* Check if MPLS TE Circuit context has not been already created */
if (circuit->ext == NULL) {
circuit->ext = isis_alloc_ext_subtlvs();
- zlog_debug(" |- Allocated new Ext-subTLVs for interface %s",
- ifp->name);
+ te_debug(" |- Allocated new Ext-subTLVs for interface %s",
+ ifp->name);
}
ext = circuit->ext;
@@ -113,19 +117,6 @@ void isis_link_params_update(struct isis_circuit *circuit,
} else
UNSET_SUBTLV(ext, EXT_LOCAL_ADDR);
- /* Same for Remote IPv4 address */
- if (circuit->circ_type == CIRCUIT_T_P2P) {
- struct isis_adjacency *adj = circuit->u.p2p.neighbor;
-
- if (adj && adj->adj_state == ISIS_ADJ_UP
- && adj->ipv4_address_count) {
- IPV4_ADDR_COPY(&ext->neigh_addr,
- &adj->ipv4_addresses[0]);
- SET_SUBTLV(ext, EXT_NEIGH_ADDR);
- }
- } else
- UNSET_SUBTLV(ext, EXT_NEIGH_ADDR);
-
/* If known, register local IPv6 addr from ip_addr list */
if (circuit->ipv6_non_link != NULL
&& listcount(circuit->ipv6_non_link) != 0) {
@@ -137,18 +128,12 @@ void isis_link_params_update(struct isis_circuit *circuit,
} else
UNSET_SUBTLV(ext, EXT_LOCAL_ADDR6);
- /* Same for Remote IPv6 address */
- if (circuit->circ_type == CIRCUIT_T_P2P) {
- struct isis_adjacency *adj = circuit->u.p2p.neighbor;
-
- if (adj && adj->adj_state == ISIS_ADJ_UP
- && adj->ipv6_address_count) {
- IPV6_ADDR_COPY(&ext->neigh_addr6,
- &adj->ipv6_addresses[0]);
- SET_SUBTLV(ext, EXT_NEIGH_ADDR6);
- }
- } else
- UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ /*
+ * Remote IPv4 and IPv6 addresses are now added in
+ * isis_mpls_te_adj_ip_enabled() to get the right IP address
+ * in particular for IPv6 to get the global IPv6 address and
+ * not the link-local IPv6 address.
+ */
if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) {
ext->max_bw = ifp->link_params->max_bw;
@@ -231,11 +216,11 @@ void isis_link_params_update(struct isis_circuit *circuit,
UNSET_SUBTLV(ext, EXT_RMT_AS);
UNSET_SUBTLV(ext, EXT_RMT_IP);
}
- zlog_debug(" |- New MPLS-TE link parameters status 0x%x",
- ext->status);
+ te_debug(" |- New MPLS-TE link parameters status 0x%x",
+ ext->status);
} else {
- zlog_debug(" |- Reset Extended subTLVs status 0x%x",
- ext->status);
+ te_debug(" |- Reset Extended subTLVs status 0x%x",
+ ext->status);
/* Reset TE subTLVs keeping SR one's */
if (IS_SUBTLV(ext, EXT_ADJ_SID))
ext->status = EXT_ADJ_SID;
@@ -248,29 +233,95 @@ void isis_link_params_update(struct isis_circuit *circuit,
return;
}
-static int isis_link_update_adj_hook(struct isis_adjacency *adj)
+static int isis_mpls_te_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
+ struct isis_circuit *circuit;
+ struct isis_ext_subtlvs *ext;
- struct isis_circuit *circuit = adj->circuit;
+ /* Sanity Check */
+ if (!adj || !adj->circuit)
+ return 0;
- /* Update MPLS TE Remote IP address parameter if possible */
- if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext))
+ circuit = adj->circuit;
+
+ /* Check that MPLS TE is enabled */
+ if (!IS_MPLS_TE(circuit->area->mta) || !circuit->ext)
return 0;
- /* IPv4 first */
- if (adj->ipv4_address_count > 0) {
- IPV4_ADDR_COPY(&circuit->ext->neigh_addr,
- &adj->ipv4_addresses[0]);
- SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR);
+ ext = circuit->ext;
+
+ /* Determine nexthop IP address */
+ switch (family) {
+ case AF_INET:
+ if (!circuit->ip_router || !adj->ipv4_address_count)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ else {
+ IPV4_ADDR_COPY(&ext->neigh_addr,
+ &adj->ipv4_addresses[0]);
+ SET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ }
+ break;
+ case AF_INET6:
+ if (!global)
+ return 0;
+
+ if (!circuit->ipv6_router || !adj->global_ipv6_count)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ else {
+ IPV6_ADDR_COPY(&ext->neigh_addr6,
+ &adj->global_ipv6_addrs[0]);
+ SET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ }
+ break;
+ default:
+ return 0;
}
- /* and IPv6 */
- if (adj->ipv6_address_count > 0) {
- IPV6_ADDR_COPY(&circuit->ext->neigh_addr6,
- &adj->ipv6_addresses[0]);
- SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR6);
+ /* Update LSP */
+ lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
+
+ return 0;
+}
+
+static int isis_mpls_te_adj_ip_disabled(struct isis_adjacency *adj, int family,
+ bool global)
+{
+ struct isis_circuit *circuit;
+ struct isis_ext_subtlvs *ext;
+
+ /* Sanity Check */
+ if (!adj || !adj->circuit || !adj->circuit->ext)
+ return 0;
+
+ circuit = adj->circuit;
+
+ /* Check that MPLS TE is enabled */
+ if (!IS_MPLS_TE(circuit->area->mta) || !circuit->ext)
+ return 0;
+
+ ext = circuit->ext;
+
+ /* Update MPLS TE IP address parameters if possible */
+ if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(ext))
+ return 0;
+
+ /* Determine nexthop IP address */
+ switch (family) {
+ case AF_INET:
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ break;
+ case AF_INET6:
+ if (global)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ break;
+ default:
+ return 0;
}
+ /* Update LSP */
+ lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
+
return 0;
}
@@ -299,9 +350,908 @@ int isis_mpls_te_update(struct interface *ifp)
return rc;
}
+
+/**
+ * Export Link State information to consumer daemon through ZAPI Link State
+ * Opaque Message.
+ *
+ * @param type Type of Link State Element i.e. Vertex, Edge or Subnet
+ * @param link_state Pointer to Link State Vertex, Edge or Subnet
+ *
+ * @return 0 if success, -1 otherwise
+ */
+static int isis_te_export(uint8_t type, void *link_state)
+{
+ struct ls_message msg = {};
+ int rc = 0;
+
+ switch (type) {
+ case LS_MSG_TYPE_NODE:
+ ls_vertex2msg(&msg, (struct ls_vertex *)link_state);
+ rc = ls_send_msg(zclient, &msg, NULL);
+ break;
+ case LS_MSG_TYPE_ATTRIBUTES:
+ ls_edge2msg(&msg, (struct ls_edge *)link_state);
+ rc = ls_send_msg(zclient, &msg, NULL);
+ break;
+ case LS_MSG_TYPE_PREFIX:
+ ls_subnet2msg(&msg, (struct ls_subnet *)link_state);
+ rc = ls_send_msg(zclient, &msg, NULL);
+ break;
+ default:
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * Parse LSP and build corresponding vertex. If vertex doesn't exist in the
+ * Link State Database it is created otherwise updated.
+ *
+ * @param ted Traffic Engineering Link State Database
+ * @param lsp IS-IS Link State PDU
+ *
+ * @return Link State Vertex or NULL in case of error
+ */
+static struct ls_vertex *lsp_to_vertex(struct ls_ted *ted, struct isis_lsp *lsp)
+{
+ struct ls_vertex *vertex = NULL;
+ struct ls_node *old, lnode = {};
+ struct isis_tlvs *tlvs;
+ const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
+
+ /* Sanity check */
+ if (!ted || !lsp)
+ return NULL;
+
+ /* Compute Link State Node ID from IS-IS sysID ... */
+ if (lsp->level == ISIS_LEVEL1)
+ lnode.adv.origin = ISIS_L1;
+ else
+ lnode.adv.origin = ISIS_L2;
+ memcpy(&lnode.adv.id.iso.sys_id, &lsp->hdr.lsp_id, ISIS_SYS_ID_LEN);
+ lnode.adv.id.iso.level = lsp->level;
+ /* ... and search the corresponding vertex */
+ vertex = ls_find_vertex_by_id(ted, lnode.adv);
+ /* Create a new one if not found */
+ if (!vertex) {
+ old = ls_node_new(lnode.adv, inaddr_any, in6addr_any);
+ old->type = STANDARD;
+ vertex = ls_vertex_add(ted, old);
+ }
+ old = vertex->node;
+ te_debug(" |- %s Vertex (%" PRIu64 ") for node %s",
+ vertex->status == NEW ? "Create" : "Found", vertex->key,
+ print_sys_hostname(old->adv.id.iso.sys_id));
+
+ /* Fulfill Link State Node information */
+ tlvs = lsp->tlvs;
+ if (tlvs) {
+ if (tlvs->te_router_id) {
+ IPV4_ADDR_COPY(&lnode.router_id, tlvs->te_router_id);
+ SET_FLAG(lnode.flags, LS_NODE_ROUTER_ID);
+ }
+ if (tlvs->te_router_id_ipv6) {
+ IPV6_ADDR_COPY(&lnode.router_id6,
+ tlvs->te_router_id_ipv6);
+ SET_FLAG(lnode.flags, LS_NODE_ROUTER_ID6);
+ }
+ if (tlvs->hostname) {
+ memcpy(&lnode.name, tlvs->hostname, MAX_NAME_LENGTH);
+ SET_FLAG(lnode.flags, LS_NODE_NAME);
+ }
+ if (tlvs->router_cap) {
+ struct isis_router_cap *cap = tlvs->router_cap;
+
+ if (cap->srgb.lower_bound != 0
+ && cap->srgb.range_size != 0) {
+ SET_FLAG(lnode.flags, LS_NODE_SR);
+ lnode.srgb.flag = cap->srgb.flags;
+ lnode.srgb.lower_bound = cap->srgb.lower_bound;
+ lnode.srgb.range_size = cap->srgb.range_size;
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+ lnode.algo[i] = cap->algo[i];
+ }
+
+ if (cap->srlb.lower_bound != 0
+ && cap->srlb.range_size != 0) {
+ lnode.srlb.lower_bound = cap->srlb.lower_bound;
+ lnode.srlb.range_size = cap->srlb.range_size;
+ SET_FLAG(lnode.flags, LS_NODE_SRLB);
+ }
+ if (cap->msd != 0) {
+ lnode.msd = cap->msd;
+ SET_FLAG(lnode.flags, LS_NODE_MSD);
+ }
+ }
+ }
+
+ /* Update Link State Node information */
+ if (!ls_node_same(old, &lnode)) {
+ te_debug(" |- Update Link State Node information");
+ memcpy(old, &lnode, sizeof(struct ls_node));
+ if (vertex->status != NEW)
+ vertex->status = UPDATE;
+ }
+
+ /* Set self TED vertex if LSP corresponds to the own router */
+ if (lsp->own_lsp)
+ ted->self = vertex;
+
+ return vertex;
+}
+
+/**
+ * Get Link State Edge from Link State Attributes in TE Database.
+ * Edge structure is dynamically allocated and fulfill with Link State
+ * Attributes if not found.
+ *
+ * @param ted Link State Database
+ * @param attr Link State Attributes
+ *
+ * @return New Link State Edge if success, NULL otherwise
+ */
+static struct ls_edge *get_edge(struct ls_ted *ted, struct ls_attributes *attr)
+{
+ struct ls_edge *edge;
+ struct ls_standard *std;
+ uint64_t key = 0;
+
+ /* Check parameters */
+ if (!ted || !attr)
+ return NULL;
+
+ std = &attr->standard;
+
+ /* Compute keys in function of local address (IPv4/v6) or identifier */
+ if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
+ key = ((uint64_t)ntohl(std->local.s_addr)) & 0xffffffff;
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
+ key = ((uint64_t)ntohl(std->local6.s6_addr32[2]) << 32
+ | (uint64_t)ntohl(std->local6.s6_addr32[3]));
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
+ key = ((uint64_t)std->remote_id << 32)
+ | (((uint64_t)std->local_id) & 0xffffffff);
+ else
+ key = 0;
+
+ /* Stop here if we don't got a valid key */
+ if (key == 0)
+ return NULL;
+
+ /* Get corresponding Edge by key from Link State Data Base */
+ edge = ls_find_edge_by_key(ted, key);
+
+ /* and create new one if not exist */
+ if (!edge) {
+ edge = ls_edge_add(ted, attr);
+ /*
+ * Edge could be Null if no local ID is found in Attributes.
+ * Stop the processing as without any local ID it is not
+ * possible to store Edge in the TED.
+ */
+ if (!edge)
+ return NULL;
+ }
+
+ if (CHECK_FLAG(edge->attributes->flags, LS_ATTR_LOCAL_ADDR))
+ te_debug(" |- %s Edge (%" PRIu64
+ ") from Extended Reach. %pI4",
+ edge->status == NEW ? "Create" : "Found", edge->key,
+ &attr->standard.local);
+ else if (CHECK_FLAG(edge->attributes->flags, LS_ATTR_LOCAL_ADDR6))
+ te_debug(" |- %s Edge (%" PRIu64
+ ") from Extended Reach. %pI6",
+ edge->status == NEW ? "Create" : "Found", edge->key,
+ &attr->standard.local6);
+ else
+ te_debug(" |- %s Edge (%" PRIu64 ")",
+ edge->status == NEW ? "Create" : "Found", edge->key);
+
+ return edge;
+}
+
+/**
+ * Get Link State Attributes from IS-IS Sub-TLVs. Structure is dynamically
+ * allocated and should be free once not use anymore.
+ *
+ * @param adv Link State Node ID
+ * @param tlvs IS-IS Sub TLVs
+ *
+ * @return New Link State attributes if success, NULL otherwise
+ */
+static struct ls_attributes *get_attributes(struct ls_node_id adv,
+ struct isis_ext_subtlvs *tlvs)
+{
+ struct ls_attributes *attr;
+ struct in_addr local = {.s_addr = INADDR_ANY};
+ struct in6_addr local6 = in6addr_any;
+ uint32_t local_id = 0;
+
+ /* Got Local identifier */
+ if (CHECK_FLAG(tlvs->status, EXT_LOCAL_ADDR))
+ local.s_addr = tlvs->local_addr.s_addr;
+
+ if (CHECK_FLAG(tlvs->status, EXT_LOCAL_ADDR6))
+ memcpy(&local6, &tlvs->local_addr6, IPV6_MAX_BYTELEN);
+
+ if (CHECK_FLAG(tlvs->status, EXT_LLRI))
+ local_id = tlvs->local_llri;
+
+ /* Create LS Attributes */
+ attr = ls_attributes_new(adv, local, local6, local_id);
+ if (!attr)
+ return NULL;
+
+ /* Browse sub-TLV and fulfill Link State Attributes */
+ if (CHECK_FLAG(tlvs->status, EXT_ADM_GRP)) {
+ attr->standard.admin_group = tlvs->adm_group;
+ SET_FLAG(attr->flags, LS_ATTR_ADM_GRP);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_LLRI)) {
+ attr->standard.local_id = tlvs->local_llri;
+ attr->standard.remote_id = tlvs->remote_llri;
+ SET_FLAG(attr->flags, LS_ATTR_LOCAL_ID);
+ SET_FLAG(attr->flags, LS_ATTR_NEIGH_ID);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_NEIGH_ADDR)) {
+ attr->standard.remote.s_addr = tlvs->neigh_addr.s_addr;
+ SET_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_NEIGH_ADDR6)) {
+ memcpy(&attr->standard.remote6, &tlvs->neigh_addr6,
+ IPV6_MAX_BYTELEN);
+ SET_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_MAX_BW)) {
+ attr->standard.max_bw = tlvs->max_bw;
+ SET_FLAG(attr->flags, LS_ATTR_MAX_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_MAX_RSV_BW)) {
+ attr->standard.max_rsv_bw = tlvs->max_rsv_bw;
+ SET_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_UNRSV_BW)) {
+ memcpy(&attr->standard.unrsv_bw, tlvs->unrsv_bw,
+ ISIS_SUBTLV_UNRSV_BW_SIZE);
+ SET_FLAG(attr->flags, LS_ATTR_UNRSV_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_TE_METRIC)) {
+ attr->standard.te_metric = tlvs->te_metric;
+ SET_FLAG(attr->flags, LS_ATTR_TE_METRIC);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_RMT_AS)) {
+ attr->standard.remote_as = tlvs->remote_as;
+ SET_FLAG(attr->flags, LS_ATTR_REMOTE_AS);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_RMT_IP)) {
+ attr->standard.remote_addr = tlvs->remote_ip;
+ SET_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_DELAY)) {
+ attr->extended.delay = tlvs->delay;
+ SET_FLAG(attr->flags, LS_ATTR_DELAY);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_MM_DELAY)) {
+ attr->extended.min_delay = tlvs->min_delay;
+ attr->extended.max_delay = tlvs->max_delay;
+ SET_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_DELAY_VAR)) {
+ attr->extended.jitter = tlvs->delay_var;
+ SET_FLAG(attr->flags, LS_ATTR_JITTER);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_PKT_LOSS)) {
+ attr->extended.pkt_loss = tlvs->pkt_loss;
+ SET_FLAG(attr->flags, LS_ATTR_PACKET_LOSS);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_AVA_BW)) {
+ attr->extended.ava_bw = tlvs->ava_bw;
+ SET_FLAG(attr->flags, LS_ATTR_AVA_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_RES_BW)) {
+ attr->extended.rsv_bw = tlvs->res_bw;
+ SET_FLAG(attr->flags, LS_ATTR_RSV_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_USE_BW)) {
+ attr->extended.used_bw = tlvs->use_bw;
+ SET_FLAG(attr->flags, LS_ATTR_USE_BW);
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_ADJ_SID)) {
+ struct isis_adj_sid *adj =
+ (struct isis_adj_sid *)tlvs->adj_sid.head;
+ int i;
+ for (; adj; adj = adj->next) {
+ i = adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG ? 1 : 0;
+ i += adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? 2 : 0;
+ attr->adj_sid[i].flags = adj->flags;
+ attr->adj_sid[i].weight = adj->weight;
+ attr->adj_sid[i].sid = adj->sid;
+ switch (i) {
+ case ADJ_PRI_IPV4:
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SID);
+ break;
+ case ADJ_BCK_IPV4:
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID);
+ break;
+ case ADJ_PRI_IPV6:
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SID6);
+ break;
+ case ADJ_BCK_IPV6:
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6);
+ break;
+ }
+ }
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_LAN_ADJ_SID)) {
+ struct isis_lan_adj_sid *ladj =
+ (struct isis_lan_adj_sid *)tlvs->lan_sid.head;
+ int i;
+ for (; ladj; ladj = ladj->next) {
+ i = ladj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG ? 1 : 0;
+ i += ladj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? 2 : 0;
+ attr->adj_sid[i].flags = ladj->flags;
+ attr->adj_sid[i].weight = ladj->weight;
+ attr->adj_sid[i].sid = ladj->sid;
+ memcpy(&attr->adj_sid[i].neighbor.sysid,
+ &ladj->neighbor_id, ISIS_SYS_ID_LEN);
+ switch (i) {
+ case ADJ_PRI_IPV4:
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SID);
+ break;
+ case ADJ_BCK_IPV4:
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID);
+ break;
+ case ADJ_PRI_IPV6:
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SID6);
+ break;
+ case ADJ_BCK_IPV6:
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6);
+ break;
+ }
+ }
+ }
+
+ return attr;
+}
+
+/**
+ * Parse Extended Reachability TLVs and create or update the corresponding
+ * Link State Edge and Attributes. Vertex connections are also updated if
+ * needed based on the remote IP address of the Edge and existing reverse Edge.
+ *
+ * @param id ID of Extended IS
+ * @param metric Metric of the link
+ * @param old_metric Boolean that indicate if it is an old metric (no TE)
+ * @param tlvs SubTlvs that contains TE information
+ * @param arg IS-IS TE argument (TED, Vertex, and export indication)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+static int lsp_to_edge_cb(const uint8_t *id, uint32_t metric, bool old_metric,
+ struct isis_ext_subtlvs *tlvs, void *arg)
+{
+ struct isis_te_args *args = (struct isis_te_args *)arg;
+ struct ls_vertex *vertex;
+ struct ls_edge *edge, *dst;
+ struct ls_attributes *attr;
+
+ te_debug(" |- Process Extended IS for %s", sysid_print(id));
+
+ /* Check parameters */
+ if (old_metric || !args || !tlvs)
+ return LSP_ITER_CONTINUE;
+
+ /* Initialize Link State Attributes */
+ vertex = args->vertex;
+ attr = get_attributes(vertex->node->adv, tlvs);
+ /*
+ * Attributes may be Null if no local ID has been found in the LSP.
+ * Stop processing here as without any local ID it is not possible to
+ * create corresponding Edge in the TED.
+ */
+ if (!attr)
+ return LSP_ITER_CONTINUE;
+
+ attr->metric = metric;
+
+ /* Get corresponding Edge from Link State Data Base */
+ edge = get_edge(args->ted, attr);
+ /*
+ * Edge could be Null if no local ID has been found in Attributes.
+ * Stop processing here as without any local ID it is not possible to
+ * create corresponding Edge in the TED.
+ */
+ if (!edge) {
+ ls_attributes_del(attr);
+ return LSP_ITER_CONTINUE;
+ }
+
+ /* Update Attribute fields if there are different */
+ if (edge->status != NEW) {
+ if (!ls_attributes_same(edge->attributes, attr)) {
+ te_debug(" |- Update Edge Attributes information");
+ ls_attributes_del(edge->attributes);
+ edge->attributes = attr;
+ edge->status = UPDATE;
+ } else {
+ if (edge->attributes != attr)
+ ls_attributes_del(attr);
+ edge->status = SYNC;
+ }
+ }
+
+ /* Try to update remote Link from remote address or reachability ID */
+ te_debug(" |- Link Edge (%" PRIu64 ") to destination vertex (%s)",
+ edge->key, print_sys_hostname(id));
+ dst = ls_find_edge_by_destination(args->ted, edge->attributes);
+ if (dst) {
+ /* Attach remote link if not set */
+ if (edge->source && dst->destination == NULL) {
+ vertex = edge->source;
+ if (vertex->incoming_edges)
+ listnode_add_sort_nodup(vertex->incoming_edges,
+ dst);
+ dst->destination = vertex;
+ }
+ /* and destination vertex to this edge if not set */
+ if (dst->source && edge->destination == NULL) {
+ vertex = dst->source;
+ if (vertex->incoming_edges)
+ listnode_add_sort_nodup(vertex->incoming_edges,
+ edge);
+ edge->destination = vertex;
+ }
+ } else {
+ /* Search dst. Vertex by Extended Reach. ID if not found */
+ if (edge->destination == NULL) {
+ vertex = ls_find_vertex_by_key(args->ted,
+ sysid_to_key(id));
+ if (vertex && vertex->incoming_edges)
+ listnode_add_sort_nodup(vertex->incoming_edges,
+ edge);
+ edge->destination = vertex;
+ }
+ }
+
+ /* Update status and Export Link State Edge if needed */
+ if (edge->status != SYNC) {
+ if (args->export)
+ isis_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
+ edge->status = SYNC;
+ }
+
+ return LSP_ITER_CONTINUE;
+}
+
+/**
+ * Parse Extended IP Reachability or MT IPv6 Reachability TLVs and create or
+ * update the corresponding Link State Subnet and Prefix.
+ *
+ * @param prefix Prefix associated to this subnet
+ * @param metric Metric of this prefix
+ * @param external Boolean to indicate if the prefix is external
+ * @param subtlvs Subtlvs if any (mostly Segment Routing ID)
+ * @param arg IS-IS TE argument (TED, Vertex, and export indication)
+ *
+ * @return 0 if success, -1 otherwise
+ */
+static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
+ bool external, struct isis_subtlvs *subtlvs,
+ void *arg)
+{
+ struct isis_te_args *args = (struct isis_te_args *)arg;
+ struct ls_vertex *vertex;
+ struct ls_subnet *subnet;
+ struct ls_prefix *ls_pref;
+ struct listnode *node;
+ struct ls_edge *edge;
+ struct ls_standard *std = NULL;
+ struct prefix p;
+
+ /* Sanity Check */
+ if (!args || !prefix)
+ return LSP_ITER_CONTINUE;
+
+ te_debug(" |- Process Extended %s Reachability %pFX",
+ prefix->family == AF_INET ? "IP" : "IPv6", prefix);
+
+ vertex = args->vertex;
+
+ /*
+ * Prefix with mask different from /32 or /128 are advertised by at
+ * least 2 nodes. To avoid subnet attached to undetermined vertex, and
+ * gives the possibility to send the information to client e.g. BGP for
+ * Link State advertisement, we adjust the prefix with the corresponding
+ * IP address of the belonging interface when it is available. Other
+ * prefixes are kept unchanged.
+ */
+ if (prefix->family == AF_INET && prefix->prefixlen < IPV4_MAX_BITLEN) {
+ std = NULL;
+ for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
+ if (!CHECK_FLAG(edge->attributes->flags,
+ LS_ATTR_LOCAL_ADDR))
+ continue;
+
+ p.u.prefix4 = edge->attributes->standard.local;
+ p.family = AF_INET;
+ p.prefixlen = prefix->prefixlen;
+ apply_mask_ipv4((struct prefix_ipv4 *)&p);
+ if (IPV4_ADDR_SAME(&p.u.prefix4, &prefix->u.prefix4)) {
+ std = &edge->attributes->standard;
+ break;
+ }
+ }
+ if (std)
+ p.u.prefix4 = std->local;
+
+ } else if (prefix->family == AF_INET6
+ && prefix->prefixlen < IPV6_MAX_BITLEN) {
+ std = NULL;
+ for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
+ if (!CHECK_FLAG(edge->attributes->flags,
+ LS_ATTR_LOCAL_ADDR6))
+ continue;
+
+ p.u.prefix6 = edge->attributes->standard.local6;
+ p.family = AF_INET6;
+ p.prefixlen = prefix->prefixlen;
+ apply_mask_ipv6((struct prefix_ipv6 *)&p);
+ if (IPV6_ADDR_SAME(&p.u.prefix6, &prefix->u.prefix6)) {
+ std = &edge->attributes->standard;
+ break;
+ }
+ }
+ if (std)
+ p.u.prefix6 = std->local6;
+ }
+ if (!std)
+ p = *prefix;
+ else
+ te_debug(" |- Adjust prefix %pFX with local address to: %pFX",
+ prefix, &p);
+
+ /* Search existing Subnet in TED ... */
+ subnet = ls_find_subnet(args->ted, p);
+ /* ... and create a new Subnet if not found */
+ if (!subnet) {
+ ls_pref = ls_prefix_new(vertex->node->adv, p);
+ subnet = ls_subnet_add(args->ted, ls_pref);
+ if (!subnet)
+ return LSP_ITER_CONTINUE;
+ }
+ ls_pref = subnet->ls_pref;
+
+ te_debug(" |- %s Subnet from prefix %pFX",
+ subnet->status == NEW ? "Create" : "Found", &p);
+
+ /* Update Metric */
+ if (!CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC)
+ || (ls_pref->metric != metric)) {
+ ls_pref->metric = metric;
+ SET_FLAG(ls_pref->flags, LS_PREF_METRIC);
+ if (subnet->status != NEW)
+ subnet->status = UPDATE;
+ } else {
+ if (subnet->status == ORPHAN)
+ subnet->status = SYNC;
+ }
+
+ /* Update Prefix SID if any */
+ if (subtlvs && subtlvs->prefix_sids.count != 0) {
+ struct isis_prefix_sid *psid;
+ struct ls_sid sr = {};
+
+ psid = (struct isis_prefix_sid *)subtlvs->prefix_sids.head;
+ sr.algo = psid->algorithm;
+ sr.sid_flag = psid->flags;
+ sr.sid = psid->value;
+
+ if (!CHECK_FLAG(ls_pref->flags, LS_PREF_SR)
+ || !memcmp(&ls_pref->sr, &sr, sizeof(struct ls_sid))) {
+ memcpy(&ls_pref->sr, &sr, sizeof(struct ls_sid));
+ SET_FLAG(ls_pref->flags, LS_PREF_SR);
+ if (subnet->status != NEW)
+ subnet->status = UPDATE;
+ } else {
+ if (subnet->status == ORPHAN)
+ subnet->status = SYNC;
+ }
+ } else {
+ if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
+ UNSET_FLAG(ls_pref->flags, LS_PREF_SR);
+ if (subnet->status != NEW)
+ subnet->status = UPDATE;
+ } else {
+ if (subnet->status == ORPHAN)
+ subnet->status = SYNC;
+ }
+ }
+
+ /* Update status and Export Link State Edge if needed */
+ if (subnet->status != SYNC) {
+ if (args->export)
+ isis_te_export(LS_MSG_TYPE_PREFIX, subnet);
+ subnet->status = SYNC;
+ }
+
+ return LSP_ITER_CONTINUE;
+}
+
+/**
+ * Parse ISIS LSP to fulfill the Link State Database
+ *
+ * @param ted Link State Database
+ * @param lsp ISIS Link State PDU
+ */
+static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
+{
+ struct ls_ted *ted;
+ struct ls_vertex *vertex;
+ struct ls_edge *edge;
+ struct ls_subnet *subnet;
+ struct listnode *node;
+ struct isis_te_args args;
+
+ /* Sanity Check */
+ if (!IS_MPLS_TE(mta) || !mta->ted || !lsp)
+ return;
+
+ ted = mta->ted;
+
+ te_debug("ISIS-TE(%s): Parse LSP %s", lsp->area->area_tag,
+ sysid_print(lsp->hdr.lsp_id));
+
+ /* First parse LSP to obtain the corresponding Vertex */
+ vertex = lsp_to_vertex(ted, lsp);
+ if (!vertex) {
+ zlog_warn("Unable to build Vertex from LSP %s. Abort!",
+ sysid_print(lsp->hdr.lsp_id));
+ return;
+ }
+
+ /* Check if Vertex has been modified */
+ if (vertex->status != SYNC) {
+ /* Vertex is out of sync: export it if requested */
+ if (IS_EXPORT_TE(mta))
+ isis_te_export(LS_MSG_TYPE_NODE, vertex);
+ vertex->status = SYNC;
+ }
+
+ /* Mark outgoing Edges and Subnets as ORPHAN to detect deletion */
+ for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge))
+ edge->status = ORPHAN;
+
+ for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
+ subnet->status = ORPHAN;
+
+ /* Process all Extended Reachability in LSP (all fragments) */
+ args.ted = ted;
+ args.vertex = vertex;
+ args.export = mta->export;
+ isis_lsp_iterate_is_reach(lsp, ISIS_MT_IPV4_UNICAST, lsp_to_edge_cb,
+ &args);
+
+ isis_lsp_iterate_is_reach(lsp, ISIS_MT_IPV6_UNICAST, lsp_to_edge_cb,
+ &args);
+
+ /* Process all Extended IP (v4 & v6) in LSP (all fragments) */
+ isis_lsp_iterate_ip_reach(lsp, AF_INET, ISIS_MT_IPV4_UNICAST,
+ lsp_to_subnet_cb, &args);
+ isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV6_UNICAST,
+ lsp_to_subnet_cb, &args);
+ isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV4_UNICAST,
+ lsp_to_subnet_cb, &args);
+
+ /* Clean remaining Orphan Edges or Subnets */
+ if (IS_EXPORT_TE(mta))
+ ls_vertex_clean(ted, vertex, zclient);
+ else
+ ls_vertex_clean(ted, vertex, NULL);
+}
+
+/**
+ * Delete Link State Database Vertex, Edge & Prefix that correspond to this
+ * ISIS Link State PDU
+ *
+ * @param ted Link State Database
+ * @param lsp ISIS Link State PDU
+ */
+static void isis_te_delete_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
+{
+ struct ls_ted *ted;
+ struct ls_vertex *vertex = NULL;
+ struct ls_node lnode = {};
+ struct ls_edge *edge;
+ struct ls_subnet *subnet;
+ struct listnode *nnode, *node;
+
+ /* Sanity Check */
+ if (!IS_MPLS_TE(mta) || !mta->ted || !lsp)
+ return;
+
+ te_debug("ISIS-TE(%s): Delete Link State TED objects from LSP %s",
+ lsp->area->area_tag, sysid_print(lsp->hdr.lsp_id));
+
+ /* Compute Link State Node ID from IS-IS sysID ... */
+ if (lsp->level == ISIS_LEVEL1)
+ lnode.adv.origin = ISIS_L1;
+ else
+ lnode.adv.origin = ISIS_L2;
+ memcpy(&lnode.adv.id.iso.sys_id, &lsp->hdr.lsp_id, ISIS_SYS_ID_LEN);
+ lnode.adv.id.iso.level = lsp->level;
+ ted = mta->ted;
+ /* ... and search the corresponding vertex */
+ vertex = ls_find_vertex_by_id(ted, lnode.adv);
+ if (!vertex)
+ return;
+
+ te_debug(" |- Delete Vertex %s", vertex->node->name);
+
+ /*
+ * We can't use the ls_vertex_del_all() function if export TE is set,
+ * as we must first advertise the client daemons of each removal.
+ */
+ /* Remove outgoing Edges */
+ for (ALL_LIST_ELEMENTS(vertex->outgoing_edges, node, nnode, edge)) {
+ if (IS_EXPORT_TE(mta)) {
+ edge->status = DELETE;
+ isis_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
+ }
+ ls_edge_del_all(ted, edge);
+ }
+
+ /* Disconnect incoming Edges */
+ for (ALL_LIST_ELEMENTS(vertex->incoming_edges, node, nnode, edge)) {
+ ls_disconnect(vertex, edge, false);
+ if (edge->source == NULL) {
+ if (IS_EXPORT_TE(mta)) {
+ edge->status = DELETE;
+ isis_te_export(LS_MSG_TYPE_ATTRIBUTES, edge);
+ }
+ ls_edge_del_all(ted, edge);
+ }
+ }
+
+ /* Remove subnets */
+ for (ALL_LIST_ELEMENTS(vertex->prefixes, node, nnode, subnet)) {
+ if (IS_EXPORT_TE(mta)) {
+ subnet->status = DELETE;
+ isis_te_export(LS_MSG_TYPE_PREFIX, subnet);
+ }
+ ls_subnet_del_all(ted, subnet);
+ }
+
+ /* Then remove Link State Node */
+ if (IS_EXPORT_TE(mta)) {
+ vertex->status = DELETE;
+ isis_te_export(LS_MSG_TYPE_NODE, vertex);
+ }
+ ls_node_del(vertex->node);
+
+ /* Finally, remove Vertex */
+ ls_vertex_del(ted, vertex);
+}
+
+/**
+ * Process ISIS LSP according to the event to add, update or remove
+ * corresponding vertex, edge and prefix in the Link State database.
+ * Since LSP could be fragmented, the function starts by searching the root LSP
+ * to retrieve the complete LSP, including eventual fragment before processing
+ * all of them.
+ *
+ * @param lsp ISIS Link State PDU
+ * @param event LSP event: ADD, UPD, INC & DEL (TICK are ignored)
+ *
+ */
+void isis_te_lsp_event(struct isis_lsp *lsp, enum lsp_event event)
+{
+ struct isis_area *area;
+ struct isis_lsp *lsp0;
+
+ /* Sanity check */
+ if (!lsp || !lsp->area)
+ return;
+
+ area = lsp->area;
+ if (!IS_MPLS_TE(area->mta))
+ return;
+
+ /* Adjust LSP0 in case of fragment */
+ if (LSP_FRAGMENT(lsp->hdr.lsp_id))
+ lsp0 = lsp->lspu.zero_lsp;
+ else
+ lsp0 = lsp;
+
+ /* Then process event */
+ switch (event) {
+ case LSP_ADD:
+ case LSP_UPD:
+ case LSP_INC:
+ isis_te_parse_lsp(area->mta, lsp0);
+ break;
+ case LSP_DEL:
+ isis_te_delete_lsp(area->mta, lsp0);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Send the whole Link State Traffic Engineering Database to the consumer that
+ * request it through a ZAPI Link State Synchronous Opaque Message.
+ *
+ * @param info ZAPI Opaque message
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int isis_te_sync_ted(struct zapi_opaque_reg_info dst)
+{
+ struct listnode *node, *inode;
+ struct isis *isis;
+ struct isis_area *area;
+ struct mpls_te_area *mta;
+ int rc = -1;
+
+ te_debug("ISIS-TE(%s): Received TED synchro from client %d", __func__,
+ dst.proto);
+ /* For each area, send TED if TE distribution is enabled */
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ mta = area->mta;
+ if (IS_MPLS_TE(mta) && IS_EXPORT_TE(mta)) {
+ te_debug(" |- Export TED from area %s",
+ area->area_tag);
+ rc = ls_sync_ted(mta->ted, zclient, &dst);
+ if (rc != 0)
+ return rc;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Initialize the Link State database from the LSP already stored for this area
+ *
+ * @param area ISIS area
+ */
+void isis_te_init_ted(struct isis_area *area)
+{
+ struct isis_lsp *lsp;
+
+ /* Iterate over all lsp. */
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++)
+ frr_each (lspdb, &area->lspdb[level - 1], lsp)
+ isis_te_parse_lsp(area->mta, lsp);
+}
+
/* Followings are vty command functions */
#ifndef FABRICD
+static void show_router_id(struct vty *vty, struct isis_area *area)
+{
+ bool no_match = true;
+
+ vty_out(vty, "Area %s:\n", area->area_tag);
+ if (area->mta->router_id.s_addr != 0) {
+ vty_out(vty, " MPLS-TE IPv4 Router-Address: %pI4\n",
+ &area->mta->router_id);
+ no_match = false;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED(&area->mta->router_id_ipv6)) {
+ vty_out(vty, " MPLS-TE IPv6 Router-Address: %pI6\n",
+ &area->mta->router_id_ipv6);
+ no_match = false;
+ }
+ if (no_match)
+ vty_out(vty, " N/A\n");
+}
+
DEFUN(show_isis_mpls_te_router,
show_isis_mpls_te_router_cmd,
"show " PROTO_NAME " [vrf <NAME|all>] mpls-te router",
@@ -331,15 +1281,7 @@ DEFUN(show_isis_mpls_te_router,
if (!IS_MPLS_TE(area->mta))
continue;
- vty_out(vty, "Area %s:\n",
- area->area_tag);
- if (ntohs(area->mta->router_id.s_addr)
- != 0)
- vty_out(vty,
- " MPLS-TE Router-Address: %pI4\n",
- &area->mta->router_id);
- else
- vty_out(vty, " N/A\n");
+ show_router_id(vty, area);
}
}
return 0;
@@ -352,13 +1294,7 @@ DEFUN(show_isis_mpls_te_router,
if (!IS_MPLS_TE(area->mta))
continue;
- vty_out(vty, "Area %s:\n", area->area_tag);
- if (ntohs(area->mta->router_id.s_addr) != 0)
- vty_out(vty,
- " MPLS-TE Router-Address: %pI4\n",
- &area->mta->router_id);
- else
- vty_out(vty, " N/A\n");
+ show_router_id(vty, area);
}
}
}
@@ -528,7 +1464,308 @@ DEFUN (show_isis_mpls_te_interface,
return CMD_SUCCESS;
}
-#endif
+
+/**
+ * Search Vertex in TED that corresponds to the given string that represent
+ * the ISO system ID in the forms <systemid/hostname>[.<pseudo-id>-<framenent>]
+ *
+ * @param ted Link State Database
+ * @param id ISO System ID
+ * @param isis Main reference to the isis daemon
+ *
+ * @return Vertex if found, NULL otherwise
+ */
+static struct ls_vertex *vertex_for_arg(struct ls_ted *ted, const char *id,
+ struct isis *isis)
+{
+ char sysid[255] = {0};
+ uint8_t number[3];
+ const char *pos;
+ uint8_t lspid[ISIS_SYS_ID_LEN + 2] = {0};
+ struct isis_dynhn *dynhn;
+ uint64_t key = 0;
+
+ if (!id)
+ return NULL;
+
+ /*
+ * extract fragment and pseudo id from the string argv
+ * in the forms:
+ * (a) <systemid/hostname>.<pseudo-id>-<framenent> or
+ * (b) <systemid/hostname>.<pseudo-id> or
+ * (c) <systemid/hostname> or
+ * Where systemid is in the form:
+ * xxxx.xxxx.xxxx
+ */
+ strlcpy(sysid, id, sizeof(sysid));
+ if (strlen(id) > 3) {
+ pos = id + strlen(id) - 3;
+ if (strncmp(pos, "-", 1) == 0) {
+ memcpy(number, ++pos, 2);
+ lspid[ISIS_SYS_ID_LEN + 1] =
+ (uint8_t)strtol((char *)number, NULL, 16);
+ pos -= 4;
+ if (strncmp(pos, ".", 1) != 0)
+ return NULL;
+ }
+ if (strncmp(pos, ".", 1) == 0) {
+ memcpy(number, ++pos, 2);
+ lspid[ISIS_SYS_ID_LEN] =
+ (uint8_t)strtol((char *)number, NULL, 16);
+ sysid[pos - id - 1] = '\0';
+ }
+ }
+
+ /*
+ * Try to find the lsp-id if the argv
+ * string is in
+ * the form
+ * hostname.<pseudo-id>-<fragment>
+ */
+ if (sysid2buff(lspid, sysid)) {
+ key = sysid_to_key(lspid);
+ } else if ((dynhn = dynhn_find_by_name(isis, sysid))) {
+ memcpy(lspid, dynhn->id, ISIS_SYS_ID_LEN);
+ key = sysid_to_key(lspid);
+ } else if (strncmp(cmd_hostname_get(), sysid, 15) == 0) {
+ memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN);
+ key = sysid_to_key(lspid);
+ }
+
+ if (key == 0)
+ return NULL;
+
+ return ls_find_vertex_by_key(ted, key);
+}
+
+/**
+ * Show Link State Traffic Engineering Database extracted from IS-IS LSP.
+ *
+ * @param vty VTY output console
+ * @param argv Command line argument
+ * @param argc Number of command line argument
+ * @param ted Traffic Engineering Database
+ * @param isis isis Main reference to the isis daemon
+ *
+ * @return Command Success if OK, Command Warning otherwise
+ */
+static int show_ted(struct vty *vty, struct cmd_token *argv[], int argc,
+ struct isis_area *area, struct isis *isis)
+{
+ int idx;
+ char *id;
+ struct in_addr ip_addr;
+ struct in6_addr ip6_addr;
+ struct prefix pref;
+ struct ls_ted *ted;
+ struct ls_vertex *vertex;
+ struct ls_edge *edge;
+ struct ls_subnet *subnet;
+ uint64_t key;
+ bool detail = false;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
+
+ if (!IS_MPLS_TE(area->mta) || !area->mta->ted) {
+ vty_out(vty, "MPLS-TE is disabled for Area %s\n",
+ area->area_tag ? area->area_tag : "null");
+ return CMD_SUCCESS;
+ }
+
+ ted = area->mta->ted;
+
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty, "Area %s:\n",
+ area->area_tag ? area->area_tag : "null");
+
+ if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "detail"))
+ detail = true;
+
+ idx = 4;
+ if (argv_find(argv, argc, "vertex", &idx)) {
+ /* Show Vertex */
+ id = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg
+ : NULL;
+ if (!id)
+ vertex = NULL;
+ else if (!strncmp(id, "self", 4))
+ vertex = ted->self;
+ else {
+ vertex = vertex_for_arg(ted, id, isis);
+ if (!vertex) {
+ vty_out(vty, "No vertex found for ID %s\n", id);
+ return CMD_WARNING;
+ }
+ }
+
+ if (vertex)
+ ls_show_vertex(vertex, vty, json, detail);
+ else
+ ls_show_vertices(ted, vty, json, detail);
+
+ } else if (argv_find(argv, argc, "edge", &idx)) {
+ /* Show Edge */
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ if (!inet_pton(AF_INET, argv[idx]->arg, &ip_addr)) {
+ vty_out(vty,
+ "Specified Edge ID %s is invalid\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Edge from the Link State Database */
+ key = ((uint64_t)ntohl(ip_addr.s_addr)) & 0xffffffff;
+ edge = ls_find_edge_by_key(ted, key);
+ if (!edge) {
+ vty_out(vty, "No edge found for ID %pI4\n",
+ &ip_addr);
+ return CMD_WARNING;
+ }
+ } else if (argv_find(argv, argc, "X:X::X:X", &idx)) {
+ if (!inet_pton(AF_INET6, argv[idx]->arg, &ip6_addr)) {
+ vty_out(vty,
+ "Specified Edge ID %s is invalid\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Edge from the Link State Database */
+ key = (uint64_t)ntohl(ip6_addr.s6_addr32[3])
+ | ((uint64_t)ntohl(ip6_addr.s6_addr32[2]) << 32);
+ edge = ls_find_edge_by_key(ted, key);
+ if (!edge) {
+ vty_out(vty, "No edge found for ID %pI6\n",
+ &ip6_addr);
+ return CMD_WARNING;
+ }
+ } else
+ edge = NULL;
+
+ if (edge)
+ ls_show_edge(edge, vty, json, detail);
+ else
+ ls_show_edges(ted, vty, json, detail);
+
+ } else if (argv_find(argv, argc, "subnet", &idx)) {
+ /* Show Subnet */
+ if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
+ if (!str2prefix(argv[idx]->arg, &pref)) {
+ vty_out(vty, "Invalid prefix format %s\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Subnet from the Link State Database */
+ subnet = ls_find_subnet(ted, pref);
+ if (!subnet) {
+ vty_out(vty, "No subnet found for ID %pFX\n",
+ &pref);
+ return CMD_WARNING;
+ }
+ } else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) {
+ if (!str2prefix(argv[idx]->arg, &pref)) {
+ vty_out(vty, "Invalid prefix format %s\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Subnet from the Link State Database */
+ subnet = ls_find_subnet(ted, pref);
+ if (!subnet) {
+ vty_out(vty, "No subnet found for ID %pFX\n",
+ &pref);
+ return CMD_WARNING;
+ }
+ } else
+ subnet = NULL;
+
+ if (subnet)
+ ls_show_subnet(subnet, vty, json, detail);
+ else
+ ls_show_subnets(ted, vty, json, detail);
+
+ } else {
+ /* Show the complete TED */
+ ls_show_ted(ted, vty, json, detail);
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+
+ return CMD_SUCCESS;
+}
+
+/**
+ * Show ISIS Traffic Engineering Database
+ *
+ * @param vty VTY output console
+ * @param argv Command line argument
+ * @param argc Number of command line argument
+ * @param isis isis Main reference to the isis daemon
+
+ * @return Command Success if OK, Command Warning otherwise
+ */
+static int show_isis_ted(struct vty *vty, struct cmd_token *argv[], int argc,
+ struct isis *isis)
+{
+ struct listnode *node;
+ struct isis_area *area;
+ int rc;
+
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ rc = show_ted(vty, argv, argc, area, isis);
+ if (rc != CMD_SUCCESS)
+ return rc;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_isis_mpls_te_db,
+ show_isis_mpls_te_db_cmd,
+ "show " PROTO_NAME " [vrf <NAME|all>] mpls-te database [<vertex [WORD]|edge [A.B.C.D|X:X::X:X]|subnet [A.B.C.D/M|X:X::X:X/M]>] [detail|json]",
+ SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
+ "All VRFs\n"
+ MPLS_TE_STR
+ "MPLS-TE database\n"
+ "MPLS-TE Vertex\n"
+ "MPLS-TE Vertex ID (as an ISO ID, hostname or \"self\")\n"
+ "MPLS-TE Edge\n"
+ "MPLS-TE Edge ID (as an IPv4 address)\n"
+ "MPLS-TE Edge ID (as an IPv6 address)\n"
+ "MPLS-TE Subnet\n"
+ "MPLS-TE Subnet ID (as an IPv4 prefix)\n"
+ "MPLS-TE Subnet ID (as an IPv6 prefix)\n"
+ "Detailed information\n"
+ JSON_STR)
+{
+ int idx_vrf = 0;
+ const char *vrf_name = VRF_DEFAULT_NAME;
+ bool all_vrf = false;
+ struct listnode *node;
+ struct isis *isis;
+ int rc = CMD_WARNING;
+
+ ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+ if (vrf_name) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
+ rc = show_isis_ted(vty, argv, argc, isis);
+ if (rc != CMD_SUCCESS)
+ return rc;
+ }
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis)
+ rc = show_isis_ted(vty, argv, argc, isis);
+ }
+
+ return rc;
+}
+
+#endif /* #ifndef FRABRICD */
/* Initialize MPLS_TE */
void isis_mpls_te_init(void)
@@ -536,13 +1773,14 @@ void isis_mpls_te_init(void)
/* Register Circuit and Adjacency hook */
hook_register(isis_if_new_hook, isis_mpls_te_update);
- hook_register(isis_adj_state_change_hook, isis_link_update_adj_hook);
-
+ hook_register(isis_adj_ip_enabled_hook, isis_mpls_te_adj_ip_enabled);
+ hook_register(isis_adj_ip_disabled_hook, isis_mpls_te_adj_ip_disabled);
#ifndef FABRICD
/* Register new VTY commands */
install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd);
install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd);
+ install_element(VIEW_NODE, &show_isis_mpls_te_db_cmd);
#endif
return;
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index 2a6911d500..56954073dd 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -88,8 +88,10 @@ typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t;
&& e->status != EXT_ADJ_SID \
&& e->status != EXT_LAN_ADJ_SID)
#define IS_MPLS_TE(a) (a && a->status == enable)
+#define IS_EXPORT_TE(a) (a->export)
/* Per area MPLS-TE parameters */
+struct ls_ted;
struct mpls_te_area {
/* Status of MPLS-TE: enable or disable */
status_t status;
@@ -101,13 +103,30 @@ struct mpls_te_area {
interas_mode_t inter_as;
struct in_addr interas_areaid;
- /* MPLS_TE router ID */
+ /* MPLS_TE IPv4 & IPv6 Router IDs */
struct in_addr router_id;
+ struct in6_addr router_id_ipv6;
+
+ /* Link State Database */
+ struct ls_ted *ted;
+ bool export;
+};
+
+/* Structure to provide parameters to lsp iterate callback function */
+struct isis_te_args {
+ struct ls_ted *ted;
+ struct ls_vertex *vertex;
+ bool export;
};
+enum lsp_event { LSP_UNKNOWN, LSP_ADD, LSP_UPD, LSP_DEL, LSP_INC, LSP_TICK };
+
/* Prototypes. */
void isis_mpls_te_init(void);
void isis_link_params_update(struct isis_circuit *, struct interface *);
int isis_mpls_te_update(struct interface *);
+void isis_te_lsp_event(struct isis_lsp *lsp, enum lsp_event event);
+int isis_te_sync_ted(struct zapi_opaque_reg_info dst);
+void isis_te_init_ted(struct isis_area *area);
#endif /* _ZEBRA_ISIS_MPLS_TE_H */
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index a66d3b00f7..9a442e0374 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -99,6 +99,7 @@ static const struct pack_order_entry pack_order[] = {
PACK_ENTRY(OLDSTYLE_IP_REACH_EXT, ISIS_ITEMS, oldstyle_ip_reach_ext),
PACK_ENTRY(IPV4_ADDRESS, ISIS_ITEMS, ipv4_address),
PACK_ENTRY(IPV6_ADDRESS, ISIS_ITEMS, ipv6_address),
+ PACK_ENTRY(GLOBAL_IPV6_ADDRESS, ISIS_ITEMS, global_ipv6_address),
PACK_ENTRY(EXTENDED_IP_REACH, ISIS_ITEMS, extended_ip_reach),
PACK_ENTRY(MT_IP_REACH, ISIS_MT_ITEMS, mt_ip_reach),
PACK_ENTRY(IPV6_REACH, ISIS_ITEMS, ipv6_reach),
@@ -128,27 +129,41 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
}
/*
- * mtid parameter is used to determine if Adjacency is related to IPv4 or IPv6.
- * A negative value could be used to skip copy of Adjacency SID.
+ * mtid parameter is used to determine if Adjacency is related to IPv4 or IPv6
+ * Multi-Topology. Special 4096 value i.e. first R flag set is used to indicate
+ * that MT is disabled i.e. IS-IS is working with a Single Topology.
*/
static struct isis_ext_subtlvs *
-copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, int16_t mtid)
+copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
{
struct isis_ext_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
struct isis_adj_sid *adj;
struct isis_lan_adj_sid *lan;
+ /* Copy the Extended IS main part */
memcpy(rv, exts, sizeof(struct isis_ext_subtlvs));
+
+ /* Disable IPv4 / IPv6 advertisement in function of MTID */
+ if (mtid == ISIS_MT_IPV4_UNICAST) {
+ UNSET_SUBTLV(rv, EXT_LOCAL_ADDR6);
+ UNSET_SUBTLV(rv, EXT_NEIGH_ADDR6);
+ }
+ if (mtid == ISIS_MT_IPV6_UNICAST) {
+ UNSET_SUBTLV(rv, EXT_LOCAL_ADDR);
+ UNSET_SUBTLV(rv, EXT_NEIGH_ADDR);
+ }
+
+ /* Prepare (LAN)-Adjacency Segment Routing ID*/
init_item_list(&rv->adj_sid);
init_item_list(&rv->lan_sid);
UNSET_SUBTLV(rv, EXT_ADJ_SID);
UNSET_SUBTLV(rv, EXT_LAN_ADJ_SID);
- /* Copy Adj SID and LAN Adj SID list for IPv4 if needed */
+ /* Copy Adj SID list for IPv4 & IPv6 in function of MT ID */
for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj != NULL;
adj = adj->next) {
- if ((mtid != -1)
+ if ((mtid != ISIS_MT_DISABLE)
&& (((mtid == ISIS_MT_IPV4_UNICAST)
&& (adj->family != AF_INET))
|| ((mtid == ISIS_MT_IPV6_UNICAST)
@@ -166,9 +181,10 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, int16_t mtid)
SET_SUBTLV(rv, EXT_ADJ_SID);
}
+ /* Same for LAN Adj SID */
for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head; lan != NULL;
lan = lan->next) {
- if ((mtid != -1)
+ if ((mtid != ISIS_MT_DISABLE)
&& (((mtid == ISIS_MT_IPV4_UNICAST)
&& (lan->family != AF_INET))
|| ((mtid == ISIS_MT_IPV6_UNICAST)
@@ -196,8 +212,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
uint16_t mtid)
{
- char ibuf[PREFIX2STR_BUFFER];
-
/* Standard metrics */
if (IS_SUBTLV(exts, EXT_ADM_GRP))
sbuf_push(buf, indent, "Administrative Group: 0x%x\n",
@@ -212,16 +226,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
sbuf_push(buf, indent, "Local Interface IP Address(es): %pI4\n",
&exts->local_addr);
if (IS_SUBTLV(exts, EXT_NEIGH_ADDR))
- sbuf_push(buf, indent, "Remote Interface IP Address(es): %pI4\n",
+ sbuf_push(buf, indent,
+ "Remote Interface IP Address(es): %pI4\n",
&exts->neigh_addr);
if (IS_SUBTLV(exts, EXT_LOCAL_ADDR6))
- sbuf_push(buf, indent, "Local Interface IPv6 Address(es): %s\n",
- inet_ntop(AF_INET6, &exts->local_addr6, ibuf,
- PREFIX2STR_BUFFER));
+ sbuf_push(buf, indent,
+ "Local Interface IPv6 Address(es): %pI6\n",
+ &exts->local_addr6);
if (IS_SUBTLV(exts, EXT_NEIGH_ADDR6))
- sbuf_push(buf, indent, "Remote Interface IPv6 Address(es): %s\n",
- inet_ntop(AF_INET6, &exts->local_addr6, ibuf,
- PREFIX2STR_BUFFER));
+ sbuf_push(buf, indent,
+ "Remote Interface IPv6 Address(es): %pI6\n",
+ &exts->neigh_addr6);
if (IS_SUBTLV(exts, EXT_MAX_BW))
sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n",
exts->max_bw);
@@ -289,11 +304,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj;
adj = adj->next) {
- if (((mtid == ISIS_MT_IPV4_UNICAST)
- && (adj->family != AF_INET))
- || ((mtid == ISIS_MT_IPV6_UNICAST)
- && (adj->family != AF_INET6)))
- continue;
sbuf_push(
buf, indent,
"Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n",
@@ -319,10 +329,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head;
lan; lan = lan->next) {
- if (((mtid == ISIS_MT_IPV4_UNICAST)
- && (lan->family != AF_INET))
- || ((mtid == ISIS_MT_IPV6_UNICAST)
- && (lan->family != AF_INET6)))
continue;
sbuf_push(buf, indent,
"Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
@@ -1839,12 +1845,12 @@ static int pack_item_ipv6_address(struct isis_item *i, struct stream *s,
{
struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
- if (STREAM_WRITEABLE(s) < 16) {
- *min_len = 16;
+ if (STREAM_WRITEABLE(s) < IPV6_MAX_BYTELEN) {
+ *min_len = IPV6_MAX_BYTELEN;
return 1;
}
- stream_put(s, &a->addr, 16);
+ stream_put(s, &a->addr, IPV6_MAX_BYTELEN);
return 0;
}
@@ -1865,7 +1871,7 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
}
struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
- stream_get(&rv->addr, s, 16);
+ stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
format_item_ipv6_address(mtid, (struct isis_item *)rv, log, indent + 2);
append_item(&tlvs->ipv6_address, (struct isis_item *)rv);
@@ -1873,6 +1879,70 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
}
+/* Functions related to TLV 233 Global IPv6 Interface addresses */
+static struct isis_item *copy_item_global_ipv6_address(struct isis_item *i)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->addr = a->addr;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_global_ipv6_address(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ char addrbuf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n", addrbuf);
+}
+
+static void free_item_global_ipv6_address(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_global_ipv6_address(struct isis_item *i, struct stream *s,
+ size_t *min_len)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+
+ if (STREAM_WRITEABLE(s) < IPV6_MAX_BYTELEN) {
+ *min_len = IPV6_MAX_BYTELEN;
+ return 1;
+ }
+
+ stream_put(s, &a->addr, IPV6_MAX_BYTELEN);
+
+ return 0;
+}
+
+static int unpack_item_global_ipv6_address(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack Global IPv6 Interface address...\n");
+ if (len < IPV6_MAX_BYTELEN) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 16 bytes of IPv6 address, got %hhu)\n",
+ len);
+ return 1;
+ }
+
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
+
+ format_item_global_ipv6_address(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+ append_item(&tlvs->global_ipv6_address, (struct isis_item *)rv);
+ return 0;
+}
+
/* Functions related to TLV 229 MT Router information */
static struct isis_item *copy_item_mt_router_info(struct isis_item *i)
{
@@ -2273,6 +2343,77 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
return 0;
}
+/* Functions related to TLV 140 IPv6 TE Router ID */
+
+static struct in6_addr *copy_tlv_te_router_id_ipv6(const struct in6_addr *id)
+{
+ if (!id)
+ return NULL;
+
+ struct in6_addr *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ memcpy(rv, id, sizeof(*rv));
+ return rv;
+}
+
+static void format_tlv_te_router_id_ipv6(const struct in6_addr *id,
+ struct sbuf *buf, int indent)
+{
+ if (!id)
+ return;
+
+ char addrbuf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, id, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
+}
+
+static void free_tlv_te_router_id_ipv6(struct in6_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, id);
+}
+
+static int pack_tlv_te_router_id_ipv6(const struct in6_addr *id,
+ struct stream *s)
+{
+ if (!id)
+ return 0;
+
+ if (STREAM_WRITEABLE(s) < (unsigned)(2 + sizeof(*id)))
+ return 1;
+
+ stream_putc(s, ISIS_TLV_TE_ROUTER_ID_IPV6);
+ stream_putc(s, IPV6_MAX_BYTELEN);
+ stream_put(s, id, IPV6_MAX_BYTELEN);
+ return 0;
+}
+
+static int unpack_tlv_te_router_id_ipv6(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpacking IPv6 TE Router ID TLV...\n");
+ if (tlv_len != IPV6_MAX_BYTELEN) {
+ sbuf_push(log, indent, "WARNING: Length invalid\n");
+ return 1;
+ }
+
+ if (tlvs->te_router_id_ipv6) {
+ sbuf_push(
+ log, indent,
+ "WARNING: IPv6 TE Router ID present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ tlvs->te_router_id_ipv6 = XCALLOC(MTYPE_ISIS_TLV, IPV6_MAX_BYTELEN);
+ stream_get(tlvs->te_router_id_ipv6, s, IPV6_MAX_BYTELEN);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, log, indent + 2);
+ return 0;
+}
+
+
/* Functions related to TLV 150 Spine-Leaf-Extension */
static struct isis_spine_leaf *copy_tlv_spine_leaf(
@@ -3640,6 +3781,7 @@ struct isis_tlvs *isis_alloc_tlvs(void)
init_item_list(&result->oldstyle_ip_reach_ext);
init_item_list(&result->ipv4_address);
init_item_list(&result->ipv6_address);
+ init_item_list(&result->global_ipv6_address);
init_item_list(&result->extended_ip_reach);
RB_INIT(isis_mt_item_list, &result->mt_ip_reach);
init_item_list(&result->ipv6_reach);
@@ -3696,8 +3838,14 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS, &tlvs->ipv6_address,
&rv->ipv6_address);
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address, &rv->global_ipv6_address);
+
rv->te_router_id = copy_tlv_te_router_id(tlvs->te_router_id);
+ rv->te_router_id_ipv6 =
+ copy_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
+
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach, &rv->extended_ip_reach);
@@ -3751,6 +3899,7 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
format_tlv_dynamic_hostname(tlvs->hostname, buf, indent);
format_tlv_te_router_id(tlvs->te_router_id, buf, indent);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, buf, indent);
format_tlv_router_cap(tlvs->router_cap, buf, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
@@ -3771,6 +3920,9 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
&tlvs->ipv6_address, buf, indent);
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address, buf, indent);
+
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach, buf, indent);
@@ -3828,7 +3980,10 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
&tlvs->ipv4_address);
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
&tlvs->ipv6_address);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address);
free_tlv_te_router_id(tlvs->te_router_id);
+ free_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach);
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
@@ -4035,6 +4190,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
copy_tlv_te_router_id(tlvs->te_router_id);
}
+ rv = pack_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ fragment_tlvs->te_router_id_ipv6 =
+ copy_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
+ }
+
rv = pack_tlv_threeway_adj(tlvs->threeway_adj, stream);
if (rv)
return rv;
@@ -4255,10 +4418,12 @@ ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
TLV_OPS(te_router_id, "TLV 134 TE Router ID");
ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
+TLV_OPS(te_router_id_ipv6, "TLV 140 IPv6 TE Router ID");
TLV_OPS(spine_leaf, "TLV 150 Spine Leaf Extensions");
ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
TLV_OPS(threeway_adj, "TLV 240 P2P Three-Way Adjacency");
ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
+ITEM_TLV_OPS(global_ipv6_address, "TLV 233 Global IPv6 Interface Address");
ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
TLV_OPS(router_cap, "TLV 242 Router Capability");
@@ -4279,12 +4444,14 @@ static const struct tlv_ops *const tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
[ISIS_TLV_OLDSTYLE_IP_REACH_EXT] = &tlv_oldstyle_ip_reach_ops,
[ISIS_TLV_IPV4_ADDRESS] = &tlv_ipv4_address_ops,
[ISIS_TLV_TE_ROUTER_ID] = &tlv_te_router_id_ops,
+ [ISIS_TLV_TE_ROUTER_ID_IPV6] = &tlv_te_router_id_ipv6_ops,
[ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
[ISIS_TLV_SPINE_LEAF_EXT] = &tlv_spine_leaf_ops,
[ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
[ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
[ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
+ [ISIS_TLV_GLOBAL_IPV6_ADDRESS] = &tlv_global_ipv6_address_ops,
[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
[ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
[ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
@@ -4427,6 +4594,26 @@ void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
}
}
+void isis_tlvs_add_global_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct listnode *node;
+ struct prefix_ipv6 *ip_addr;
+ unsigned int addr_count = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, ip_addr)) {
+ if (addr_count >= 15)
+ break;
+
+ struct isis_ipv6_address *a =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
+
+ a->addr = ip_addr->prefix;
+ append_item(&tlvs->global_ipv6_address, (struct isis_item *)a);
+ addr_count++;
+ }
+}
+
typedef bool (*auth_validator_func)(struct isis_passwd *passwd,
struct stream *stream,
struct isis_auth *auth, bool is_lsp);
@@ -4606,10 +4793,12 @@ static void tlvs_protocols_supported_to_adj(struct isis_tlvs *tlvs,
memcpy(adj->nlpids.nlpids, reduced.nlpids, reduced.count);
}
-DEFINE_HOOK(isis_adj_ip_enabled_hook, (struct isis_adjacency *adj, int family),
- (adj, family));
+DEFINE_HOOK(isis_adj_ip_enabled_hook,
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
DEFINE_HOOK(isis_adj_ip_disabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
struct isis_adjacency *adj,
@@ -4620,7 +4809,7 @@ static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
if (adj->ipv4_address_count == 0 && tlvs->ipv4_address.count > 0)
ipv4_enabled = true;
else if (adj->ipv4_address_count > 0 && tlvs->ipv4_address.count == 0)
- hook_call(isis_adj_ip_disabled_hook, adj, AF_INET);
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET, false);
if (adj->ipv4_address_count != tlvs->ipv4_address.count) {
uint32_t oc = adj->ipv4_address_count;
@@ -4654,7 +4843,7 @@ static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
}
if (ipv4_enabled)
- hook_call(isis_adj_ip_enabled_hook, adj, AF_INET);
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET, false);
}
static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
@@ -4663,23 +4852,23 @@ static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
{
bool ipv6_enabled = false;
- if (adj->ipv6_address_count == 0 && tlvs->ipv6_address.count > 0)
+ if (adj->ll_ipv6_count == 0 && tlvs->ipv6_address.count > 0)
ipv6_enabled = true;
- else if (adj->ipv6_address_count > 0 && tlvs->ipv6_address.count == 0)
- hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6);
+ else if (adj->ll_ipv6_count > 0 && tlvs->ipv6_address.count == 0)
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6, false);
- if (adj->ipv6_address_count != tlvs->ipv6_address.count) {
- uint32_t oc = adj->ipv6_address_count;
+ if (adj->ll_ipv6_count != tlvs->ipv6_address.count) {
+ uint32_t oc = adj->ll_ipv6_count;
*changed = true;
- adj->ipv6_address_count = tlvs->ipv6_address.count;
- adj->ipv6_addresses = XREALLOC(
- MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses,
- adj->ipv6_address_count * sizeof(*adj->ipv6_addresses));
-
- for (; oc < adj->ipv6_address_count; oc++) {
- memset(&adj->ipv6_addresses[oc], 0,
- sizeof(adj->ipv6_addresses[oc]));
+ adj->ll_ipv6_count = tlvs->ipv6_address.count;
+ adj->ll_ipv6_addrs = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs,
+ adj->ll_ipv6_count * sizeof(*adj->ll_ipv6_addrs));
+
+ for (; oc < adj->ll_ipv6_count; oc++) {
+ memset(&adj->ll_ipv6_addrs[oc], 0,
+ sizeof(adj->ll_ipv6_addrs[oc]));
}
}
@@ -4691,16 +4880,65 @@ static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
else
addr = addr->next;
- if (!memcmp(&adj->ipv6_addresses[i], &addr->addr,
+ if (!memcmp(&adj->ll_ipv6_addrs[i], &addr->addr,
sizeof(addr->addr)))
continue;
*changed = true;
- adj->ipv6_addresses[i] = addr->addr;
+ adj->ll_ipv6_addrs[i] = addr->addr;
}
if (ipv6_enabled)
- hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6);
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6, false);
+}
+
+
+static void tlvs_global_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ bool global_ipv6_enabled = false;
+
+ if (adj->global_ipv6_count == 0 && tlvs->global_ipv6_address.count > 0)
+ global_ipv6_enabled = true;
+ else if (adj->global_ipv6_count > 0
+ && tlvs->global_ipv6_address.count == 0)
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6, true);
+
+ if (adj->global_ipv6_count != tlvs->global_ipv6_address.count) {
+ uint32_t oc = adj->global_ipv6_count;
+
+ *changed = true;
+ adj->global_ipv6_count = tlvs->global_ipv6_address.count;
+ adj->global_ipv6_addrs = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->global_ipv6_addrs,
+ adj->global_ipv6_count
+ * sizeof(*adj->global_ipv6_addrs));
+
+ for (; oc < adj->global_ipv6_count; oc++) {
+ memset(&adj->global_ipv6_addrs[oc], 0,
+ sizeof(adj->global_ipv6_addrs[oc]));
+ }
+ }
+
+ struct isis_ipv6_address *addr = NULL;
+ for (unsigned int i = 0; i < tlvs->global_ipv6_address.count; i++) {
+ if (!addr)
+ addr = (struct isis_ipv6_address *)
+ tlvs->global_ipv6_address.head;
+ else
+ addr = addr->next;
+
+ if (!memcmp(&adj->global_ipv6_addrs[i], &addr->addr,
+ sizeof(addr->addr)))
+ continue;
+
+ *changed = true;
+ adj->global_ipv6_addrs[i] = addr->addr;
+ }
+
+ if (global_ipv6_enabled)
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6, true);
}
void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
@@ -4712,6 +4950,7 @@ void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
tlvs_protocols_supported_to_adj(tlvs, adj, changed);
tlvs_ipv4_addresses_to_adj(tlvs, adj, changed);
tlvs_ipv6_addresses_to_adj(tlvs, adj, changed);
+ tlvs_global_ipv6_addresses_to_adj(tlvs, adj, changed);
}
bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa)
@@ -4793,6 +5032,16 @@ void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
memcpy(tlvs->te_router_id, id, sizeof(*id));
}
+void isis_tlvs_set_te_router_id_ipv6(struct isis_tlvs *tlvs,
+ const struct in6_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, tlvs->te_router_id_ipv6);
+ if (!id)
+ return;
+ tlvs->te_router_id_ipv6 = XCALLOC(MTYPE_ISIS_TLV, sizeof(*id));
+ memcpy(tlvs->te_router_id_ipv6, id, sizeof(*id));
+}
+
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint8_t metric)
{
@@ -4922,7 +5171,7 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
r->subtlvs = copy_item_ext_subtlvs(exts, mtid);
struct isis_item_list *l;
- if (mtid == ISIS_MT_IPV4_UNICAST)
+ if ((mtid == ISIS_MT_IPV4_UNICAST) || (mtid == ISIS_MT_DISABLE))
l = &tlvs->extended_reach;
else
l = isis_get_mt_items(&tlvs->mt_reach, mtid);
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 0438d13ae0..38470ef85e 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -324,9 +324,11 @@ struct isis_tlvs {
struct isis_item_list oldstyle_ip_reach_ext;
struct isis_item_list ipv4_address;
struct isis_item_list ipv6_address;
+ struct isis_item_list global_ipv6_address;
struct isis_item_list mt_router_info;
bool mt_router_info_empty;
struct in_addr *te_router_id;
+ struct in6_addr *te_router_id_ipv6;
struct isis_item_list extended_ip_reach;
struct isis_mt_item_list mt_ip_reach;
char *hostname;
@@ -372,10 +374,12 @@ enum isis_tlv_type {
ISIS_TLV_TE_ROUTER_ID = 134,
ISIS_TLV_EXTENDED_IP_REACH = 135,
ISIS_TLV_DYNAMIC_HOSTNAME = 137,
+ ISIS_TLV_TE_ROUTER_ID_IPV6 = 140,
ISIS_TLV_SPINE_LEAF_EXT = 150,
ISIS_TLV_MT_REACH = 222,
ISIS_TLV_MT_ROUTER_INFO = 229,
ISIS_TLV_IPV6_ADDRESS = 232,
+ ISIS_TLV_GLOBAL_IPV6_ADDRESS = 233,
ISIS_TLV_MT_IP_REACH = 235,
ISIS_TLV_IPV6_REACH = 236,
ISIS_TLV_MT_IPV6_REACH = 237,
@@ -575,6 +579,8 @@ void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
+void isis_tlvs_add_global_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses);
int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
struct stream *stream, bool is_lsp);
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
@@ -594,6 +600,8 @@ void isis_tlvs_set_router_capability(struct isis_tlvs *tlvs,
const struct isis_router_cap *cap);
void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
const struct in_addr *id);
+void isis_tlvs_set_te_router_id_ipv6(struct isis_tlvs *tlvs,
+ const struct in6_addr *id);
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint8_t metric);
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 27e80e2501..52a5cdd64f 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -38,6 +38,7 @@
#include "vrf.h"
#include "libfrr.h"
#include "bfd.h"
+#include "link_state.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
@@ -747,6 +748,25 @@ static void isis_zebra_connected(struct zclient *zclient)
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
}
+/**
+ * Register / unregister Link State ZAPI Opaque Message
+ *
+ * @param up True to register, false to unregister
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int isis_zebra_ls_register(bool up)
+{
+ int rc;
+
+ if (up)
+ rc = ls_register(zclient, true);
+ else
+ rc = ls_unregister(zclient, true);
+
+ return rc;
+}
+
/*
* opaque messages between processes
*/
@@ -754,6 +774,7 @@ static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
{
struct stream *s;
struct zapi_opaque_msg info;
+ struct zapi_opaque_reg_info dst;
struct ldp_igp_sync_if_state state;
struct ldp_igp_sync_announce announce;
struct zapi_rlfa_response rlfa;
@@ -764,6 +785,13 @@ static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
return -1;
switch (info.type) {
+ case LINK_STATE_SYNC:
+ STREAM_GETC(s, dst.proto);
+ STREAM_GETW(s, dst.instance);
+ STREAM_GETL(s, dst.session_id);
+ dst.type = LINK_STATE_SYNC;
+ ret = isis_te_sync_ted(dst);
+ break;
case LDP_IGP_SYNC_IF_STATE_UPDATE:
STREAM_GET(&state, s, sizeof(state));
ret = isis_ldp_sync_state_update(state);
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
index 348d7b3eab..84dc58ec6c 100644
--- a/isisd/isis_zebra.h
+++ b/isisd/isis_zebra.h
@@ -67,5 +67,6 @@ int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
int isis_zebra_release_label_range(uint32_t start, uint32_t end);
void isis_zebra_vrf_register(struct isis *isis);
void isis_zebra_vrf_deregister(struct isis *isis);
+int isis_zebra_ls_register(bool up);
#endif /* _ZEBRA_ISIS_ZEBRA_H */
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 21c97aced4..3fa2b7cc20 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -81,6 +81,7 @@ unsigned long debug_tx_queue;
unsigned long debug_sr;
unsigned long debug_ldp_sync;
unsigned long debug_lfa;
+unsigned long debug_te;
DEFINE_MGROUP(ISISD, "isisd");
@@ -1374,6 +1375,10 @@ void print_debug(struct vty *vty, int flags, int onoff)
if (flags & DEBUG_SR)
vty_out(vty, "IS-IS Segment Routing events debugging is %s\n",
onoffs);
+ if (flags & DEBUG_TE)
+ vty_out(vty,
+ "IS-IS Traffic Engineering events debugging is %s\n",
+ onoffs);
if (flags & DEBUG_LFA)
vty_out(vty, "IS-IS LFA events debugging is %s\n", onoffs);
if (flags & DEBUG_UPDATE_PACKETS)
@@ -1416,6 +1421,8 @@ DEFUN_NOSH (show_debugging,
print_debug(vty, DEBUG_SPF_EVENTS, 1);
if (IS_DEBUG_SR)
print_debug(vty, DEBUG_SR, 1);
+ if (IS_DEBUG_TE)
+ print_debug(vty, DEBUG_TE, 1);
if (IS_DEBUG_UPDATE_PACKETS)
print_debug(vty, DEBUG_UPDATE_PACKETS, 1);
if (IS_DEBUG_RTE_EVENTS)
@@ -1473,6 +1480,10 @@ static int config_write_debug(struct vty *vty)
vty_out(vty, "debug " PROTO_NAME " sr-events\n");
write++;
}
+ if (IS_DEBUG_TE) {
+ vty_out(vty, "debug " PROTO_NAME " te-events\n");
+ write++;
+ }
if (IS_DEBUG_LFA) {
vty_out(vty, "debug " PROTO_NAME " lfa\n");
write++;
@@ -1707,6 +1718,33 @@ DEFUN (no_debug_isis_srevents,
return CMD_SUCCESS;
}
+DEFUN (debug_isis_teevents,
+ debug_isis_teevents_cmd,
+ "debug " PROTO_NAME " te-events",
+ DEBUG_STR
+ PROTO_HELP
+ "IS-IS Traffic Engineering Events\n")
+{
+ debug_te |= DEBUG_TE;
+ print_debug(vty, DEBUG_TE, 1);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_isis_teevents,
+ no_debug_isis_teevents_cmd,
+ "no debug " PROTO_NAME " te-events",
+ NO_STR
+ UNDEBUG_STR
+ PROTO_HELP
+ "IS-IS Traffic Engineering Events\n")
+{
+ debug_te &= ~DEBUG_TE;
+ print_debug(vty, DEBUG_TE, 0);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (debug_isis_lfa,
debug_isis_lfa_cmd,
"debug " PROTO_NAME " lfa",
@@ -3095,6 +3133,8 @@ void isis_init(void)
install_element(ENABLE_NODE, &no_debug_isis_spfevents_cmd);
install_element(ENABLE_NODE, &debug_isis_srevents_cmd);
install_element(ENABLE_NODE, &no_debug_isis_srevents_cmd);
+ install_element(ENABLE_NODE, &debug_isis_teevents_cmd);
+ install_element(ENABLE_NODE, &no_debug_isis_teevents_cmd);
install_element(ENABLE_NODE, &debug_isis_lfa_cmd);
install_element(ENABLE_NODE, &no_debug_isis_lfa_cmd);
install_element(ENABLE_NODE, &debug_isis_rtevents_cmd);
@@ -3126,6 +3166,8 @@ void isis_init(void)
install_element(CONFIG_NODE, &no_debug_isis_spfevents_cmd);
install_element(CONFIG_NODE, &debug_isis_srevents_cmd);
install_element(CONFIG_NODE, &no_debug_isis_srevents_cmd);
+ install_element(CONFIG_NODE, &debug_isis_teevents_cmd);
+ install_element(CONFIG_NODE, &no_debug_isis_teevents_cmd);
install_element(CONFIG_NODE, &debug_isis_lfa_cmd);
install_element(CONFIG_NODE, &no_debug_isis_lfa_cmd);
install_element(CONFIG_NODE, &debug_isis_rtevents_cmd);
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 3febda1d87..7f8474a5f2 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -331,6 +331,7 @@ extern unsigned long debug_tx_queue;
extern unsigned long debug_sr;
extern unsigned long debug_ldp_sync;
extern unsigned long debug_lfa;
+extern unsigned long debug_te;
#define DEBUG_ADJ_PACKETS (1<<0)
#define DEBUG_SNP_PACKETS (1<<1)
@@ -347,6 +348,7 @@ extern unsigned long debug_lfa;
#define DEBUG_SR (1<<12)
#define DEBUG_LDP_SYNC (1<<13)
#define DEBUG_LFA (1<<14)
+#define DEBUG_TE (1<<15)
/* Debug related macro. */
#define IS_DEBUG_ADJ_PACKETS (debug_adj_pkt & DEBUG_ADJ_PACKETS)
@@ -364,6 +366,7 @@ extern unsigned long debug_lfa;
#define IS_DEBUG_SR (debug_sr & DEBUG_SR)
#define IS_DEBUG_LDP_SYNC (debug_ldp_sync & DEBUG_LDP_SYNC)
#define IS_DEBUG_LFA (debug_lfa & DEBUG_LFA)
+#define IS_DEBUG_TE (debug_te & DEBUG_TE)
#define lsp_debug(...) \
do { \
@@ -383,6 +386,10 @@ extern unsigned long debug_lfa;
zlog_debug(__VA_ARGS__); \
} while (0)
-#define DEBUG_TE DEBUG_LSP_GEN
+#define te_debug(...) \
+ do { \
+ if (IS_DEBUG_TE) \
+ zlog_debug(__VA_ARGS__); \
+ } while (0)
#endif /* ISISD_H */
diff --git a/lib/elf_py.c b/lib/elf_py.c
index f230add695..5289faece4 100644
--- a/lib/elf_py.c
+++ b/lib/elf_py.c
@@ -1071,26 +1071,25 @@ static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata,
* always be a pointer...
*/
if (elffile_virt2file(w, rel->r_offset, &offs)) {
- Elf_Data *ptr, *conv;
- GElf_Addr tmp;
- Elf_Data mem = {
- .d_buf = (void *)&tmp,
- .d_type = ELF_T_ADDR,
- .d_version = EV_CURRENT,
- .d_size = sizeof(tmp),
- .d_off = 0,
- .d_align = 0,
- };
+ Elf_Data *ptr;
+ /* NB: this endian-converts! */
ptr = elf_getdata_rawchunk(w->elf, offs,
w->elfclass / 8,
ELF_T_ADDR);
- conv = gelf_xlatetom(w->elf, &mem, ptr,
- w->mmap[EI_DATA]);
- if (conv) {
- memcpy(&rel_offs, conv->d_buf,
- conv->d_size);
+ if (ptr) {
+ char *dst = (char *)&rel_offs;
+
+ /* sigh. it endian-converts. but
+ * doesn't size-convert.
+ */
+ if (BYTE_ORDER == BIG_ENDIAN &&
+ ptr->d_size < sizeof(rel_offs))
+ dst += sizeof(rel_offs) -
+ ptr->d_size;
+
+ memcpy(dst, ptr->d_buf, ptr->d_size);
relw->relative = false;
relw->rela->r_addend = rel_offs;
diff --git a/lib/if.c b/lib/if.c
index 99fa83719a..158303a387 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1285,6 +1285,22 @@ static void cli_show_interface_end(struct vty *vty,
vty_out(vty, "exit\n");
}
+void if_vty_config_start(struct vty *vty, struct interface *ifp)
+{
+ vty_frame(vty, "!\n");
+ vty_frame(vty, "interface %s", ifp->name);
+
+ if (vrf_is_backend_netns() && strcmp(ifp->vrf->name, VRF_DEFAULT_NAME))
+ vty_frame(vty, " vrf %s", ifp->vrf->name);
+
+ vty_frame(vty, "\n");
+}
+
+void if_vty_config_end(struct vty *vty)
+{
+ vty_endframe(vty, "exit\n!\n");
+}
+
/*
* XPath: /frr-interface:lib/interface/description
*/
diff --git a/lib/if.h b/lib/if.h
index c8f4d9ab9d..53cd019464 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -592,6 +592,8 @@ void if_link_params_free(struct interface *);
/* Northbound. */
struct vty;
+extern void if_vty_config_start(struct vty *vty, struct interface *ifp);
+extern void if_vty_config_end(struct vty *vty);
extern void if_cmd_init(int (*config_write)(struct vty *));
extern void if_cmd_init_default(void);
extern void if_zapi_callbacks(int (*create)(struct interface *ifp),
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index 730c7ce130..a334ea969e 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -170,6 +170,19 @@ static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b)
}
}
+static inline bool ipaddr_is_zero(const struct ipaddr *ip)
+{
+ switch (ip->ipa_type) {
+ case IPADDR_NONE:
+ return true;
+ case IPADDR_V4:
+ return ip->ipaddr_v4.s_addr == INADDR_ANY;
+ case IPADDR_V6:
+ return IN6_IS_ADDR_UNSPECIFIED(&ip->ipaddr_v6);
+ }
+ return true;
+}
+
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
#endif
diff --git a/lib/lib_errors.c b/lib/lib_errors.c
index a139b9a14c..acc9a05c33 100644
--- a/lib/lib_errors.c
+++ b/lib/lib_errors.c
@@ -57,6 +57,12 @@ static struct log_ref ferr_lib_warn[] = {
.suggestion = "Gather log data and open an Issue",
},
{
+ .code = EC_LIB_STARVE_THREAD,
+ .title = "The Event subsystem has detected a thread starvation issue",
+ .description = "The event subsystem has detected a thread starvation issue. This typically indicates that the system FRR is running on is heavily loaded and this load might be impacting FRR's ability to handle events in a timely fashion",
+ .suggestion = "Gather log data and open an Issue",
+ },
+ {
.code = EC_LIB_NO_THREAD,
.title = "The Event subsystem has detected an internal FD problem",
.description = "The Event subsystem has detected a file descriptor read/write event without an associated handling function. This is a bug, please collect log data and open an issue.",
diff --git a/lib/lib_errors.h b/lib/lib_errors.h
index 9f0f58d20b..64ac6c1ceb 100644
--- a/lib/lib_errors.h
+++ b/lib/lib_errors.h
@@ -46,6 +46,7 @@ enum lib_log_refs {
EC_LIB_LINUX_NS,
EC_LIB_SLOW_THREAD_CPU,
EC_LIB_SLOW_THREAD_WALL,
+ EC_LIB_STARVE_THREAD,
EC_LIB_NO_THREAD,
EC_LIB_RMAP_RECURSION_LIMIT,
EC_LIB_BACKUP_CONFIG,
diff --git a/lib/link_state.c b/lib/link_state.c
index b0bc386b79..e4ccd0fb65 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -89,7 +89,7 @@ struct ls_node *ls_node_new(struct ls_node_id adv, struct in_addr rid,
}
}
if (!IN6_IS_ADDR_UNSPECIFIED(&rid6)) {
- new->router6_id = rid6;
+ new->router_id6 = rid6;
SET_FLAG(new->flags, LS_NODE_ROUTER_ID6);
}
return new;
@@ -127,7 +127,7 @@ int ls_node_same(struct ls_node *n1, struct ls_node *n2)
&& !IPV4_ADDR_SAME(&n1->router_id, &n2->router_id))
return 0;
if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID6)
- && !IPV6_ADDR_SAME(&n1->router6_id, &n2->router6_id))
+ && !IPV6_ADDR_SAME(&n1->router_id6, &n2->router_id6))
return 0;
if (CHECK_FLAG(n1->flags, LS_NODE_FLAG)
&& (n1->node_flag != n2->node_flag))
@@ -306,36 +306,23 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
if (CHECK_FLAG(l1->flags, LS_ATTR_USE_BW)
&& (l1->extended.used_bw != l2->extended.used_bw))
return 0;
- if (CHECK_FLAG(l1->flags, LS_ATTR_ADJ_SID)) {
- if ((l1->adj_sid[0].sid != l2->adj_sid[0].sid)
- || (l1->adj_sid[0].flags != l2->adj_sid[0].flags)
- || (l1->adj_sid[0].weight != l2->adj_sid[0].weight))
+ for (int i = 0; i < LS_ADJ_MAX; i++) {
+ if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SID << i)))
+ continue;
+ if ((l1->adj_sid[i].sid != l2->adj_sid[i].sid)
+ || (l1->adj_sid[i].flags != l2->adj_sid[i].flags)
+ || (l1->adj_sid[i].weight != l2->adj_sid[i].weight))
return 0;
if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
- && (memcmp(&l1->adj_sid[0].neighbor.sysid,
- &l2->adj_sid[0].neighbor.sysid, ISO_SYS_ID_LEN)
+ && (memcmp(&l1->adj_sid[i].neighbor.sysid,
+ &l2->adj_sid[i].neighbor.sysid, ISO_SYS_ID_LEN)
!= 0))
return 0;
if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
|| (l1->adv.origin == DIRECT))
- && (!IPV4_ADDR_SAME(&l1->adj_sid[0].neighbor.addr,
- &l2->adj_sid[0].neighbor.addr)))
- return 0;
- }
- if (CHECK_FLAG(l1->flags, LS_ATTR_BCK_ADJ_SID)) {
- if ((l1->adj_sid[1].sid != l2->adj_sid[1].sid)
- || (l1->adj_sid[1].flags != l2->adj_sid[1].flags)
- || (l1->adj_sid[1].weight != l2->adj_sid[1].weight))
- return 0;
- if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
- && (memcmp(&l1->adj_sid[1].neighbor.sysid,
- &l2->adj_sid[1].neighbor.sysid, ISO_SYS_ID_LEN)
- != 0))
- return 0;
- if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
- || (l1->adv.origin == DIRECT))
- && (!IPV4_ADDR_SAME(&l1->adj_sid[1].neighbor.addr,
- &l2->adj_sid[1].neighbor.addr)))
+ && (i < ADJ_PRI_IPV6)
+ && (!IPV4_ADDR_SAME(&l1->adj_sid[i].neighbor.addr,
+ &l2->adj_sid[i].neighbor.addr)))
return 0;
}
if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG)
@@ -417,6 +404,25 @@ int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
/**
* Link State Vertices management functions
*/
+uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN])
+{
+ uint64_t key = 0;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t *byte = (uint8_t *)&key;
+
+ for (int i = 0; i < ISO_SYS_ID_LEN; i++)
+ byte[i] = sysid[ISO_SYS_ID_LEN - i - 1];
+
+ byte[6] = 0;
+ byte[7] = 0;
+#else
+ memcpy(&key, sysid, ISO_SYS_ID_LEN);
+#endif
+
+ return key;
+}
+
struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
{
struct ls_vertex *new;
@@ -435,7 +441,7 @@ struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
break;
case ISIS_L1:
case ISIS_L2:
- memcpy(&key, &node->adv.id.iso.sys_id, ISO_SYS_ID_LEN);
+ key = sysid_to_key(node->adv.id.iso.sys_id);
break;
default:
key = 0;
@@ -557,7 +563,7 @@ struct ls_vertex *ls_find_vertex_by_id(struct ls_ted *ted,
break;
case ISIS_L1:
case ISIS_L2:
- memcpy(&vertex.key, &nid.id.iso.sys_id, ISO_SYS_ID_LEN);
+ vertex.key = sysid_to_key(nid.id.iso.sys_id);
break;
default:
return NULL;
@@ -673,6 +679,46 @@ static void ls_edge_connect_to(struct ls_ted *ted, struct ls_edge *edge)
}
}
+static uint64_t get_edge_key(struct ls_attributes *attr, bool dst)
+{
+ uint64_t key = 0;
+ struct ls_standard *std;
+
+ if (!attr)
+ return key;
+
+ std = &attr->standard;
+
+ if (dst) {
+ /* Key is the IPv4 remote address */
+ if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
+ key = ((uint64_t)ntohl(std->remote.s_addr))
+ & 0xffffffff;
+ /* or the 64 bits LSB of IPv6 remote address */
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
+ key = ((uint64_t)ntohl(std->remote6.s6_addr32[2]) << 32
+ | (uint64_t)ntohl(std->remote6.s6_addr32[3]));
+ /* of remote identifier if no IP addresses are defined */
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
+ key = (((uint64_t)std->remote_id) & 0xffffffff)
+ | ((uint64_t)std->local_id << 32);
+ } else {
+ /* Key is the IPv4 local address */
+ if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
+ key = ((uint64_t)ntohl(std->local.s_addr)) & 0xffffffff;
+ /* or the 64 bits LSB of IPv6 local address */
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
+ key = ((uint64_t)ntohl(std->local6.s6_addr32[2]) << 32
+ | (uint64_t)ntohl(std->local6.s6_addr32[3]));
+ /* of local identifier if no IP addresses are defined */
+ else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
+ key = (((uint64_t)std->local_id) & 0xffffffff)
+ | ((uint64_t)std->remote_id << 32);
+ }
+
+ return key;
+}
+
struct ls_edge *ls_edge_add(struct ls_ted *ted,
struct ls_attributes *attributes)
{
@@ -682,23 +728,7 @@ struct ls_edge *ls_edge_add(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
- /* Key is the IPv4 local address */
- if (!IPV4_NET0(attributes->standard.local.s_addr))
- key = ((uint64_t)ntohl(attributes->standard.local.s_addr))
- & 0xffffffff;
- /* or the IPv6 local address if IPv4 is not defined */
- else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.local6))
- key = (uint64_t)(attributes->standard.local6.s6_addr32[0]
- & 0xffffffff)
- | ((uint64_t)attributes->standard.local6.s6_addr32[1]
- << 32);
- /* of local identifier if no IP addresses are defined */
- else if (attributes->standard.local_id != 0)
- key = (uint64_t)(
- (attributes->standard.local_id & 0xffffffff)
- | ((uint64_t)attributes->standard.remote_id << 32));
-
- /* Check that key is valid */
+ key = get_edge_key(attributes, false);
if (key == 0)
return NULL;
@@ -736,23 +766,7 @@ struct ls_edge *ls_find_edge_by_source(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
- edge.key = 0;
- /* Key is the IPv4 local address */
- if (!IPV4_NET0(attributes->standard.local.s_addr))
- edge.key = ((uint64_t)ntohl(attributes->standard.local.s_addr))
- & 0xffffffff;
- /* or the IPv6 local address if IPv4 is not defined */
- else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.local6))
- edge.key = (uint64_t)(attributes->standard.local6.s6_addr32[0]
- & 0xffffffff)
- | ((uint64_t)attributes->standard.local6.s6_addr32[1]
- << 32);
- /* of local identifier if no IP addresses are defined */
- else if (attributes->standard.local_id != 0)
- edge.key = (uint64_t)(
- (attributes->standard.local_id & 0xffffffff)
- | ((uint64_t)attributes->standard.remote_id << 32));
-
+ edge.key = get_edge_key(attributes, false);
if (edge.key == 0)
return NULL;
@@ -767,24 +781,7 @@ struct ls_edge *ls_find_edge_by_destination(struct ls_ted *ted,
if (attributes == NULL)
return NULL;
- edge.key = 0;
- /* Key is the IPv4 remote address */
- if (!IPV4_NET0(attributes->standard.remote.s_addr))
- edge.key = ((uint64_t)ntohl(attributes->standard.remote.s_addr))
- & 0xffffffff;
- /* or the IPv6 remote address if IPv4 is not defined */
- else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.remote6))
- edge.key =
- (uint64_t)(attributes->standard.remote6.s6_addr32[0]
- & 0xffffffff)
- | ((uint64_t)attributes->standard.remote6.s6_addr32[1]
- << 32);
- /* of remote identifier if no IP addresses are defined */
- else if (attributes->standard.remote_id != 0)
- edge.key = (uint64_t)(
- (attributes->standard.remote_id & 0xffffffff)
- | ((uint64_t)attributes->standard.local_id << 32));
-
+ edge.key = get_edge_key(attributes, true);
if (edge.key == 0)
return NULL;
@@ -1177,7 +1174,7 @@ static struct ls_node *ls_parse_node(struct stream *s)
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
node->router_id.s_addr = stream_get_ipv4(s);
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
- STREAM_GET(&node->router6_id, s, IPV6_MAX_BYTELEN);
+ STREAM_GET(&node->router_id6, s, IPV6_MAX_BYTELEN);
if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
STREAM_GETC(s, node->node_flag);
if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
@@ -1267,26 +1264,32 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s)
if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
STREAM_GETF(s, attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
- STREAM_GETL(s, attr->adj_sid[0].sid);
- STREAM_GETC(s, attr->adj_sid[0].flags);
- STREAM_GETC(s, attr->adj_sid[0].weight);
- if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
- STREAM_GET(attr->adj_sid[0].neighbor.sysid, s,
- ISO_SYS_ID_LEN);
- else if (attr->adv.origin == OSPFv2)
- attr->adj_sid[0].neighbor.addr.s_addr =
- stream_get_ipv4(s);
+ STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
+ STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
+ STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
+ attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr =
+ stream_get_ipv4(s);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
- STREAM_GETL(s, attr->adj_sid[1].sid);
- STREAM_GETC(s, attr->adj_sid[1].flags);
- STREAM_GETC(s, attr->adj_sid[1].weight);
- if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
- STREAM_GET(attr->adj_sid[1].neighbor.sysid, s,
- ISO_SYS_ID_LEN);
- else if (attr->adv.origin == OSPFv2)
- attr->adj_sid[1].neighbor.addr.s_addr =
- stream_get_ipv4(s);
+ STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
+ STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
+ STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
+ attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr =
+ stream_get_ipv4(s);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
+ STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
+ STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
+ STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
+ STREAM_GET(attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid, s,
+ ISO_SYS_ID_LEN);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
+ STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
+ STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
+ STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
+ STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
+ ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
STREAM_GETC(s, len);
@@ -1401,7 +1404,7 @@ static int ls_format_node(struct stream *s, struct ls_node *node)
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
stream_put_ipv4(s, node->router_id.s_addr);
if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
- stream_put(s, &node->router6_id, IPV6_MAX_BYTELEN);
+ stream_put(s, &node->router_id6, IPV6_MAX_BYTELEN);
if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
stream_putc(s, node->node_flag);
if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
@@ -1487,26 +1490,32 @@ static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
stream_putf(s, attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
- stream_putl(s, attr->adj_sid[0].sid);
- stream_putc(s, attr->adj_sid[0].flags);
- stream_putc(s, attr->adj_sid[0].weight);
- if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
- stream_put(s, attr->adj_sid[0].neighbor.sysid,
- ISO_SYS_ID_LEN);
- else if (attr->adv.origin == OSPFv2)
- stream_put_ipv4(s,
- attr->adj_sid[0].neighbor.addr.s_addr);
+ stream_putl(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
+ stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
+ stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
+ stream_put_ipv4(
+ s, attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
- stream_putl(s, attr->adj_sid[1].sid);
- stream_putc(s, attr->adj_sid[1].flags);
- stream_putc(s, attr->adj_sid[1].weight);
- if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
- stream_put(s, attr->adj_sid[1].neighbor.sysid,
- ISO_SYS_ID_LEN);
- else if (attr->adv.origin == OSPFv2)
- stream_put_ipv4(s,
- attr->adj_sid[1].neighbor.addr.s_addr);
+ stream_putl(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
+ stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
+ stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
+ stream_put_ipv4(
+ s, attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
+ stream_putl(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
+ stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
+ stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
+ stream_put(s, attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid,
+ ISO_SYS_ID_LEN);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
+ stream_putl(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
+ stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
+ stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
+ stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
+ ISO_SYS_ID_LEN);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
stream_putc(s, attr->srlg_len);
@@ -1955,6 +1964,7 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
struct listnode *node;
struct ls_node *lsn;
struct ls_edge *edge;
+ struct ls_attributes *attr;
struct ls_subnet *subnet;
struct sbuf sbuf;
uint32_t upper;
@@ -2019,9 +2029,15 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
} else {
sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
}
- sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
- &edge->attributes->standard.local,
- &edge->attributes->standard.remote);
+ attr = edge->attributes;
+ if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
+ sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
+ &attr->standard.local,
+ &attr->standard.remote);
+ else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
+ sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
+ &attr->standard.local6,
+ &attr->standard.remote6);
}
sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
@@ -2034,9 +2050,15 @@ static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
} else {
sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
}
- sbuf_push(&sbuf, 0, "\tRemote: %pI4\tLocal: %pI4\n",
- &edge->attributes->standard.local,
- &edge->attributes->standard.remote);
+ attr = edge->attributes;
+ if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
+ sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
+ &attr->standard.local,
+ &attr->standard.remote);
+ else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
+ sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
+ &attr->standard.local6,
+ &attr->standard.remote6);
}
sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
@@ -2071,7 +2093,7 @@ static void ls_show_vertex_json(struct ls_vertex *vertex,
json_object_string_add(json, "router-id", buf);
}
if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
- snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router6_id);
+ snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router_id6);
json_object_string_add(json, "router-id-v6", buf);
}
if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
@@ -2235,15 +2257,32 @@ static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
attr->extended.used_bw);
if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
- sbuf_push(&sbuf, 4, "Adjacency-SID: %u", attr->adj_sid[0].sid);
+ sbuf_push(&sbuf, 4, "IPv4 Adjacency-SID: %u",
+ attr->adj_sid[ADJ_PRI_IPV4].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
- attr->adj_sid[0].flags, attr->adj_sid[0].weight);
+ attr->adj_sid[ADJ_PRI_IPV4].flags,
+ attr->adj_sid[ADJ_PRI_IPV4].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
- sbuf_push(&sbuf, 4, "Bck. Adjacency-SID: %u",
- attr->adj_sid[1].sid);
+ sbuf_push(&sbuf, 4, "IPv4 Bck. Adjacency-SID: %u",
+ attr->adj_sid[ADJ_BCK_IPV4].sid);
+ sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
+ attr->adj_sid[ADJ_BCK_IPV4].flags,
+ attr->adj_sid[ADJ_BCK_IPV4].weight);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
+ sbuf_push(&sbuf, 4, "IPv6 Adjacency-SID: %u",
+ attr->adj_sid[ADJ_PRI_IPV6].sid);
sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
- attr->adj_sid[1].flags, attr->adj_sid[1].weight);
+ attr->adj_sid[ADJ_PRI_IPV6].flags,
+ attr->adj_sid[ADJ_PRI_IPV6].weight);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
+ sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SID: %u",
+ attr->adj_sid[ADJ_BCK_IPV6].sid);
+ sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
+ attr->adj_sid[ADJ_BCK_IPV6].flags,
+ attr->adj_sid[ADJ_BCK_IPV6].weight);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
@@ -2374,10 +2413,12 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
jsr = json_object_new_array();
json_object_object_add(json, "segment-routing", jsr);
jobj = json_object_new_object();
- json_object_int_add(jobj, "adj-sid", attr->adj_sid[0].sid);
- snprintfrr(buf, 6, "0x%x", attr->adj_sid[0].flags);
+ json_object_int_add(jobj, "adj-sid",
+ attr->adj_sid[ADJ_PRI_IPV4].sid);
+ snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV4].flags);
json_object_string_add(jobj, "flags", buf);
- json_object_int_add(jobj, "weight", attr->adj_sid[0].weight);
+ json_object_int_add(jobj, "weight",
+ attr->adj_sid[ADJ_PRI_IPV4].weight);
json_object_array_add(jsr, jobj);
}
if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
@@ -2386,10 +2427,38 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
json_object_object_add(json, "segment-routing", jsr);
}
jobj = json_object_new_object();
- json_object_int_add(jobj, "adj-sid", attr->adj_sid[1].sid);
- snprintfrr(buf, 6, "0x%x", attr->adj_sid[1].flags);
+ json_object_int_add(jobj, "adj-sid",
+ attr->adj_sid[ADJ_BCK_IPV4].sid);
+ snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV4].flags);
+ json_object_string_add(jobj, "flags", buf);
+ json_object_int_add(jobj, "weight",
+ attr->adj_sid[ADJ_BCK_IPV4].weight);
+ json_object_array_add(jsr, jobj);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
+ jsr = json_object_new_array();
+ json_object_object_add(json, "segment-routing", jsr);
+ jobj = json_object_new_object();
+ json_object_int_add(jobj, "adj-sid",
+ attr->adj_sid[ADJ_PRI_IPV6].sid);
+ snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV6].flags);
+ json_object_string_add(jobj, "flags", buf);
+ json_object_int_add(jobj, "weight",
+ attr->adj_sid[ADJ_PRI_IPV6].weight);
+ json_object_array_add(jsr, jobj);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
+ if (!jsr) {
+ jsr = json_object_new_array();
+ json_object_object_add(json, "segment-routing", jsr);
+ }
+ jobj = json_object_new_object();
+ json_object_int_add(jobj, "adj-sid",
+ attr->adj_sid[ADJ_BCK_IPV6].sid);
+ snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV6].flags);
json_object_string_add(jobj, "flags", buf);
- json_object_int_add(jobj, "weight", attr->adj_sid[1].weight);
+ json_object_int_add(jobj, "weight",
+ attr->adj_sid[ADJ_BCK_IPV6].weight);
json_object_array_add(jsr, jobj);
}
}
diff --git a/lib/link_state.h b/lib/link_state.h
index 981e8b5285..761e8b6a27 100644
--- a/lib/link_state.h
+++ b/lib/link_state.h
@@ -122,7 +122,7 @@ struct ls_node {
struct ls_node_id adv; /* Adv. Router of this Link State */
char name[MAX_NAME_LENGTH]; /* Name of the Node (IS-IS only) */
struct in_addr router_id; /* IPv4 Router ID */
- struct in6_addr router6_id; /* IPv6 Router ID */
+ struct in6_addr router_id6; /* IPv6 Router ID */
uint8_t node_flag; /* IS-IS or OSPF Node flag */
enum ls_node_type type; /* Type of Node */
uint32_t as_number; /* Local or neighbor AS number */
@@ -166,6 +166,8 @@ struct ls_node {
#define LS_ATTR_USE_BW 0x00400000
#define LS_ATTR_ADJ_SID 0x01000000
#define LS_ATTR_BCK_ADJ_SID 0x02000000
+#define LS_ATTR_ADJ_SID6 0x04000000
+#define LS_ATTR_BCK_ADJ_SID6 0x08000000
#define LS_ATTR_SRLG 0x10000000
/* Link State Attributes */
@@ -200,6 +202,11 @@ struct ls_attributes {
float rsv_bw; /* Reserved Bandwidth */
float used_bw; /* Utilized Bandwidth */
} extended;
+#define ADJ_PRI_IPV4 0
+#define ADJ_BCK_IPV4 1
+#define ADJ_PRI_IPV6 2
+#define ADJ_BCK_IPV6 3
+#define LS_ADJ_MAX 4
struct ls_adjacency { /* (LAN)-Adjacency SID for OSPF */
uint32_t sid; /* SID as MPLS label or index */
uint8_t flags; /* Flags */
@@ -208,7 +215,7 @@ struct ls_attributes {
struct in_addr addr; /* Neighbor @IP for OSPF */
uint8_t sysid[ISO_SYS_ID_LEN]; /* or Sys-ID for ISIS */
} neighbor;
- } adj_sid[2]; /* Primary & Backup (LAN)-Adj. SID */
+ } adj_sid[4]; /* IPv4/IPv6 & Primary/Backup (LAN)-Adj. SID */
uint32_t *srlgs; /* List of Shared Risk Link Group */
uint8_t srlg_len; /* number of SRLG in the list */
};
@@ -412,21 +419,34 @@ struct ls_subnet {
macro_inline int vertex_cmp(const struct ls_vertex *node1,
const struct ls_vertex *node2)
{
- return (node1->key - node2->key);
+ return numcmp(node1->key, node2->key);
}
DECLARE_RBTREE_UNIQ(vertices, struct ls_vertex, entry, vertex_cmp);
macro_inline int edge_cmp(const struct ls_edge *edge1,
const struct ls_edge *edge2)
{
- return (edge1->key - edge2->key);
+ return numcmp(edge1->key, edge2->key);
}
DECLARE_RBTREE_UNIQ(edges, struct ls_edge, entry, edge_cmp);
+/*
+ * Prefix comparison are done to the host part so, 10.0.0.1/24
+ * and 10.0.0.2/24 are considered come different
+ */
macro_inline int subnet_cmp(const struct ls_subnet *a,
- const struct ls_subnet *b)
+ const struct ls_subnet *b)
{
- return prefix_cmp(&a->key, &b->key);
+ if (a->key.family != b->key.family)
+ return numcmp(a->key.family, b->key.family);
+
+ if (a->key.prefixlen != b->key.prefixlen)
+ return numcmp(a->key.prefixlen, b->key.prefixlen);
+
+ if (a->key.family == AF_INET)
+ return memcmp(&a->key.u.val, &b->key.u.val, 4);
+
+ return memcmp(&a->key.u.val, &b->key.u.val, 16);
}
DECLARE_RBTREE_UNIQ(subnets, struct ls_subnet, entry, subnet_cmp);
@@ -503,6 +523,16 @@ extern struct ls_vertex *ls_vertex_update(struct ls_ted *ted,
*/
extern void ls_vertex_clean(struct ls_ted *ted, struct ls_vertex *vertex,
struct zclient *zclient);
+
+/**
+ * This function convert the ISIS ISO system ID into a 64 bits unsigned integer
+ * following the architecture dependent byte order.
+ *
+ * @param sysid The ISO system ID
+ * @return Key as 64 bits unsigned integer
+ */
+extern uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN]);
+
/**
* Find Vertex in the Link State DB by its unique key.
*
diff --git a/lib/route_opaque.h b/lib/route_opaque.h
index c5e7d6a327..bf6081c054 100644
--- a/lib/route_opaque.h
+++ b/lib/route_opaque.h
@@ -24,9 +24,12 @@
#include "assert.h"
#include "zclient.h"
-#include "bgpd/bgp_aspath.h"
-#include "bgpd/bgp_community.h"
-#include "bgpd/bgp_lcommunity.h"
+/* copied from bgpd/bgp_community.h */
+#define COMMUNITY_SIZE 4
+/* copied from bgpd/bgp_lcommunity.h */
+#define LCOMMUNITY_SIZE 12
+/* copied from bgpd/bgp_route.h */
+#define BGP_MAX_SELECTION_REASON_STR_BUF 32
struct bgp_zebra_opaque {
char aspath[256];
@@ -44,7 +47,15 @@ struct bgp_zebra_opaque {
char selection_reason[BGP_MAX_SELECTION_REASON_STR_BUF];
};
+struct ospf_zebra_opaque {
+ char path_type[32];
+ char area_id[INET_ADDRSTRLEN];
+ char tag[16];
+};
+
static_assert(sizeof(struct bgp_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH,
"BGP opaque data shouldn't be larger than zebra's buffer");
+static_assert(sizeof(struct ospf_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH,
+ "OSPF opaque data shouldn't be larger than zebra's buffer");
#endif /* FRR_ROUTE_OPAQUE_H */
diff --git a/lib/thread.c b/lib/thread.c
index 77e34f48f3..376f61c247 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -787,6 +787,7 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
thread->arg = arg;
thread->yield = THREAD_YIELD_TIME_SLOT; /* default */
thread->ref = NULL;
+ thread->ignore_timer_late = false;
/*
* So if the passed in funcname is not what we have
@@ -1651,12 +1652,31 @@ static void thread_process_io(struct thread_master *m, unsigned int num)
static unsigned int thread_process_timers(struct thread_master *m,
struct timeval *timenow)
{
+ struct timeval prev = *timenow;
+ bool displayed = false;
struct thread *thread;
unsigned int ready = 0;
while ((thread = thread_timer_list_first(&m->timer))) {
if (timercmp(timenow, &thread->u.sands, <))
break;
+ prev = thread->u.sands;
+ prev.tv_sec += 4;
+ /*
+ * If the timer would have popped 4 seconds in the
+ * past then we are in a situation where we are
+ * really getting behind on handling of events.
+ * Let's log it and do the right thing with it.
+ */
+ if (!displayed && !thread->ignore_timer_late &&
+ timercmp(timenow, &prev, >)) {
+ flog_warn(
+ EC_LIB_STARVE_THREAD,
+ "Thread Starvation: %pTHD was scheduled to pop greater than 4s ago",
+ thread);
+ displayed = true;
+ }
+
thread_timer_list_pop(&m->timer);
thread->type = THREAD_READY;
thread_list_add_tail(&m->ready, thread);
diff --git a/lib/thread.h b/lib/thread.h
index 49a70696d0..660f8bd28e 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -126,6 +126,7 @@ struct thread {
unsigned long yield; /* yield time in microseconds */
const struct xref_threadsched *xref; /* origin location */
pthread_mutex_t mtx; /* mutex for thread.c functions */
+ bool ignore_timer_late;
};
#ifdef _FRR_ATTRIBUTE_PRINTFRR
@@ -285,6 +286,11 @@ extern bool thread_is_scheduled(struct thread *thread);
/* Debug signal mask */
void debug_signals(const sigset_t *sigs);
+static inline void thread_ignore_late_timer(struct thread *thread)
+{
+ thread->ignore_timer_late = true;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 2a8326c056..86afe4082e 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -135,10 +135,11 @@ static int work_queue_schedule(struct work_queue *wq, unsigned int delay)
/* Schedule timer if there's a delay, otherwise just schedule
* as an 'event'
*/
- if (delay > 0)
+ if (delay > 0) {
thread_add_timer_msec(wq->master, work_queue_run, wq,
delay, &wq->thread);
- else
+ thread_ignore_late_timer(wq->thread);
+ } else
thread_add_event(wq->master, work_queue_run, wq, 0,
&wq->thread);
diff --git a/lib/yang.c b/lib/yang.c
index 1e241f049e..ef1cf898aa 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -49,6 +49,11 @@ static LY_ERR yang_module_imp_clb(const char *mod_name, const char *mod_rev,
{
struct yang_module_embed *e;
+ if (!strcmp(mod_name, "ietf-inet-types") ||
+ !strcmp(mod_name, "ietf-yang-types"))
+ /* libyang has these built in, don't try finding them here */
+ return LY_ENOTFOUND;
+
for (e = embeds; e; e = e->next) {
if (e->sub_mod_name && submod_name) {
if (strcmp(e->sub_mod_name, submod_name))
diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c
index 0dfabcf6ae..97290ca84f 100644
--- a/nhrpd/nhrp_vty.c
+++ b/nhrpd/nhrp_vty.c
@@ -1150,7 +1150,7 @@ static int interface_config_write(struct vty *vty)
int i;
FOR_ALL_INTERFACES (vrf, ifp) {
- vty_frame(vty, "interface %s\n", ifp->name);
+ if_vty_config_start(vty, ifp);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@@ -1221,7 +1221,7 @@ static int interface_config_write(struct vty *vty)
}
}
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
return 0;
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 417fc69694..a612f7d1b8 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -446,7 +446,9 @@ void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
json_area = json_object_new_object();
json_object_boolean_add(json_area, "areaIsStub",
IS_AREA_STUB(oa));
- if (IS_AREA_STUB(oa)) {
+ json_object_boolean_add(json_area, "areaIsNSSA",
+ IS_AREA_NSSA(oa));
+ if (IS_AREA_STUB(oa) || IS_AREA_NSSA(oa)) {
json_object_boolean_add(json_area, "areaNoSummary",
oa->no_summary);
}
@@ -490,14 +492,16 @@ void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
} else {
- if (!IS_AREA_STUB(oa))
+ if (!IS_AREA_STUB(oa) && !IS_AREA_NSSA(oa))
vty_out(vty, " Area %s\n", oa->name);
else {
if (oa->no_summary) {
- vty_out(vty, " Area %s[Stub, No Summary]\n",
- oa->name);
+ vty_out(vty, " Area %s[%s, No Summary]\n",
+ oa->name,
+ IS_AREA_STUB(oa) ? "Stub" : "NSSA");
} else {
- vty_out(vty, " Area %s[Stub]\n", oa->name);
+ vty_out(vty, " Area %s[%s]\n", oa->name,
+ IS_AREA_STUB(oa) ? "Stub" : "NSSA");
}
}
vty_out(vty, " Number of Area scoped LSAs is %u\n",
@@ -511,11 +515,13 @@ void ospf6_area_show(struct vty *vty, struct ospf6_area *oa,
if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) {
result = monotime_since(&oa->ts_spf, NULL);
if (result / TIMER_SECOND_MICRO > 0) {
- vty_out(vty, "SPF last executed %ld.%lds ago\n",
+ vty_out(vty,
+ " SPF last executed %ld.%lds ago\n",
result / TIMER_SECOND_MICRO,
result % TIMER_SECOND_MICRO);
} else {
- vty_out(vty, "SPF last executed %ldus ago\n",
+ vty_out(vty,
+ " SPF last executed %ldus ago\n",
result);
}
} else
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index 905fbac949..1c8c5dfd3e 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -124,7 +124,6 @@ struct ospf6_area {
#define OSPF6_NSSA_TRANSLATE_ENABLED 1
};
-#define OSPF6_AREA_DEFAULT 0x00
#define OSPF6_AREA_ENABLE 0x01
#define OSPF6_AREA_ACTIVE 0x02
#define OSPF6_AREA_TRANSIT 0x04 /* TransitCapability */
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index ae9f13bc10..0d9f15d08f 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -2522,11 +2522,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
if (oi == NULL)
continue;
- if (vrf->vrf_id == VRF_DEFAULT)
- vty_frame(vty, "interface %s\n", oi->interface->name);
- else
- vty_frame(vty, "interface %s vrf %s\n",
- oi->interface->name, vrf->name);
+ if_vty_config_start(vty, ifp);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@@ -2581,7 +2577,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
ospf6_bfd_write_config(vty, oi);
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
return 0;
}
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 633b8d77cd..bb5827a176 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -148,8 +148,7 @@ struct ospf6_path {
#define OSPF6_PATH_TYPE_INTER 2
#define OSPF6_PATH_TYPE_EXTERNAL1 3
#define OSPF6_PATH_TYPE_EXTERNAL2 4
-#define OSPF6_PATH_TYPE_REDISTRIBUTE 5
-#define OSPF6_PATH_TYPE_MAX 6
+#define OSPF6_PATH_TYPE_MAX 5
#define OSPF6_PATH_SUBTYPE_DEFAULT_RT 1
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 54f6c85cea..e2db77d44b 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -436,6 +436,7 @@ static struct ospf6 *ospf6_create(const char *name)
o->fd = -1;
o->max_multipath = MULTIPATH_NUM;
+ SET_FLAG(o->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
o->oi_write_q = list_new();
@@ -885,6 +886,39 @@ DEFUN (no_ospf6_log_adjacency_changes_detail,
return CMD_SUCCESS;
}
+static void ospf6_reinstall_routes(struct ospf6 *ospf6)
+{
+ struct ospf6_route *route;
+
+ for (route = ospf6_route_head(ospf6->route_table); route;
+ route = ospf6_route_next(route))
+ ospf6_zebra_route_update_add(route, ospf6);
+}
+
+DEFPY (ospf6_send_extra_data,
+ ospf6_send_extra_data_cmd,
+ "[no] ospf6 send-extra-data zebra",
+ NO_STR
+ OSPF6_STR
+ "Extra data to Zebra for display/use\n"
+ "To zebra\n")
+{
+ VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+
+ if (no
+ && CHECK_FLAG(ospf6->config_flags,
+ OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
+ UNSET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
+ ospf6_reinstall_routes(ospf6);
+ } else if (!CHECK_FLAG(ospf6->config_flags,
+ OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) {
+ SET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA);
+ ospf6_reinstall_routes(ospf6);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf6_timers_lsa,
ospf6_timers_lsa_cmd,
"timers lsa min-arrival (0-600000)",
@@ -2202,6 +2236,10 @@ static int config_write_ospf6(struct vty *vty)
vty_out(vty, " ospf6 router-id %pI4\n",
&ospf6->router_id_static);
+ if (!CHECK_FLAG(ospf6->config_flags,
+ OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
+ vty_out(vty, " no ospf6 send-extra-data zebra\n");
+
/* log-adjacency-changes flag print. */
if (CHECK_FLAG(ospf6->config_flags,
OSPF6_LOG_ADJACENCY_CHANGES)) {
@@ -2287,6 +2325,7 @@ void ospf6_top_init(void)
install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
+ install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd);
/* LSA timers commands */
install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd);
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 4cc0923e93..77156f961d 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -32,9 +32,9 @@ struct ospf6_master {
};
/* ospf6->config_flags */
-enum {
- OSPF6_LOG_ADJACENCY_CHANGES = (1 << 0),
- OSPF6_LOG_ADJACENCY_DETAIL = (1 << 1),
+enum { OSPF6_LOG_ADJACENCY_CHANGES = (1 << 0),
+ OSPF6_LOG_ADJACENCY_DETAIL = (1 << 1),
+ OSPF6_SEND_EXTRA_DATA_TO_ZEBRA = (1 << 2),
};
/* For processing route-map change update in the callback */
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 5e50a6cc55..b818633518 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -27,6 +27,7 @@
#include "stream.h"
#include "zclient.h"
#include "memory.h"
+#include "route_opaque.h"
#include "lib/bfd.h"
#include "lib_errors.h"
@@ -371,6 +372,38 @@ DEFUN(show_zebra,
return CMD_SUCCESS;
}
+static void ospf6_zebra_append_opaque_attr(struct ospf6_route *request,
+ struct zapi_route *api)
+{
+ struct ospf_zebra_opaque ospf_opaque = {};
+
+ /* OSPF path type */
+ snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s",
+ OSPF6_PATH_TYPE_NAME(request->path.type));
+
+ switch (request->path.type) {
+ case OSPF6_PATH_TYPE_INTRA:
+ case OSPF6_PATH_TYPE_INTER:
+ /* OSPF area ID */
+ (void)inet_ntop(AF_INET, &request->path.area_id,
+ ospf_opaque.area_id,
+ sizeof(ospf_opaque.area_id));
+ break;
+ case OSPF6_PATH_TYPE_EXTERNAL1:
+ case OSPF6_PATH_TYPE_EXTERNAL2:
+ /* OSPF route tag */
+ snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u",
+ request->path.tag);
+ break;
+ default:
+ break;
+ }
+
+ SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE);
+ api->opaque.length = sizeof(struct ospf_zebra_opaque);
+ memcpy(api->opaque.data, &ospf_opaque, api->opaque.length);
+}
+
#define ADD 0
#define REM 1
static void ospf6_zebra_route_update(int type, struct ospf6_route *request,
@@ -455,6 +488,10 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request,
api.distance = ospf6_distance_apply((struct prefix_ipv6 *)dest, request,
ospf6);
+ if (type == ADD
+ && CHECK_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA))
+ ospf6_zebra_append_opaque_attr(request, &api);
+
if (type == REM)
ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
else
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 6588d70208..c169996e01 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2090,8 +2090,7 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf)
p.prefix.s_addr = 0;
p.prefixlen = 0;
- default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
- ospf->instance, &p);
+ default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE, 0, &p);
if (!default_ei)
return NULL;
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 502a4a08c1..ec0c5524c9 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -39,6 +39,22 @@
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_dump.h"
+const char *ospf_path_type_name(int path_type)
+{
+ switch (path_type) {
+ case OSPF_PATH_INTRA_AREA:
+ return "Intra-Area";
+ case OSPF_PATH_INTER_AREA:
+ return "Inter-Area";
+ case OSPF_PATH_TYPE1_EXTERNAL:
+ return "External-1";
+ case OSPF_PATH_TYPE2_EXTERNAL:
+ return "External-2";
+ default:
+ return "Unknown";
+ }
+}
+
struct ospf_route *ospf_route_new(void)
{
struct ospf_route *new;
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index c2ce0569db..5463e70ffb 100644
--- a/ospfd/ospf_route.h
+++ b/ospfd/ospf_route.h
@@ -128,6 +128,7 @@ struct ospf_route {
bool changed;
};
+extern const char *ospf_path_type_name(int path_type);
extern struct ospf_path *ospf_path_new(void);
extern void ospf_path_free(struct ospf_path *);
extern struct ospf_path *ospf_path_lookup(struct list *, struct ospf_path *);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 1a20eb515f..27cdce13c5 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2218,6 +2218,56 @@ ALIAS(no_ospf_compatible_rfc1583, no_ospf_rfc1583_flag_cmd,
"OSPF specific commands\n"
"Disable the RFC1583Compatibility flag\n")
+static void ospf_table_reinstall_routes(struct ospf *ospf,
+ struct route_table *rt)
+{
+ struct route_node *rn;
+
+ if (!rt)
+ return;
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ struct ospf_route *or;
+
+ or = rn->info;
+ if (!or)
+ continue;
+
+ if (or->type == OSPF_DESTINATION_NETWORK)
+ ospf_zebra_add(ospf, (struct prefix_ipv4 *)&rn->p, or);
+ else if (or->type == OSPF_DESTINATION_DISCARD)
+ ospf_zebra_add_discard(ospf,
+ (struct prefix_ipv4 *)&rn->p);
+ }
+}
+
+static void ospf_reinstall_routes(struct ospf *ospf)
+{
+ ospf_table_reinstall_routes(ospf, ospf->new_table);
+ ospf_table_reinstall_routes(ospf, ospf->new_external_route);
+}
+
+DEFPY (ospf_send_extra_data,
+ ospf_send_extra_data_cmd,
+ "[no] ospf send-extra-data zebra",
+ NO_STR
+ OSPF_STR
+ "Extra data to Zebra for display/use\n"
+ "To zebra\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
+
+ if (no && CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) {
+ UNSET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA);
+ ospf_reinstall_routes(ospf);
+ } else if (!CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) {
+ SET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA);
+ ospf_reinstall_routes(ospf);
+ }
+
+ return CMD_SUCCESS;
+}
+
static int ospf_timers_spf_set(struct vty *vty, unsigned int delay,
unsigned int hold, unsigned int max)
{
@@ -5892,7 +5942,7 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
struct as_external_lsa *asel;
struct prefix_ipv4 p;
- if (lsa != NULL)
+ if (lsa != NULL) {
/* If self option is set, check LSA self flag. */
if (self == 0 || IS_LSA_SELF(lsa)) {
@@ -6000,6 +6050,9 @@ static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self,
vty_out(vty, "\n");
}
+ return 1;
+ }
+
return 0;
}
@@ -6033,6 +6086,21 @@ static const char * const show_database_desc_json[] = {
"asExternalOpaqueLsa",
};
+static const char *const show_database_desc_count_json[] = {
+ "unknownCount",
+ "routerLinkStatesCount",
+ "networkLinkStatesCount",
+ "summaryLinkStatesCount",
+ "asbrSummaryLinkStatesCount",
+ "asExternalLinkStatesCount",
+ "groupMembershipLsaCount",
+ "nssaExternalLinkStatesCount",
+ "type8LsaCount",
+ "linkLocalOpaqueLsaCount",
+ "areaLocalOpaqueLsaCount",
+ "asExternalOpaqueLsaCount",
+};
+
static const char *const show_database_header[] = {
"",
"Link ID ADV Router Age Seq# CkSum Link count",
@@ -6705,6 +6773,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,
json_object *json_lsa = NULL;
int type;
json_object *json_lsa_array = NULL;
+ uint32_t count;
if (json)
json_areas = json_object_new_object();
@@ -6714,6 +6783,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,
json_area = json_object_new_object();
for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) {
+ count = 0;
switch (type) {
case OSPF_AS_EXTERNAL_LSA:
case OSPF_OPAQUE_AS_LSA:
@@ -6750,12 +6820,19 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,
json_lsa);
}
- show_lsa_summary(vty, lsa, self,
- json_lsa);
+ count += show_lsa_summary(
+ vty, lsa, self, json_lsa);
}
if (!json)
vty_out(vty, "\n");
+ else
+ json_object_int_add(
+ json_area,
+
+ show_database_desc_count_json
+ [type],
+ count);
}
}
if (json)
@@ -6770,6 +6847,7 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,
json_object_object_add(json, "areas", json_areas);
for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) {
+ count = 0;
switch (type) {
case OSPF_AS_EXTERNAL_LSA:
case OSPF_OPAQUE_AS_LSA:
@@ -6798,11 +6876,17 @@ void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self,
json_lsa);
}
- show_lsa_summary(vty, lsa, self, json_lsa);
+ count += show_lsa_summary(vty, lsa, self,
+ json_lsa);
}
if (!json)
vty_out(vty, "\n");
+ else
+ json_object_int_add(
+ json,
+ show_database_desc_count_json[type],
+ count);
}
}
@@ -11535,12 +11619,8 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
if (memcmp(ifp->name, "VLINK", 5) == 0)
continue;
- vty_frame(vty, "!\n");
- if (ifp->vrf->vrf_id == VRF_DEFAULT)
- vty_frame(vty, "interface %s\n", ifp->name);
- else
- vty_frame(vty, "interface %s vrf %s\n", ifp->name,
- vrf->name);
+ if_vty_config_start(vty, ifp);
+
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@@ -11750,7 +11830,7 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
ospf_opaque_config_write_if(vty, ifp);
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
return write;
@@ -12212,6 +12292,10 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf)
vty_out(vty, " ospf router-id %pI4\n",
&ospf->router_id_static);
+ /* zebra opaque attributes configuration. */
+ if (!CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA))
+ vty_out(vty, " no ospf send-extra-data zebra\n");
+
/* ABR type print. */
if (ospf->abr_type != OSPF_ABR_DEFAULT)
vty_out(vty, " ospf abr-type %s\n",
@@ -12663,6 +12747,9 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &ospf_rfc1583_flag_cmd);
install_element(OSPF_NODE, &no_ospf_rfc1583_flag_cmd);
+ /* "ospf send-extra-data zebra" commands. */
+ install_element(OSPF_NODE, &ospf_send_extra_data_cmd);
+
/* "network area" commands. */
install_element(OSPF_NODE, &ospf_network_area_cmd);
install_element(OSPF_NODE, &no_ospf_network_area_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index b0ed66da5f..7834b7d934 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -33,6 +33,7 @@
#include "filter.h"
#include "plist.h"
#include "log.h"
+#include "route_opaque.h"
#include "lib/bfd.h"
#include "nexthop.h"
@@ -255,6 +256,38 @@ static void ospf_zebra_add_nexthop(struct ospf *ospf, struct ospf_path *path,
api->nexthop_num++;
}
+static void ospf_zebra_append_opaque_attr(struct ospf_route *or,
+ struct zapi_route *api)
+{
+ struct ospf_zebra_opaque ospf_opaque = {};
+
+ /* OSPF path type */
+ snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s",
+ ospf_path_type_name(or->path_type));
+
+ switch (or->path_type) {
+ case OSPF_PATH_INTRA_AREA:
+ case OSPF_PATH_INTER_AREA:
+ /* OSPF area ID */
+ (void)inet_ntop(AF_INET, &or->u.std.area_id,
+ ospf_opaque.area_id,
+ sizeof(ospf_opaque.area_id));
+ break;
+ case OSPF_PATH_TYPE1_EXTERNAL:
+ case OSPF_PATH_TYPE2_EXTERNAL:
+ /* OSPF route tag */
+ snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u",
+ or->u.ext.tag);
+ break;
+ default:
+ break;
+ }
+
+ SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE);
+ api->opaque.length = sizeof(struct ospf_zebra_opaque);
+ memcpy(api->opaque.data, &ospf_opaque, api->opaque.length);
+}
+
void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
struct ospf_route * or)
{
@@ -322,6 +355,9 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
}
}
+ if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA))
+ ospf_zebra_append_opaque_attr(or, &api);
+
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index e5f3eec603..726ce329e3 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -406,6 +406,8 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
ospf_opaque_type11_lsa_init(new);
+ SET_FLAG(new->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA);
+
QOBJ_REG(new, ospf);
new->fd = -1;
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index d64a044e14..3369429eba 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -125,6 +125,7 @@ enum {
OSPF_OPAQUE_CAPABLE = (1 << 2),
OSPF_LOG_ADJACENCY_CHANGES = (1 << 3),
OSPF_LOG_ADJACENCY_DETAIL = (1 << 4),
+ OSPF_SEND_EXTRA_DATA_TO_ZEBRA = (1 << 5),
};
/* TI-LFA */
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index ebcbbb7205..c9ec532bb9 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -1197,18 +1197,14 @@ static int pbr_interface_config_write(struct vty *vty)
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
FOR_ALL_INTERFACES (vrf, ifp) {
- if (vrf->vrf_id == VRF_DEFAULT)
- vty_frame(vty, "interface %s\n", ifp->name);
- else
- vty_frame(vty, "interface %s vrf %s\n",
- ifp->name, vrf->name);
+ if_vty_config_start(vty, ifp);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
pbr_map_write_interfaces(vty, ifp);
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
}
diff --git a/pimd/pim6_main.c b/pimd/pim6_main.c
index 02654e1cb6..3d8ebd0d86 100644
--- a/pimd/pim6_main.c
+++ b/pimd/pim6_main.c
@@ -178,8 +178,7 @@ int main(int argc, char **argv, char **envp)
/*
* Initialize zclient "update" and "lookup" sockets
*/
- if_zapi_callbacks(pim_ifp_create, pim_ifp_up,
- pim_ifp_down, pim_ifp_destroy);
+ pim_iface_init();
/* TODO PIM6: next line is temporary since pim_cmd_init is disabled */
if_cmd_init(NULL);
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 696544c8d6..31f672bb80 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -29,7 +29,6 @@
#include "pim_instance.h"
#include "pim_neighbor.h"
-#include "pim_cmd.h"
#include "pim_vty.h"
#include "pim_iface.h"
#include "pim_bfd.h"
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index c0401b83ce..e2ac777304 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -7380,9 +7380,10 @@ DEFUN (no_ip_pim_rp,
int idx_rp = 4, idx_group = 5;
const char *group_str =
(argc == 6) ? argv[idx_group]->arg : "224.0.0.0/4";
- char group_list_xpath[XPATH_MAXLEN + 32];
- char group_xpath[XPATH_MAXLEN + 64];
+ char group_list_xpath[XPATH_MAXLEN];
+ char group_xpath[XPATH_MAXLEN];
char rp_xpath[XPATH_MAXLEN];
+ int printed;
const char *vrfname;
const struct lyd_node *group_dnode;
@@ -7394,11 +7395,24 @@ DEFUN (no_ip_pim_rp,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
argv[idx_rp]->arg);
- snprintf(group_list_xpath, sizeof(group_list_xpath), "%s/group-list",
- rp_xpath);
- snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
- group_list_xpath, group_str);
+ printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
+ "%s/group-list", rp_xpath);
+
+ if (printed >= (int)(sizeof(group_list_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
+ group_list_xpath, group_str);
+
+ if (printed >= (int)(sizeof(group_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
if (!yang_dnode_exists(vty->candidate_config->dnode, group_xpath)) {
vty_out(vty, "%% Unable to find specified RP\n");
@@ -7859,11 +7873,18 @@ DEFUN (interface_no_ip_igmp,
IFACE_IGMP_STR)
{
const struct lyd_node *pim_enable_dnode;
- char pim_if_xpath[XPATH_MAXLEN + 20];
+ char pim_if_xpath[XPATH_MAXLEN];
- snprintf(pim_if_xpath, sizeof(pim_if_xpath),
- "%s/frr-pim:pim/address-family[address-family='%s']",
- VTY_CURR_XPATH, "frr-routing:ipv4");
+ int printed =
+ snprintf(pim_if_xpath, sizeof(pim_if_xpath),
+ "%s/frr-pim:pim/address-family[address-family='%s']",
+ VTY_CURR_XPATH, "frr-routing:ipv4");
+
+ if (printed >= (int)(sizeof(pim_if_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
@@ -8406,11 +8427,19 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm,
IFACE_PIM_STR)
{
const struct lyd_node *igmp_enable_dnode;
- char igmp_if_xpath[XPATH_MAXLEN + 20];
+ char igmp_if_xpath[XPATH_MAXLEN];
+
+ int printed =
+ snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
+ "%s/frr-gmp:gmp/address-family[address-family='%s']",
+ VTY_CURR_XPATH, "frr-routing:ipv4");
+
+ if (printed >= (int)(sizeof(igmp_if_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
- "%s/frr-gmp:gmp/address-family[address-family='%s']",
- VTY_CURR_XPATH, "frr-routing:ipv4");
igmp_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
FRR_GMP_ENABLE_XPATH,
VTY_CURR_XPATH,
@@ -8441,11 +8470,19 @@ DEFUN_HIDDEN (interface_no_ip_pim_sm,
IFACE_PIM_SM_STR)
{
const struct lyd_node *igmp_enable_dnode;
- char igmp_if_xpath[XPATH_MAXLEN + 20];
+ char igmp_if_xpath[XPATH_MAXLEN];
+
+ int printed =
+ snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
+ "%s/frr-gmp:gmp/address-family[address-family='%s']",
+ VTY_CURR_XPATH, "frr-routing:ipv4");
+
+ if (printed >= (int)(sizeof(igmp_if_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
- "%s/frr-gmp:gmp/address-family[address-family='%s']",
- VTY_CURR_XPATH, "frr-routing:ipv4");
igmp_enable_dnode =
yang_dnode_getf(vty->candidate_config->dnode,
FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
@@ -8477,11 +8514,19 @@ DEFUN (interface_no_ip_pim,
PIM_STR)
{
const struct lyd_node *igmp_enable_dnode;
- char igmp_if_xpath[XPATH_MAXLEN + 20];
+ char igmp_if_xpath[XPATH_MAXLEN];
+
+ int printed =
+ snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
+ "%s/frr-gmp:gmp/address-family[address-family='%s']",
+ VTY_CURR_XPATH, "frr-routing:ipv4");
+
+ if (printed >= (int)(sizeof(igmp_if_xpath))) {
+ vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
+ XPATH_MAXLEN);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
- "%s/frr-gmp:gmp/address-family[address-family='%s']",
- VTY_CURR_XPATH, "frr-routing:ipv4");
igmp_enable_dnode =
yang_dnode_getf(vty->candidate_config->dnode,
FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
@@ -11227,6 +11272,10 @@ void pim_cmd_init(void)
install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
install_element(CONFIG_NODE, &debug_pim_packets_cmd);
install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
+ install_element(CONFIG_NODE, &debug_pim_packetdump_send_cmd);
+ install_element(CONFIG_NODE, &no_debug_pim_packetdump_send_cmd);
+ install_element(CONFIG_NODE, &debug_pim_packetdump_recv_cmd);
+ install_element(CONFIG_NODE, &no_debug_pim_packetdump_recv_cmd);
install_element(CONFIG_NODE, &debug_pim_trace_cmd);
install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 8b27809c7c..72e04460d5 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1521,7 +1521,7 @@ int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
return count;
}
-int pim_ifp_create(struct interface *ifp)
+static int pim_ifp_create(struct interface *ifp)
{
struct pim_instance *pim;
@@ -1589,7 +1589,7 @@ int pim_ifp_create(struct interface *ifp)
return 0;
}
-int pim_ifp_up(struct interface *ifp)
+static int pim_ifp_up(struct interface *ifp)
{
struct pim_interface *pim_ifp;
struct pim_instance *pim;
@@ -1645,7 +1645,7 @@ int pim_ifp_up(struct interface *ifp)
return 0;
}
-int pim_ifp_down(struct interface *ifp)
+static int pim_ifp_down(struct interface *ifp)
{
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
@@ -1681,7 +1681,7 @@ int pim_ifp_down(struct interface *ifp)
return 0;
}
-int pim_ifp_destroy(struct interface *ifp)
+static int pim_ifp_destroy(struct interface *ifp)
{
struct pim_instance *pim;
@@ -1702,3 +1702,25 @@ int pim_ifp_destroy(struct interface *ifp)
return 0;
}
+
+static int pim_if_new_hook(struct interface *ifp)
+{
+ return 0;
+}
+
+static int pim_if_delete_hook(struct interface *ifp)
+{
+ if (ifp->info)
+ pim_if_delete(ifp);
+
+ return 0;
+}
+
+void pim_iface_init(void)
+{
+ hook_register_prio(if_add, 0, pim_if_new_hook);
+ hook_register_prio(if_del, 0, pim_if_delete_hook);
+
+ if_zapi_callbacks(pim_ifp_create, pim_ifp_up, pim_ifp_down,
+ pim_ifp_destroy);
+}
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index f251c55e72..1ddf743619 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -259,9 +259,6 @@ bool pim_if_is_vrf_device(struct interface *ifp);
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
-extern int pim_ifp_create(struct interface *ifp);
-extern int pim_ifp_up(struct interface *ifp);
-extern int pim_ifp_down(struct interface *ifp);
-extern int pim_ifp_destroy(struct interface *ifp);
+void pim_iface_init(void);
#endif /* PIM_IFACE_H */
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index eb1cedd90d..92c34f51a1 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -136,8 +136,7 @@ int main(int argc, char **argv, char **envp)
/*
* Initialize zclient "update" and "lookup" sockets
*/
- if_zapi_callbacks(pim_ifp_create, pim_ifp_up,
- pim_ifp_down, pim_ifp_destroy);
+ pim_iface_init();
pim_zebra_init();
pim_bfd_init();
pim_mlag_init();
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index 40d864d1da..673347b4f6 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -31,7 +31,6 @@
#include <lib/lib_errors.h>
#include "pimd.h"
-#include "pim_cmd.h"
#include "pim_memory.h"
#include "pim_iface.h"
#include "pim_rp.h"
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index c7411070d3..8c0132a9ac 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -29,7 +29,6 @@
#include "pimd.h"
#include "pim_vty.h"
#include "pim_iface.h"
-#include "pim_cmd.h"
#include "pim_str.h"
#include "pim_ssmpingd.h"
#include "pim_pim.h"
@@ -162,6 +161,11 @@ int pim_debug_config_write(struct vty *vty)
++writes;
}
+ if (PIM_DEBUG_PIM_NHT_RP) {
+ vty_out(vty, "debug pim nht rp\n");
+ ++writes;
+ }
+
return writes;
}
@@ -298,11 +302,8 @@ int pim_interface_config_write(struct vty *vty)
continue;
/* IF name */
- if (vrf->vrf_id == VRF_DEFAULT)
- vty_frame(vty, "interface %s\n", ifp->name);
- else
- vty_frame(vty, "interface %s vrf %s\n",
- ifp->name, vrf->name);
+ if_vty_config_start(vty, ifp);
+
++writes;
if (ifp->desc) {
@@ -451,7 +452,7 @@ int pim_interface_config_write(struct vty *vty)
pim_bfd_write_config(vty, ifp);
++writes;
}
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
++writes;
}
}
diff --git a/redhat/frr.logrotate b/redhat/frr.logrotate
index b488ad08dc..22b2332b7c 100644
--- a/redhat/frr.logrotate
+++ b/redhat/frr.logrotate
@@ -138,7 +138,7 @@
notifempty
missingok
postrotate
- /bin/kill -USR1 `cat /var/run/frr/static.pid 2> /dev/null` 2> /dev/null || true
+ /bin/kill -USR1 `cat /var/run/frr/staticd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
index b50c5683bf..accc906bf2 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_llgr/r0/bgpd.conf b/tests/topotests/bgp_llgr/r0/bgpd.conf
index d93ee193bc..a20e64fa42 100644
--- a/tests/topotests/bgp_llgr/r0/bgpd.conf
+++ b/tests/topotests/bgp_llgr/r0/bgpd.conf
@@ -4,6 +4,8 @@ router bgp 65000
bgp graceful-restart restart-time 0
bgp long-lived-graceful-restart stale-time 20
neighbor 192.168.0.2 remote-as external
+ neighbor 192.168.0.2 timers 3 10
+ neighbor 192.168.0.2 timers connect 1
address-family ipv4 unicast
redistribute connected
exit-address-family
diff --git a/tests/topotests/bgp_llgr/r1/bgpd.conf b/tests/topotests/bgp_llgr/r1/bgpd.conf
index f8c9877730..bf33eebc51 100644
--- a/tests/topotests/bgp_llgr/r1/bgpd.conf
+++ b/tests/topotests/bgp_llgr/r1/bgpd.conf
@@ -4,6 +4,8 @@ router bgp 65001
bgp graceful-restart restart-time 0
bgp long-lived-graceful-restart stale-time 20
neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 3 10
+ neighbor 192.168.1.2 timers connect 1
address-family ipv4 unicast
redistribute connected
exit-address-family
diff --git a/tests/topotests/bgp_llgr/r2/bgpd.conf b/tests/topotests/bgp_llgr/r2/bgpd.conf
index ea8e6beef1..6515ef83a0 100644
--- a/tests/topotests/bgp_llgr/r2/bgpd.conf
+++ b/tests/topotests/bgp_llgr/r2/bgpd.conf
@@ -3,7 +3,16 @@ router bgp 65002
bgp graceful-restart
bgp long-lived-graceful-restart stale-time 20
neighbor 192.168.0.1 remote-as external
+ neighbor 192.168.0.1 timers 3 10
+ neighbor 192.168.0.1 timers connect 1
neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 3 10
+ neighbor 192.168.1.1 timers connect 1
neighbor 192.168.2.1 remote-as external
+ neighbor 192.168.2.1 timers 3 10
+ neighbor 192.168.2.1 timers connect 1
+ neighbor PG peer-group
+ neighbor PG remote-as external
+ bgp listen range 192.168.3.0/24 peer-group PG
address-family ipv4 unicast
neighbor 192.168.1.1 weight 100
diff --git a/tests/topotests/bgp_llgr/r2/zebra.conf b/tests/topotests/bgp_llgr/r2/zebra.conf
index 0fa589f3a9..e5e88d4773 100644
--- a/tests/topotests/bgp_llgr/r2/zebra.conf
+++ b/tests/topotests/bgp_llgr/r2/zebra.conf
@@ -8,3 +8,6 @@ int r2-eth1
int r2-eth2
ip address 192.168.2.2/24
!
+int r2-eth3
+ ip address 192.168.3.2/24
+!
diff --git a/tests/topotests/bgp_llgr/r3/bgpd.conf b/tests/topotests/bgp_llgr/r3/bgpd.conf
index d73fdccb1d..dfe20c1069 100644
--- a/tests/topotests/bgp_llgr/r3/bgpd.conf
+++ b/tests/topotests/bgp_llgr/r3/bgpd.conf
@@ -4,3 +4,5 @@ router bgp 65003
bgp graceful-restart
bgp long-lived-graceful-restart stale-time 20
neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers 3 10
+ neighbor 192.168.2.2 timers connect 1
diff --git a/tests/topotests/bgp_llgr/r4/bgpd.conf b/tests/topotests/bgp_llgr/r4/bgpd.conf
new file mode 100644
index 0000000000..49ce387392
--- /dev/null
+++ b/tests/topotests/bgp_llgr/r4/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 65004
+ bgp router-id 192.168.3.1
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ bgp graceful-restart restart-time 0
+ bgp long-lived-graceful-restart stale-time 30
+ neighbor 192.168.3.2 remote-as external
+ neighbor 192.168.3.2 timers 3 10
+ neighbor 192.168.3.2 timers connect 1
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_llgr/r4/zebra.conf b/tests/topotests/bgp_llgr/r4/zebra.conf
new file mode 100644
index 0000000000..7ec20be8bb
--- /dev/null
+++ b/tests/topotests/bgp_llgr/r4/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.1.2/32
+!
+int r4-eth0
+ ip address 192.168.3.1/24
+!
diff --git a/tests/topotests/bgp_llgr/test_bgp_llgr.py b/tests/topotests/bgp_llgr/test_bgp_llgr.py
index df4f401d02..fa57f66400 100644
--- a/tests/topotests/bgp_llgr/test_bgp_llgr.py
+++ b/tests/topotests/bgp_llgr/test_bgp_llgr.py
@@ -53,7 +53,7 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
- for routern in range(0, 5):
+ for routern in range(0, 6):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s0")
@@ -68,6 +68,11 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
+ # Dynamic neighbor
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r4"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -104,14 +109,15 @@ def test_bgp_llgr():
output = json.loads(router.vtysh_cmd("show ip bgp json"))
expected = {
"routes": {
- "172.16.1.1/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}]
+ "172.16.1.1/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}],
+ "172.16.1.2/32": [{"nexthops": [{"ip": "192.168.2.2", "used": True}]}],
}
}
return topotest.json_cmp(output, expected)
step("Check if we can see 172.16.1.1/32 after initial converge in R3")
test_func = functools.partial(_bgp_converge, r3)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Cannot see 172.16.1.1/32 in r3"
def _bgp_weight_prefered_route(router):
@@ -134,7 +140,7 @@ def test_bgp_llgr():
"Check if we can see 172.16.1.1/32 as best selected due to higher weigth in R2"
)
test_func = functools.partial(_bgp_weight_prefered_route, r2)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert (
result is None
), "Prefix 172.16.1.1/32 is not selected as bests path due to weight"
@@ -142,14 +148,14 @@ def test_bgp_llgr():
step("Kill bgpd in R1")
kill_router_daemons(tgen, "r1", ["bgpd"])
- def _bgp_stale_route(router):
- output = json.loads(router.vtysh_cmd("show ip bgp 172.16.1.1/32 json"))
+ def _bgp_stale_route(router, prefix):
+ output = json.loads(router.vtysh_cmd("show ip bgp {} json".format(prefix)))
expected = {"paths": [{"community": {"string": "llgr-stale"}, "stale": True}]}
return topotest.json_cmp(output, expected)
step("Check if we can see 172.16.1.1/32 as stale in R2")
- test_func = functools.partial(_bgp_stale_route, r2)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ test_func = functools.partial(_bgp_stale_route, r2, "172.16.1.1/32")
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Prefix 172.16.1.1/32 is not stale"
def _bgp_llgr_depreference_route(router):
@@ -170,14 +176,22 @@ def test_bgp_llgr():
step("Check if we can see 172.16.1.1/32 depreferenced due to LLGR_STALE in R2")
test_func = functools.partial(_bgp_llgr_depreference_route, r2)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Prefix 172.16.1.1/32 is not depreferenced due to LLGR_STALE"
step("Check if we can see 172.16.1.1/32 after R1 was killed in R3")
test_func = functools.partial(_bgp_converge, r3)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Cannot see 172.16.1.1/32 in r3"
+ step("Kill bgpd in R4 (dynamic peer)")
+ kill_router_daemons(tgen, "r4", ["bgpd"])
+
+ step("Check if we can see 172.16.1.2/32 after R4 (dynamic peer) was killed")
+ test_func = functools.partial(_bgp_stale_route, r2, "172.16.1.2/32")
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
+ assert result is None, "Cannot see 172.16.1.2/32 in r2"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/isis_te_topo1/__init__.py b/tests/topotests/isis_te_topo1/__init__.py
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/__init__.py
diff --git a/tests/topotests/isis_te_topo1/r1/isisd.conf b/tests/topotests/isis_te_topo1/r1/isisd.conf
new file mode 100644
index 0000000000..938d713ced
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r1/isisd.conf
@@ -0,0 +1,31 @@
+!
+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
+!
+
diff --git a/tests/topotests/isis_te_topo1/r1/zebra.conf b/tests/topotests/isis_te_topo1/r1/zebra.conf
new file mode 100644
index 0000000000..814d8f8c97
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r1/zebra.conf
@@ -0,0 +1,25 @@
+!
+hostname r1
+!
+interface lo
+ ip address 10.0.255.1/32
+ ipv6 address 2001:db8:ffff::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
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/isis_te_topo1/r2/isisd.conf b/tests/topotests/isis_te_topo1/r2/isisd.conf
new file mode 100644
index 0000000000..f389e90762
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r2/isisd.conf
@@ -0,0 +1,45 @@
+!
+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
+!
diff --git a/tests/topotests/isis_te_topo1/r2/zebra.conf b/tests/topotests/isis_te_topo1/r2/zebra.conf
new file mode 100644
index 0000000000..26b48ded78
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r2/zebra.conf
@@ -0,0 +1,39 @@
+!
+hostname r2
+!
+interface lo
+ ip address 10.0.255.2/32
+ ipv6 address 2001:db8:ffff::2/128
+!
+interface r2-eth0
+ ip address 10.0.0.2/24
+ link-params
+ enable
+ exit-link-params
+!
+interface r2-eth1
+ ip address 10.0.1.2/24
+ ipv6 address 2001:db8:1::1:2/64
+ link-params
+ enable
+ exit-link-params
+!
+interface r2-eth2
+ ip address 10.0.3.2/24
+ ipv6 address 2001:db8:3::3:2/64
+ link-params
+ 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 30
+ delay 25000
+ use-bw 1.25e+8
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/isis_te_topo1/r3/isisd.conf b/tests/topotests/isis_te_topo1/r3/isisd.conf
new file mode 100644
index 0000000000..4920a17c4c
--- /dev/null
+++ b/tests/topotests/isis_te_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:1000::3
+!
diff --git a/tests/topotests/isis_te_topo1/r3/zebra.conf b/tests/topotests/isis_te_topo1/r3/zebra.conf
new file mode 100644
index 0000000000..6a82f30d82
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r3/zebra.conf
@@ -0,0 +1,25 @@
+!
+hostname r3
+!
+interface lo
+ ip address 10.0.255.3/32
+ ipv6 address 2001:db8:ffff::3/128
+!
+interface r3-eth0
+ ip address 10.0.3.3/24
+ ipv6 address 2001:db8:3::3:3/64
+ link-params
+ enable
+ admin-grp 0x20
+ exit-link-params
+!
+interface r3-eth1
+ ipv6 address 2001:db8:5::4:3/64
+ link-params
+ enable
+ metric 10
+ delay 50000
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/isis_te_topo1/r4/isisd.conf b/tests/topotests/isis_te_topo1/r4/isisd.conf
new file mode 100644
index 0000000000..51e9ba6dec
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r4/isisd.conf
@@ -0,0 +1,39 @@
+!
+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
+ 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/isis_te_topo1/r4/zebra.conf b/tests/topotests/isis_te_topo1/r4/zebra.conf
new file mode 100644
index 0000000000..2f6a38e77a
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/r4/zebra.conf
@@ -0,0 +1,22 @@
+!
+hostname r4
+!
+interface lo
+ ip address 10.0.255.4/32
+ ipv6 address 2001:db8:ffff::4/128
+!
+interface r4-eth0
+ ip address 10.0.4.4/24
+ ipv6 address 2001:db8:4::2:4/64
+ link-params
+ enable
+ exit-link-params
+!
+interface r4-eth1
+ ipv6 address 2001:db8:5::3:4/64
+ link-params
+ enable
+ exit-link-params
+!
+ip forwarding
+!
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step1.json b/tests/topotests/isis_te_topo1/reference/ted_step1.json
new file mode 100644
index 0000000000..7a47733801
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step1.json
@@ -0,0 +1,851 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "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"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step2.json b/tests/topotests/isis_te_topo1/reference/ted_step2.json
new file mode 100644
index 0000000000..8277e6d532
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step2.json
@@ -0,0 +1,651 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":10,
+ "subnetsCount":18,
+ "vertices":[
+ {
+ "vertex-id":1,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r1",
+ "router-id":"10.0.255.1"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.4",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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.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: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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step3.json b/tests/topotests/isis_te_topo1/reference/ted_step3.json
new file mode 100644
index 0000000000..0ade398847
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step3.json
@@ -0,0 +1,752 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":12,
+ "subnetsCount":20,
+ "vertices":[
+ {
+ "vertex-id":1,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r1",
+ "router-id":"10.0.255.1"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.4",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":1,
+ "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-v6":"2001:db8::1",
+ "remote-address-v6":"2001:db8::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":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "local-vertex-id":2,
+ "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,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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.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\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8::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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step4.json b/tests/topotests/isis_te_topo1/reference/ted_step4.json
new file mode 100644
index 0000000000..0ade398847
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step4.json
@@ -0,0 +1,752 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":12,
+ "subnetsCount":20,
+ "vertices":[
+ {
+ "vertex-id":1,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r1",
+ "router-id":"10.0.255.1"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.4",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":1,
+ "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-v6":"2001:db8::1",
+ "remote-address-v6":"2001:db8::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":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "local-vertex-id":2,
+ "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,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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.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\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8::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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step5.json b/tests/topotests/isis_te_topo1/reference/ted_step5.json
new file mode 100644
index 0000000000..ba9bdb01ff
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step5.json
@@ -0,0 +1,952 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":16,
+ "subnetsCount":24,
+ "vertices":[
+ {
+ "vertex-id":1,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r1",
+ "router-id":"10.0.255.1"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.4",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":1,
+ "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-v6":"2001:db8::1",
+ "remote-address-v6":"2001:db8::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":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "local-vertex-id":2,
+ "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,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8::2\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/reference/ted_step6.json b/tests/topotests/isis_te_topo1/reference/ted_step6.json
new file mode 100644
index 0000000000..83bb27235e
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/reference/ted_step6.json
@@ -0,0 +1,953 @@
+{
+ "ted":{
+ "name":"ISIS",
+ "key":1,
+ "verticesCount":4,
+ "edgesCount":16,
+ "subnetsCount":24,
+ "vertices":[
+ {
+ "vertex-id":1,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r1",
+ "router-id":"10.0.255.1"
+ },
+ {
+ "vertex-id":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r2",
+ "router-id":"10.0.255.2"
+ },
+ {
+ "vertex-id":3,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r3",
+ "router-id":"10.0.255.3",
+ "router-id-v6":"2001:db8:1000::3"
+ },
+ {
+ "vertex-id":4,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "name":"r4",
+ "router-id":"10.0.255.4",
+ "segment-routing":{
+ "srgb-size":10000,
+ "srgb-lower":10000,
+ "algorithms":[
+ {
+ "0":"SPF"
+ }
+ ],
+ "srlb-size":1000,
+ "srlb-lower":5000,
+ "msd":12
+ }
+ }
+ ],
+ "edges":[
+ {
+ "edge-id":1,
+ "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-v6":"2001:db8::1",
+ "remote-address-v6":"2001:db8::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":2,
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "local-vertex-id":2,
+ "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,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ },
+ "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":50000
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":0,
+ "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
+ }
+ ]
+ }
+ },
+ {
+ "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":30,
+ "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
+ }
+ },
+ {
+ "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":0,
+ "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":20000,
+ "jitter":10000
+ },
+ "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\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8::2\/64",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "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:ffff::1\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0001",
+ "vertex-id":1,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::2\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0002",
+ "vertex-id":2,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::3\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0003",
+ "vertex-id":3,
+ "metric":10
+ },
+ {
+ "subnet-id":"2001:db8:ffff::4\/128",
+ "status":"Sync",
+ "origin":"ISIS_L2",
+ "advertised-router":"0000.0000.0004",
+ "vertex-id":4,
+ "metric":10,
+ "segment-routing":{
+ "pref-sid":1400,
+ "algo":0,
+ "flags":"0x60"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
new file mode 100644
index 0000000000..0e453d30e3
--- /dev/null
+++ b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
@@ -0,0 +1,265 @@
+#!/usr/bin/env python
+
+#
+# test_isis_te_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 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_isis_te_topo1.py: Test the FRR IS-IS with Traffic Engineering.
+
+ +------------+
+ | |
+ | 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 IS-IS TE 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))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module():
+ "Teardown the pytest environment"
+
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+ logger.info("\n\n---- IS-IS TE 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 isis mpls-te database 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 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")
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step1.json")
+
+
+def test_step2():
+ "Step2: Shutdown interface between r1 and r2 and verify that \
+ corresponding Edges are removed from the TED on all routers "
+
+ tgen = setup_testcase("Step2: Shutdown interface between r1 & r2")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "shutdown"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "shutdown"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step2.json")
+
+
+def test_step3():
+ "Step3: Enable IPv6 address between r1 and r2 and verify that \
+ corresponding Edges are added in the TED on all routers"
+
+ tgen = setup_testcase("Step3: Add IPv6 on r1 and r2 interfaces")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"')
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"')
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step3.json")
+
+
+def test_step4():
+ "Step4: Modify Segment Routing Prefix SID advertisement on Router r4"
+
+ tgen = setup_testcase("Step4: Modify Prefix SID on router r4")
+
+ tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"')
+ tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step4.json")
+
+
+def test_step5():
+ "Step5: Re-enable interface between r1 & r2 and verify that corresponding \
+ Edges are added in the TED on all routers"
+
+ tgen = setup_testcase("Step5: Re-enable interface between r1 & r2")
+
+ tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth1" -c "no shutdown"')
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth1" -c "no shutdown"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step5.json")
+
+
+def test_step6():
+ "Step6: Set delay and jitter for interface r4-eth0 on r4, remove use-bw \
+ for interface r2-eth3 on r2 and verify that corresponding Edges are \
+ updated in the TED on all routers"
+
+ tgen = setup_testcase("Step6: Modify link parameters on r2 & r4")
+
+ tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"')
+ tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"')
+ tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"')
+
+ for rname in ["r1", "r2", "r3", "r4"]:
+ compare_ted_json_output(tgen, rname, "ted_step6.json")
+
+
+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_topo1_vrf/r1/isisd.conf b/tests/topotests/isis_topo1_vrf/r1/isisd.conf
index 0e8e490c94..4dd681527b 100755
--- a/tests/topotests/isis_topo1_vrf/r1/isisd.conf
+++ b/tests/topotests/isis_topo1_vrf/r1/isisd.conf
@@ -2,9 +2,9 @@ hostname r1
! debug isis adj-packets
! debug isis events
! debug isis update-packets
-interface r1-eth0
- ip router isis 1 vrf r1-cust1
- ipv6 router isis 1 vrf r1-cust1
+interface r1-eth0 vrf r1-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-2-only
!
router isis 1 vrf r1-cust1
diff --git a/tests/topotests/isis_topo1_vrf/r2/isisd.conf b/tests/topotests/isis_topo1_vrf/r2/isisd.conf
index 1e9bb9fb7f..955bb5412a 100755
--- a/tests/topotests/isis_topo1_vrf/r2/isisd.conf
+++ b/tests/topotests/isis_topo1_vrf/r2/isisd.conf
@@ -2,9 +2,9 @@ hostname r2
! debug isis adj-packets
! debug isis events
! debug isis update-packets
-interface r2-eth0
- ip router isis 1 vrf r2-cust1
- ipv6 router isis 1 vrf r2-cust1
+interface r2-eth0 vrf r2-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-2-only
!
router isis 1 vrf r2-cust1
diff --git a/tests/topotests/isis_topo1_vrf/r3/isisd.conf b/tests/topotests/isis_topo1_vrf/r3/isisd.conf
index 93a33f6db2..d127b3aa29 100755
--- a/tests/topotests/isis_topo1_vrf/r3/isisd.conf
+++ b/tests/topotests/isis_topo1_vrf/r3/isisd.conf
@@ -2,14 +2,14 @@ hostname r3
! debug isis adj-packets
! debug isis events
! debug isis update-packets
-interface r3-eth0
- ip router isis 1 vrf r3-cust1
- ipv6 router isis 1 vrf r3-cust1
+interface r3-eth0 vrf r3-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-2-only
!
-interface r3-eth1
- ip router isis 1 vrf r3-cust1
- ipv6 router isis 1 vrf r3-cust1
+interface r3-eth1 vrf r3-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-1
!
router isis 1 vrf r3-cust1
diff --git a/tests/topotests/isis_topo1_vrf/r4/isisd.conf b/tests/topotests/isis_topo1_vrf/r4/isisd.conf
index b8c0b77f44..fd11b2cf92 100755
--- a/tests/topotests/isis_topo1_vrf/r4/isisd.conf
+++ b/tests/topotests/isis_topo1_vrf/r4/isisd.conf
@@ -5,14 +5,14 @@ hostname r4
! debug isis lsp-gen
! debug isis lsp-sched
-interface r4-eth0
- ip router isis 1 vrf r4-cust1
- ipv6 router isis 1 vrf r4-cust1
+interface r4-eth0 vrf r4-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-2-only
!
-interface r4-eth1
- ip router isis 1 vrf r4-cust1
- ipv6 router isis 1 vrf r4-cust1
+interface r4-eth1 vrf r4-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-1
!
router isis 1 vrf r4-cust1
diff --git a/tests/topotests/isis_topo1_vrf/r5/isisd.conf b/tests/topotests/isis_topo1_vrf/r5/isisd.conf
index e6febd5dea..67776373f3 100755
--- a/tests/topotests/isis_topo1_vrf/r5/isisd.conf
+++ b/tests/topotests/isis_topo1_vrf/r5/isisd.conf
@@ -2,14 +2,14 @@ hostname r5
! debug isis adj-packets
! debug isis events
! debug isis update-packets
-interface r5-eth0
- ip router isis 1 vrf r5-cust1
- ipv6 router isis 1 vrf r5-cust1
+interface r5-eth0 vrf r5-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-1
!
-interface r5-eth1
- ip router isis 1 vrf r5-cust1
- ipv6 router isis 1 vrf r5-cust1
+interface r5-eth1 vrf r5-cust1
+ ip router isis 1
+ ipv6 router isis 1
isis circuit-type level-1
!
router isis 1 vrf r5-cust1
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index c744e5bbbf..f538b5a52b 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -2083,15 +2083,7 @@ def create_interfaces_cfg(tgen, topo, build=False):
else:
interface_name = data["interface"]
- # Include vrf if present
- if "vrf" in data:
- interface_data.append(
- "interface {} vrf {}".format(
- str(interface_name), str(data["vrf"])
- )
- )
- else:
- interface_data.append("interface {}".format(str(interface_name)))
+ interface_data.append("interface {}".format(str(interface_name)))
if "ipv4" in data:
intf_addr = c_data["links"][destRouterLink]["ipv4"]
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
index 1fc6fddefe..1b7158d597 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
@@ -197,6 +197,28 @@ def teardown_module():
#####################################################
+def reset_stats(stats):
+ """
+ API to reset the stats
+
+ Parameters
+ ----------
+ * `stats` : State dictionary holding helloRx and helloTx values
+ """
+
+ for router, state_data in stats.items():
+ for state, value in state_data.items():
+ stats[router][state] = 0
+ logger.info(
+ "[DUT: %s]: stats %s value has reset" " reset, Current value: %s",
+ router,
+ state,
+ stats[router][state],
+ )
+
+ return True
+
+
def verify_state_incremented(state_before, state_after):
"""
API to compare interface traffic state incrementing
@@ -925,7 +947,6 @@ def test_PIM_hello_tx_rx_p1(request):
intf_l1_c1 = topo["routers"]["l1"]["links"]["c1"]["interface"]
intf_c1_l1 = topo["routers"]["c1"]["links"]["l1"]["interface"]
- step("verify before stats on C1")
state_dict = {
"c1": {
intf_c1_l1: ["helloTx", "helloRx"],
@@ -942,13 +963,12 @@ def test_PIM_hello_tx_rx_p1(request):
step("Flap PIM nbr while doing interface c1-l1 interface shut from f1 side")
shutdown_bringup_interface(tgen, "c1", intf_c1_l1, False)
- step(
- "After shut of local interface from c1 , verify rx/tx hello counters are cleared on c1 side"
- "verify using 'show ip pim interface traffic'"
- )
+ """ Resetting the stats here since shutdown resets the stats.
+ """
+ reset_stats(c1_state_before)
shutdown_bringup_interface(tgen, "c1", intf_c1_l1, True)
- step("verify stats after on c1 and that they are incremented")
+ step("verify stats after no shutdown on c1 and that they are incremented")
count = 0
done = False
diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json
new file mode 100644
index 0000000000..c0f71bb05d
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_default_information.json
@@ -0,0 +1,33 @@
+{
+ "ospfInstance":3,
+ "routerId":"192.168.100.1",
+ "areas":{
+ },
+ "asExternalLinkStates":[
+ {
+ "lsId":"0.0.0.0",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"0.0.0.0/0",
+ "tag":0
+ },
+ {
+ "lsId":"4.5.6.7",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"4.5.6.7/32",
+ "tag":0
+ },
+ {
+ "lsId":"4.5.6.10",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"4.5.6.10/32",
+ "tag":0
+ }
+ ],
+ "asExternalLinkStatesCount":3
+}
diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json
new file mode 100644
index 0000000000..fc8e349d2e
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa.json
@@ -0,0 +1,17 @@
+{
+ "ospfInstance":3,
+ "routerId":"192.168.100.1",
+ "areas":{
+ },
+ "asExternalLinkStates":[
+ {
+ "lsId":"4.5.6.7",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"4.5.6.7/32",
+ "tag":0
+ }
+ ],
+ "asExternalLinkStatesCount":1
+}
diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json
new file mode 100644
index 0000000000..b7d6f7c0c4
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/ospf_instance_lsa2.json
@@ -0,0 +1,25 @@
+{
+ "ospfInstance":3,
+ "routerId":"192.168.100.1",
+ "areas":{
+ },
+ "asExternalLinkStates":[
+ {
+ "lsId":"4.5.6.7",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"4.5.6.7/32",
+ "tag":0
+ },
+ {
+ "lsId":"4.5.6.10",
+ "advertisedRouter":"192.168.100.1",
+ "sequenceNumber":"80000001",
+ "metricType":"E2",
+ "route":"4.5.6.10/32",
+ "tag":0
+ }
+ ],
+ "asExternalLinkStatesCount":2
+}
diff --git a/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf b/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf
new file mode 100644
index 0000000000..88432fed63
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/ospfd-3.conf
@@ -0,0 +1,2 @@
+router ospf 3
+ redistribute sharp
diff --git a/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json b/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json
new file mode 100644
index 0000000000..c0a1f6ac00
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/sharp_installed.json
@@ -0,0 +1,13 @@
+{
+ "routes":[
+ {
+ "fib":3,
+ "rib":3,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"sharp"
+ }
+ ],
+ "routesTotal":4,
+ "routesTotalFib":4
+}
diff --git a/tests/topotests/ospf_instance_redistribute/r1/zebra.conf b/tests/topotests/ospf_instance_redistribute/r1/zebra.conf
new file mode 100644
index 0000000000..6bb2a65eaf
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/r1/zebra.conf
@@ -0,0 +1,2 @@
+interface lo
+ ip address 192.168.100.1/24
diff --git a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
new file mode 100644
index 0000000000..88c236d7a0
--- /dev/null
+++ b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+
+#
+# test_ospf_instance_redistribute.py
+#
+# Copyright (c) 2022 by
+# Nvidia, Inc.
+# Donald Sharp
+#
+# 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_ospf_instance_redistribute
+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.sharpd]
+
+# 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
+from functools import partial
+
+# Required to instantiate the topology builder class.
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+
+def build_topo(tgen):
+ tgen.add_router("r1")
+
+ # Connect r1 and r2 through the eth0 interface
+ switch = tgen.add_switch("sw1")
+ switch.add_link(tgen.gears["r1"])
+
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+
+def setup_module(module):
+ "Setup topology"
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ r1 = tgen.gears["r1"]
+ r1.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")
+ )
+ r1.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"),
+ "-n 3"
+ )
+ r1.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf")
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_install_sharp_instance_routes():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Installing sharp routes")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("sharp install route 4.5.6.7 nexthop 192.168.100.2 1")
+ r1.vtysh_cmd("sharp install route 4.5.6.8 nexthop 192.168.100.2 1 instance 3")
+ r1.vtysh_cmd("sharp install route 4.5.6.9 nexthop 192.168.100.3 1 instance 4")
+ r1.vtysh_cmd("conf\nrouter ospf 3\nredistribute sharp")
+
+ json_file = "{}/r1/sharp_installed.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route summ json", expected)
+
+ logger.info("Ensuring that they exist in the rib/fib")
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertmsg = '"r1" sharp routes are not installed'
+ assert result is None, assertmsg
+
+def test_ospf_instance_redistribute():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing that ospf instance 3 has the redistributed sharp route")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf\nrouter ospf 3\nredistribute sharp")
+
+ json_file = "{}/r1/ospf_instance_lsa.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
+ assert result is None, assertmsg
+
+ r1.vtysh_cmd("sharp install route 4.5.6.10 nexthop 192.168.100.2 1")
+ r1.vtysh_cmd("sharp install route 4.5.6.11 nexthop 192.168.100.2 1 instance 3")
+ r1.vtysh_cmd("sharp install route 4.5.6.12 nexthop 192.168.100.2 1 instance 4")
+
+ logger.info("Added new sharp routes let's see if we pick up only the .10")
+ json_file = "{}/r1/ospf_instance_lsa2.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
+ assert result is None, assertmsg
+
+
+def test_ospf_instance_default_information():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Testing the using default information originate")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf\nrouter ospf 3\ndefault-information originate")
+
+ r1.vtysh_cmd("conf\nip route 0.0.0.0/0 192.168.100.2")
+ json_file = "{}/r1/ospf_default_information.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
+ assertmsg = '"r1" ospf instance 3 does not properly redistribute the default route'
+ assert result is None, assertmsg
+
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
+
diff --git a/tests/topotests/zebra_opaque/r3/ospf6d.conf b/tests/topotests/zebra_opaque/r3/ospf6d.conf
new file mode 100644
index 0000000000..bf3d18c6dd
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r3/ospf6d.conf
@@ -0,0 +1,8 @@
+!
+interface r3-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+!
diff --git a/tests/topotests/zebra_opaque/r3/ospfd.conf b/tests/topotests/zebra_opaque/r3/ospfd.conf
new file mode 100644
index 0000000000..fdc7a97866
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r3/ospfd.conf
@@ -0,0 +1,8 @@
+!
+interface r3-eth0
+ ip ospf area 0
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+!
diff --git a/tests/topotests/zebra_opaque/r3/zebra.conf b/tests/topotests/zebra_opaque/r3/zebra.conf
new file mode 100644
index 0000000000..744f2f1f78
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r3/zebra.conf
@@ -0,0 +1,5 @@
+!
+int r3-eth0
+ ip address 192.168.1.1/24
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/zebra_opaque/r4/ospf6d.conf b/tests/topotests/zebra_opaque/r4/ospf6d.conf
new file mode 100644
index 0000000000..3b6846ff13
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r4/ospf6d.conf
@@ -0,0 +1,8 @@
+!
+interface r4-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6
+!
diff --git a/tests/topotests/zebra_opaque/r4/ospfd.conf b/tests/topotests/zebra_opaque/r4/ospfd.conf
new file mode 100644
index 0000000000..6e08beebca
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r4/ospfd.conf
@@ -0,0 +1,8 @@
+!
+interface r4-eth0
+ ip ospf area 0
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+!
+router ospf
+!
diff --git a/tests/topotests/zebra_opaque/r4/zebra.conf b/tests/topotests/zebra_opaque/r4/zebra.conf
new file mode 100644
index 0000000000..5916f5f882
--- /dev/null
+++ b/tests/topotests/zebra_opaque/r4/zebra.conf
@@ -0,0 +1,5 @@
+!
+int r4-eth0
+ ip address 192.168.1.2/24
+ ipv6 address 2001:db8:1::2/64
+!
diff --git a/tests/topotests/zebra_opaque/test_zebra_opaque.py b/tests/topotests/zebra_opaque/test_zebra_opaque.py
index 2983df3ed6..202e28a178 100644
--- a/tests/topotests/zebra_opaque/test_zebra_opaque.py
+++ b/tests/topotests/zebra_opaque/test_zebra_opaque.py
@@ -35,11 +35,11 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.ospf6d]
def setup_module(mod):
- topodef = {"s1": ("r1", "r2")}
+ topodef = {"s1": ("r1", "r2"), "s2": ("r3", "r4")}
tgen = Topogen(topodef, mod.__name__)
tgen.start_topology()
@@ -52,6 +52,12 @@ def setup_module(mod):
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname))
+ )
tgen.start_router()
@@ -67,8 +73,6 @@ def test_zebra_opaque():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears["r1"]
-
def _bgp_converge(router):
output = json.loads(router.vtysh_cmd("show ip route 192.168.1.0/24 json"))
expected = {
@@ -81,11 +85,45 @@ def test_zebra_opaque():
}
return topotest.json_cmp(output, expected)
+ def _ospf_converge(router):
+ output = json.loads(router.vtysh_cmd("show ip route 192.168.1.0/24 json"))
+ expected = {
+ "192.168.1.0/24": [
+ {
+ "ospfPathType": "Intra-Area",
+ "ospfAreaId": "0.0.0.0",
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _ospf6_converge(router):
+ output = json.loads(router.vtysh_cmd("show ipv6 route 2001:db8:1::/64 json"))
+ expected = {
+ "2001:db8:1::/64": [
+ {
+ "ospfPathType": "Intra-Area",
+ "ospfAreaId": "0.0.0.0",
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ router = tgen.gears["r1"]
test_func = functools.partial(_bgp_converge, router)
success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
-
assert result is None, 'Cannot see BGP community aliases "{}"'.format(router)
+ router = tgen.gears["r3"]
+ test_func = functools.partial(_ospf_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, 'Cannot see OSPFv2 opaque attributes "{}"'.format(router)
+
+ router = tgen.gears["r3"]
+ test_func = functools.partial(_ospf6_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, 'Cannot see OSPFv3 opaque attributes "{}"'.format(router)
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 5997e8866a..defb2b2038 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -1481,6 +1481,17 @@ module frr-isisd {
description
"Stable IP address of the advertising router.";
}
+ leaf router-address-v6 {
+ type inet:ipv6-address;
+ description
+ "Stable IPv6 address of the advertising router.";
+ }
+ leaf export {
+ type boolean;
+ default "false";
+ description
+ "Export Link State informatin.";
+ }
}
container segment-routing {
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 1c6c70ae84..141e4074d5 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1761,16 +1761,16 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
}
- /* If VRF, create or update the VRF structure itself. */
- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
- netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
- vrf_id = (vrf_id_t)ifi->ifi_index;
- }
-
/* See if interface is present. */
ifp = if_lookup_by_name_per_ns(zns, name);
if (h->nlmsg_type == RTM_NEWLINK) {
+ /* If VRF, create or update the VRF structure itself. */
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) {
+ netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
+ vrf_id = (vrf_id_t)ifi->ifi_index;
+ }
+
if (tb[IFLA_MASTER]) {
if (slave_kind && (strcmp(slave_kind, "vrf") == 0)
&& !vrf_is_backend_netns()) {
@@ -2032,6 +2032,10 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zebra_l2_vxlanif_del(ifp);
if_delete_update(ifp);
+
+ /* If VRF, delete the VRF structure itself. */
+ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
+ netlink_vrf_change(h, tb[IFLA_LINKINFO], ns_id, name);
}
return 0;
diff --git a/zebra/interface.c b/zebra/interface.c
index 8b5dbabb92..e4e80ec4e9 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -91,9 +91,12 @@ static int if_zebra_speed_update(struct thread *thread)
changed = true;
}
- if (changed || new_speed == UINT32_MAX)
+ if (changed || new_speed == UINT32_MAX) {
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 5,
&zif->speed_update);
+ thread_ignore_late_timer(zif->speed_update);
+ }
+
return 1;
}
@@ -187,6 +190,8 @@ static int if_zebra_new_hook(struct interface *ifp)
*/
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15,
&zebra_if->speed_update);
+ thread_ignore_late_timer(zebra_if->speed_update);
+
return 0;
}
@@ -1074,6 +1079,7 @@ void if_up(struct interface *ifp)
thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
&zif->speed_update);
+ thread_ignore_late_timer(zif->speed_update);
}
/* Interface goes down. We have to manage different behavior of based
@@ -4207,11 +4213,7 @@ static int if_config_write(struct vty *vty)
if_data = ifp->info;
- if (ifp->vrf->vrf_id == VRF_DEFAULT)
- vty_frame(vty, "interface %s\n", ifp->name);
- else
- vty_frame(vty, "interface %s vrf %s\n",
- ifp->name, vrf->name);
+ if_vty_config_start(vty, ifp);
if (if_data) {
if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
@@ -4277,7 +4279,7 @@ static int if_config_write(struct vty *vty)
zebra_evpn_mh_if_write(vty, ifp);
link_params_config_write(vty, ifp);
- vty_endframe(vty, "exit\n!\n");
+ if_vty_config_end(vty);
}
return 0;
}
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 86e8f65b5f..d614aa26d0 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -271,9 +271,6 @@ static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize)
safe_strerror(errno));
return -1;
}
-
- zlog_info("Setting netlink socket receive buffer size: %u -> %u",
- oldsize, newsize);
return 0;
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index c59ff1bbec..fdd2c8405f 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -94,7 +94,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
zsend_redistribute_route(
ZEBRA_REDISTRIBUTE_ROUTE_ADD, client,
- &rn->p, NULL, newre);
+ rn, newre);
}
route_unlock_node(rn);
@@ -116,20 +116,17 @@ static void zebra_redistribute(struct zserv *client, int type,
for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
RNODE_FOREACH_RE (rn, newre) {
- const struct prefix *dst_p, *src_p;
-
- srcdest_rnode_prefixes(rn, &dst_p, &src_p);
-
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
- "%s: client %s %pFX(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d",
+ "%s: client %s %pRN(%u:%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d",
__func__,
- zebra_route_string(client->proto),
- dst_p, vrf_id,
- CHECK_FLAG(newre->flags,
- ZEBRA_FLAG_SELECTED),
+ zebra_route_string(client->proto), rn,
+ vrf_id, newre->instance,
+ !!CHECK_FLAG(newre->flags,
+ ZEBRA_FLAG_SELECTED),
newre->type, newre->distance,
- newre->metric, zebra_check_addr(dst_p));
+ newre->metric,
+ zebra_check_addr(&rn->p));
if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
continue;
@@ -137,11 +134,11 @@ static void zebra_redistribute(struct zserv *client, int type,
&& (newre->type != type
|| newre->instance != instance)))
continue;
- if (!zebra_check_addr(dst_p))
+ if (!zebra_check_addr(&rn->p))
continue;
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, dst_p, src_p, newre);
+ client, rn, newre);
}
}
@@ -149,23 +146,25 @@ static void zebra_redistribute(struct zserv *client, int type,
* Function to check if prefix is candidate for
* redistribute.
*/
-static bool zebra_redistribute_check(const struct route_entry *re,
- struct zserv *client,
- const struct prefix *p, int afi)
+static bool zebra_redistribute_check(const struct route_node *rn,
+ const struct route_entry *re,
+ struct zserv *client)
{
struct zebra_vrf *zvrf;
+ afi_t afi;
/* Process only if there is valid re */
if (!re)
return false;
+ afi = family2afi(rn->p.family);
zvrf = vrf_info_lookup(re->vrf_id);
if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
return false;
/* If default route and redistributed */
- if (is_default_prefix(p)
- && vrf_bitmap_check(client->redist_default[afi], re->vrf_id))
+ if (is_default_prefix(&rn->p) &&
+ vrf_bitmap_check(client->redist_default[afi], re->vrf_id))
return true;
/* If redistribute in enabled for zebra route all */
@@ -176,10 +175,13 @@ static bool zebra_redistribute_check(const struct route_entry *re,
* If multi-instance then check for route
* redistribution for given instance.
*/
- if (re->instance
- && redist_check_instance(&client->mi_redist[afi][re->type],
- re->instance))
- return true;
+ if (re->instance) {
+ if (redist_check_instance(&client->mi_redist[afi][re->type],
+ re->instance))
+ return true;
+ else
+ return false;
+ }
/* If redistribution is enabled for give route type. */
if (vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id))
@@ -190,49 +192,42 @@ static bool zebra_redistribute_check(const struct route_entry *re,
/* Either advertise a route for redistribution to registered clients or */
/* withdraw redistribution if add cannot be done for client */
-void redistribute_update(const struct prefix *p, const struct prefix *src_p,
+void redistribute_update(const struct route_node *rn,
const struct route_entry *re,
const struct route_entry *prev_re)
{
struct listnode *node, *nnode;
struct zserv *client;
- int afi;
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
- "(%u:%u):%pFX: Redist update re %p (%s), old %p (%s)",
- re->vrf_id, re->table, p, re,
+ "(%u:%u):%pRN(%u): Redist update re %p (%s), old %p (%s)",
+ re->vrf_id, re->table, rn, re->instance, re,
zebra_route_string(re->type), prev_re,
prev_re ? zebra_route_string(prev_re->type) : "None");
- afi = family2afi(p->family);
- if (!afi) {
- flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
- "%s: Unknown AFI/SAFI prefix received", __func__);
- return;
- }
- if (!zebra_check_addr(p)) {
+ if (!zebra_check_addr(&rn->p)) {
if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug("Redist update filter prefix %pFX", p);
+ zlog_debug("Redist update filter prefix %pRN", rn);
return;
}
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
- if (zebra_redistribute_check(re, client, p, afi)) {
+ if (zebra_redistribute_check(rn, re, client)) {
if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
- "%s: client %s %pFX(%u:%u), type=%d, distance=%d, metric=%d",
+ "%s: client %s %pRN(%u:%u), type=%d, distance=%d, metric=%d",
__func__,
- zebra_route_string(client->proto), p,
+ zebra_route_string(client->proto), rn,
re->vrf_id, re->table, re->type,
re->distance, re->metric);
}
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, p, src_p, re);
- } else if (zebra_redistribute_check(prev_re, client, p, afi))
+ client, rn, re);
+ } else if (zebra_redistribute_check(rn, prev_re, client))
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, p, src_p, prev_re);
+ client, rn, prev_re);
}
}
@@ -244,13 +239,12 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
* may have seen a redist for 'old_re', but will not see
* the redist for 'new_re'.
*/
-void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
+void redistribute_delete(const struct route_node *rn,
const struct route_entry *old_re,
const struct route_entry *new_re)
{
struct listnode *node, *nnode;
struct zserv *client;
- int afi;
vrf_id_t vrfid;
if (old_re)
@@ -261,27 +255,34 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
return;
if (IS_ZEBRA_DEBUG_RIB) {
- zlog_debug("%u:%pFX: Redist del: re %p (%s), new re %p (%s)",
- vrfid, p, old_re,
- old_re ? zebra_route_string(old_re->type) : "None",
- new_re,
- new_re ? zebra_route_string(new_re->type) : "None");
- }
+ uint8_t old_inst, new_inst;
+ uint32_t table = 0;
- afi = family2afi(p->family);
- if (!afi) {
- flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
- "%s: Unknown AFI/SAFI prefix received",
- __func__);
- return;
+ old_inst = new_inst = 0;
+
+ if (old_re) {
+ old_inst = old_re->instance;
+ table = old_re->table;
+ }
+ if (new_re) {
+ new_inst = new_re->instance;
+ table = new_re->table;
+ }
+
+ zlog_debug(
+ "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
+ vrfid, table, rn, old_re, old_inst,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re, new_inst,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Skip invalid (e.g. linklocal) prefix */
- if (!zebra_check_addr(p)) {
+ if (!zebra_check_addr(&rn->p)) {
if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
- "%u:%pFX: Redist del old: skipping invalid prefix",
- vrfid, p);
+ "%u:%pRN: Redist del old: skipping invalid prefix",
+ vrfid, rn);
}
return;
}
@@ -294,13 +295,13 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
* Skip this client if it will receive an update for the
* 'new' re
*/
- if (zebra_redistribute_check(new_re, client, p, afi))
+ if (zebra_redistribute_check(rn, new_re, client))
continue;
/* Send a delete for the 'old' re to any subscribed client. */
- if (zebra_redistribute_check(old_re, client, p, afi))
+ if (zebra_redistribute_check(rn, old_re, client))
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, p, src_p, old_re);
+ client, rn, old_re);
}
}
@@ -533,14 +534,12 @@ void zebra_interface_address_add_update(struct interface *ifp,
{
struct listnode *node, *nnode;
struct zserv *client;
- struct prefix *p;
- if (IS_ZEBRA_DEBUG_EVENT) {
- p = ifc->address;
+ if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s vrf %s(%u)",
- p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
- }
+ ifc->address, ifp->name, ifp->vrf->name,
+ ifp->vrf->vrf_id);
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
flog_warn(
@@ -570,14 +569,12 @@ void zebra_interface_address_delete_update(struct interface *ifp,
{
struct listnode *node, *nnode;
struct zserv *client;
- struct prefix *p;
- if (IS_ZEBRA_DEBUG_EVENT) {
- p = ifc->address;
+ if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s vrf %s(%u)",
- p, ifp->name, ifp->vrf->name, ifp->vrf->vrf_id);
- }
+ ifc->address, ifp->name, ifp->vrf->name,
+ ifp->vrf->vrf_id);
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0);
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 2685458f96..ac257d6389 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -40,8 +40,7 @@ extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS);
extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
/* ----------------- */
-extern void redistribute_update(const struct prefix *p,
- const struct prefix *src_p,
+extern void redistribute_update(const struct route_node *rn,
const struct route_entry *re,
const struct route_entry *prev_re);
/*
@@ -52,24 +51,24 @@ extern void redistribute_update(const struct prefix *p,
* may have seen a redist for 'old_re', but will not see
* the redist for 'new_re'.
*/
-void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
+void redistribute_delete(const struct route_node *rn,
const struct route_entry *old_re,
const struct route_entry *new_re);
-extern void zebra_interface_up_update(struct interface *);
-extern void zebra_interface_down_update(struct interface *);
+extern void zebra_interface_up_update(struct interface *ifp);
+extern void zebra_interface_down_update(struct interface *ifp);
-extern void zebra_interface_add_update(struct interface *);
-extern void zebra_interface_delete_update(struct interface *);
+extern void zebra_interface_add_update(struct interface *ifp);
+extern void zebra_interface_delete_update(struct interface *ifp);
-extern void zebra_interface_address_add_update(struct interface *,
- struct connected *);
-extern void zebra_interface_address_delete_update(struct interface *,
+extern void zebra_interface_address_add_update(struct interface *ifp,
+ struct connected *c);
+extern void zebra_interface_address_delete_update(struct interface *ifp,
struct connected *c);
-extern void zebra_interface_parameters_update(struct interface *);
-extern void zebra_interface_vrf_update_del(struct interface *,
+extern void zebra_interface_parameters_update(struct interface *ifp);
+extern void zebra_interface_vrf_update_del(struct interface *ifp,
vrf_id_t new_vrf_id);
-extern void zebra_interface_vrf_update_add(struct interface *,
+extern void zebra_interface_vrf_update_add(struct interface *ifp,
vrf_id_t old_vrf_id);
extern int zebra_import_table(afi_t afi, vrf_id_t vrf_id,
diff --git a/zebra/rib.h b/zebra/rib.h
index b7416322f9..a0ec1f0e4f 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -493,6 +493,9 @@ extern uint8_t route_distance(int type);
extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
bool rt_delete);
+extern struct route_node *
+rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx);
+
/*
* Inline functions.
*/
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 421438a051..c3d7bcd909 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -546,18 +546,19 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
}
int zsend_redistribute_route(int cmd, struct zserv *client,
- const struct prefix *p,
- const struct prefix *src_p,
+ const struct route_node *rn,
const struct route_entry *re)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
struct nexthop *nexthop;
+ const struct prefix *p, *src_p;
uint8_t count = 0;
afi_t afi;
size_t stream_size =
MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
+ srcdest_rnode_prefixes(rn, &p, &src_p);
memset(&api, 0, sizeof(api));
api.vrf_id = re->vrf_id;
api.type = re->type;
@@ -742,11 +743,11 @@ int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
* Common utility send route notification, called from a path using a
* route_entry and from a path using a dataplane context.
*/
-static int route_notify_internal(const struct prefix *p, int type,
+static int route_notify_internal(const struct route_node *rn, int type,
uint16_t instance, vrf_id_t vrf_id,
uint32_t table_id,
- enum zapi_route_notify_owner note,
- afi_t afi, safi_t safi)
+ enum zapi_route_notify_owner note, afi_t afi,
+ safi_t safi)
{
struct zserv *client;
struct stream *s;
@@ -756,16 +757,16 @@ static int route_notify_internal(const struct prefix *p, int type,
if (!client || !client->notify_owner) {
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
- "Not Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u",
- zebra_route_string(type), p, table_id, note,
+ "Not Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u",
+ zebra_route_string(type), rn, table_id, note,
vrf_id);
return 0;
}
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
- "Notifying Owner: %s about prefix %pFX(%u) %d vrf: %u",
- zebra_route_string(type), p, table_id, note, vrf_id);
+ "Notifying Owner: %s about prefix %pRN(%u) %d vrf: %u",
+ zebra_route_string(type), rn, table_id, note, vrf_id);
/* We're just allocating a small-ish buffer here, since we only
* encode a small amount of data.
@@ -778,11 +779,11 @@ static int route_notify_internal(const struct prefix *p, int type,
stream_put(s, &note, sizeof(note));
- stream_putc(s, p->family);
+ stream_putc(s, rn->p.family);
- blen = prefix_blen(p);
- stream_putc(s, p->prefixlen);
- stream_put(s, &p->u.prefix, blen);
+ blen = prefix_blen(&rn->p);
+ stream_putc(s, rn->p.prefixlen);
+ stream_put(s, &rn->p.u.prefix, blen);
stream_putl(s, table_id);
@@ -795,11 +796,12 @@ static int route_notify_internal(const struct prefix *p, int type,
return zserv_send_message(client, s);
}
-int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
- enum zapi_route_notify_owner note,
- afi_t afi, safi_t safi)
+int zsend_route_notify_owner(const struct route_node *rn,
+ struct route_entry *re,
+ enum zapi_route_notify_owner note, afi_t afi,
+ safi_t safi)
{
- return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
+ return (route_notify_internal(rn, re->type, re->instance, re->vrf_id,
re->table, note, afi, safi));
}
@@ -809,14 +811,11 @@ int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
enum zapi_route_notify_owner note)
{
- return (route_notify_internal(dplane_ctx_get_dest(ctx),
- dplane_ctx_get_type(ctx),
- dplane_ctx_get_instance(ctx),
- dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx),
- note,
- dplane_ctx_get_afi(ctx),
- dplane_ctx_get_safi(ctx)));
+ return (route_notify_internal(
+ rib_find_rn_from_ctx(ctx), dplane_ctx_get_type(ctx),
+ dplane_ctx_get_instance(ctx), dplane_ctx_get_vrf(ctx),
+ dplane_ctx_get_table(ctx), note, dplane_ctx_get_afi(ctx),
+ dplane_ctx_get_safi(ctx)));
}
static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
@@ -2093,6 +2092,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
__func__);
nexthop_group_delete(&ng);
zebra_nhg_backup_free(&bnhg);
+ XFREE(MTYPE_OPAQUE, re->opaque);
XFREE(MTYPE_RE, re);
return;
}
@@ -2105,6 +2105,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
__func__, api.safi);
nexthop_group_delete(&ng);
zebra_nhg_backup_free(&bnhg);
+ XFREE(MTYPE_OPAQUE, re->opaque);
XFREE(MTYPE_RE, re);
return;
}
@@ -2133,6 +2134,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
*/
if (ret == -1) {
client->error_cnt++;
+ XFREE(MTYPE_OPAQUE, re->opaque);
XFREE(MTYPE_RE, re);
}
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index dad40c200d..b3fe7318f9 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -65,8 +65,7 @@ extern void nbr_connected_delete_ipv6(struct interface *ifp,
extern int zsend_interface_update(int cmd, struct zserv *client,
struct interface *ifp);
extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
- const struct prefix *p,
- const struct prefix *src_p,
+ const struct route_node *rn,
const struct route_entry *re);
extern int zsend_router_id_update(struct zserv *zclient, afi_t afi,
@@ -76,8 +75,8 @@ extern int zsend_interface_vrf_update(struct zserv *zclient,
extern int zsend_interface_link_params(struct zserv *zclient,
struct interface *ifp);
extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
-extern int zsend_route_notify_owner(struct route_entry *re,
- const struct prefix *p,
+extern int zsend_route_notify_owner(const struct route_node *rn,
+ struct route_entry *re,
enum zapi_route_notify_owner note,
afi_t afi, safi_t safi);
extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 1279c7c9a9..1374b932ae 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -575,7 +575,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
* know that they've lost
*/
if (old && (old != re) && (old->type != re->type))
- zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON,
+ zsend_route_notify_owner(rn, old, ZAPI_ROUTE_BETTER_ADMIN_WON,
info->afi, info->safi);
/* Update fib selection */
@@ -745,9 +745,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
zlog_debug(
- "%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u",
- zvrf_name(zvrf), zvrf_id(zvrf), rn, p,
- seq, rnh->seqno);
+ "%s(%u):%pRN has Nexthop(%pRN) depending on it, evaluating %u:%u",
+ zvrf_name(zvrf), zvrf_id(zvrf), rn,
+ rnh->node, seq, rnh->seqno);
/*
* If we have evaluated this node on this pass
@@ -1088,9 +1088,7 @@ static void rib_process(struct route_node *rn)
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
struct vrf *vrf;
- const struct prefix *p, *src_p;
- srcdest_rnode_prefixes(rn, &p, &src_p);
vrf_id_t vrf_id = VRF_UNKNOWN;
assert(rn);
@@ -1194,9 +1192,9 @@ static void rib_process(struct route_node *rn)
info = srcdest_rnode_table_info(rn);
srcdest_rnode_prefixes(rn, &p, NULL);
- zsend_route_notify_owner(re, p,
- ZAPI_ROUTE_FAIL_INSTALL,
- info->afi, info->safi);
+ zsend_route_notify_owner(
+ rn, re, ZAPI_ROUTE_FAIL_INSTALL,
+ info->afi, info->safi);
continue;
}
} else {
@@ -1288,8 +1286,7 @@ static void rib_process(struct route_node *rn)
*/
if (!new_selected || CHECK_FLAG(old_selected->status,
ROUTE_ENTRY_REMOVED))
- redistribute_delete(p, src_p,
- old_selected,
+ redistribute_delete(rn, old_selected,
new_selected);
if (old_selected != new_selected)
@@ -1758,8 +1755,7 @@ done:
* when processing dplane results, e.g. Note well: the route-node is returned
* with a ref held - route_unlock_node() must be called eventually.
*/
-static struct route_node *
-rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx)
+struct route_node *rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx)
{
struct route_table *table = NULL;
struct route_node *rn = NULL;
@@ -1806,7 +1802,6 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
bool is_update = false;
enum dplane_op_e op;
enum zebra_dplane_result status;
- const struct prefix *dest_pfx, *src_pfx;
uint32_t seq;
rib_dest_t *dest;
bool fib_changed = false;
@@ -1815,22 +1810,19 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
- dest_pfx = dplane_ctx_get_dest(ctx);
/* Locate rn and re(s) from ctx */
rn = rib_find_rn_from_ctx(ctx);
if (rn == NULL) {
if (IS_ZEBRA_DEBUG_DPLANE) {
zlog_debug(
- "Failed to process dplane results: no route for %s(%u):%pFX",
- VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dest_pfx);
+ "Failed to process dplane results: no route for %s(%u):%pRN",
+ VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), rn);
}
goto done;
}
dest = rib_dest_from_rnode(rn);
- srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
info = srcdest_rnode_table_info(rn);
op = dplane_ctx_get_op(ctx);
@@ -1838,10 +1830,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug(
- "%s(%u:%u):%pFX Processing dplane result ctx %p, op %s result %s",
+ "%s(%u:%u):%pRN Processing dplane result ctx %p, op %s result %s",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx, ctx,
- dplane_op2str(op), dplane_res2str(status));
+ dplane_ctx_get_table(ctx), rn, ctx, dplane_op2str(op),
+ dplane_res2str(status));
/*
* Update is a bit of a special case, where we may have both old and new
@@ -1880,9 +1872,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
if (re->dplane_sequence != seq) {
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug(
- "%s(%u):%pFX Stale dplane result for re %p",
+ "%s(%u):%pRN Stale dplane result for re %p",
VRF_LOGNAME(vrf),
- dplane_ctx_get_vrf(ctx), dest_pfx, re);
+ dplane_ctx_get_vrf(ctx), rn, re);
} else {
if (!zrouter.asic_offloaded ||
(CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) ||
@@ -1895,10 +1887,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) {
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug(
- "%s(%u:%u):%pFX Stale dplane result for old_re %p",
+ "%s(%u:%u):%pRN Stale dplane result for old_re %p",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx), old_re->table,
- dest_pfx, old_re);
+ rn, old_re);
} else
UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED);
}
@@ -1936,18 +1928,17 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
if (!fib_changed) {
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug(
- "%s(%u:%u):%pFX no fib change for re",
+ "%s(%u:%u):%pRN no fib change for re",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx),
dplane_ctx_get_table(
ctx),
- dest_pfx);
+ rn);
}
/* Redistribute if this is the selected re */
if (dest && re == dest->selected_fib)
- redistribute_update(dest_pfx, src_pfx,
- re, old_re);
+ redistribute_update(rn, re, old_re);
}
/*
@@ -1989,13 +1980,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
} if (old_re)
SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
if (re)
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL,
- info->afi, info->safi);
+ zsend_route_notify_owner(
+ rn, re, ZAPI_ROUTE_FAIL_INSTALL,
+ info->afi, info->safi);
- zlog_warn("%s(%u:%u):%pFX: Route install failed",
+ zlog_warn("%s(%u:%u):%pRN: Route install failed",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
}
break;
case DPLANE_OP_ROUTE_DELETE:
@@ -2022,9 +2013,9 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zsend_route_notify_owner_ctx(ctx,
ZAPI_ROUTE_REMOVE_FAIL);
- zlog_warn("%s(%u:%u):%pFX: Route Deletion failure",
+ zlog_warn("%s(%u:%u):%pRN: Route Deletion failure",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
}
/*
@@ -2099,12 +2090,11 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
struct route_entry *re = NULL;
struct vrf *vrf;
struct nexthop *nexthop;
- const struct prefix *dest_pfx, *src_pfx;
rib_dest_t *dest;
bool fib_changed = false;
bool debug_p = IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_RIB;
int start_count, end_count;
- dest_pfx = dplane_ctx_get_dest(ctx);
+
vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
/* Locate rn and re(s) from ctx */
@@ -2112,20 +2102,19 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (rn == NULL) {
if (debug_p) {
zlog_debug(
- "Failed to process dplane notification: no routes for %s(%u:%u):%pFX",
+ "Failed to process dplane notification: no routes for %s(%u:%u):%pRN",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
}
goto done;
}
dest = rib_dest_from_rnode(rn);
- srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
if (debug_p)
- zlog_debug("%s(%u:%u):%pFX Processing dplane notif ctx %p",
+ zlog_debug("%s(%u:%u):%pRN Processing dplane notif ctx %p",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx, ctx);
+ dplane_ctx_get_table(ctx), rn, ctx);
/*
* Take a pass through the routes, look for matches with the context
@@ -2140,9 +2129,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (re == NULL) {
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX Unable to process dplane notification: no entry for type %s",
+ "%s(%u:%u):%pRN Unable to process dplane notification: no entry for type %s",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx,
+ dplane_ctx_get_table(ctx), rn,
zebra_route_string(dplane_ctx_get_type(ctx)));
goto done;
@@ -2175,20 +2164,20 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX dplane notif, uninstalled type %s route",
+ "%s(%u:%u):%pRN dplane notif, uninstalled type %s route",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx,
+ dplane_ctx_get_table(ctx), rn,
zebra_route_string(
dplane_ctx_get_type(ctx)));
} else {
/* At least report on the event. */
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX dplane notif, but type %s not selected_fib",
+ "%s(%u:%u):%pRN dplane notif, but type %s not selected_fib",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx,
+ dplane_ctx_get_table(ctx), rn,
zebra_route_string(
dplane_ctx_get_type(ctx)));
}
@@ -2212,9 +2201,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (!fib_changed) {
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX dplane notification: rib_update returns FALSE",
+ "%s(%u:%u):%pRN dplane notification: rib_update returns FALSE",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
}
/*
@@ -2229,9 +2218,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (start_count > 0 && end_count > 0) {
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX applied nexthop changes from dplane notification",
+ "%s(%u:%u):%pRN applied nexthop changes from dplane notification",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
/* Changed nexthops - update kernel/others */
dplane_route_notif_update(rn, re,
@@ -2240,9 +2229,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
} else if (start_count == 0 && end_count > 0) {
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX installed transition from dplane notification",
+ "%s(%u:%u):%pRN installed transition from dplane notification",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
/* We expect this to be the selected route, so we want
* to tell others about this transition.
@@ -2253,14 +2242,14 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_UPDATE, ctx);
/* Redistribute, lsp, and nht update */
- redistribute_update(dest_pfx, src_pfx, re, NULL);
+ redistribute_update(rn, re, NULL);
} else if (start_count > 0 && end_count == 0) {
if (debug_p)
zlog_debug(
- "%s(%u:%u):%pFX un-installed transition from dplane notification",
+ "%s(%u:%u):%pRN un-installed transition from dplane notification",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
- dplane_ctx_get_table(ctx), dest_pfx);
+ dplane_ctx_get_table(ctx), rn);
/* Transition from _something_ installed to _nothing_
* installed.
@@ -2274,7 +2263,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
dplane_route_notif_update(rn, re, DPLANE_OP_ROUTE_DELETE, ctx);
/* Redistribute, lsp, and nht update */
- redistribute_delete(dest_pfx, src_pfx, re, NULL);
+ redistribute_delete(rn, re, NULL);
}
/* Make any changes visible for lsp and nexthop-tracking processing */
@@ -3522,8 +3511,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
else
src_buf[0] = '\0';
- zlog_debug("%s[%d]:%pFX%s%s doesn't exist in rib",
- vrf->name, table_id, p,
+ zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib",
+ vrf->name, table_id, rn,
(src_buf[0] != '\0') ? " from " : "",
src_buf);
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 04f2e91e69..f35c9f65fb 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -429,6 +429,7 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
struct json_object *json)
{
struct bgp_zebra_opaque bzo = {};
+ struct ospf_zebra_opaque ozo = {};
if (!re->opaque)
return;
@@ -442,7 +443,7 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
vty_out(vty, " Opaque Data: %s",
(char *)re->opaque->data);
break;
- case ZEBRA_ROUTE_BGP: {
+ case ZEBRA_ROUTE_BGP:
memcpy(&bzo, re->opaque->data, re->opaque->length);
if (json) {
@@ -467,7 +468,31 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
vty_out(vty, " Selection reason : %s\n",
bzo.selection_reason);
}
- }
+ break;
+ case ZEBRA_ROUTE_OSPF:
+ case ZEBRA_ROUTE_OSPF6:
+ memcpy(&ozo, re->opaque->data, re->opaque->length);
+
+ if (json) {
+ json_object_string_add(json, "ospfPathType",
+ ozo.path_type);
+ if (ozo.area_id[0] != '\0')
+ json_object_string_add(json, "ospfAreaId",
+ ozo.area_id);
+ if (ozo.tag[0] != '\0')
+ json_object_string_add(json, "ospfTag",
+ ozo.tag);
+ } else {
+ vty_out(vty, " OSPF path type : %s\n",
+ ozo.path_type);
+ if (ozo.area_id[0] != '\0')
+ vty_out(vty, " OSPF area ID : %s\n",
+ ozo.area_id);
+ if (ozo.tag[0] != '\0')
+ vty_out(vty, " OSPF tag : %s\n",
+ ozo.tag);
+ }
+ break;
default:
break;
}