summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--bfdd/bfd.c69
-rw-r--r--bfdd/bfd.h1
-rw-r--r--bfdd/bfdd_vty.c3
-rw-r--r--bfdd/ptm_adapter.c8
-rw-r--r--bgpd/bgp_attr.c49
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--bgpd/bgp_bmp.c2
-rw-r--r--bgpd/bgp_fsm.c2
-rw-r--r--bgpd/bgp_keepalives.c9
-rw-r--r--bgpd/bgp_main.c12
-rw-r--r--bgpd/bgp_mplsvpn.c10
-rw-r--r--bgpd/bgp_open.c4
-rw-r--r--bgpd/bgp_open.h8
-rw-r--r--bgpd/bgp_packet.h12
-rw-r--r--bgpd/bgp_route.c9
-rw-r--r--bgpd/bgp_route.h4
-rw-r--r--bgpd/bgp_routemap.c99
-rw-r--r--bgpd/bgp_rpki.c5
-rw-r--r--bgpd/bgp_updgrp.c6
-rw-r--r--bgpd/bgp_updgrp_adv.c5
-rw-r--r--bgpd/bgpd.c7
-rw-r--r--bgpd/rfapi/rfapi.c4
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c8
-rwxr-xr-xconfigure.ac2
-rw-r--r--debian/frr-pythontools.install1
-rwxr-xr-xdebian/rules1
-rw-r--r--doc/user/bgp.rst17
-rw-r--r--doc/user/index.rst1
-rw-r--r--doc/user/pim.rst7
-rw-r--r--doc/user/routemap.rst6
-rw-r--r--doc/user/subdir.am1
-rw-r--r--doc/user/watchfrr.rst30
-rw-r--r--doc/user/zebra.rst29
-rw-r--r--eigrpd/eigrp_routemap.c6
-rw-r--r--fpm/subdir.am4
-rw-r--r--grpc/subdir.am2
-rw-r--r--include/linux/fib_rules.h20
-rw-r--r--include/linux/if_addr.h3
-rw-r--r--include/linux/if_bridge.h10
-rw-r--r--include/linux/if_link.h92
-rw-r--r--include/linux/lwtunnel.h7
-rw-r--r--include/linux/mpls_iptunnel.h7
-rw-r--r--include/linux/neighbour.h3
-rw-r--r--include/linux/net_namespace.h7
-rw-r--r--include/linux/netlink.h11
-rw-r--r--include/linux/rtnetlink.h49
-rw-r--r--include/linux/socket.h7
-rw-r--r--isisd/isis_adjacency.c1
-rw-r--r--isisd/isis_circuit.c11
-rw-r--r--isisd/isis_circuit.h9
-rw-r--r--isisd/isis_cli.c111
-rw-r--r--isisd/isis_lsp.c83
-rw-r--r--isisd/isis_main.c2
-rw-r--r--isisd/isis_mt.c17
-rw-r--r--isisd/isis_mt.h6
-rw-r--r--isisd/isis_northbound.c511
-rw-r--r--isisd/isis_pdu.c40
-rw-r--r--isisd/isis_route.c42
-rw-r--r--isisd/isis_route.h5
-rw-r--r--isisd/isis_te.c1262
-rw-r--r--isisd/isis_te.h228
-rw-r--r--isisd/isis_tlvs.c1098
-rw-r--r--isisd/isis_tlvs.h272
-rw-r--r--isisd/isis_zebra.c36
-rw-r--r--isisd/isis_zebra.h11
-rw-r--r--isisd/isisd.c3
-rw-r--r--isisd/isisd.h4
-rw-r--r--ldpd/l2vpn.c8
-rw-r--r--ldpd/lde.c15
-rw-r--r--ldpd/lde.h9
-rw-r--r--ldpd/lde_lib.c24
-rw-r--r--ldpd/ldp_zebra.c71
-rw-r--r--ldpd/ldpd.h3
-rw-r--r--lib/command.c16
-rw-r--r--lib/frr_pthread.c33
-rw-r--r--lib/if.c76
-rw-r--r--lib/libfrr.c11
-rw-r--r--lib/log.c1
-rw-r--r--lib/mpls.h3
-rw-r--r--lib/northbound.c265
-rw-r--r--lib/northbound.h26
-rw-r--r--lib/northbound_cli.c139
-rw-r--r--lib/northbound_confd.c6
-rw-r--r--lib/northbound_grpc.cpp19
-rw-r--r--lib/northbound_sysrepo.c6
-rw-r--r--lib/routemap.c44
-rw-r--r--lib/routemap.h8
-rw-r--r--lib/vrf.c8
-rw-r--r--lib/vty.c21
-rw-r--r--lib/yang_wrappers.c107
-rw-r--r--lib/yang_wrappers.h18
-rw-r--r--lib/zclient.c137
-rw-r--r--lib/zclient.h29
-rw-r--r--ospf6d/ospf6_asbr.c1
-rw-r--r--ospf6d/ospf6_top.c5
-rw-r--r--ospf6d/ospf6_top.h3
-rw-r--r--ospfd/ospf_main.c10
-rw-r--r--ospfd/ospf_sr.c95
-rw-r--r--ospfd/ospf_sr.h3
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--pbrd/pbr_nht.c120
-rw-r--r--qpb/subdir.am3
-rw-r--r--redhat/frr.spec.in3
-rw-r--r--ripd/ripd.c33
-rw-r--r--ripngd/ripngd.c46
-rw-r--r--staticd/static_vrf.c4
-rw-r--r--staticd/static_zebra.c14
-rw-r--r--staticd/static_zebra.h3
-rw-r--r--tests/bgpd/test_aspath.c1
-rw-r--r--tests/bgpd/test_capability.c1
-rw-r--r--tests/bgpd/test_peer_attr.c1
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin221946 -> 206007 bytes
-rw-r--r--tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py44
-rw-r--r--tests/topotests/ldp-topo1/r1/ip_mpls_route.ref-15
-rw-r--r--tests/topotests/ldp-topo1/r1/show_ipv4_route.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_ldp_binding.ref-142
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_ldp_discovery.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_ldp_interface.ref-12
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_ldp_neighbor.ref-18
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_table.ref16
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_table.ref-18
-rw-r--r--tests/topotests/ldp-topo1/r1/show_mpls_table.ref-no-impl-null8
-rw-r--r--tests/topotests/ldp-topo1/r2/show_ipv4_route.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_ldp_binding.ref-156
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_ldp_discovery.ref-112
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_ldp_interface.ref-13
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_ldp_neighbor.ref-126
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_table.ref14
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_table.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r2/show_mpls_table.ref-no-impl-null7
-rw-r--r--tests/topotests/ldp-topo1/r3/show_ipv4_route.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_ldp_binding.ref-149
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_ldp_discovery.ref-19
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_ldp_interface.ref-12
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_ldp_neighbor.ref-117
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_table.ref20
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_table.ref-110
-rw-r--r--tests/topotests/ldp-topo1/r3/show_mpls_table.ref-no-impl-null10
-rw-r--r--tests/topotests/ldp-topo1/r4/show_ipv4_route.ref-17
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_ldp_binding.ref-149
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_ldp_discovery.ref-19
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_ldp_interface.ref-12
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_ldp_neighbor.ref-117
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_table.ref18
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_table.ref-19
-rw-r--r--tests/topotests/ldp-topo1/r4/show_mpls_table.ref-no-impl-null9
-rwxr-xr-xtests/topotests/ldp-topo1/test_ldp_topo1.py119
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref31
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist14
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref30
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist14
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref30
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist14
-rwxr-xr-xtests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py27
-rw-r--r--tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json12
-rw-r--r--tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json18
-rw-r--r--tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json10
-rw-r--r--tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json12
-rw-r--r--tests/topotests/pytest.ini2
-rw-r--r--tools/etc/frr/support_bundle_commands.conf10
-rwxr-xr-x[-rw-r--r--]tools/generate_support_bundle.py2
-rw-r--r--tools/subdir.am2
-rw-r--r--vtysh/vtysh.c57
-rw-r--r--vtysh/vtysh_config.c4
-rw-r--r--watchfrr/subdir.am3
-rw-r--r--watchfrr/watchfrr.c37
-rw-r--r--watchfrr/watchfrr.h2
-rw-r--r--watchfrr/watchfrr_vty.c20
-rw-r--r--yang/frr-isisd.yang682
-rw-r--r--yang/libyang_plugins/frr_user_types.c35
-rw-r--r--zebra/connected.c2
-rw-r--r--zebra/if_netlink.c3
-rw-r--r--zebra/interface.c9
-rw-r--r--zebra/main.c4
-rw-r--r--zebra/redistribute.c98
-rw-r--r--zebra/redistribute.h18
-rw-r--r--zebra/rt_netlink.c12
-rw-r--r--zebra/rule_netlink.c4
-rw-r--r--zebra/zapi_msg.c198
-rw-r--r--zebra/zapi_msg.h3
-rw-r--r--zebra/zebra_fpm.c5
-rw-r--r--zebra/zebra_mpls.c187
-rw-r--r--zebra/zebra_mpls.h34
-rw-r--r--zebra/zebra_rib.c28
-rw-r--r--zebra/zebra_rnh.c12
-rw-r--r--zebra/zebra_routemap.c11
-rw-r--r--zebra/zebra_vrf.c2
-rw-r--r--zebra/zebra_vty.c11
192 files changed, 4924 insertions, 3355 deletions
diff --git a/README.md b/README.md
index e8c775684a..bb13481cf2 100644
--- a/README.md
+++ b/README.md
@@ -27,14 +27,15 @@ FRR currently supports the following protocols:
Installation & Use
------------------
-Packages are available for various distributions on our
+For source tarballs, see the
[releases page](https://github.com/FRRouting/frr/releases).
-Snaps are also available [here](https://snapcraft.io/frr).
+For Debian and its derivatives, use the APT repository at
+[https://deb.frrouting.org/](https://deb.frrouting.org/).
Instructions on building and installing from source for supported platforms may
-be found
-[here](http://docs.frrouting.org/projects/dev-guide/en/latest/building.html).
+be found in the
+[developer docs](http://docs.frrouting.org/projects/dev-guide/en/latest/building.html).
Once installed, please refer to the [user guide](http://docs.frrouting.org/)
for instructions on use.
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 1f1568f511..245f2dc5ee 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -391,10 +391,8 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
/* Search for session without using discriminator. */
ifp = if_lookup_by_index(ifindex, vrfid);
- if (vrfid != VRF_DEFAULT)
- vrf = vrf_lookup_by_id(vrfid);
- else
- vrf = NULL;
+
+ vrf = vrf_lookup_by_id(vrfid);
gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
vrf ? vrf->name : VRF_DEFAULT_NAME);
@@ -1632,6 +1630,16 @@ static int bfd_vrf_delete(struct vrf *vrf)
return 0;
}
+static int bfd_vrf_update(struct vrf *vrf)
+{
+ if (!vrf_is_enabled(vrf))
+ return 0;
+ log_debug("VRF update: %s(%u)", vrf->name, vrf->vrf_id);
+ /* a different name is given; update bfd list */
+ bfdd_sessions_enable_vrf(vrf);
+ return 0;
+}
+
static int bfd_vrf_enable(struct vrf *vrf)
{
struct bfd_vrf_global *bvrf;
@@ -1719,7 +1727,7 @@ static int bfd_vrf_disable(struct vrf *vrf)
void bfd_vrf_init(void)
{
vrf_init(bfd_vrf_new, bfd_vrf_enable, bfd_vrf_disable,
- bfd_vrf_delete, NULL);
+ bfd_vrf_delete, bfd_vrf_update);
}
void bfd_vrf_terminate(void)
@@ -1743,3 +1751,54 @@ struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd)
return NULL;
return bfd->vrf->info;
}
+
+void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf)
+{
+ if (!vrf || !bs)
+ return;
+ /* update key */
+ hash_release(bfd_key_hash, bs);
+ /*
+ * HACK: Change the BFD VRF in the running configuration directly,
+ * bypassing the northbound layer. This is necessary to avoid deleting
+ * the BFD and readding it in the new VRF, which would have
+ * several implications.
+ */
+ if (yang_module_find("frr-bfdd") && bs->key.vrfname[0]) {
+ struct lyd_node *bfd_dnode;
+ char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32];
+ char addr_buf[INET6_ADDRSTRLEN];
+ int slen;
+
+ /* build xpath */
+ if (bs->key.mhop) {
+ inet_ntop(bs->key.family, &bs->key.local, addr_buf, sizeof(addr_buf));
+ snprintf(xpath_srcaddr, sizeof(xpath_srcaddr), "[source-addr='%s']",
+ addr_buf);
+ } else
+ xpath_srcaddr[0] = 0;
+ inet_ntop(bs->key.family, &bs->key.peer, addr_buf, sizeof(addr_buf));
+ slen = snprintf(xpath, sizeof(xpath),
+ "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']",
+ bs->key.mhop ? "multi-hop" : "single-hop", xpath_srcaddr,
+ addr_buf);
+ if (bs->key.ifname[0])
+ slen += snprintf(xpath + slen, sizeof(xpath) - slen,
+ "[interface='%s']", bs->key.ifname);
+ else
+ slen += snprintf(xpath + slen, sizeof(xpath) - slen,
+ "[interface='']");
+ snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']/vrf",
+ bs->key.vrfname);
+
+ bfd_dnode = yang_dnode_get(running_config->dnode, xpath,
+ bs->key.vrfname);
+ if (bfd_dnode) {
+ yang_dnode_change_leaf(bfd_dnode, vrf->name);
+ running_config->version++;
+ }
+ }
+ memset(bs->key.vrfname, 0, sizeof(bs->key.vrfname));
+ strlcpy(bs->key.vrfname, vrf->name, sizeof(bs->key.vrfname));
+ hash_get(bfd_key_hash, bs, hash_alloc_intern);
+}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 10aeb3e52c..cdec78d122 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -630,6 +630,7 @@ void bfdd_zclient_unregister(vrf_id_t vrf_id);
void bfdd_zclient_register(vrf_id_t vrf_id);
void bfdd_sessions_enable_vrf(struct vrf *vrf);
void bfdd_sessions_disable_vrf(struct vrf *vrf);
+void bfd_session_update_vrf_name(struct bfd_session *bs, struct vrf *vrf);
int ptm_bfd_notify(struct bfd_session *bs);
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index a211f34219..5663ce54cb 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -685,6 +685,9 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
snprintf(ebuf, ebuflen, "vrf name too long");
return -1;
}
+ } else {
+ bpc->bpc_has_vrfname = true;
+ strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
}
return 0;
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 3e2ace6ea6..ae6d04e77d 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -376,6 +376,9 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
log_error("ptm-read: vrf id %u could not be identified", vrf_id);
return -1;
}
+ } else {
+ bpc->bpc_has_vrfname = true;
+ strlcpy(bpc->bpc_vrfname, VRF_DEFAULT_NAME, sizeof(bpc->bpc_vrfname));
}
STREAM_GETC(msg, bpc->bpc_cbit);
@@ -627,6 +630,11 @@ void bfdd_sessions_enable_vrf(struct vrf *vrf)
/* it may affect configs without interfaces */
TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
bs = bso->bso_bs;
+ /* update name */
+ if (bs->vrf && bs->vrf == vrf) {
+ if (!strmatch(bs->key.vrfname, vrf->name))
+ bfd_session_update_vrf_name(bs, vrf);
+ }
if (bs->vrf)
continue;
if (bs->key.vrfname[0] &&
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index ab9dc3092a..a7cd3fee88 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -519,8 +519,7 @@ unsigned int attrhash_key_make(const void *p)
MIX(attr->mp_nexthop_len);
key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
- MIX(attr->nh_ifindex);
- MIX(attr->nh_lla_ifindex);
+ MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
return key;
}
@@ -562,7 +561,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
&attr2->originator_id)
&& overlay_index_same(attr1, attr2)
&& attr1->nh_ifindex == attr2->nh_ifindex
- && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex)
+ && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
+ && attr1->distance == attr2->distance)
return true;
}
@@ -1305,14 +1305,20 @@ bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
|| IPV4_CLASS_DE(nexthop_h))
&& !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
+ uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
INET_ADDRSTRLEN);
flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
buf);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP);
+ data[0] = BGP_ATTR_FLAG_TRANS;
+ data[1] = BGP_ATTR_NEXT_HOP;
+ data[2] = BGP_ATTR_NHLEN_IPV4;
+ memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
+ bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
+ data, 7);
return BGP_ATTR_PARSE_ERROR;
}
@@ -1685,8 +1691,8 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
#define BGP_MP_REACH_MIN_SIZE 5
#define LEN_LEFT (length - (stream_get_getp(s) - start))
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
- zlog_info("%s: %s sent invalid length, %lu", __func__,
- peer->host, (unsigned long)length);
+ zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
+ __func__, peer->host, (unsigned long)length);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
@@ -1702,7 +1708,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
*/
if (bgp_debug_update(peer, NULL, NULL, 0))
zlog_debug(
- "%s: MP_REACH received AFI %s or SAFI %s is unrecognized",
+ "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
peer->host, iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
return BGP_ATTR_PARSE_ERROR;
@@ -1713,7 +1719,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
if (LEN_LEFT < attr->mp_nexthop_len) {
zlog_info(
- "%s: %s, MP nexthop length, %u, goes past end of attribute",
+ "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
__func__, peer->host, attr->mp_nexthop_len);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
@@ -1722,7 +1728,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
switch (attr->mp_nexthop_len) {
case 0:
if (safi != SAFI_FLOWSPEC) {
- zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
+ zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
__func__, peer->host, attr->mp_nexthop_len);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
@@ -1754,7 +1760,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
if (!peer->nexthop.ifp) {
- zlog_warn("%s: Received a V6/VPNV6 Global attribute but address is a V6 LL and we have no peer interface information, withdrawing",
+ zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
peer->host);
return BGP_ATTR_PARSE_WITHDRAW;
}
@@ -1771,7 +1777,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
if (!peer->nexthop.ifp) {
- zlog_warn("%s: Received V6/VPNV6 Global and LL attribute but global address is a V6 LL and we have no peer interface information, withdrawing",
+ zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
peer->host);
return BGP_ATTR_PARSE_WITHDRAW;
}
@@ -1789,7 +1795,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
if (bgp_debug_update(peer, NULL, NULL, 1))
zlog_debug(
- "%s rcvd nexthops %s, %s -- ignoring non-LL value",
+ "%s sent next-hops %s and %s. Ignoring non-LL value",
peer->host,
inet_ntop(AF_INET6,
&attr->mp_nexthop_global,
@@ -1801,21 +1807,21 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
}
if (!peer->nexthop.ifp) {
- zlog_warn("%s: Received a V6 LL nexthop and we have no peer interface information, withdrawing",
+ zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
peer->host);
return BGP_ATTR_PARSE_WITHDRAW;
}
attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
break;
default:
- zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d",
+ zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
__func__, peer->host, attr->mp_nexthop_len);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
if (!LEN_LEFT) {
- zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__,
- peer->host);
+ zlog_info("%s: %s sent SNPA which couldn't be read",
+ __func__, peer->host);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
@@ -1831,12 +1837,13 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
/* must have nrli_len, what is left of the attribute */
nlri_len = LEN_LEFT;
if (nlri_len > STREAM_READABLE(s)) {
- zlog_info("%s: (%s) Failed to read NLRI", __func__, peer->host);
+ zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
+ __func__, peer->host);
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
if (!nlri_len) {
- zlog_info("%s: (%s) No Reachability, Treating as a EOR marker",
+ zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
__func__, peer->host);
mp_update->afi = afi;
@@ -2043,8 +2050,8 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
length -= 4;
if (tlv_length != length) {
- zlog_info("%s: tlv_length(%d) != length(%d)", __func__,
- tlv_length, length);
+ zlog_info("%s: tlv_length(%d) != length(%d)",
+ __func__, tlv_length, length);
}
}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index f1a871fe43..cfa428a796 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -206,6 +206,9 @@ struct attr {
/* EVPN local router-mac */
struct ethaddr rmac;
+
+ /* Distance as applied by Route map */
+ uint8_t distance;
};
/* rmap_change_flags definition */
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 3af373b562..551102151e 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -1767,7 +1767,7 @@ static struct cmd_node bmp_node = {BMP_NODE, "%s(config-bgp-bmp)# "};
#define BMP_STR "BGP Monitoring Protocol\n"
#ifndef VTYSH_EXTRACT_PL
-#include "bgp_bmp_clippy.c"
+#include "bgpd/bgp_bmp_clippy.c"
#endif
DEFPY_NOSH(bmp_targets_main,
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 79c873e601..0be8becbab 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1324,7 +1324,7 @@ static int bgp_connect_check(struct thread *thread)
/* If getsockopt is fail, this is fatal error. */
if (ret < 0) {
- zlog_info("can't get sockopt for nonblocking connect: %d(%s)",
+ zlog_err("can't get sockopt for nonblocking connect: %d(%s)",
errno, safe_strerror(errno));
BGP_EVENT_ADD(peer, TCP_fatal_error);
return -1;
diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c
index 6de1c216a6..3a49e8bc00 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -97,11 +97,18 @@ static void peer_process(struct hash_bucket *hb, void *arg)
static struct timeval tolerance = {0, 100000};
+ uint32_t v_ka = atomic_load_explicit(&pkat->peer->v_keepalive,
+ memory_order_relaxed);
+
+ /* 0 keepalive timer means no keepalives */
+ if (v_ka == 0)
+ return;
+
/* calculate elapsed time since last keepalive */
monotime_since(&pkat->last, &elapsed);
/* calculate difference between elapsed time and configured time */
- ka.tv_sec = pkat->peer->v_keepalive;
+ ka.tv_sec = v_ka;
timersub(&ka, &elapsed, &diff);
int send_keepalive =
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index abd8586f4c..ef73b47ffb 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -269,12 +269,20 @@ static int bgp_vrf_enable(struct vrf *vrf)
zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name(vrf->name);
- if (bgp) {
+ if (bgp && bgp->vrf_id != vrf->vrf_id) {
if (bgp->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
XFREE(MTYPE_BGP, bgp->name);
bgp->name = NULL;
XFREE(MTYPE_BGP, bgp->name_pretty);
bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
+ bgp->inst_type = BGP_INSTANCE_TYPE_DEFAULT;
+#if ENABLE_BGP_VNC
+ if (!bgp->rfapi) {
+ bgp->rfapi = bgp_rfapi_new(bgp);
+ assert(bgp->rfapi);
+ assert(bgp->rfapi_cfg);
+ }
+#endif /* ENABLE_BGP_VNC */
}
old_vrf_id = bgp->vrf_id;
/* We have instance configured, link to VRF and make it "up". */
@@ -343,7 +351,7 @@ static int bgp_vrf_disable(struct vrf *vrf)
static void bgp_vrf_init(void)
{
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable,
- bgp_vrf_delete, NULL);
+ bgp_vrf_delete, bgp_vrf_enable);
}
static void bgp_vrf_terminate(void)
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 1156810510..c81abd643f 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -781,12 +781,12 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
static_attr.nexthop.s_addr = nexthop->u.prefix4.s_addr;
static_attr.mp_nexthop_global_in = nexthop->u.prefix4;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
break;
case AF_INET6:
static_attr.mp_nexthop_global = nexthop->u.prefix6;
- static_attr.mp_nexthop_len = 16;
+ static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
break;
default:
@@ -802,7 +802,8 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
*/
static_attr.mp_nexthop_global_in =
static_attr.nexthop;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV4;
/*
* XXX Leave static_attr.nexthop
* intact for NHT
@@ -821,7 +822,8 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
&& !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
static_attr.mp_nexthop_global_in.s_addr =
static_attr.nexthop.s_addr;
- static_attr.mp_nexthop_len = 4;
+ static_attr.mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV4;
static_attr.flag |=
ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
}
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 7e5e07099d..f17bc7b8c0 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1031,7 +1031,7 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
as_t as4 = 0;
if (BGP_DEBUG(as4, AS4))
- zlog_info(
+ zlog_debug(
"%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
" peeking for as4",
peer->host, length);
@@ -1075,7 +1075,7 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
if (hdr.code == CAPABILITY_CODE_AS4) {
if (BGP_DEBUG(as4, AS4))
- zlog_info(
+ zlog_debug(
"[AS4] found AS4 capability, about to parse");
as4 = bgp_capability_as4(peer, &hdr);
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 8359f59a41..5250a68581 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -68,13 +68,13 @@ struct graceful_restart_af {
/* Cooperative Route Filtering Capability. */
/* ORF Type */
-#define ORF_TYPE_PREFIX 64
+#define ORF_TYPE_PREFIX 64
#define ORF_TYPE_PREFIX_OLD 128
/* ORF Mode */
-#define ORF_MODE_RECEIVE 1
-#define ORF_MODE_SEND 2
-#define ORF_MODE_BOTH 3
+#define ORF_MODE_RECEIVE 1
+#define ORF_MODE_SEND 2
+#define ORF_MODE_BOTH 3
/* Capability Message Action. */
#define CAPABILITY_ACTION_SET 0
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index fc6fc66a4c..49e401790f 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -39,14 +39,14 @@ DECLARE_HOOK(bgp_packet_send,
/* When to refresh */
#define REFRESH_IMMEDIATE 1
-#define REFRESH_DEFER 2
+#define REFRESH_DEFER 2
/* ORF Common part flag */
-#define ORF_COMMON_PART_ADD 0x00
-#define ORF_COMMON_PART_REMOVE 0x80
-#define ORF_COMMON_PART_REMOVE_ALL 0xC0
-#define ORF_COMMON_PART_PERMIT 0x00
-#define ORF_COMMON_PART_DENY 0x20
+#define ORF_COMMON_PART_ADD 0x00
+#define ORF_COMMON_PART_REMOVE 0x80
+#define ORF_COMMON_PART_REMOVE_ALL 0xC0
+#define ORF_COMMON_PART_PERMIT 0x00
+#define ORF_COMMON_PART_DENY 0x20
/* Packet send and receive function prototypes. */
extern void bgp_keepalive_send(struct peer *);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 5eeab36742..05974bb2ba 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -7269,7 +7269,8 @@ void route_vty_out(struct vty *vty, struct prefix *p,
/* We display both LL & GL if both have been
* received */
- if ((attr->mp_nexthop_len == 32)
+ if ((attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|| (path->peer->conf_if)) {
json_nexthop_ll = json_object_new_object();
json_object_string_add(
@@ -7301,7 +7302,8 @@ void route_vty_out(struct vty *vty, struct prefix *p,
} else {
/* Display LL if LL/Global both in table unless
* prefer-global is set */
- if (((attr->mp_nexthop_len == 32)
+ if (((attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
&& !attr->mp_nexthop_prefer_global)
|| (path->peer->conf_if)) {
if (path->peer->conf_if) {
@@ -11875,6 +11877,9 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo,
peer = pinfo->peer;
+ if (pinfo->attr->distance)
+ return pinfo->attr->distance;
+
/* Check source address. */
sockunion2hostprefix(&peer->su, &q);
rn = bgp_node_match(bgp_distance_table[afi][safi], &q);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index ba4e32c23d..a710873ea7 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -236,9 +236,9 @@ struct bgp_path_info {
#define BGP_ROUTE_NORMAL 0
#define BGP_ROUTE_STATIC 1
#define BGP_ROUTE_AGGREGATE 2
-#define BGP_ROUTE_REDISTRIBUTE 3
+#define BGP_ROUTE_REDISTRIBUTE 3
#ifdef ENABLE_BGP_VNC
-# define BGP_ROUTE_RFP 4
+# define BGP_ROUTE_RFP 4
#endif
#define BGP_ROUTE_IMPORTED 5 /* from another bgp instance/safi */
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index b1f1819b6b..a5286cea69 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1210,10 +1210,26 @@ static void route_match_community_free(void *rule)
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
}
+/*
+ * In routemap processing there is a need to add the
+ * name as a rule_key in the dependency table. Routemap
+ * lib is unaware of rule_key when exact-match clause
+ * is in use. routemap lib uses the compiled output to
+ * get the rule_key value.
+ */
+static void *route_match_get_community_key(void *rule)
+{
+ struct rmap_community *rcom;
+
+ rcom = rule;
+ return rcom->name;
+}
+
+
/* Route map commands for community matching. */
struct route_map_rule_cmd route_match_community_cmd = {
"community", route_match_community, route_match_community_compile,
- route_match_community_free};
+ route_match_community_free, route_match_get_community_key};
/* Match function for lcommunity match. */
static enum route_map_cmd_result_t
@@ -1284,7 +1300,8 @@ static void route_match_lcommunity_free(void *rule)
/* Route map commands for community matching. */
struct route_map_rule_cmd route_match_lcommunity_cmd = {
"large-community", route_match_lcommunity,
- route_match_lcommunity_compile, route_match_lcommunity_free};
+ route_match_lcommunity_compile, route_match_lcommunity_free,
+ route_match_get_community_key};
/* Match function for extcommunity match. */
@@ -1683,6 +1700,30 @@ struct route_map_rule_cmd route_set_weight_cmd = {
"weight", route_set_weight, route_value_compile, route_value_free,
};
+/* `set distance DISTANCE */
+static enum route_map_cmd_result_t
+route_set_distance(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct bgp_path_info *path = object;
+ struct rmap_value *rv = rule;
+
+ if (type != RMAP_BGP)
+ return RMAP_OKAY;
+
+ path->attr->distance = rv->value;
+
+ return RMAP_OKAY;
+}
+
+/* set distance rule structure */
+struct route_map_rule_cmd route_set_distance_cmd = {
+ "distance",
+ route_set_distance,
+ route_value_compile,
+ route_value_free,
+};
+
/* `set metric METRIC' */
/* Set metric to attribute. */
@@ -2731,10 +2772,8 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
path = object;
peer = path->peer;
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET6) {
+ if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
/* Set next hop preference to global */
path->attr->mp_nexthop_prefer_global = true;
SET_FLAG(path->attr->rmap_change_flags,
@@ -2856,12 +2895,15 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx,
/* Set next hop value and length in attribute. */
if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
path->attr->mp_nexthop_local = peer_address;
- if (path->attr->mp_nexthop_len != 32)
- path->attr->mp_nexthop_len = 32;
+ if (path->attr->mp_nexthop_len
+ != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ path->attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
} else {
path->attr->mp_nexthop_global = peer_address;
if (path->attr->mp_nexthop_len == 0)
- path->attr->mp_nexthop_len = 16;
+ path->attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL;
}
} else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
@@ -2926,7 +2968,7 @@ route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix,
/* Set next hop value. */
path->attr->mp_nexthop_global_in = *address;
- path->attr->mp_nexthop_len = 4;
+ path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
}
return RMAP_OKAY;
@@ -3073,11 +3115,6 @@ static int bgp_route_match_add(struct vty *vty, const char *command,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_ADDED) {
- route_map_upd8_dependency(type, arg, index->map->name);
- }
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Intentionally doing nothing here.
*/
@@ -3111,7 +3148,7 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
}
- ret = route_map_delete_match(index, command, dep_name);
+ ret = route_map_delete_match(index, command, dep_name, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% BGP Can't find rule.\n");
@@ -3122,10 +3159,6 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
- route_map_upd8_dependency(type, dep_name, rmap_name);
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
@@ -4061,6 +4094,29 @@ DEFUN (set_ip_nexthop_unchanged,
"unchanged");
}
+DEFUN (set_distance,
+ set_distance_cmd,
+ "set distance (0-255)",
+ SET_STR
+ "BGP Administrative Distance to use\n"
+ "Distance value\n")
+{
+ int idx_number = 2;
+
+ return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
+ "distance", argv[idx_number]->arg);
+}
+
+DEFUN (no_set_distance,
+ no_set_distance_cmd,
+ "no set distance [(0-255)]",
+ NO_STR SET_STR
+ "BGP Administrative Distance to use\n"
+ "Distance value\n")
+{
+ return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
+ "distance", NULL);
+}
DEFUN (set_local_pref,
set_local_pref_cmd,
@@ -5116,6 +5172,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_weight_cmd);
route_map_install_set(&route_set_label_index_cmd);
route_map_install_set(&route_set_metric_cmd);
+ route_map_install_set(&route_set_distance_cmd);
route_map_install_set(&route_set_aspath_prepend_cmd);
route_map_install_set(&route_set_aspath_exclude_cmd);
route_map_install_set(&route_set_origin_cmd);
@@ -5169,6 +5226,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
install_element(RMAP_NODE, &set_local_pref_cmd);
+ install_element(RMAP_NODE, &set_distance_cmd);
+ install_element(RMAP_NODE, &no_set_distance_cmd);
install_element(RMAP_NODE, &no_set_local_pref_cmd);
install_element(RMAP_NODE, &set_weight_cmd);
install_element(RMAP_NODE, &set_label_index_cmd);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 2cfd65896c..352e3b87e8 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -1420,7 +1420,6 @@ DEFUN (match_rpki,
vty_out(vty, "%% BGP Argument is malformed.\n");
return CMD_WARNING_CONFIG_FAILED;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* Intentionally doing nothing here
*/
@@ -1443,7 +1442,8 @@ DEFUN (no_match_rpki,
VTY_DECLVAR_CONTEXT(route_map_index, index);
enum rmap_compile_rets ret;
- ret = route_map_delete_match(index, "rpki", argv[3]->arg);
+ ret = route_map_delete_match(index, "rpki", argv[3]->arg,
+ RMAP_EVENT_MATCH_DELETED);
if (ret) {
switch (ret) {
case RMAP_RULE_MISSING:
@@ -1453,7 +1453,6 @@ DEFUN (no_match_rpki,
vty_out(vty, "%% BGP Argument is malformed.\n");
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index de7b05bdd9..4b6af935e0 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -570,8 +570,7 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime));
filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi];
if (filter->map[RMAP_OUT].name)
- vty_out(vty, " Outgoing route map: %s%s\n",
- filter->map[RMAP_OUT].map ? "X" : "",
+ vty_out(vty, " Outgoing route map: %s\n",
filter->map[RMAP_OUT].name);
vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv);
if (updgrp->conf->change_local_as)
@@ -613,6 +612,9 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
subgrp->peer_refreshes_combined);
vty_out(vty, " Merge checks triggered: %u\n",
subgrp->merge_checks_triggered);
+ vty_out(vty, " Coalesce Time: %u%s\n",
+ (UPDGRP_INST(subgrp->update_group))->coalesce_time,
+ subgrp->t_coalesce ? "(Running)" : "");
vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version);
vty_out(vty, " Packet queue length: %d\n",
bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 21f1dff60d..5c1483a768 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -324,8 +324,9 @@ static int subgroup_coalesce_timer(struct thread *thread)
subgrp = THREAD_ARG(thread);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
zlog_debug("u%" PRIu64 ":s%" PRIu64
- " announcing routes upon coalesce timer expiry",
- (SUBGRP_UPDGRP(subgrp))->id, subgrp->id);
+ " announcing routes upon coalesce timer expiry(%u ms)",
+ (SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
+ subgrp->v_coalesce),
subgrp->t_coalesce = NULL;
subgrp->v_coalesce = 0;
subgroup_announce_route(subgrp);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 5b31fbb3a8..e815334bfc 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2053,7 +2053,7 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
&& !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_info(
+ zlog_debug(
"peer(s) are now active for labeled-unicast, allocate MPLS labels");
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
@@ -2156,7 +2156,7 @@ int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
&& !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_info(
+ zlog_debug(
"peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
@@ -7931,8 +7931,6 @@ static void bgp_pthreads_init(void)
assert(!bgp_pth_io);
assert(!bgp_pth_ka);
- frr_pthread_init();
-
struct frr_pthread_attr io = {
.start = frr_pthread_attr_default.start,
.stop = frr_pthread_attr_default.stop,
@@ -7958,7 +7956,6 @@ void bgp_pthreads_run(void)
void bgp_pthreads_finish(void)
{
frr_pthread_stop_all();
- frr_pthread_finish();
}
void bgp_init(unsigned short instance)
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 9b8f64ee67..0aa102feab 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -880,12 +880,12 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
attr.nexthop.s_addr = nexthop->addr.v4.s_addr;
attr.mp_nexthop_global_in = nexthop->addr.v4;
- attr.mp_nexthop_len = 4;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
break;
case AF_INET6:
attr.mp_nexthop_global = nexthop->addr.v6;
- attr.mp_nexthop_len = 16;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
break;
default:
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 3d8d5bccb0..b97c8c3030 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -86,13 +86,13 @@ static void encap_attr_export_ce(struct attr *new, struct attr *orig,
switch (use_nexthop->family) {
case AF_INET:
new->nexthop = use_nexthop->u.prefix4;
- new->mp_nexthop_len = 4; /* bytes */
+ new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
break;
case AF_INET6:
new->mp_nexthop_global = use_nexthop->u.prefix6;
- new->mp_nexthop_len = 16; /* bytes */
+ new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
break;
default:
@@ -624,13 +624,13 @@ encap_attr_export(struct attr *new, struct attr *orig,
switch (use_nexthop->family) {
case AF_INET:
new->nexthop = use_nexthop->u.prefix4;
- new->mp_nexthop_len = 4; /* bytes */
+ new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
break;
case AF_INET6:
new->mp_nexthop_global = use_nexthop->u.prefix6;
- new->mp_nexthop_len = 16; /* bytes */
+ new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
break;
default:
diff --git a/configure.ac b/configure.ac
index be3a9c763d..88f1c4f627 100755
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.60])
-AC_INIT([frr], [7.2-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [7.3-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
diff --git a/debian/frr-pythontools.install b/debian/frr-pythontools.install
index 28140382f6..5f7eaebed5 100644
--- a/debian/frr-pythontools.install
+++ b/debian/frr-pythontools.install
@@ -1 +1,2 @@
usr/lib/frr/frr-reload.py
+usr/lib/frr/generate_support_bundle.py
diff --git a/debian/rules b/debian/rules
index a546f38d70..c8550ecb52 100755
--- a/debian/rules
+++ b/debian/rules
@@ -71,6 +71,7 @@ override_dh_auto_install:
dh_auto_install
sed -e '1c #!/usr/bin/python3' -i debian/tmp/usr/lib/frr/frr-reload.py
+ sed -e '1c #!/usr/bin/python3' -i debian/tmp/usr/lib/frr/generate_support_bundle.py
# let dh_systemd_* and dh_installinit do their thing automatically
ifeq ($(filter pkg.frr.nosystemd,$(DEB_BUILD_PROFILES)),)
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 7b3cdf2c4b..8edd19026d 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -2396,6 +2396,23 @@ Displaying Routes by AS Path
Print a summary of neighbor connections for the specified AFI/SAFI combination.
+Displaying Update Group Information
+-----------------------------------
+
+..index:: show bgp update-groups SUBGROUP-ID [advertise-queue|advertised-routes|packet-queue]
+..clicmd:: show bgp update-groups [advertise-queue|advertised-routes|packet-queue]
+
+ Display Information about each individual update-group being used.
+ If SUBGROUP-ID is specified only display about that particular group. If
+ advertise-queue is specified the list of routes that need to be sent
+ to the peers in the update-group is displayed, advertised-routes means
+ the list of routes we have sent to the peers in the update-group and
+ packet-queue specifies the list of packets in the queue to be sent.
+
+..index:: show bgp update-groups statistics
+..clicmd:: show bgp update-groups statistics
+
+ Display Information about update-group events in FRR.
.. _bgp-route-reflector:
diff --git a/doc/user/index.rst b/doc/user/index.rst
index 6c3b14e062..416c51f13b 100644
--- a/doc/user/index.rst
+++ b/doc/user/index.rst
@@ -58,6 +58,7 @@ Protocols
vnc
vrrp
bmp
+ watchfrr
########
Appendix
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 805d6264a8..4f9c573a24 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -201,14 +201,15 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
.. clicmd:: ip pim sm
Tell pim that we would like to use this interface to form pim neighbors
- over. Please note we will *not* accept igmp reports over this interface with
- this command.
+ over. Please note that this command does not enable the reception of IGMP
+ reports on the interface. Refer to the next `ip igmp` command for IGMP
+ management.
.. index:: ip igmp
.. clicmd:: ip igmp
Tell pim to receive IGMP reports and Query on this interface. The default
- version is v3. This command is useful on the LHR.
+ version is v3. This command is useful on a LHR.
.. index:: ip igmp join A.B.C.D A.B.C.D
.. clicmd:: ip igmp join A.B.C.D A.B.C.D
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 09cbd7c7b0..e36783d176 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -270,6 +270,12 @@ Route Map Set Command
Set the BGP local preference to `local_pref`.
+.. index:: [no] set distance DISTANCE
+.. clicmd:: [no] set distance DISTANCE
+
+ Set the Administrative distance to DISTANCE to use for the route.
+ This is only locally significant and will not be dispersed to peers.
+
.. index:: set weight WEIGHT
.. clicmd:: set weight WEIGHT
diff --git a/doc/user/subdir.am b/doc/user/subdir.am
index 0f0a8a0774..ce519fbfbf 100644
--- a/doc/user/subdir.am
+++ b/doc/user/subdir.am
@@ -43,6 +43,7 @@ user_RSTFILES = \
doc/user/zebra.rst \
doc/user/bfd.rst \
doc/user/flowspec.rst \
+ doc/user/watchfrr.rst \
# end
EXTRA_DIST += \
diff --git a/doc/user/watchfrr.rst b/doc/user/watchfrr.rst
new file mode 100644
index 0000000000..df04a1e375
--- /dev/null
+++ b/doc/user/watchfrr.rst
@@ -0,0 +1,30 @@
+.. _watchfrr:
+
+********
+WATCHFRR
+********
+
+:abbr:`WATCHFRR` is a daemon that handles failed daemon processes and
+intelligently restarts them as needed.
+
+Starting WATCHFRR
+=================
+
+WATCHFRR is started as per normal systemd startup and typically does not
+require end users management.
+
+WATCHFRR commands
+=================
+
+.. index:: show watchfrr
+.. clicmd:: show watchfrr
+
+ Give status information about the state of the different daemons being
+ watched by WATCHFRR
+
+.. index:: [no] watchfrr ignore DAEMON
+.. clicmd:: [no] watchfrr ignore DAEMON
+
+ Tell WATCHFRR to ignore a particular DAEMON if it goes unresponsive.
+ This is particularly useful when you are a developer and need to debug
+ a working system, without watchfrr pulling the rug out from under you.
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index b7283d83de..5d2cfbc337 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -663,19 +663,30 @@ kernel.
.. clicmd:: ip protocol PROTOCOL route-map ROUTEMAP
Apply a route-map filter to routes for the specified protocol. PROTOCOL can
- be **any** or one of
+ be:
- - system,
- - kernel,
+ - any,
+ - babel,
+ - bgp,
- connected,
- - static,
- - rip,
- - ripng,
+ - eigrp,
+ - isis,
+ - kernel,
+ - nhrp,
+ - openfabric,
- ospf,
- ospf6,
- - isis,
- - bgp,
- - hsls.
+ - rip,
+ - sharp,
+ - static,
+ - ripng,
+ - table,
+ - vnc.
+
+ If you choose any as the option that will cause all protocols that are sending
+ routes to zebra. You can specify a :dfn:`ip protocol PROTOCOL route-map ROUTEMAP`
+ on a per vrf basis, by entering this command under vrf mode for the vrf you
+ want to apply the route-map against.
.. index:: set src ADDRESS
.. clicmd:: set src ADDRESS
diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c
index d78588644f..e7a7cc56aa 100644
--- a/eigrpd/eigrp_routemap.c
+++ b/eigrpd/eigrp_routemap.c
@@ -148,7 +148,6 @@ static int eigrp_route_match_add(struct vty *vty, struct route_map_index *index,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* Intentionally not handling these cases
*/
@@ -165,7 +164,7 @@ static int eigrp_route_match_delete(struct vty *vty,
{
enum rmap_compile_rets ret;
- ret = route_map_delete_match(index, command, arg);
+ ret = route_map_delete_match(index, command, arg, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% Can't find rule.\n");
@@ -176,7 +175,6 @@ static int eigrp_route_match_delete(struct vty *vty,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* These cases intentionally ignored
*/
@@ -211,7 +209,6 @@ static int eigrp_route_set_add(struct vty *vty, struct route_map_index *index,
}
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* These cases intentionally left blank here
*/
@@ -239,7 +236,6 @@ static int eigrp_route_set_delete(struct vty *vty,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
/*
* These cases intentionally not handled
*/
diff --git a/fpm/subdir.am b/fpm/subdir.am
index a0fa3d274f..a645ca2b03 100644
--- a/fpm/subdir.am
+++ b/fpm/subdir.am
@@ -12,9 +12,13 @@ fpm_libfrrfpm_pb_la_SOURCES = \
fpm/fpm_pb.c \
# end
+if FPM
+if HAVE_PROTOBUF
nodist_fpm_libfrrfpm_pb_la_SOURCES = \
fpm/fpm.pb-c.c \
# end
+endif
+endif
CLEANFILES += \
fpm/fpm.pb-c.c \
diff --git a/grpc/subdir.am b/grpc/subdir.am
index 3fb163fccf..048e12a024 100644
--- a/grpc/subdir.am
+++ b/grpc/subdir.am
@@ -5,10 +5,12 @@ endif
grpc_libfrrgrpc_pb_la_LDFLAGS = -version-info 0:0:0
grpc_libfrrgrpc_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(GRPC_CXXFLAGS)
+if GRPC
nodist_grpc_libfrrgrpc_pb_la_SOURCES = \
grpc/frr-northbound.pb.cc \
grpc/frr-northbound.grpc.pb.cc \
# end
+endif
CLEANFILES += \
grpc/frr-northbound.pb.cc \
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index bc6688012c..232df14e12 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_FIB_RULES_H
#define __LINUX_FIB_RULES_H
@@ -22,13 +23,23 @@ struct fib_rule_hdr {
__u8 tos;
__u8 table;
- __u8 res1; /* reserved */
+ __u8 res1; /* reserved */
__u8 res2; /* reserved */
__u8 action;
__u32 flags;
};
+struct fib_rule_uid_range {
+ __u32 start;
+ __u32 end;
+};
+
+struct fib_rule_port_range {
+ __u16 start;
+ __u16 end;
+};
+
enum {
FRA_UNSPEC,
FRA_DST, /* destination address */
@@ -43,7 +54,7 @@ enum {
FRA_UNUSED5,
FRA_FWMARK, /* mark */
FRA_FLOW, /* flow/class id */
- FRA_UNUSED6,
+ FRA_TUN_ID,
FRA_SUPPRESS_IFGROUP,
FRA_SUPPRESS_PREFIXLEN,
FRA_TABLE, /* Extended table id */
@@ -51,6 +62,11 @@ enum {
FRA_OIFNAME,
FRA_PAD,
FRA_L3MDEV, /* iif or oif is l3mdev goto its table */
+ FRA_UID_RANGE, /* UID range */
+ FRA_PROTOCOL, /* Originator of the rule */
+ FRA_IP_PROTO, /* ip proto */
+ FRA_SPORT_RANGE, /* sport */
+ FRA_DPORT_RANGE, /* dport */
__FRA_MAX
};
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index a924606f36..dfcf3ce009 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -34,6 +34,7 @@ enum {
IFA_MULTICAST,
IFA_FLAGS,
IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
+ IFA_TARGET_NETNSID,
__IFA_MAX,
};
@@ -63,7 +64,9 @@ struct ifa_cacheinfo {
};
/* backwards compatibility for userspace */
+#ifndef __KERNEL__
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
#endif
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 156f4434ca..fb79481cb2 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* Linux ethernet bridge
*
@@ -10,8 +11,8 @@
* 2 of the License, or (at your option) any later version.
*/
-#ifndef _LINUX_IF_BRIDGE_H
-#define _LINUX_IF_BRIDGE_H
+#ifndef _UAPI_LINUX_IF_BRIDGE_H
+#define _UAPI_LINUX_IF_BRIDGE_H
#include <linux/types.h>
#include <linux/if_ether.h>
@@ -96,7 +97,7 @@ struct __fdb_entry {
__u32 ageing_timer_value;
__u8 port_hi;
__u8 pad0;
- __u16 unused;
+ __u16 vlan;
};
/* Bridge Flags */
@@ -236,6 +237,7 @@ struct br_mdb_entry {
#define MDB_PERMANENT 1
__u8 state;
#define MDB_FLAGS_OFFLOAD (1 << 0)
+#define MDB_FLAGS_FAST_LEAVE (1 << 1)
__u8 flags;
__u16 vid;
struct {
@@ -291,4 +293,4 @@ struct br_mcast_stats {
__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
__u64 mcast_packets[BR_MCAST_DIR_SIZE];
};
-#endif /* _LINUX_IF_BRIDGE_H */
+#endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 1f97d0560b..22a45914a2 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -1,5 +1,6 @@
-#ifndef _LINUX_IF_LINK_H
-#define _LINUX_IF_LINK_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_IF_LINK_H
+#define _UAPI_LINUX_IF_LINK_H
#include <linux/types.h>
#include <linux/netlink.h>
@@ -158,6 +159,14 @@ enum {
IFLA_PAD,
IFLA_XDP,
IFLA_EVENT,
+ IFLA_NEW_NETNSID,
+ IFLA_IF_NETNSID,
+ IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */
+ IFLA_CARRIER_UP_COUNT,
+ IFLA_CARRIER_DOWN_COUNT,
+ IFLA_NEW_IFINDEX,
+ IFLA_MIN_MTU,
+ IFLA_MAX_MTU,
__IFLA_MAX
};
@@ -165,8 +174,10 @@ enum {
#define IFLA_MAX (__IFLA_MAX - 1)
/* backwards compatibility for userspace */
+#ifndef __KERNEL__
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+#endif
enum {
IFLA_INET_UNSPEC,
@@ -276,6 +287,7 @@ enum {
IFLA_BR_MCAST_STATS_ENABLED,
IFLA_BR_MCAST_IGMP_VERSION,
IFLA_BR_MCAST_MLD_VERSION,
+ IFLA_BR_VLAN_STATS_PER_PORT,
__IFLA_BR_MAX,
};
@@ -323,6 +335,14 @@ enum {
IFLA_BRPORT_MCAST_TO_UCAST,
IFLA_BRPORT_VLAN_TUNNEL,
IFLA_BRPORT_BCAST_FLOOD,
+ IFLA_BRPORT_GROUP_FWD_MASK,
+ IFLA_BRPORT_NEIGH_SUPPRESS,
+ IFLA_BRPORT_ISOLATED,
+ IFLA_BRPORT_BACKUP_PORT,
+ IFLA_BRPORT_PEER_LINK = 60, /* MLAG peer link */
+ IFLA_BRPORT_DUAL_LINK, /* MLAG Dual Connected link */
+ IFLA_BRPORT_GROUP_FWD_MASKHI,
+ IFLA_BRPORT_DUAL_LINK_READY,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -448,6 +468,16 @@ enum {
#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)
+/* XFRM section */
+enum {
+ IFLA_XFRM_UNSPEC,
+ IFLA_XFRM_LINK,
+ IFLA_XFRM_IF_ID,
+ __IFLA_XFRM_MAX
+};
+
+#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
+
enum macsec_validation_type {
MACSEC_VALIDATE_DISABLED = 0,
MACSEC_VALIDATE_CHECK = 1,
@@ -460,6 +490,7 @@ enum macsec_validation_type {
enum {
IFLA_IPVLAN_UNSPEC,
IFLA_IPVLAN_MODE,
+ IFLA_IPVLAN_FLAGS,
__IFLA_IPVLAN_MAX
};
@@ -472,6 +503,9 @@ enum ipvlan_mode {
IPVLAN_MODE_MAX
};
+#define IPVLAN_F_PRIVATE 0x01
+#define IPVLAN_F_VEPA 0x02
+
/* VXLAN section */
enum {
IFLA_VXLAN_UNSPEC,
@@ -502,6 +536,7 @@ enum {
IFLA_VXLAN_COLLECT_METADATA,
IFLA_VXLAN_LABEL,
IFLA_VXLAN_GPE,
+ IFLA_VXLAN_TTL_INHERIT,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -585,6 +620,8 @@ enum {
IFLA_BOND_AD_USER_PORT_KEY,
IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB,
+ IFLA_BOND_CL_START = 60,
+ IFLA_BOND_AD_LACP_BYPASS = IFLA_BOND_CL_START,
__IFLA_BOND_MAX,
};
@@ -612,6 +649,9 @@ enum {
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
+
+ IFLA_BOND_SLAVE_CL_START = 50,
+ IFLA_BOND_SLAVE_AD_RX_BYPASS = IFLA_BOND_SLAVE_CL_START,
__IFLA_BOND_SLAVE_MAX,
};
@@ -721,6 +761,8 @@ enum {
IFLA_VF_STATS_BROADCAST,
IFLA_VF_STATS_MULTICAST,
IFLA_VF_STATS_PAD,
+ IFLA_VF_STATS_RX_DROPPED,
+ IFLA_VF_STATS_TX_DROPPED,
__IFLA_VF_STATS_MAX,
};
@@ -872,6 +914,7 @@ enum {
enum {
LINK_XSTATS_TYPE_UNSPEC,
LINK_XSTATS_TYPE_BRIDGE,
+ LINK_XSTATS_TYPE_BOND,
__LINK_XSTATS_TYPE_MAX
};
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
@@ -902,6 +945,7 @@ enum {
XDP_ATTACHED_DRV,
XDP_ATTACHED_SKB,
XDP_ATTACHED_HW,
+ XDP_ATTACHED_MULTI,
};
enum {
@@ -910,6 +954,9 @@ enum {
IFLA_XDP_ATTACHED,
IFLA_XDP_FLAGS,
IFLA_XDP_PROG_ID,
+ IFLA_XDP_DRV_PROG_ID,
+ IFLA_XDP_SKB_PROG_ID,
+ IFLA_XDP_HW_PROG_ID,
__IFLA_XDP_MAX,
};
@@ -925,4 +972,43 @@ enum {
IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */
};
-#endif /* _LINUX_IF_LINK_H */
+/* tun section */
+
+enum {
+ IFLA_TUN_UNSPEC,
+ IFLA_TUN_OWNER,
+ IFLA_TUN_GROUP,
+ IFLA_TUN_TYPE,
+ IFLA_TUN_PI,
+ IFLA_TUN_VNET_HDR,
+ IFLA_TUN_PERSIST,
+ IFLA_TUN_MULTI_QUEUE,
+ IFLA_TUN_NUM_QUEUES,
+ IFLA_TUN_NUM_DISABLED_QUEUES,
+ __IFLA_TUN_MAX,
+};
+
+#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
+
+/* rmnet section */
+
+#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0)
+#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1)
+#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2)
+#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3)
+
+enum {
+ IFLA_RMNET_UNSPEC,
+ IFLA_RMNET_MUX_ID,
+ IFLA_RMNET_FLAGS,
+ __IFLA_RMNET_MAX,
+};
+
+#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1)
+
+struct ifla_rmnet_flags {
+ __u32 flags;
+ __u32 mask;
+};
+
+#endif /* _UAPI_LINUX_IF_LINK_H */
diff --git a/include/linux/lwtunnel.h b/include/linux/lwtunnel.h
index 3298426271..de696ca12f 100644
--- a/include/linux/lwtunnel.h
+++ b/include/linux/lwtunnel.h
@@ -1,5 +1,6 @@
-#ifndef _LWTUNNEL_H_
-#define _LWTUNNEL_H_
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LWTUNNEL_H_
+#define _UAPI_LWTUNNEL_H_
#include <linux/types.h>
@@ -67,4 +68,4 @@ enum {
#define LWT_BPF_MAX_HEADROOM 256
-#endif /* _LWTUNNEL_H_ */
+#endif /* _UAPI_LWTUNNEL_H_ */
diff --git a/include/linux/mpls_iptunnel.h b/include/linux/mpls_iptunnel.h
index 1a0e57b45a..521f2e605f 100644
--- a/include/linux/mpls_iptunnel.h
+++ b/include/linux/mpls_iptunnel.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* mpls tunnel api
*
@@ -10,8 +11,8 @@
* 2 of the License, or (at your option) any later version.
*/
-#ifndef _LINUX_MPLS_IPTUNNEL_H
-#define _LINUX_MPLS_IPTUNNEL_H
+#ifndef _UAPI_LINUX_MPLS_IPTUNNEL_H
+#define _UAPI_LINUX_MPLS_IPTUNNEL_H
/* MPLS tunnel attributes
* [RTA_ENCAP] = {
@@ -27,4 +28,4 @@ enum {
};
#define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1)
-#endif /* _LINUX_MPLS_IPTUNNEL_H */
+#endif /* _UAPI_LINUX_MPLS_IPTUNNEL_H */
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index 3199d28980..cd144e3099 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_NEIGHBOUR_H
#define __LINUX_NEIGHBOUR_H
@@ -27,6 +28,7 @@ enum {
NDA_MASTER,
NDA_LINK_NETNSID,
NDA_SRC_VNI,
+ NDA_PROTOCOL, /* Originator of entry */
__NDA_MAX
};
@@ -42,6 +44,7 @@ enum {
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_EXT_LEARNED 0x10
#define NTF_OFFLOADED 0x20
+#define NTF_STICKY 0x40
#define NTF_ROUTER 0x80
/*
diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h
index 9a92b7e14a..0187c74d88 100644
--- a/include/linux/net_namespace.h
+++ b/include/linux/net_namespace.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* Copyright (c) 2015 6WIND S.A.
* Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
*
@@ -5,8 +6,8 @@
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
-#ifndef _LINUX_NET_NAMESPACE_H_
-#define _LINUX_NET_NAMESPACE_H_
+#ifndef _UAPI_LINUX_NET_NAMESPACE_H_
+#define _UAPI_LINUX_NET_NAMESPACE_H_
/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
enum {
@@ -20,4 +21,4 @@ enum {
#define NETNSA_MAX (__NETNSA_MAX - 1)
-#endif /* _LINUX_NET_NAMESPACE_H_ */
+#endif /* _UAPI_LINUX_NET_NAMESPACE_H_ */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 0b2c29bd08..0a4d733177 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __LINUX_NETLINK_H
-#define __LINUX_NETLINK_H
+#ifndef _UAPI__LINUX_NETLINK_H
+#define _UAPI__LINUX_NETLINK_H
#include <linux/kernel.h>
#include <linux/socket.h> /* for __kernel_sa_family_t */
@@ -147,12 +147,15 @@ enum nlmsgerr_attrs {
#define NETLINK_PKTINFO 3
#define NETLINK_BROADCAST_ERROR 4
#define NETLINK_NO_ENOBUFS 5
+#ifndef __KERNEL__
#define NETLINK_RX_RING 6
#define NETLINK_TX_RING 7
+#endif
#define NETLINK_LISTEN_ALL_NSID 8
#define NETLINK_LIST_MEMBERSHIPS 9
#define NETLINK_CAP_ACK 10
#define NETLINK_EXT_ACK 11
+#define NETLINK_GET_STRICT_CHK 12
struct nl_pktinfo {
__u32 group;
@@ -175,6 +178,7 @@ struct nl_mmap_hdr {
__u32 nm_gid;
};
+#ifndef __KERNEL__
enum nl_mmap_status {
NL_MMAP_STATUS_UNUSED,
NL_MMAP_STATUS_RESERVED,
@@ -186,6 +190,7 @@ enum nl_mmap_status {
#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
+#endif
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
@@ -244,4 +249,4 @@ struct nla_bitfield32 {
__u32 selector;
};
-#endif /* __LINUX_NETLINK_H */
+#endif /* _UAPI__LINUX_NETLINK_H */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 813e9e0767..ce2a623abb 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -1,5 +1,6 @@
-#ifndef __LINUX_RTNETLINK_H
-#define __LINUX_RTNETLINK_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI__LINUX_RTNETLINK_H
+#define _UAPI__LINUX_RTNETLINK_H
#include <linux/types.h>
#include <linux/netlink.h>
@@ -149,6 +150,20 @@ enum {
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+ RTM_NEWCHAIN = 100,
+#define RTM_NEWCHAIN RTM_NEWCHAIN
+ RTM_DELCHAIN,
+#define RTM_DELCHAIN RTM_DELCHAIN
+ RTM_GETCHAIN,
+#define RTM_GETCHAIN RTM_GETCHAIN
+
+ RTM_NEWNEXTHOP = 104,
+#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP
+ RTM_DELNEXTHOP,
+#define RTM_DELNEXTHOP RTM_DELNEXTHOP
+ RTM_GETNEXTHOP,
+#define RTM_GETNEXTHOP RTM_GETNEXTHOP
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -253,6 +268,11 @@ enum {
#define RTPROT_DHCP 16 /* DHCP client */
#define RTPROT_MROUTED 17 /* Multicast daemon */
#define RTPROT_BABEL 42 /* Babel daemon */
+#define RTPROT_BGP 186 /* BGP Routes */
+#define RTPROT_ISIS 187 /* ISIS Routes */
+#define RTPROT_OSPF 188 /* OSPF Routes */
+#define RTPROT_RIP 189 /* RIP Routes */
+#define RTPROT_EIGRP 192 /* EIGRP Routes */
/* rtm_scope
@@ -326,6 +346,10 @@ enum rtattr_type_t {
RTA_PAD,
RTA_UID,
RTA_TTL_PROPAGATE,
+ RTA_IP_PROTO,
+ RTA_SPORT,
+ RTA_DPORT,
+ RTA_NH_ID,
__RTA_MAX
};
@@ -430,6 +454,8 @@ enum {
#define RTAX_QUICKACK RTAX_QUICKACK
RTAX_CC_ALGO,
#define RTAX_CC_ALGO RTAX_CC_ALGO
+ RTAX_FASTOPEN_NO_COOKIE,
+#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE
__RTAX_MAX
};
@@ -538,9 +564,19 @@ struct tcmsg {
int tcm_ifindex;
__u32 tcm_handle;
__u32 tcm_parent;
+/* tcm_block_index is used instead of tcm_parent
+ * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK
+ */
+#define tcm_block_index tcm_parent
__u32 tcm_info;
};
+/* For manipulation of filters in shared block, tcm_ifindex is set to
+ * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index
+ * which is the block index.
+ */
+#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU)
+
enum {
TCA_UNSPEC,
TCA_KIND,
@@ -554,6 +590,9 @@ enum {
TCA_PAD,
TCA_DUMP_INVISIBLE,
TCA_CHAIN,
+ TCA_HW_OFFLOAD,
+ TCA_INGRESS_BLOCK,
+ TCA_EGRESS_BLOCK,
__TCA_MAX
};
@@ -586,6 +625,7 @@ enum {
#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1)
+#ifndef __KERNEL__
/* RTnetlink multicast groups - backwards compatibility for userspace */
#define RTMGRP_LINK 1
#define RTMGRP_NOTIFY 2
@@ -606,6 +646,7 @@ enum {
#define RTMGRP_DECnet_ROUTE 0x4000
#define RTMGRP_IPV6_PREFIX 0x20000
+#endif
/* RTnetlink multicast groups */
enum rtnetlink_groups {
@@ -671,6 +712,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
RTNLGRP_IPV6_MROUTE_R,
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
+ RTNLGRP_NEXTHOP,
+#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
@@ -715,4 +758,4 @@ enum {
-#endif /* __LINUX_RTNETLINK_H */
+#endif /* _UAPI__LINUX_RTNETLINK_H */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 8c1e501774..8eb9602170 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -1,5 +1,6 @@
-#ifndef _LINUX_SOCKET_H
-#define _LINUX_SOCKET_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_SOCKET_H
+#define _UAPI_LINUX_SOCKET_H
/*
* Desired design of maximum size and alignment (see RFC2553)
@@ -18,4 +19,4 @@ struct __kernel_sockaddr_storage {
/* _SS_MAXSIZE value minus size of ss_family */
} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
-#endif /* _LINUX_SOCKET_H */
+#endif /* _UAPI_LINUX_SOCKET_H */
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 9b368cc404..d2ec6ff566 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -254,6 +254,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
reason ? reason : "unspecified");
}
+ circuit->adj_state_changes++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_adj_state_change(adj, new_state, reason);
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 8d008d78bd..5da8e6ee9e 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -135,8 +135,6 @@ struct isis_circuit *isis_circuit_new(void)
}
#endif /* ifndef FABRICD */
- circuit->mtc = mpls_te_circuit_new();
-
circuit_mt_init(circuit);
QOBJ_REG(circuit, isis_circuit);
@@ -266,8 +264,11 @@ void isis_circuit_add_addr(struct isis_circuit *circuit,
ipv4->prefix = connected->address->u.prefix4;
listnode_add(circuit->ip_addrs, ipv4);
- /* Update MPLS TE Local IP address parameter */
- set_circuitparams_local_ipaddr(circuit->mtc, ipv4->prefix);
+ /* Update Local IP address parameter if MPLS TE is enable */
+ if (circuit->ext && IS_MPLS_TE(circuit->ext)) {
+ circuit->ext->local_addr.s_addr = ipv4->prefix.s_addr;
+ SET_SUBTLV(circuit->ext, EXT_LOCAL_ADDR);
+ }
if (circuit->area)
lsp_regenerate_schedule(circuit->area, circuit->is_type,
@@ -478,6 +479,7 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp)
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, conn))
isis_circuit_add_addr(circuit, conn);
+
}
void isis_circuit_if_del(struct isis_circuit *circuit, struct interface *ifp)
@@ -521,7 +523,6 @@ void isis_circuit_if_bind(struct isis_circuit *circuit, struct interface *ifp)
assert(ifp->info == circuit);
else
ifp->info = circuit;
- isis_link_params_update(circuit, ifp);
}
void isis_circuit_if_unbind(struct isis_circuit *circuit, struct interface *ifp)
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 2371c0b73a..b77c8ce352 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -121,7 +121,7 @@ struct isis_circuit {
uint16_t psnp_interval[2]; /* psnp-interval in seconds */
uint8_t metric[2];
uint32_t te_metric[2];
- struct mpls_te_circuit *mtc; /* MPLS-TE parameters */
+ struct isis_ext_subtlvs *ext; /* Extended parameters (TE + Adj SID */
int ip_router; /* Route IP ? */
int is_passive; /* Is Passive ? */
struct list *mt_settings; /* IS-IS MT Settings */
@@ -144,6 +144,13 @@ struct isis_circuit {
uint32_t
desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */
uint32_t rej_adjacencies; /* rejectedAdjacencies */
+ /*
+ * Counters as in ietf-isis@2019-09-09.yang
+ */
+ uint32_t id_len_mismatches; /* id-len-mismatch */
+ uint32_t max_area_addr_mismatches; /* max-area-addresses-mismatch */
+ uint32_t auth_type_failures; /*authentication-type-fails */
+ uint32_t auth_failures; /* authentication-fails */
QOBJ_FIELDS
};
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index bd06286755..37f4dcfabd 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -188,14 +188,10 @@ DEFPY(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
}
/* check if the interface is a loopback and if so set it as passive */
- pthread_rwlock_rdlock(&running_config->lock);
- {
- ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
- if (ifp && if_is_loopback(ifp))
- nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
- NB_OP_MODIFY, "true");
- }
- pthread_rwlock_unlock(&running_config->lock);
+ ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
+ if (ifp && if_is_loopback(ifp))
+ nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
+ NB_OP_MODIFY, "true");
return nb_cli_apply_changes(vty, NULL);
}
@@ -262,14 +258,10 @@ DEFPY(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
}
/* check if the interface is a loopback and if so set it as passive */
- pthread_rwlock_rdlock(&running_config->lock);
- {
- ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
- if (ifp && if_is_loopback(ifp))
- nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
- NB_OP_MODIFY, "true");
- }
- pthread_rwlock_unlock(&running_config->lock);
+ ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
+ if (ifp && if_is_loopback(ifp))
+ nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
+ NB_OP_MODIFY, "true");
return nb_cli_apply_changes(vty, NULL);
}
@@ -410,26 +402,20 @@ DEFPY(no_is_type, no_is_type_cmd,
"Act as both a station router and an area router\n"
"Act as an area router only\n")
{
- const char *value;
-
- pthread_rwlock_rdlock(&running_config->lock);
- {
- struct isis_area *area;
+ const char *value = NULL;
+ struct isis_area *area;
- area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-
- /*
- * Put the is-type back to defaults:
- * - level-1-2 on first area
- * - level-1 for the rest
- */
- if (area && listgetdata(listhead(isis->area_list)) == area)
- value = "level-1-2";
- else
- value = NULL;
- }
- pthread_rwlock_unlock(&running_config->lock);
+ area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
+ /*
+ * Put the is-type back to defaults:
+ * - level-1-2 on first area
+ * - level-1 for the rest
+ */
+ if (area && listgetdata(listhead(isis->area_list)) == area)
+ value = "level-1-2";
+ else
+ value = NULL;
nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, NULL);
@@ -1817,45 +1803,52 @@ DEFPY(no_isis_circuit_type, no_isis_circuit_type_cmd,
"Level-1-2 adjacencies are formed\n"
"Level-2 only adjacencies are formed\n")
{
- const char *circ_type = NULL;
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ int is_type;
+ const char *circ_type;
/*
* Default value depends on whether the circuit is part of an area,
* and the is-type of the area if there is one. So we need to do this
* here.
*/
- pthread_rwlock_rdlock(&running_config->lock);
- {
- struct interface *ifp;
- struct isis_circuit *circuit;
+ ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
+ if (!ifp)
+ goto def_val;
- ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
- if (!ifp)
- goto unlock;
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ goto def_val;
- circuit = circuit_scan_by_ifp(ifp);
- if (!circuit || circuit->state != C_STATE_UP)
- goto unlock;
+ if (circuit->state == C_STATE_UP)
+ is_type = circuit->area->is_type;
+ else
+ goto def_val;
- switch (circuit->area->is_type) {
- case IS_LEVEL_1:
- circ_type = "level-1";
- break;
- case IS_LEVEL_2:
- circ_type = "level-2";
- break;
- case IS_LEVEL_1_AND_2:
- circ_type = "level-1-2";
- break;
- }
+ switch (is_type) {
+ case IS_LEVEL_1:
+ circ_type = "level-1";
+ break;
+ case IS_LEVEL_2:
+ circ_type = "level-2";
+ break;
+ case IS_LEVEL_1_AND_2:
+ circ_type = "level-1-2";
+ break;
+ default:
+ return CMD_ERR_NO_MATCH;
}
-unlock:
- pthread_rwlock_unlock(&running_config->lock);
-
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
NB_OP_MODIFY, circ_type);
return nb_cli_apply_changes(vty, NULL);
+
+def_val:
+ nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
+ NB_OP_MODIFY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
}
void cli_show_ip_isis_circ_type(struct vty *vty, struct lyd_node *dnode,
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 4b29e6dc7e..061e758831 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -52,9 +52,9 @@
#include "isisd/isis_csm.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_spf.h"
-#include "isisd/isis_te.h"
#include "isisd/isis_mt.h"
#include "isisd/isis_tlvs.h"
+#include "isisd/isis_te.h"
#include "isisd/fabricd.h"
#include "isisd/isis_tx_queue.h"
@@ -781,8 +781,8 @@ static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp,
if (!rn->info)
continue;
struct isis_ext_info *info = rn->info;
-
struct prefix_ipv6 *p, *src_p;
+
srcdest_rnode_prefixes(rn, (const struct prefix **)&p,
(const struct prefix **)&src_p);
@@ -863,6 +863,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
/* Protocols Supported */
if (area->ip_circuits > 0 || area->ipv6_circuits > 0) {
struct nlpids nlpids = {.count = 0};
+
if (area->ip_circuits > 0) {
lsp_debug(
"ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs",
@@ -908,10 +909,12 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
area->area_tag);
}
- /* IPv4 address and TE router ID TLVs. In case of the first one we don't
- * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put
- * into
- * LSP and this address is same as router id. */
+ /* IPv4 address and TE router ID TLVs.
+ * In case of the first one we don't follow "C" vendor,
+ * but "J" vendor behavior - one IPv4 address is put
+ * into LSP. TE router ID will be the same if MPLS-TE
+ * is not activate or MPLS-TE router-id not specified
+ */
if (isis->router_id != 0) {
struct in_addr id = {.s_addr = isis->router_id};
inet_ntop(AF_INET, &id, buf, sizeof(buf));
@@ -919,11 +922,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
area->area_tag, buf);
isis_tlvs_add_ipv4_address(lsp->tlvs, &id);
- /* Exactly same data is put into TE router ID TLV, but only if
- * new style
- * TLV's are in use. */
+ /* If new style TLV's are in use, add TE router ID TLV
+ * Check if MPLS-TE is activate and mpls-te router-id set
+ * otherwise add exactly same data as for IPv4 address
+ */
if (area->newmetric) {
-
+ if (IS_MPLS_TE(area->mta)
+ && area->mta->router_id.s_addr != 0)
+ id.s_addr = area->mta->router_id.s_addr;
lsp_debug(
"ISIS (%s): Adding router ID also as TE router ID tlv.",
area->area_tag);
@@ -1004,6 +1010,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
&& circuit->ipv6_non_link->count > 0) {
struct listnode *ipnode;
struct prefix_ipv6 *ipv6;
+
for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
ipnode, ipv6)) {
lsp_debug(
@@ -1036,25 +1043,10 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
lsp->tlvs, ne_id,
metric);
}
- if (area->newmetric) {
- uint8_t subtlvs[256];
- uint8_t subtlv_len;
-
- if (IS_MPLS_TE(area->mta)
- && circuit->interface
- && HAS_LINK_PARAMS(
- circuit->interface))
- subtlv_len = add_te_subtlvs(
- subtlvs,
- circuit->mtc);
- else
- subtlv_len = 0;
-
+ if (area->newmetric)
tlvs_add_mt_bcast(
lsp->tlvs, circuit,
- level, ne_id, metric,
- subtlvs, subtlv_len);
- }
+ level, ne_id, metric);
}
} else {
lsp_debug(
@@ -1079,36 +1071,6 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
lsp->tlvs, ne_id, metric);
}
if (area->newmetric) {
- uint8_t subtlvs[256];
- uint8_t subtlv_len;
-
- if (IS_MPLS_TE(area->mta)
- && circuit->interface != NULL
- && HAS_LINK_PARAMS(
- circuit->interface))
- /* Update Local and Remote IP
- * address for MPLS TE circuit
- * parameters */
- /* NOTE sure that it is the
- * pertinent place for that
- * updates */
- /* Local IP address could be
- * updated in isis_circuit.c -
- * isis_circuit_add_addr() */
- /* But, where update remote IP
- * address ? in isis_pdu.c -
- * process_p2p_hello() ? */
-
- /* Add SubTLVs & Adjust real
- * size of SubTLVs */
- subtlv_len = add_te_subtlvs(
- subtlvs, circuit->mtc);
- else
- /* Or keep only TE metric with
- * no SubTLVs if MPLS_TE is off
- */
- subtlv_len = 0;
-
uint32_t neighbor_metric;
if (fabricd_tier(area) == 0) {
neighbor_metric = 0xffe;
@@ -1117,8 +1079,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
}
tlvs_add_mt_p2p(lsp->tlvs, circuit,
- ne_id, neighbor_metric,
- subtlvs, subtlv_len);
+ ne_id, neighbor_metric);
}
} else {
lsp_debug(
@@ -1512,7 +1473,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
}
if (circuit->area->newmetric) {
isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST,
- ne_id, 0, NULL, 0);
+ ne_id, 0, circuit->ext);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
area->area_tag, sysid_print(ne_id),
@@ -1554,7 +1515,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
if (circuit->area->newmetric) {
isis_tlvs_add_extended_reach(lsp->tlvs,
ISIS_MT_IPV4_UNICAST,
- ne_id, 0, NULL, 0);
+ ne_id, 0, circuit->ext);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (peer)",
area->area_tag, sysid_print(ne_id),
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 7f49e9d89a..718924daf2 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -243,7 +243,7 @@ int main(int argc, char **argv, char **envp)
mt_init();
/* create the global 'isis' instance */
- isis_new(1);
+ isis_new(1, VRF_DEFAULT);
isis_zebra_init(master);
isis_bfd_init();
diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c
index f7d4c7170f..36413bac59 100644
--- a/isisd/isis_mt.c
+++ b/isisd/isis_mt.c
@@ -511,8 +511,8 @@ static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level,
static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
unsigned int mt_count, uint16_t *mt_set,
- uint8_t *id, uint32_t metric, uint8_t *subtlvs,
- uint8_t subtlv_len)
+ uint8_t *id, uint32_t metric,
+ struct isis_ext_subtlvs *ext)
{
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
@@ -527,30 +527,27 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
area->area_tag, sysid_print(id),
LSP_PSEUDO_ID(id), isis_mtid2str(mtid));
}
- isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, subtlvs,
- subtlv_len);
+ isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, ext);
}
}
void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
- int level, uint8_t *id, uint32_t metric,
- uint8_t *subtlvs, uint8_t subtlv_len)
+ int level, uint8_t *id, uint32_t metric)
{
unsigned int mt_count;
uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count);
tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, id, metric,
- subtlvs, subtlv_len);
+ circuit->ext);
}
void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
- uint8_t *id, uint32_t metric, uint8_t *subtlvs,
- uint8_t subtlv_len)
+ uint8_t *id, uint32_t metric)
{
struct isis_adjacency *adj = circuit->u.p2p.neighbor;
tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id,
- metric, subtlvs, subtlv_len);
+ metric, circuit->ext);
}
void mt_init(void)
diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h
index 515b63f50f..b40139c50a 100644
--- a/isisd/isis_mt.h
+++ b/isisd/isis_mt.h
@@ -116,10 +116,8 @@ bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid);
void adj_mt_finish(struct isis_adjacency *adj);
void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
- int level, uint8_t *id, uint32_t metric,
- uint8_t *subtlvs, uint8_t subtlv_len);
+ int level, uint8_t *id, uint32_t metric);
void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
- uint8_t *id, uint32_t metric, uint8_t *subtlvs,
- uint8_t subtlv_len);
+ uint8_t *id, uint32_t metric);
void mt_init(void);
#endif
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index c1b630eb2d..ccd4cfbd1c 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -49,6 +49,23 @@
#include "lib/vrf.h"
/*
+ * Helper functions.
+ */
+static const char *isis_yang_adj_state(enum isis_adj_state state)
+{
+ switch (state) {
+ case ISIS_ADJ_DOWN:
+ return "down";
+ case ISIS_ADJ_UP:
+ return "up";
+ case ISIS_ADJ_INITIALIZING:
+ return "init";
+ default:
+ return "failed";
+ }
+}
+
+/*
* XPath: /frr-isisd:isis/instance
*/
static int isis_instance_create(enum nb_event event,
@@ -1384,7 +1401,7 @@ static int isis_instance_mpls_te_create(enum nb_event event,
struct mpls_te_area *new;
- zlog_debug("ISIS MPLS-TE: Initialize area %s",
+ zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering",
area->area_tag);
new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area));
@@ -1410,12 +1427,12 @@ static int isis_instance_mpls_te_create(enum nb_event event,
* 2) MPLS-TE was once enabled then disabled, and now enabled again.
*/
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
- if (circuit->mtc == NULL || IS_FLOOD_AS(circuit->mtc->type))
+ if (circuit->ext == NULL)
continue;
- if (!IS_MPLS_TE(circuit->mtc)
+ if (!IS_EXT_TE(circuit->ext)
&& HAS_LINK_PARAMS(circuit->interface))
- circuit->mtc->status = enable;
+ isis_link_params_update(circuit, circuit->interface);
else
continue;
@@ -1446,11 +1463,16 @@ static int isis_instance_mpls_te_destroy(enum nb_event event,
/* Flush LSP if circuit engage */
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
- if (circuit->mtc == NULL || (circuit->mtc->status == disable))
+ if (!IS_EXT_TE(circuit->ext))
continue;
- /* disable MPLS_TE Circuit */
- circuit->mtc->status = disable;
+ /* disable MPLS_TE Circuit keeping SR one's */
+ if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID))
+ circuit->ext->status = EXT_ADJ_SID;
+ else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID))
+ circuit->ext->status = EXT_LAN_ADJ_SID;
+ else
+ circuit->ext->status = 0;
/* Re-originate circuit without STD_TE & GMPLS parameters */
if (circuit->area)
@@ -1458,6 +1480,9 @@ static int isis_instance_mpls_te_destroy(enum nb_event event,
0);
}
+ zlog_debug("ISIS-TE(%s): Disabled MPLS Traffic Engineering",
+ area->area_tag);
+
return NB_OK;
}
@@ -2296,6 +2321,368 @@ static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
}
/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency
+ */
+static const void *
+lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj, *adj_next = NULL;
+ struct list *list;
+ struct listnode *node, *node_next;
+
+ /* Get first adjacency. */
+ if (list_entry == NULL) {
+ ifp = (struct interface *)parent_list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS;
+ level++) {
+ adj = listnode_head(
+ circuit->u.bc.adjdb[level - 1]);
+ if (adj)
+ break;
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ break;
+ default:
+ adj = NULL;
+ break;
+ }
+
+ return adj;
+ }
+
+ /* Get next adjacency. */
+ adj = (struct isis_adjacency *)list_entry;
+ circuit = adj->circuit;
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ list = circuit->u.bc.adjdb[adj->level - 1];
+ node = listnode_lookup(list, adj);
+ node_next = listnextnode(node);
+ if (node_next)
+ adj_next = listgetdata(node_next);
+ else if (adj->level == ISIS_LEVEL1) {
+ /*
+ * Once we finish the L1 adjacencies, move to the L2
+ * adjacencies list.
+ */
+ list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1];
+ adj_next = listnode_head(list);
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ /* P2P circuits have at most one adjacency. */
+ default:
+ break;
+ }
+
+ return adj_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_enum(xpath, adj->level);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, sysid_print(adj->sysid));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint32(xpath, adj->circuit->circuit_id);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, snpa_print(adj->snpa));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint16(xpath, adj->hold_time);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_changes_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->adj_state_changes);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_number_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj;
+ struct listnode *node;
+ uint32_t total = 0;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ /*
+ * TODO: keep track of the number of adjacencies instead of calculating
+ * it on demand.
+ */
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
+ for (ALL_LIST_ELEMENTS_RO(
+ circuit->u.bc.adjdb[level - 1], node, adj))
+ total++;
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ if (adj)
+ total = 1;
+ break;
+ default:
+ break;
+ }
+
+ return yang_data_new_uint32(xpath, total);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->init_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_rejects_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->rej_adjacencies);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_id_len_mismatch_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->id_len_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_authentication_type_fails_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->auth_type_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_authentication_fails_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->auth_failures);
+}
+
+/*
* NOTIFICATIONS
*/
static void notif_prep_instance_hdr(const char *xpath,
@@ -2537,19 +2924,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath);
- switch (new_state) {
- case ISIS_ADJ_DOWN:
- data = yang_data_new_string(xpath_arg, "down");
- break;
- case ISIS_ADJ_UP:
- data = yang_data_new_string(xpath_arg, "up");
- break;
- case ISIS_ADJ_INITIALIZING:
- data = yang_data_new_string(xpath_arg, "init");
- break;
- default:
- data = yang_data_new_string(xpath_arg, "failed");
- }
+ data = yang_data_new_string(xpath_arg, isis_yang_adj_state(new_state));
listnode_add(arguments, data);
if (new_state == ISIS_ADJ_DOWN) {
snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath);
@@ -3476,6 +3851,102 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency",
+ .cbs = {
+ .get_next = lib_interface_isis_adjacencies_adjacency_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_init_fails_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem,
+ }
+ },
+ {
.xpath = NULL,
},
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 3d16d56016..46b013ddd0 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -199,13 +199,6 @@ static int process_p2p_hello(struct iih_info *iih)
changed |= tlvs_to_adj_mt_set(iih->tlvs, iih->v4_usable, iih->v6_usable,
adj);
- /* Update MPLS TE Remote IP address parameter if possible */
- if (IS_MPLS_TE(iih->circuit->area->mta)
- && IS_MPLS_TE(iih->circuit->mtc)
- && adj->ipv4_address_count)
- set_circuitparams_rmt_ipaddr(iih->circuit->mtc,
- adj->ipv4_addresses[0]);
-
/* lets take care of the expiry */
THREAD_TIMER_OFF(adj->t_expire);
thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time,
@@ -583,6 +576,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (p2p_hello) {
if (circuit->circ_type != CIRCUIT_T_P2P) {
zlog_warn("p2p hello on non p2p circuit");
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "p2p hello on non p2p circuit",
@@ -593,6 +587,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
} else {
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
zlog_warn("lan hello on non broadcast circuit");
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "lan hello on non broadcast circuit",
@@ -605,6 +600,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_debug(
"level %d LAN Hello received over circuit with externalDomain = true",
level);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit,
@@ -621,6 +617,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
circuit->area->area_tag,
circuit->interface->name);
}
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Interface level mismatch", raw_pdu);
@@ -650,6 +647,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16,
circuit->area->area_tag, pdu_name,
circuit->interface->name, iih.pdu_len);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Invalid PDU length",
raw_pdu);
@@ -661,6 +659,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
flog_err(EC_ISIS_PACKET,
"Level %d LAN Hello with Circuit Type %d", level,
iih.circ_type);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "LAN Hello with wrong IS-level", raw_pdu);
@@ -674,6 +673,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
circuit->rcv_stream, &iih.tlvs, &error_log)) {
zlog_warn("isis_unpack_tlvs() failed: %s", error_log);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Failed to unpack TLVs",
raw_pdu);
@@ -692,6 +692,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (!iih.tlvs->protocols_supported.count) {
zlog_warn("No supported protocols TLV in %s", pdu_name);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "No supported protocols TLV", raw_pdu);
@@ -709,11 +710,14 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
/* send northbound notification */
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
pdu_end - pdu_start);
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit, raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -722,6 +726,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_warn(
"ISIS-Adj (%s): Received IIH with own sysid - discard",
circuit->area->area_tag);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Received IIH with our own sysid", raw_pdu);
@@ -759,6 +764,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Neither IPv4 nor IPv6 considered usable. Ignoring IIH",
circuit->area->area_tag);
}
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Neither IPv4 not IPv6 considered usable",
@@ -947,11 +953,14 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
hdr.lsp_id);
#ifndef FABRICD
/* send northbound notification */
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit, raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -1380,12 +1389,15 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
/* send northbound notification */
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
pdu_end - pdu_start);
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit,
raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -1621,6 +1633,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
"IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8
", while the parameter for this IS is %u",
id_len, ISIS_SYS_ID_LEN);
+ circuit->id_len_mismatches++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_id_len_mismatch(circuit, id_len, raw_pdu);
@@ -1673,6 +1686,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
"maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
" while the parameter for this IS is %u",
max_area_addrs, isis->max_area_addrs);
+ circuit->max_area_addr_mismatches++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_max_area_addr_mismatch(circuit, max_area_addrs,
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index 636a63e290..05394e0fe4 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -49,8 +49,16 @@
#include "isis_route.h"
#include "isis_zebra.h"
+DEFINE_HOOK(isis_route_update_hook,
+ (struct isis_area * area, struct prefix *prefix,
+ struct isis_route_info *route_info),
+ (area, prefix, route_info))
+
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
union g_addr *ip, ifindex_t ifindex);
+static void isis_route_update(struct isis_area *area, struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info);
static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
ifindex_t ifindex)
@@ -316,7 +324,7 @@ struct isis_route_info *isis_route_create(struct prefix *prefix,
return route_info;
}
-static void isis_route_delete(struct route_node *rode,
+static void isis_route_delete(struct isis_area *area, struct route_node *rode,
struct route_table *table)
{
struct isis_route_info *rinfo;
@@ -343,13 +351,37 @@ static void isis_route_delete(struct route_node *rode,
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
if (isis->debugs & DEBUG_RTE_EVENTS)
zlog_debug("ISIS-Rte: route delete %s", buff);
- isis_zebra_route_update(prefix, src_p, rinfo);
+ isis_route_update(area, prefix, src_p, rinfo);
}
isis_route_info_delete(rinfo);
rode->info = NULL;
route_unlock_node(rode);
}
+static void isis_route_update(struct isis_area *area, struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info)
+{
+ if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
+ if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
+ return;
+
+ isis_zebra_route_add_route(prefix, src_p, route_info);
+ hook_call(isis_route_update_hook, area, prefix, route_info);
+
+ SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+ UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
+ } else {
+ if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
+ return;
+
+ isis_zebra_route_del_route(prefix, src_p, route_info);
+ hook_call(isis_route_update_hook, area, prefix, route_info);
+
+ UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+ }
+}
+
static void _isis_route_verify_table(struct isis_area *area,
struct route_table *table,
struct route_table **tables)
@@ -390,7 +422,7 @@ static void _isis_route_verify_table(struct isis_area *area,
buff);
}
- isis_zebra_route_update(dst_p, src_p, rinfo);
+ isis_route_update(area, dst_p, src_p, rinfo);
if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
continue;
@@ -399,7 +431,7 @@ static void _isis_route_verify_table(struct isis_area *area,
* directly for
* validating => no problems with deleting routes. */
if (!tables) {
- isis_route_delete(rnode, table);
+ isis_route_delete(area, rnode, table);
continue;
}
@@ -422,7 +454,7 @@ static void _isis_route_verify_table(struct isis_area *area,
route_unlock_node(drnode);
}
- isis_route_delete(rnode, table);
+ isis_route_delete(area, rnode, table);
}
}
diff --git a/isisd/isis_route.h b/isisd/isis_route.h
index a20a7e038f..2326bb8228 100644
--- a/isisd/isis_route.h
+++ b/isisd/isis_route.h
@@ -44,6 +44,11 @@ struct isis_route_info {
struct list *nexthops;
};
+DECLARE_HOOK(isis_route_update_hook,
+ (struct isis_area * area, struct prefix *prefix,
+ struct isis_route_info *route_info),
+ (area, prefix, route_info))
+
struct isis_route_info *isis_route_create(struct prefix *prefix,
struct prefix_ipv6 *src_p,
uint32_t cost,
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 4ea6c2c60d..44fa45d02b 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -3,8 +3,9 @@
*
* This is an implementation of RFC5305 & RFC 7810
*
- * Copyright (C) 2014 Orange Labs
- * http://www.orange.com
+ * Author: Olivier Dugeon <olivier.dugeon@orange.com>
+ *
+ * Copyright (C) 2014 - 2019 Orange Labs http://www.orange.com
*
* This file is part of GNU Zebra.
*
@@ -47,6 +48,7 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
+#include "isisd/isis_adjacency.h"
#include "isisd/isisd.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
@@ -56,6 +58,7 @@
#include "isisd/isis_adjacency.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_te.h"
+#include "isisd/isis_zebra.h"
const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"};
@@ -63,424 +66,6 @@ const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"};
* Followings are control functions for MPLS-TE parameters management.
*------------------------------------------------------------------------*/
-/* Create new MPLS TE Circuit context */
-struct mpls_te_circuit *mpls_te_circuit_new(void)
-{
- struct mpls_te_circuit *mtc;
-
- zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context");
-
- mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_circuit));
-
- mtc->status = disable;
- mtc->type = STD_TE;
- mtc->length = 0;
-
- return mtc;
-}
-
-/* Copy SUB TLVs parameters into a buffer - No space verification are performed
- */
-/* Caller must verify before that there is enough free space in the buffer */
-uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc)
-{
- uint8_t size, *tlvs = buf;
-
- zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
-
- if (mtc == NULL) {
- zlog_debug(
- "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified");
- return 0;
- }
-
- /* Create buffer if not provided */
- if (buf == NULL) {
- zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified");
- return 0;
- }
-
- /* TE_SUBTLV_ADMIN_GRP */
- if (SUBTLV_TYPE(mtc->admin_grp) != 0) {
- size = SUBTLV_SIZE(&(mtc->admin_grp.header));
- memcpy(tlvs, &(mtc->admin_grp), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_LLRI */
- if (SUBTLV_TYPE(mtc->llri) != 0) {
- size = SUBTLV_SIZE(&(mtc->llri.header));
- memcpy(tlvs, &(mtc->llri), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_LCLIF_IPADDR */
- if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) {
- size = SUBTLV_SIZE(&(mtc->local_ipaddr.header));
- memcpy(tlvs, &(mtc->local_ipaddr), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_RMTIF_IPADDR */
- if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) {
- size = SUBTLV_SIZE(&(mtc->rmt_ipaddr.header));
- memcpy(tlvs, &(mtc->rmt_ipaddr), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_MAX_BW */
- if (SUBTLV_TYPE(mtc->max_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->max_bw.header));
- memcpy(tlvs, &(mtc->max_bw), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_MAX_RSV_BW */
- if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->max_rsv_bw.header));
- memcpy(tlvs, &(mtc->max_rsv_bw), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_UNRSV_BW */
- if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->unrsv_bw.header));
- memcpy(tlvs, &(mtc->unrsv_bw), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_TE_METRIC */
- if (SUBTLV_TYPE(mtc->te_metric) != 0) {
- size = SUBTLV_SIZE(&(mtc->te_metric.header));
- memcpy(tlvs, &(mtc->te_metric), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_AV_DELAY */
- if (SUBTLV_TYPE(mtc->av_delay) != 0) {
- size = SUBTLV_SIZE(&(mtc->av_delay.header));
- memcpy(tlvs, &(mtc->av_delay), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_MM_DELAY */
- if (SUBTLV_TYPE(mtc->mm_delay) != 0) {
- size = SUBTLV_SIZE(&(mtc->mm_delay.header));
- memcpy(tlvs, &(mtc->mm_delay), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_DELAY_VAR */
- if (SUBTLV_TYPE(mtc->delay_var) != 0) {
- size = SUBTLV_SIZE(&(mtc->delay_var.header));
- memcpy(tlvs, &(mtc->delay_var), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_PKT_LOSS */
- if (SUBTLV_TYPE(mtc->pkt_loss) != 0) {
- size = SUBTLV_SIZE(&(mtc->pkt_loss.header));
- memcpy(tlvs, &(mtc->pkt_loss), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_RES_BW */
- if (SUBTLV_TYPE(mtc->res_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->res_bw.header));
- memcpy(tlvs, &(mtc->res_bw), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_AVA_BW */
- if (SUBTLV_TYPE(mtc->ava_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->ava_bw.header));
- memcpy(tlvs, &(mtc->ava_bw), size);
- tlvs += size;
- }
-
- /* TE_SUBTLV_USE_BW */
- if (SUBTLV_TYPE(mtc->use_bw) != 0) {
- size = SUBTLV_SIZE(&(mtc->use_bw.header));
- memcpy(tlvs, &(mtc->use_bw), size);
- tlvs += size;
- }
-
- /* Add before this line any other parsing of TLV */
- (void)tlvs;
-
- /* Update SubTLVs length */
- mtc->length = subtlvs_len(mtc);
-
- zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length);
-
- return mtc->length;
-}
-
-/* Compute total Sub-TLVs size */
-uint8_t subtlvs_len(struct mpls_te_circuit *mtc)
-{
- int length = 0;
-
- /* Sanity Check */
- if (mtc == NULL)
- return 0;
-
- /* TE_SUBTLV_ADMIN_GRP */
- if (SUBTLV_TYPE(mtc->admin_grp) != 0)
- length += SUBTLV_SIZE(&(mtc->admin_grp.header));
-
- /* TE_SUBTLV_LLRI */
- if (SUBTLV_TYPE(mtc->llri) != 0)
- length += SUBTLV_SIZE(&mtc->llri.header);
-
- /* TE_SUBTLV_LCLIF_IPADDR */
- if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
- length += SUBTLV_SIZE(&mtc->local_ipaddr.header);
-
- /* TE_SUBTLV_RMTIF_IPADDR */
- if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
- length += SUBTLV_SIZE(&mtc->rmt_ipaddr.header);
-
- /* TE_SUBTLV_MAX_BW */
- if (SUBTLV_TYPE(mtc->max_bw) != 0)
- length += SUBTLV_SIZE(&mtc->max_bw.header);
-
- /* TE_SUBTLV_MAX_RSV_BW */
- if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0)
- length += SUBTLV_SIZE(&mtc->max_rsv_bw.header);
-
- /* TE_SUBTLV_UNRSV_BW */
- if (SUBTLV_TYPE(mtc->unrsv_bw) != 0)
- length += SUBTLV_SIZE(&mtc->unrsv_bw.header);
-
- /* TE_SUBTLV_TE_METRIC */
- if (SUBTLV_TYPE(mtc->te_metric) != 0)
- length += SUBTLV_SIZE(&mtc->te_metric.header);
-
- /* TE_SUBTLV_AV_DELAY */
- if (SUBTLV_TYPE(mtc->av_delay) != 0)
- length += SUBTLV_SIZE(&mtc->av_delay.header);
-
- /* TE_SUBTLV_MM_DELAY */
- if (SUBTLV_TYPE(mtc->mm_delay) != 0)
- length += SUBTLV_SIZE(&mtc->mm_delay.header);
-
- /* TE_SUBTLV_DELAY_VAR */
- if (SUBTLV_TYPE(mtc->delay_var) != 0)
- length += SUBTLV_SIZE(&mtc->delay_var.header);
-
- /* TE_SUBTLV_PKT_LOSS */
- if (SUBTLV_TYPE(mtc->pkt_loss) != 0)
- length += SUBTLV_SIZE(&mtc->pkt_loss.header);
-
- /* TE_SUBTLV_RES_BW */
- if (SUBTLV_TYPE(mtc->res_bw) != 0)
- length += SUBTLV_SIZE(&mtc->res_bw.header);
-
- /* TE_SUBTLV_AVA_BW */
- if (SUBTLV_TYPE(mtc->ava_bw) != 0)
- length += SUBTLV_SIZE(&mtc->ava_bw.header);
-
- /* TE_SUBTLV_USE_BW */
- if (SUBTLV_TYPE(mtc->use_bw) != 0)
- length += SUBTLV_SIZE(&mtc->use_bw.header);
-
- /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */
- if (length > MAX_SUBTLV_SIZE) {
- mtc->length = 0;
- return 0;
- }
-
- mtc->length = (uint8_t)length;
-
- return mtc->length;
-}
-
-/* Following are various functions to set MPLS TE parameters */
-static void set_circuitparams_admin_grp(struct mpls_te_circuit *mtc,
- uint32_t admingrp)
-{
- SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP;
- SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE;
- mtc->admin_grp.value = htonl(admingrp);
- return;
-}
-
-static void __attribute__((unused))
-set_circuitparams_llri(struct mpls_te_circuit *mtc, uint32_t local,
- uint32_t remote)
-{
- SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI;
- SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE;
- mtc->llri.local = htonl(local);
- mtc->llri.remote = htonl(remote);
-}
-
-void set_circuitparams_local_ipaddr(struct mpls_te_circuit *mtc,
- struct in_addr addr)
-{
-
- SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR;
- SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE;
- mtc->local_ipaddr.value.s_addr = addr.s_addr;
- return;
-}
-
-void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *mtc,
- struct in_addr addr)
-{
-
- SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR;
- SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE;
- mtc->rmt_ipaddr.value.s_addr = addr.s_addr;
- return;
-}
-
-static void set_circuitparams_max_bw(struct mpls_te_circuit *mtc, float fp)
-{
- SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW;
- SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE;
- mtc->max_bw.value = htonf(fp);
- return;
-}
-
-static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit *mtc, float fp)
-{
- SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW;
- SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE;
- mtc->max_rsv_bw.value = htonf(fp);
- return;
-}
-
-static void set_circuitparams_unrsv_bw(struct mpls_te_circuit *mtc,
- int priority, float fp)
-{
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW;
- SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE;
- mtc->unrsv_bw.value[priority] = htonf(fp);
- return;
-}
-
-static void set_circuitparams_te_metric(struct mpls_te_circuit *mtc,
- uint32_t te_metric)
-{
- SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC;
- SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE;
- mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF;
- mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF;
- mtc->te_metric.value[2] = te_metric & 0xFF;
- return;
-}
-
-static void set_circuitparams_inter_as(struct mpls_te_circuit *mtc,
- struct in_addr addr, uint32_t as)
-{
-
- /* Set the Remote ASBR IP address and then the associated AS number */
- SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP;
- SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE;
- mtc->rip.value.s_addr = addr.s_addr;
-
- SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS;
- SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE;
- mtc->ras.value = htonl(as);
-}
-
-static void unset_circuitparams_inter_as(struct mpls_te_circuit *mtc)
-{
-
- /* Reset the Remote ASBR IP address and then the associated AS number */
- SUBTLV_TYPE(mtc->rip) = 0;
- SUBTLV_LEN(mtc->rip) = 0;
- mtc->rip.value.s_addr = 0;
-
- SUBTLV_TYPE(mtc->ras) = 0;
- SUBTLV_LEN(mtc->ras) = 0;
- mtc->ras.value = 0;
-}
-
-static void set_circuitparams_av_delay(struct mpls_te_circuit *mtc,
- uint32_t delay, uint8_t anormal)
-{
- uint32_t tmp;
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY;
- SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE;
- tmp = delay & TE_EXT_MASK;
- if (anormal)
- tmp |= TE_EXT_ANORMAL;
- mtc->av_delay.value = htonl(tmp);
- return;
-}
-
-static void set_circuitparams_mm_delay(struct mpls_te_circuit *mtc,
- uint32_t low, uint32_t high,
- uint8_t anormal)
-{
- uint32_t tmp;
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY;
- SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE;
- tmp = low & TE_EXT_MASK;
- if (anormal)
- tmp |= TE_EXT_ANORMAL;
- mtc->mm_delay.low = htonl(tmp);
- mtc->mm_delay.high = htonl(high);
- return;
-}
-
-static void set_circuitparams_delay_var(struct mpls_te_circuit *mtc,
- uint32_t jitter)
-{
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR;
- SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE;
- mtc->delay_var.value = htonl(jitter & TE_EXT_MASK);
- return;
-}
-
-static void set_circuitparams_pkt_loss(struct mpls_te_circuit *mtc,
- uint32_t loss, uint8_t anormal)
-{
- uint32_t tmp;
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS;
- SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE;
- tmp = loss & TE_EXT_MASK;
- if (anormal)
- tmp |= TE_EXT_ANORMAL;
- mtc->pkt_loss.value = htonl(tmp);
- return;
-}
-
-static void set_circuitparams_res_bw(struct mpls_te_circuit *mtc, float fp)
-{
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW;
- SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE;
- mtc->res_bw.value = htonf(fp);
- return;
-}
-
-static void set_circuitparams_ava_bw(struct mpls_te_circuit *mtc, float fp)
-{
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW;
- SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE;
- mtc->ava_bw.value = htonf(fp);
- return;
-}
-
-static void set_circuitparams_use_bw(struct mpls_te_circuit *mtc, float fp)
-{
- /* Note that TLV-length field is the size of array. */
- SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW;
- SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE;
- mtc->use_bw.value = htonf(fp);
- return;
-}
-
/* Main initialization / update function of the MPLS TE Circuit context */
/* Call when interface TE Link parameters are modified */
void isis_link_params_update(struct isis_circuit *circuit,
@@ -488,155 +73,223 @@ void isis_link_params_update(struct isis_circuit *circuit,
{
int i;
struct prefix_ipv4 *addr;
- struct mpls_te_circuit *mtc;
+ struct prefix_ipv6 *addr6;
+ struct isis_ext_subtlvs *ext;
+
+ /* Check if TE is enable or not */
+ if (!circuit->area || !IS_MPLS_TE(circuit->area->mta))
+ return;
/* Sanity Check */
- if ((circuit == NULL) || (ifp == NULL))
+ if ((circuit == NULL) || (ifp == NULL)
+ || (circuit->state != C_STATE_UP))
return;
- zlog_info("MPLS-TE: Initialize circuit parameters for interface %s",
- ifp->name);
+ zlog_debug("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->mtc == NULL)
- circuit->mtc = mpls_te_circuit_new();
+ if (circuit->ext == NULL) {
+ circuit->ext = isis_alloc_ext_subtlvs();
+ zlog_debug(" |- Allocated new Ext-subTLVs for interface %s",
+ ifp->name);
+ }
- mtc = circuit->mtc;
+ ext = circuit->ext;
- /* Fulfil MTC TLV from ifp TE Link parameters */
+ /* Fulfill Extended subTLVs from interface link parameters */
if (HAS_LINK_PARAMS(ifp)) {
- mtc->status = enable;
/* STD_TE metrics */
- if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP))
- set_circuitparams_admin_grp(
- mtc, ifp->link_params->admin_grp);
- else
- SUBTLV_TYPE(mtc->admin_grp) = 0;
-
- /* If not already set, register local IP addr from ip_addr list
- * if it exists */
- if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) {
- if (circuit->ip_addrs != NULL
- && listcount(circuit->ip_addrs) != 0) {
- addr = (struct prefix_ipv4 *)listgetdata(
- (struct listnode *)listhead(
- circuit->ip_addrs));
- set_circuitparams_local_ipaddr(mtc,
- addr->prefix);
- }
- }
-
- /* If not already set, try to determine Remote IP addr if
- * circuit is P2P */
- if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0)
- && (circuit->circ_type == CIRCUIT_T_P2P)) {
+ if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) {
+ ext->adm_group = ifp->link_params->admin_grp;
+ SET_SUBTLV(ext, EXT_ADM_GRP);
+ } else
+ UNSET_SUBTLV(ext, EXT_ADM_GRP);
+
+ /* If known, register local IPv4 addr from ip_addr list */
+ if (circuit->ip_addrs != NULL
+ && listcount(circuit->ip_addrs) != 0) {
+ addr = (struct prefix_ipv4 *)listgetdata(
+ (struct listnode *)listhead(circuit->ip_addrs));
+ IPV4_ADDR_COPY(&ext->local_addr, &addr->prefix);
+ SET_SUBTLV(ext, EXT_LOCAL_ADDR);
+ } 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) {
- set_circuitparams_rmt_ipaddr(
- mtc, adj->ipv4_addresses[0]);
+ IPV4_ADDR_COPY(&ext->neigh_addr,
+ &adj->ipv4_addresses[0]);
+ SET_SUBTLV(ext, EXT_NEIGH_ADDR);
}
- }
-
- if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW))
- set_circuitparams_max_bw(mtc, ifp->link_params->max_bw);
- else
- SUBTLV_TYPE(mtc->max_bw) = 0;
-
- if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW))
- set_circuitparams_max_rsv_bw(
- mtc, ifp->link_params->max_rsv_bw);
- else
- SUBTLV_TYPE(mtc->max_rsv_bw) = 0;
+ } 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) {
+ addr6 = (struct prefix_ipv6 *)listgetdata(
+ (struct listnode *)listhead(
+ circuit->ipv6_non_link));
+ IPV6_ADDR_COPY(&ext->local_addr6, &addr6->prefix);
+ SET_SUBTLV(ext, EXT_LOCAL_ADDR6);
+ } 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 (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW))
+ 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);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) {
+ ext->max_bw = ifp->link_params->max_bw;
+ SET_SUBTLV(ext, EXT_MAX_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_MAX_BW);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) {
+ ext->max_rsv_bw = ifp->link_params->max_rsv_bw;
+ SET_SUBTLV(ext, EXT_MAX_RSV_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_MAX_RSV_BW);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) {
for (i = 0; i < MAX_CLASS_TYPE; i++)
- set_circuitparams_unrsv_bw(
- mtc, i, ifp->link_params->unrsv_bw[i]);
- else
- SUBTLV_TYPE(mtc->unrsv_bw) = 0;
-
- if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC))
- set_circuitparams_te_metric(
- mtc, ifp->link_params->te_metric);
- else
- SUBTLV_TYPE(mtc->te_metric) = 0;
-
- /* TE metric Extensions */
- if (IS_PARAM_SET(ifp->link_params, LP_DELAY))
- set_circuitparams_av_delay(
- mtc, ifp->link_params->av_delay, 0);
- else
- SUBTLV_TYPE(mtc->av_delay) = 0;
+ ext->unrsv_bw[i] =
+ ifp->link_params->unrsv_bw[i];
+ SET_SUBTLV(ext, EXT_UNRSV_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_UNRSV_BW);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) {
+ ext->te_metric = ifp->link_params->te_metric;
+ SET_SUBTLV(ext, EXT_TE_METRIC);
+ } else
+ UNSET_SUBTLV(ext, EXT_TE_METRIC);
+
+ /* TE metric extensions */
+ if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) {
+ ext->delay = ifp->link_params->av_delay;
+ SET_SUBTLV(ext, EXT_DELAY);
+ } else
+ UNSET_SUBTLV(ext, EXT_DELAY);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) {
+ ext->min_delay = ifp->link_params->min_delay;
+ ext->max_delay = ifp->link_params->max_delay;
+ SET_SUBTLV(ext, EXT_MM_DELAY);
+ } else
+ UNSET_SUBTLV(ext, EXT_MM_DELAY);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) {
+ ext->delay_var = ifp->link_params->delay_var;
+ SET_SUBTLV(ext, EXT_DELAY_VAR);
+ } else
+ UNSET_SUBTLV(ext, EXT_DELAY_VAR);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) {
+ ext->pkt_loss = ifp->link_params->pkt_loss;
+ SET_SUBTLV(ext, EXT_PKT_LOSS);
+ } else
+ UNSET_SUBTLV(ext, EXT_PKT_LOSS);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) {
+ ext->res_bw = ifp->link_params->res_bw;
+ SET_SUBTLV(ext, EXT_RES_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_RES_BW);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) {
+ ext->ava_bw = ifp->link_params->ava_bw;
+ SET_SUBTLV(ext, EXT_AVA_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_AVA_BW);
+
+ if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) {
+ ext->use_bw = ifp->link_params->use_bw;
+ SET_SUBTLV(ext, EXT_USE_BW);
+ } else
+ UNSET_SUBTLV(ext, EXT_USE_BW);
- if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY))
- set_circuitparams_mm_delay(
- mtc, ifp->link_params->min_delay,
- ifp->link_params->max_delay, 0);
- else
- SUBTLV_TYPE(mtc->mm_delay) = 0;
-
- if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR))
- set_circuitparams_delay_var(
- mtc, ifp->link_params->delay_var);
- else
- SUBTLV_TYPE(mtc->delay_var) = 0;
-
- if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS))
- set_circuitparams_pkt_loss(
- mtc, ifp->link_params->pkt_loss, 0);
+ /* INTER_AS */
+ if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) {
+ ext->remote_as = ifp->link_params->rmt_as;
+ ext->remote_ip = ifp->link_params->rmt_ip;
+ SET_SUBTLV(ext, EXT_RMT_AS);
+ SET_SUBTLV(ext, EXT_RMT_IP);
+ } else {
+ /* reset inter-as TE params */
+ UNSET_SUBTLV(ext, EXT_RMT_AS);
+ UNSET_SUBTLV(ext, EXT_RMT_IP);
+ }
+ zlog_debug(" |- New MPLS-TE link parameters status 0x%x",
+ ext->status);
+ } else {
+ zlog_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;
+ else if (IS_SUBTLV(ext, EXT_LAN_ADJ_SID))
+ ext->status = EXT_LAN_ADJ_SID;
else
- SUBTLV_TYPE(mtc->pkt_loss) = 0;
+ ext->status = 0;
+ }
- if (IS_PARAM_SET(ifp->link_params, LP_RES_BW))
- set_circuitparams_res_bw(mtc, ifp->link_params->res_bw);
- else
- SUBTLV_TYPE(mtc->res_bw) = 0;
+ return;
+}
- if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW))
- set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw);
- else
- SUBTLV_TYPE(mtc->ava_bw) = 0;
+static int isis_link_update_adj_hook(struct isis_adjacency *adj)
+{
- if (IS_PARAM_SET(ifp->link_params, LP_USE_BW))
- set_circuitparams_use_bw(mtc, ifp->link_params->use_bw);
- else
- SUBTLV_TYPE(mtc->use_bw) = 0;
+ struct isis_circuit *circuit = adj->circuit;
- /* INTER_AS */
- if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS))
- set_circuitparams_inter_as(mtc,
- ifp->link_params->rmt_ip,
- ifp->link_params->rmt_as);
- else
- /* reset inter-as TE params */
- unset_circuitparams_inter_as(mtc);
+ /* Update MPLS TE Remote IP address parameter if possible */
+ if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext))
+ return 0;
- /* Compute total length of SUB TLVs */
- mtc->length = subtlvs_len(mtc);
+ /* 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);
+ }
- } else
- mtc->status = disable;
+ /* 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);
+ }
-/* Finally Update LSP */
-#if 0
- if (circuit->area && IS_MPLS_TE(circuit->area->mta))
- lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
-#endif
- return;
+ return 0;
}
-void isis_mpls_te_update(struct interface *ifp)
+int isis_mpls_te_update(struct interface *ifp)
{
struct isis_circuit *circuit;
+ uint8_t rc = 1;
/* Sanity Check */
if (ifp == NULL)
- return;
+ return rc;
/* Get circuit context from interface */
- if ((circuit = circuit_scan_by_ifp(ifp)) == NULL)
- return;
+ circuit = circuit_scan_by_ifp(ifp);
+ if (circuit == NULL)
+ return rc;
/* Update TE TLVs ... */
isis_link_params_update(circuit, ifp);
@@ -645,418 +298,11 @@ void isis_mpls_te_update(struct interface *ifp)
if (circuit->area && IS_MPLS_TE(circuit->area->mta))
lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
- return;
-}
-
-/*------------------------------------------------------------------------*
- * Followings are vty session control functions.
- *------------------------------------------------------------------------*/
-
-static uint8_t print_subtlv_admin_grp(struct sbuf *buf, int indent,
- struct te_subtlv_admin_grp *tlv)
-{
- sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
- ntohl(tlv->value));
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_llri(struct sbuf *buf, int indent,
- struct te_subtlv_llri *tlv)
-{
- sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
- ntohl(tlv->local));
- sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
- ntohl(tlv->remote));
-
- return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE);
-}
-
-static uint8_t print_subtlv_local_ipaddr(struct sbuf *buf, int indent,
- struct te_subtlv_local_ipaddr *tlv)
-{
- sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
- inet_ntoa(tlv->value));
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent,
- struct te_subtlv_rmt_ipaddr *tlv)
-{
- sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
- inet_ntoa(tlv->value));
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_max_bw(struct sbuf *buf, int indent,
- struct te_subtlv_max_bw *tlv)
-{
- float fval;
-
- fval = ntohf(tlv->value);
-
- sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
- struct te_subtlv_max_rsv_bw *tlv)
-{
- float fval;
-
- fval = ntohf(tlv->value);
-
- sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
- fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
- struct te_subtlv_unrsv_bw *tlv)
-{
- float fval1, fval2;
- int i;
-
- sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
-
- for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
- fval1 = ntohf(tlv->value[i]);
- fval2 = ntohf(tlv->value[i + 1]);
- sbuf_push(buf, indent + 2,
- "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i,
- fval1, i + 1, fval2);
- }
-
- return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
-}
-
-static uint8_t print_subtlv_te_metric(struct sbuf *buf, int indent,
- struct te_subtlv_te_metric *tlv)
-{
- uint32_t te_metric;
-
- te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16;
- sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_ras(struct sbuf *buf, int indent,
- struct te_subtlv_ras *tlv)
-{
- sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n",
- ntohl(tlv->value));
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_rip(struct sbuf *buf, int indent,
- struct te_subtlv_rip *tlv)
-{
- sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n",
- inet_ntoa(tlv->value));
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
+ rc = 0;
+ return rc;
}
-static uint8_t print_subtlv_av_delay(struct sbuf *buf, int indent,
- struct te_subtlv_av_delay *tlv)
-{
- uint32_t delay;
- uint32_t A;
-
- delay = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
- A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
-
- sbuf_push(buf, indent,
- "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
- A ? "Anomalous" : "Normal", delay);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_mm_delay(struct sbuf *buf, int indent,
- struct te_subtlv_mm_delay *tlv)
-{
- uint32_t low, high;
- uint32_t A;
-
- low = (uint32_t)ntohl(tlv->low) & TE_EXT_MASK;
- A = (uint32_t)ntohl(tlv->low) & TE_EXT_ANORMAL;
- high = (uint32_t)ntohl(tlv->high) & TE_EXT_MASK;
-
- sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
- A ? "Anomalous" : "Normal", low, high);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_delay_var(struct sbuf *buf, int indent,
- struct te_subtlv_delay_var *tlv)
-{
- uint32_t jitter;
-
- jitter = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
-
- sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n",
- jitter);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_pkt_loss(struct sbuf *buf, int indent,
- struct te_subtlv_pkt_loss *tlv)
-{
- uint32_t loss;
- uint32_t A;
- float fval;
-
- loss = (uint32_t)ntohl(tlv->value) & TE_EXT_MASK;
- fval = (float)(loss * LOSS_PRECISION);
- A = (uint32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
-
- sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
- A ? "Anomalous" : "Normal", fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_res_bw(struct sbuf *buf, int indent,
- struct te_subtlv_res_bw *tlv)
-{
- float fval;
-
- fval = ntohf(tlv->value);
-
- sbuf_push(buf, indent,
- "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_ava_bw(struct sbuf *buf, int indent,
- struct te_subtlv_ava_bw *tlv)
-{
- float fval;
-
- fval = ntohf(tlv->value);
-
- sbuf_push(buf, indent,
- "Unidirectional Available Bandwidth: %g (Bytes/sec)\n", fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_subtlv_use_bw(struct sbuf *buf, int indent,
- struct te_subtlv_use_bw *tlv)
-{
- float fval;
-
- fval = ntohf(tlv->value);
-
- sbuf_push(buf, indent,
- "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", fval);
-
- return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
-}
-
-static uint8_t print_unknown_tlv(struct sbuf *buf, int indent,
- struct subtlv_header *tlvh)
-{
- int i, rtn;
- uint8_t *v = (uint8_t *)tlvh;
-
- if (tlvh->length != 0) {
- sbuf_push(buf, indent,
- "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
- tlvh->type, tlvh->length);
- sbuf_push(buf, indent + 2, "Dump: [00]");
- rtn = 1; /* initialize end of line counter */
- for (i = 0; i < tlvh->length; i++) {
- sbuf_push(buf, 0, " %#.2x", v[i]);
- if (rtn == 8) {
- sbuf_push(buf, 0, "\n");
- sbuf_push(buf, indent + 8, "[%.2x]", i + 1);
- rtn = 1;
- } else
- rtn++;
- }
- sbuf_push(buf, 0, "\n");
- } else {
- sbuf_push(buf, indent,
- "Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
- tlvh->type, tlvh->length);
- }
-
- return SUBTLV_SIZE(tlvh);
-}
-
-/* Main Show function */
-void mpls_te_print_detail(struct sbuf *buf, int indent,
- uint8_t *subtlvs, uint8_t subtlv_len)
-{
- struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
- uint16_t sum = 0;
-
- for (; sum < subtlv_len;
- tlvh = (struct subtlv_header *)(subtlvs + sum)) {
- if (subtlv_len - sum < SUBTLV_SIZE(tlvh)) {
- sbuf_push(buf, indent, "Available data %" PRIu8 " is less than TLV size %u!\n",
- subtlv_len - sum, SUBTLV_SIZE(tlvh));
- return;
- }
-
- switch (tlvh->type) {
- case TE_SUBTLV_ADMIN_GRP:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Administrative Group!\n");
- return;
- }
- sum += print_subtlv_admin_grp(buf, indent,
- (struct te_subtlv_admin_grp *)tlvh);
- break;
- case TE_SUBTLV_LLRI:
- if (tlvh->length != TE_SUBTLV_LLRI_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Link ID!\n");
- return;
- }
- sum += print_subtlv_llri(buf, indent,
- (struct te_subtlv_llri *)tlvh);
- break;
- case TE_SUBTLV_LOCAL_IPADDR:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Local IP address!\n");
- return;
- }
- sum += print_subtlv_local_ipaddr(buf, indent,
- (struct te_subtlv_local_ipaddr *)tlvh);
- break;
- case TE_SUBTLV_RMT_IPADDR:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Remote Interface address!\n");
- return;
- }
- sum += print_subtlv_rmt_ipaddr(buf, indent,
- (struct te_subtlv_rmt_ipaddr *)tlvh);
- break;
- case TE_SUBTLV_MAX_BW:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Bandwidth!\n");
- return;
- }
- sum += print_subtlv_max_bw(buf, indent,
- (struct te_subtlv_max_bw *)tlvh);
- break;
- case TE_SUBTLV_MAX_RSV_BW:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
- return;
- }
- sum += print_subtlv_max_rsv_bw(buf, indent,
- (struct te_subtlv_max_rsv_bw *)tlvh);
- break;
- case TE_SUBTLV_UNRSV_BW:
- if (tlvh->length != TE_SUBTLV_UNRSV_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Unreserved Bandwidth!\n");
- return;
- }
- sum += print_subtlv_unrsv_bw(buf, indent,
- (struct te_subtlv_unrsv_bw *)tlvh);
- break;
- case TE_SUBTLV_TE_METRIC:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Traffic Engineering Metric!\n");
- return;
- }
- sum += print_subtlv_te_metric(buf, indent,
- (struct te_subtlv_te_metric *)tlvh);
- break;
- case TE_SUBTLV_RAS:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Remote AS number!\n");
- return;
- }
- sum += print_subtlv_ras(buf, indent,
- (struct te_subtlv_ras *)tlvh);
- break;
- case TE_SUBTLV_RIP:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Remote ASBR IP Address!\n");
- return;
- }
- sum += print_subtlv_rip(buf, indent,
- (struct te_subtlv_rip *)tlvh);
- break;
- case TE_SUBTLV_AV_DELAY:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Average Link Delay!\n");
- return;
- }
- sum += print_subtlv_av_delay(buf, indent,
- (struct te_subtlv_av_delay *)tlvh);
- break;
- case TE_SUBTLV_MM_DELAY:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Min/Max Link Delay!\n");
- return;
- }
- sum += print_subtlv_mm_delay(buf, indent,
- (struct te_subtlv_mm_delay *)tlvh);
- break;
- case TE_SUBTLV_DELAY_VAR:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Delay Variation!\n");
- return;
- }
- sum += print_subtlv_delay_var(buf, indent,
- (struct te_subtlv_delay_var *)tlvh);
- break;
- case TE_SUBTLV_PKT_LOSS:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Link Packet Loss!\n");
- return;
- }
- sum += print_subtlv_pkt_loss(buf, indent,
- (struct te_subtlv_pkt_loss *)tlvh);
- break;
- case TE_SUBTLV_RES_BW:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
- return;
- }
- sum += print_subtlv_res_bw(buf, indent,
- (struct te_subtlv_res_bw *)tlvh);
- break;
- case TE_SUBTLV_AVA_BW:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
- return;
- }
- sum += print_subtlv_ava_bw(buf, indent,
- (struct te_subtlv_ava_bw *)tlvh);
- break;
- case TE_SUBTLV_USE_BW:
- if (tlvh->length != SUBTLV_DEF_SIZE) {
- sbuf_push(buf, indent, "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
- return;
- }
- sum += print_subtlv_use_bw(buf, indent,
- (struct te_subtlv_use_bw *)tlvh);
- break;
- default:
- sum += print_unknown_tlv(buf, indent, tlvh);
- break;
- }
- }
- return;
-}
-
-/*------------------------------------------------------------------------*
- * Followings are vty command functions.
- *------------------------------------------------------------------------*/
+/* Followings are vty command functions */
#ifndef FABRICD
DEFUN (show_isis_mpls_te_router,
@@ -1092,45 +338,104 @@ DEFUN (show_isis_mpls_te_router,
return CMD_SUCCESS;
}
-static void show_mpls_te_sub(struct vty *vty, char *name,
- struct mpls_te_circuit *mtc)
+static void show_ext_sub(struct vty *vty, char *name,
+ struct isis_ext_subtlvs *ext)
{
struct sbuf buf;
+ char ibuf[PREFIX2STR_BUFFER];
sbuf_init(&buf, NULL, 0);
- if (mtc->status != enable)
+ if (!ext || ext->status == EXT_DISABLE)
return;
vty_out(vty, "-- MPLS-TE link parameters for %s --\n", name);
sbuf_reset(&buf);
- print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp);
-
- if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
- print_subtlv_local_ipaddr(&buf, 4, &mtc->local_ipaddr);
- if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
- print_subtlv_rmt_ipaddr(&buf, 4, &mtc->rmt_ipaddr);
-
- print_subtlv_max_bw(&buf, 4, &mtc->max_bw);
- print_subtlv_max_rsv_bw(&buf, 4, &mtc->max_rsv_bw);
- print_subtlv_unrsv_bw(&buf, 4, &mtc->unrsv_bw);
- print_subtlv_te_metric(&buf, 4, &mtc->te_metric);
-
- if (IS_INTER_AS(mtc->type)) {
- if (SUBTLV_TYPE(mtc->ras) != 0)
- print_subtlv_ras(&buf, 4, &mtc->ras);
- if (SUBTLV_TYPE(mtc->rip) != 0)
- print_subtlv_rip(&buf, 4, &mtc->rip);
- }
- print_subtlv_av_delay(&buf, 4, &mtc->av_delay);
- print_subtlv_mm_delay(&buf, 4, &mtc->mm_delay);
- print_subtlv_delay_var(&buf, 4, &mtc->delay_var);
- print_subtlv_pkt_loss(&buf, 4, &mtc->pkt_loss);
- print_subtlv_res_bw(&buf, 4, &mtc->res_bw);
- print_subtlv_ava_bw(&buf, 4, &mtc->ava_bw);
- print_subtlv_use_bw(&buf, 4, &mtc->use_bw);
+ if (IS_SUBTLV(ext, EXT_ADM_GRP))
+ sbuf_push(&buf, 4, "Administrative Group: 0x%" PRIx32 "\n",
+ ext->adm_group);
+ if (IS_SUBTLV(ext, EXT_LLRI)) {
+ sbuf_push(&buf, 4, "Link Local ID: %" PRIu32 "\n",
+ ext->local_llri);
+ sbuf_push(&buf, 4, "Link Remote ID: %" PRIu32 "\n",
+ ext->remote_llri);
+ }
+ if (IS_SUBTLV(ext, EXT_LOCAL_ADDR))
+ sbuf_push(&buf, 4, "Local Interface IP Address(es): %s\n",
+ inet_ntoa(ext->local_addr));
+ if (IS_SUBTLV(ext, EXT_NEIGH_ADDR))
+ sbuf_push(&buf, 4, "Remote Interface IP Address(es): %s\n",
+ inet_ntoa(ext->neigh_addr));
+ if (IS_SUBTLV(ext, EXT_LOCAL_ADDR6))
+ sbuf_push(&buf, 4, "Local Interface IPv6 Address(es): %s\n",
+ inet_ntop(AF_INET6, &ext->local_addr6, ibuf,
+ PREFIX2STR_BUFFER));
+ if (IS_SUBTLV(ext, EXT_NEIGH_ADDR6))
+ sbuf_push(&buf, 4, "Remote Interface IPv6 Address(es): %s\n",
+ inet_ntop(AF_INET6, &ext->local_addr6, ibuf,
+ PREFIX2STR_BUFFER));
+ if (IS_SUBTLV(ext, EXT_MAX_BW))
+ sbuf_push(&buf, 4, "Maximum Bandwidth: %g (Bytes/sec)\n",
+ ext->max_bw);
+ if (IS_SUBTLV(ext, EXT_MAX_RSV_BW))
+ sbuf_push(&buf, 4,
+ "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
+ ext->max_rsv_bw);
+ if (IS_SUBTLV(ext, EXT_UNRSV_BW)) {
+ sbuf_push(&buf, 4, "Unreserved Bandwidth:\n");
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
+ sbuf_push(&buf, 4 + 2,
+ "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
+ j, ext->unrsv_bw[j],
+ j + 1, ext->unrsv_bw[j + 1]);
+ }
+ }
+ if (IS_SUBTLV(ext, EXT_TE_METRIC))
+ sbuf_push(&buf, 4, "Traffic Engineering Metric: %u\n",
+ ext->te_metric);
+ if (IS_SUBTLV(ext, EXT_RMT_AS))
+ sbuf_push(&buf, 4,
+ "Inter-AS TE Remote AS number: %" PRIu32 "\n",
+ ext->remote_as);
+ if (IS_SUBTLV(ext, EXT_RMT_IP))
+ sbuf_push(&buf, 4,
+ "Inter-AS TE Remote ASBR IP address: %s\n",
+ inet_ntoa(ext->remote_ip));
+ if (IS_SUBTLV(ext, EXT_DELAY))
+ sbuf_push(&buf, 4,
+ "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
+ IS_ANORMAL(ext->delay) ? "Anomalous" : "Normal",
+ ext->delay);
+ if (IS_SUBTLV(ext, EXT_MM_DELAY)) {
+ sbuf_push(&buf, 4, "%s Min/Max Link Delay: %" PRIu32 " / %"
+ PRIu32 " (micro-sec)\n",
+ IS_ANORMAL(ext->min_delay) ? "Anomalous" : "Normal",
+ ext->min_delay & TE_EXT_MASK,
+ ext->max_delay & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(ext, EXT_DELAY_VAR))
+ sbuf_push(&buf, 4,
+ "Delay Variation: %" PRIu32 " (micro-sec)\n",
+ ext->delay_var & TE_EXT_MASK);
+ if (IS_SUBTLV(ext, EXT_PKT_LOSS))
+ sbuf_push(&buf, 4, "%s Link Packet Loss: %g (%%)\n",
+ IS_ANORMAL(ext->pkt_loss) ? "Anomalous" : "Normal",
+ (float)((ext->pkt_loss & TE_EXT_MASK)
+ * LOSS_PRECISION));
+ if (IS_SUBTLV(ext, EXT_RES_BW))
+ sbuf_push(&buf, 4,
+ "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
+ ext->res_bw);
+ if (IS_SUBTLV(ext, EXT_AVA_BW))
+ sbuf_push(&buf, 4,
+ "Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
+ ext->ava_bw);
+ if (IS_SUBTLV(ext, EXT_USE_BW))
+ sbuf_push(&buf, 4,
+ "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
+ ext->use_bw);
vty_multiline(vty, "", "%s", sbuf_buf(&buf));
vty_out(vty, "---------------\n\n");
@@ -1170,8 +475,8 @@ DEFUN (show_isis_mpls_te_interface,
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode,
circuit))
- show_mpls_te_sub(vty, circuit->interface->name,
- circuit->mtc);
+ show_ext_sub(vty, circuit->interface->name,
+ circuit->ext);
}
} else {
/* Interface name is specified. */
@@ -1185,7 +490,7 @@ DEFUN (show_isis_mpls_te_interface,
"ISIS is not enabled on circuit %s\n",
ifp->name);
else
- show_mpls_te_sub(vty, ifp->name, circuit->mtc);
+ show_ext_sub(vty, ifp->name, circuit->ext);
}
}
@@ -1197,6 +502,11 @@ DEFUN (show_isis_mpls_te_interface,
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);
+
+
#ifndef FABRICD
/* Register new VTY commands */
install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd);
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index beb0c1836f..2a6911d500 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -3,8 +3,9 @@
*
* This is an implementation of RFC5305, RFC 5307 and RFC 7810
*
- * Copyright (C) 2014 Orange Labs
- * http://www.orange.com
+ * Author: Olivier Dugeon <olivier.dugeon@orange.com>
+ *
+ * Copyright (C) 2014 - 2019 Orange Labs http://www.orange.com
*
* This file is part of GNU Zebra.
*
@@ -50,10 +51,10 @@
* Remote AS number 24 RFC5316
* IPv4 Remote ASBR identifier 25 RFC5316
*
+ * NOTE: RFC5316 is not fully supported in this version
+ * only subTLVs decoding is provided
*/
-/* NOTE: RFC5316 is not yet supported in this version */
-
/* Following define the type of TE link regarding the various RFC */
#define STD_TE 0x01
#define GMPLS 0x02
@@ -73,170 +74,9 @@
#define IS_INTER_AS_AS(x) (x & INTER_AS & FLOOD_AS)
/*
- * Following section defines subTLV (tag, length, value) structures,
- * used for Traffic Engineering.
+ * Note (since release 7.2), subTLVs definition, serialization
+ * and de-serialization have mode to isis_tlvs.[c,h]
*/
-struct subtlv_header {
- uint8_t type; /* sub_TLV_XXX type (see above) */
- uint8_t length; /* Value portion only, in byte */
-};
-
-#define MAX_SUBTLV_SIZE 256
-
-#define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */
-
-#define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length)
-
-#define SUBTLV_HDR_TOP(lsph) (struct subtlv_header *)((char *)(lsph) + ISIS_LSP_HEADER_SIZE)
-
-#define SUBTLV_HDR_NEXT(stlvh) (struct subtlv_header *)((char *)(stlvh) + SUBTLV_SIZE(stlvh))
-
-#define SUBTLV_TYPE(stlvh) stlvh.header.type
-#define SUBTLV_LEN(stlvh) stlvh.header.length
-#define SUBTLV_VAL(stlvh) stlvh.value
-#define SUBTLV_DATA(stlvh) stlvh + SUBTLV_HDR_SIZE
-
-#define SUBTLV_DEF_SIZE 4
-
-/* Link Sub-TLV: Resource Class/Color - RFC 5305 */
-#define TE_SUBTLV_ADMIN_GRP 3
-struct te_subtlv_admin_grp {
- struct subtlv_header header; /* Value length is 4 octets. */
- uint32_t value; /* Admin. group membership. */
-} __attribute__((__packed__));
-
-/* Link Local/Remote Identifiers - RFC 5307 */
-#define TE_SUBTLV_LLRI 4
-#define TE_SUBTLV_LLRI_SIZE 8
-struct te_subtlv_llri {
- struct subtlv_header header; /* Value length is 8 octets. */
- uint32_t local; /* Link Local Identifier */
- uint32_t remote; /* Link Remote Identifier */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Local Interface IP Address - RFC 5305 */
-#define TE_SUBTLV_LOCAL_IPADDR 6
-struct te_subtlv_local_ipaddr {
- struct subtlv_header header; /* Value length is 4 x N octets. */
- struct in_addr value; /* Local IP address(es). */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Neighbor Interface IP Address - RFC 5305 */
-#define TE_SUBTLV_RMT_IPADDR 8
-struct te_subtlv_rmt_ipaddr {
- struct subtlv_header header; /* Value length is 4 x N octets. */
- struct in_addr value; /* Neighbor's IP address(es). */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Maximum Bandwidth - RFC 5305 */
-#define TE_SUBTLV_MAX_BW 9
-struct te_subtlv_max_bw {
- struct subtlv_header header; /* Value length is 4 octets. */
- float value; /* bytes/sec */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Maximum Reservable Bandwidth - RFC 5305 */
-#define TE_SUBTLV_MAX_RSV_BW 10
-struct te_subtlv_max_rsv_bw {
- struct subtlv_header header; /* Value length is 4 octets. */
- float value; /* bytes/sec */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Unreserved Bandwidth - RFC 5305 */
-#define TE_SUBTLV_UNRSV_BW 11
-#define TE_SUBTLV_UNRSV_SIZE 32
-struct te_subtlv_unrsv_bw {
- struct subtlv_header header; /* Value length is 32 octets. */
- float value[8]; /* One for each priority level. */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Traffic Engineering Metric - RFC 5305 */
-#define TE_SUBTLV_TE_METRIC 18
-#define TE_SUBTLV_TE_METRIC_SIZE 3
-struct te_subtlv_te_metric {
- struct subtlv_header header; /* Value length is 4 octets. */
- uint8_t value[3]; /* Link metric for TE purpose. */
-} __attribute__((__packed__));
-
-/* Remote AS Number sub-TLV - RFC5316 */
-#define TE_SUBTLV_RAS 24
-struct te_subtlv_ras {
- struct subtlv_header header; /* Value length is 4 octets. */
- uint32_t value; /* Remote AS number */
-} __attribute__((__packed__));
-
-/* IPv4 Remote ASBR ID Sub-TLV - RFC5316 */
-#define TE_SUBTLV_RIP 25
-struct te_subtlv_rip {
- struct subtlv_header header; /* Value length is 4 octets. */
- struct in_addr value; /* Remote ASBR IP address */
-} __attribute__((__packed__));
-
-
-/* TE Metric Extensions - RFC 7810 */
-/* Link Sub-TLV: Average Link Delay */
-#define TE_SUBTLV_AV_DELAY 33
-struct te_subtlv_av_delay {
- struct subtlv_header header; /* Value length is 4 bytes. */
- uint32_t value; /* Average delay in micro-seconds only 24 bits => 0 ...
- 16777215
- with Anomalous Bit (A) as Upper most bit */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Low/High Link Delay */
-#define TE_SUBTLV_MM_DELAY 34
-#define TE_SUBTLV_MM_DELAY_SIZE 8
-struct te_subtlv_mm_delay {
- struct subtlv_header header; /* Value length is 8 bytes. */
- uint32_t low; /* low delay in micro-seconds only 24 bits => 0 ...
- 16777215
- with Anomalous Bit (A) as Upper most bit */
- uint32_t high; /* high delay in micro-seconds only 24 bits => 0 ...
- 16777215 */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Link Delay Variation i.e. Jitter */
-#define TE_SUBTLV_DELAY_VAR 35
-struct te_subtlv_delay_var {
- struct subtlv_header header; /* Value length is 4 bytes. */
- uint32_t value; /* interval in micro-seconds only 24 bits => 0 ...
- 16777215 */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Routine Unidirectional Link Packet Loss */
-#define TE_SUBTLV_PKT_LOSS 36
-struct te_subtlv_pkt_loss {
- struct subtlv_header header; /* Value length is 4 bytes. */
- uint32_t
- value; /* in percentage of total traffic only 24 bits (2^24 - 2)
- with Anomalous Bit (A) as Upper most bit */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */
-#define TE_SUBTLV_RES_BW 37
-struct te_subtlv_res_bw {
- struct subtlv_header header; /* Value length is 4 bytes. */
- float value; /* bandwidth in IEEE floating point format with units in
- bytes per second */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */
-#define TE_SUBTLV_AVA_BW 38
-struct te_subtlv_ava_bw {
- struct subtlv_header header; /* Value length is 4 octets. */
- float value; /* bandwidth in IEEE floating point format with units in
- bytes per second */
-} __attribute__((__packed__));
-
-/* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */
-#define TE_SUBTLV_USE_BW 39
-struct te_subtlv_use_bw {
- struct subtlv_header header; /* Value length is 4 octets. */
- float value; /* bandwidth in IEEE floating point format with units in
- bytes per second */
-} __attribute__((__packed__));
-
-#define TE_SUBTLV_MAX 40 /* Last SUBTLV + 1 */
/* Following declaration concerns the MPLS-TE and LINk-TE management */
typedef enum _status_t { disable, enable, learn } status_t;
@@ -244,7 +84,10 @@ typedef enum _status_t { disable, enable, learn } status_t;
/* Mode for Inter-AS LSP */ /* TODO: Check how if LSP is flooded in RFC5316 */
typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t;
-#define IS_MPLS_TE(m) (m && m->status == enable)
+#define IS_EXT_TE(e) (e && e->status != 0 \
+ && e->status != EXT_ADJ_SID \
+ && e->status != EXT_LAN_ADJ_SID)
+#define IS_MPLS_TE(a) (a && a->status == enable)
/* Per area MPLS-TE parameters */
struct mpls_te_area {
@@ -262,56 +105,9 @@ struct mpls_te_area {
struct in_addr router_id;
};
-/* Per Circuit MPLS-TE parameters */
-struct mpls_te_circuit {
-
- /* Status of MPLS-TE on this interface */
- status_t status;
-
- /* Type of MPLS-TE circuit: STD_TE(RFC5305), INTER_AS(RFC5316),
- * INTER_AS_EMU(RFC5316 emulated) */
- uint8_t type;
-
- /* Total size of sub_tlvs */
- uint8_t length;
-
- /* Store subTLV in network byte order. */
- /* RFC5305 */
- struct te_subtlv_admin_grp admin_grp;
- /* RFC5307 */
- struct te_subtlv_llri llri;
- /* RFC5305 */
- struct te_subtlv_local_ipaddr local_ipaddr;
- struct te_subtlv_rmt_ipaddr rmt_ipaddr;
- struct te_subtlv_max_bw max_bw;
- struct te_subtlv_max_rsv_bw max_rsv_bw;
- struct te_subtlv_unrsv_bw unrsv_bw;
- struct te_subtlv_te_metric te_metric;
- /* RFC5316 */
- struct te_subtlv_ras ras;
- struct te_subtlv_rip rip;
- /* RFC7810 */
- struct te_subtlv_av_delay av_delay;
- struct te_subtlv_mm_delay mm_delay;
- struct te_subtlv_delay_var delay_var;
- struct te_subtlv_pkt_loss pkt_loss;
- struct te_subtlv_res_bw res_bw;
- struct te_subtlv_ava_bw ava_bw;
- struct te_subtlv_use_bw use_bw;
-};
-
/* Prototypes. */
void isis_mpls_te_init(void);
-struct mpls_te_circuit *mpls_te_circuit_new(void);
-struct sbuf;
-void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs,
- uint8_t subtlv_len);
-void set_circuitparams_local_ipaddr(struct mpls_te_circuit *, struct in_addr);
-void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *, struct in_addr);
-uint8_t subtlvs_len(struct mpls_te_circuit *);
-uint8_t add_te_subtlvs(uint8_t *, struct mpls_te_circuit *);
-uint8_t build_te_subtlvs(uint8_t *, struct isis_circuit *);
void isis_link_params_update(struct isis_circuit *, struct interface *);
-void isis_mpls_te_update(struct interface *);
+int isis_mpls_te_update(struct interface *);
#endif /* _ZEBRA_ISIS_MPLS_TE_H */
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index ee253c7a31..442442152c 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -3,6 +3,8 @@
*
* Copyright (C) 2015,2017 Christian Franke
*
+ * Copyright (C) 2019 Olivier Dugeon - Orange Labs (for TE and SR)
+ *
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
@@ -28,6 +30,7 @@
#include "memory.h"
#include "stream.h"
#include "sbuf.h"
+#include "network.h"
#include "isisd/isisd.h"
#include "isisd/isis_memory.h"
@@ -98,7 +101,8 @@ static struct pack_order_entry pack_order[] = {
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),
- PACK_ENTRY(MT_IPV6_REACH, ISIS_MT_ITEMS, mt_ipv6_reach)};
+ PACK_ENTRY(MT_IPV6_REACH, ISIS_MT_ITEMS, mt_ipv6_reach)
+};
/* This is a forward definition. The table is actually initialized
* in at the bottom. */
@@ -108,9 +112,683 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX];
/* Prototypes */
static void append_item(struct isis_item_list *dest, struct isis_item *item);
+static void init_item_list(struct isis_item_list *items);
-/* Functions for Sub-TLV 3 SR Prefix-SID */
+/* Functions for Extended IS Reachability SubTLVs a.k.a Traffic Engineering */
+struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
+{
+ struct isis_ext_subtlvs *ext;
+
+ ext = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(struct isis_ext_subtlvs));
+ init_item_list(&ext->adj_sid);
+ init_item_list(&ext->lan_sid);
+
+ return ext;
+}
+
+/*
+ * 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.
+ */
+static struct isis_ext_subtlvs *
+copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, int16_t mtid)
+{
+ struct isis_ext_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
+ struct isis_adj_sid *adj;
+ struct isis_lan_adj_sid *lan;
+
+ memcpy(rv, exts, sizeof(struct isis_ext_subtlvs));
+ 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 */
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj != NULL;
+ adj = adj->next) {
+ if ((mtid != -1)
+ && (((mtid == ISIS_MT_IPV4_UNICAST)
+ && (adj->family != AF_INET))
+ || ((mtid == ISIS_MT_IPV6_UNICAST)
+ && (adj->family != AF_INET6))))
+ continue;
+
+ struct isis_adj_sid *new;
+
+ new = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(struct isis_adj_sid));
+ new->family = adj->family;
+ new->flags = adj->flags;
+ new->weight = adj->weight;
+ new->sid = adj->sid;
+ append_item(&rv->adj_sid, (struct isis_item *)new);
+ SET_SUBTLV(rv, EXT_ADJ_SID);
+ }
+
+ for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head; lan != NULL;
+ lan = lan->next) {
+ if ((mtid != -1)
+ && (((mtid == ISIS_MT_IPV4_UNICAST)
+ && (lan->family != AF_INET))
+ || ((mtid == ISIS_MT_IPV6_UNICAST)
+ && (lan->family != AF_INET6))))
+ continue;
+
+ struct isis_lan_adj_sid *new;
+
+ new = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(struct isis_lan_adj_sid));
+ new->family = lan->family;
+ new->flags = lan->flags;
+ new->weight = lan->weight;
+ memcpy(new->neighbor_id, lan->neighbor_id, 6);
+ new->sid = lan->sid;
+ append_item(&rv->lan_sid, (struct isis_item *)new);
+ SET_SUBTLV(rv, EXT_LAN_ADJ_SID);
+ }
+
+ return rv;
+}
+
+/* mtid parameter is used to manage multi-topology i.e. IPv4 / IPv6 */
+static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
+ struct sbuf *buf, int indent,
+ uint16_t mtid)
+{
+
+ char ibuf[PREFIX2STR_BUFFER];
+
+ /* Standard metrics */
+ if (IS_SUBTLV(exts, EXT_ADM_GRP))
+ sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
+ exts->adm_group);
+ if (IS_SUBTLV(exts, EXT_LLRI)) {
+ sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
+ exts->local_llri);
+ sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
+ exts->remote_llri);
+ }
+ if (IS_SUBTLV(exts, EXT_LOCAL_ADDR))
+ sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
+ inet_ntoa(exts->local_addr));
+ if (IS_SUBTLV(exts, EXT_NEIGH_ADDR))
+ sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
+ inet_ntoa(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));
+ 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));
+ if (IS_SUBTLV(exts, EXT_MAX_BW))
+ sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n",
+ exts->max_bw);
+ if (IS_SUBTLV(exts, EXT_MAX_RSV_BW))
+ sbuf_push(buf, indent,
+ "Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
+ exts->max_rsv_bw);
+ if (IS_SUBTLV(exts, EXT_UNRSV_BW)) {
+ sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
+ sbuf_push(buf, indent + 2,
+ "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
+ j, exts->unrsv_bw[j],
+ j + 1, exts->unrsv_bw[j + 1]);
+ }
+ }
+ if (IS_SUBTLV(exts, EXT_TE_METRIC))
+ sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n",
+ exts->te_metric);
+ if (IS_SUBTLV(exts, EXT_RMT_AS))
+ sbuf_push(buf, indent,
+ "Inter-AS TE Remote AS number: %" PRIu32 "\n",
+ exts->remote_as);
+ if (IS_SUBTLV(exts, EXT_RMT_IP))
+ sbuf_push(buf, indent,
+ "Inter-AS TE Remote ASBR IP address: %s\n",
+ inet_ntoa(exts->remote_ip));
+ /* Extended metrics */
+ if (IS_SUBTLV(exts, EXT_DELAY))
+ sbuf_push(buf, indent,
+ "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
+ IS_ANORMAL(exts->delay) ? "Anomalous" : "Normal",
+ exts->delay);
+ if (IS_SUBTLV(exts, EXT_MM_DELAY)) {
+ sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %"
+ PRIu32 " (micro-sec)\n",
+ IS_ANORMAL(exts->min_delay) ? "Anomalous" : "Normal",
+ exts->min_delay & TE_EXT_MASK,
+ exts->max_delay & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(exts, EXT_DELAY_VAR)) {
+ sbuf_push(buf, indent,
+ "Delay Variation: %" PRIu32 " (micro-sec)\n",
+ exts->delay_var & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(exts, EXT_PKT_LOSS))
+ sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
+ IS_ANORMAL(exts->pkt_loss) ? "Anomalous" : "Normal",
+ (float)((exts->pkt_loss & TE_EXT_MASK)
+ * LOSS_PRECISION));
+ if (IS_SUBTLV(exts, EXT_RES_BW))
+ sbuf_push(buf, indent,
+ "Unidir. Residual Bandwidth: %g (Bytes/sec)\n",
+ exts->res_bw);
+ if (IS_SUBTLV(exts, EXT_AVA_BW))
+ sbuf_push(buf, indent,
+ "Unidir. Available Bandwidth: %g (Bytes/sec)\n",
+ exts->ava_bw);
+ if (IS_SUBTLV(exts, EXT_USE_BW))
+ sbuf_push(buf, indent,
+ "Unidir. Utilized Bandwidth: %g (Bytes/sec)\n",
+ exts->use_bw);
+ /* Segment Routing Adjacency */
+ if (IS_SUBTLV(exts, EXT_ADJ_SID)) {
+ struct isis_adj_sid *adj;
+
+ 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: %" PRIu32 ", Weight: %" PRIu8
+ ", Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n",
+ adj->sid, adj->weight,
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG ? '1'
+ : '0',
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? '1'
+ : '0');
+ }
+ }
+ if (IS_SUBTLV(exts, EXT_LAN_ADJ_SID)) {
+ struct isis_lan_adj_sid *lan;
+
+ 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: %" PRIu32
+ ", Weight: %" PRIu8
+ ", Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
+ " Neighbor-ID: %s\n",
+ lan->sid, lan->weight,
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? '1'
+ : '0',
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? '1'
+ : '0',
+ isis_format_id(lan->neighbor_id, 6));
+ }
+ }
+}
+
+static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
+{
+ struct isis_item *item, *next_item;
+
+ /* First, free Adj SID and LAN Adj SID list if needed */
+ for (item = exts->adj_sid.head; item; item = next_item) {
+ next_item = item->next;
+ XFREE(MTYPE_ISIS_SUBTLV, item);
+ }
+ for (item = exts->lan_sid.head; item; item = next_item) {
+ next_item = item->next;
+ XFREE(MTYPE_ISIS_SUBTLV, item);
+ }
+ XFREE(MTYPE_ISIS_SUBTLV, exts);
+}
+
+static int pack_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
+ struct stream *s)
+{
+ uint8_t size;
+
+ if (STREAM_WRITEABLE(s) < ISIS_SUBTLV_MAX_SIZE)
+ return 1;
+
+ if (IS_SUBTLV(exts, EXT_ADM_GRP)) {
+ stream_putc(s, ISIS_SUBTLV_ADMIN_GRP);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putl(s, exts->adm_group);
+ }
+ if (IS_SUBTLV(exts, EXT_LLRI)) {
+ stream_putc(s, ISIS_SUBTLV_LLRI);
+ stream_putc(s, ISIS_SUBTLV_LLRI_SIZE);
+ stream_putl(s, exts->local_llri);
+ stream_putl(s, exts->remote_llri);
+ }
+ if (IS_SUBTLV(exts, EXT_LOCAL_ADDR)) {
+ stream_putc(s, ISIS_SUBTLV_LOCAL_IPADDR);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_put(s, &exts->local_addr.s_addr, 4);
+ }
+ if (IS_SUBTLV(exts, EXT_NEIGH_ADDR)) {
+ stream_putc(s, ISIS_SUBTLV_RMT_IPADDR);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_put(s, &exts->neigh_addr.s_addr, 4);
+ }
+ if (IS_SUBTLV(exts, EXT_LOCAL_ADDR6)) {
+ stream_putc(s, ISIS_SUBTLV_LOCAL_IPADDR6);
+ stream_putc(s, ISIS_SUBTLV_IPV6_ADDR_SIZE);
+ stream_put(s, &exts->local_addr6, 16);
+ }
+ if (IS_SUBTLV(exts, EXT_NEIGH_ADDR6)) {
+ stream_putc(s, ISIS_SUBTLV_RMT_IPADDR6);
+ stream_putc(s, ISIS_SUBTLV_IPV6_ADDR_SIZE);
+ stream_put(s, &exts->neigh_addr6, 16);
+ }
+ if (IS_SUBTLV(exts, EXT_MAX_BW)) {
+ stream_putc(s, ISIS_SUBTLV_MAX_BW);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putf(s, exts->max_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_MAX_RSV_BW)) {
+ stream_putc(s, ISIS_SUBTLV_MAX_RSV_BW);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putf(s, exts->max_rsv_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_UNRSV_BW)) {
+ stream_putc(s, ISIS_SUBTLV_UNRSV_BW);
+ stream_putc(s, ISIS_SUBTLV_UNRSV_BW_SIZE);
+ for (int j = 0; j < MAX_CLASS_TYPE; j++)
+ stream_putf(s, exts->unrsv_bw[j]);
+ }
+ if (IS_SUBTLV(exts, EXT_TE_METRIC)) {
+ stream_putc(s, ISIS_SUBTLV_TE_METRIC);
+ stream_putc(s, ISIS_SUBTLV_TE_METRIC_SIZE);
+ stream_put3(s, exts->te_metric);
+ }
+ if (IS_SUBTLV(exts, EXT_RMT_AS)) {
+ stream_putc(s, ISIS_SUBTLV_RAS);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putl(s, exts->remote_as);
+ }
+ if (IS_SUBTLV(exts, EXT_RMT_IP)) {
+ stream_putc(s, ISIS_SUBTLV_RIP);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_put(s, &exts->remote_ip.s_addr, 4);
+ }
+ if (IS_SUBTLV(exts, EXT_DELAY)) {
+ stream_putc(s, ISIS_SUBTLV_AV_DELAY);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putl(s, exts->delay);
+ }
+ if (IS_SUBTLV(exts, EXT_MM_DELAY)) {
+ stream_putc(s, ISIS_SUBTLV_MM_DELAY);
+ stream_putc(s, ISIS_SUBTLV_MM_DELAY_SIZE);
+ stream_putl(s, exts->min_delay);
+ stream_putl(s, exts->max_delay);
+ }
+ if (IS_SUBTLV(exts, EXT_DELAY_VAR)) {
+ stream_putc(s, ISIS_SUBTLV_DELAY_VAR);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putl(s, exts->delay_var);
+ }
+ if (IS_SUBTLV(exts, EXT_PKT_LOSS)) {
+ stream_putc(s, ISIS_SUBTLV_PKT_LOSS);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putl(s, exts->pkt_loss);
+ }
+ if (IS_SUBTLV(exts, EXT_RES_BW)) {
+ stream_putc(s, ISIS_SUBTLV_RES_BW);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putf(s, exts->res_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_AVA_BW)) {
+ stream_putc(s, ISIS_SUBTLV_AVA_BW);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putf(s, exts->ava_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_USE_BW)) {
+ stream_putc(s, ISIS_SUBTLV_USE_BW);
+ stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
+ stream_putf(s, exts->use_bw);
+ }
+ if (IS_SUBTLV(exts, EXT_ADJ_SID)) {
+ struct isis_adj_sid *adj;
+
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj;
+ adj = adj->next) {
+ stream_putc(s, ISIS_SUBTLV_ADJ_SID);
+ size = ISIS_SUBTLV_ADJ_SID_SIZE;
+ if (!(adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG))
+ size++;
+ stream_putc(s, size);
+ stream_putc(s, adj->flags);
+ stream_putc(s, adj->weight);
+ if (adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG)
+ stream_put3(s, adj->sid);
+ else
+ stream_putl(s, adj->sid);
+
+ }
+ }
+ if (IS_SUBTLV(exts, EXT_LAN_ADJ_SID)) {
+ struct isis_lan_adj_sid *lan;
+
+ for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head; lan;
+ lan = lan->next) {
+ stream_putc(s, ISIS_SUBTLV_LAN_ADJ_SID);
+ size = ISIS_SUBTLV_LAN_ADJ_SID_SIZE;
+ if (!(lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG))
+ size++;
+ stream_putc(s, size);
+ stream_putc(s, lan->flags);
+ stream_putc(s, lan->weight);
+ stream_put(s, lan->neighbor_id, 6);
+ if (lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG)
+ stream_put3(s, lan->sid);
+ else
+ stream_putl(s, lan->sid);
+ }
+ }
+
+ return 0;
+}
+
+static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
+ struct sbuf *log, void *dest, int indent)
+{
+ uint8_t sum = 0;
+ uint8_t subtlv_type;
+ uint8_t subtlv_len;
+
+ struct isis_extended_reach *rv = dest;
+ struct isis_ext_subtlvs *exts = isis_alloc_ext_subtlvs();
+
+ rv->subtlvs = exts;
+
+ /*
+ * Parse subTLVs until reach subTLV length
+ * Check that it remains at least 2 bytes: subTLV Type & Length
+ */
+ while (len > sum + 2) {
+ /* Read SubTLV Type and Length */
+ subtlv_type = stream_getc(s);
+ subtlv_len = stream_getc(s);
+ if (subtlv_len > len - sum) {
+ sbuf_push(log, indent, "TLV %" PRIu8 ": Available data %" PRIu8 " is less than TLV size %u !\n",
+ subtlv_type, len - sum, subtlv_len);
+ return 1;
+ }
+ switch (subtlv_type) {
+ /* Standard Metric as defined in RFC5305 */
+ case ISIS_SUBTLV_ADMIN_GRP:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Administrative Group!\n");
+ } else {
+ exts->adm_group = stream_getl(s);
+ SET_SUBTLV(exts, EXT_ADM_GRP);
+ }
+ break;
+ case ISIS_SUBTLV_LLRI:
+ if (subtlv_len != ISIS_SUBTLV_LLRI_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Link ID!\n");
+ } else {
+ exts->local_llri = stream_getl(s);
+ exts->remote_llri = stream_getl(s);
+ SET_SUBTLV(exts, EXT_LLRI);
+ }
+ break;
+ case ISIS_SUBTLV_LOCAL_IPADDR:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Local IP address!\n");
+ } else {
+ stream_get(&exts->local_addr.s_addr, s, 4);
+ SET_SUBTLV(exts, EXT_LOCAL_ADDR);
+ }
+ break;
+ case ISIS_SUBTLV_RMT_IPADDR:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Remote IP address!\n");
+ } else {
+ stream_get(&exts->neigh_addr.s_addr, s, 4);
+ SET_SUBTLV(exts, EXT_NEIGH_ADDR);
+ }
+ break;
+ case ISIS_SUBTLV_LOCAL_IPADDR6:
+ if (subtlv_len != ISIS_SUBTLV_IPV6_ADDR_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Local IPv6 address!\n");
+ } else {
+ stream_get(&exts->local_addr6, s, 16);
+ SET_SUBTLV(exts, EXT_LOCAL_ADDR6);
+ }
+ break;
+ case ISIS_SUBTLV_RMT_IPADDR6:
+ if (subtlv_len != ISIS_SUBTLV_IPV6_ADDR_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Remote IPv6 address!\n");
+ } else {
+ stream_get(&exts->neigh_addr6, s, 16);
+ SET_SUBTLV(exts, EXT_NEIGH_ADDR6);
+ }
+ break;
+ case ISIS_SUBTLV_MAX_BW:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Maximum Bandwidth!\n");
+ } else {
+ exts->max_bw = stream_getf(s);
+ SET_SUBTLV(exts, EXT_MAX_BW);
+ }
+ break;
+ case ISIS_SUBTLV_MAX_RSV_BW:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Maximum Reservable Bandwidth!\n");
+ } else {
+ exts->max_rsv_bw = stream_getf(s);
+ SET_SUBTLV(exts, EXT_MAX_RSV_BW);
+ }
+ break;
+ case ISIS_SUBTLV_UNRSV_BW:
+ if (subtlv_len != ISIS_SUBTLV_UNRSV_BW_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Unreserved Bandwidth!\n");
+ } else {
+ for (int i = 0; i < MAX_CLASS_TYPE; i++)
+ exts->unrsv_bw[i] = stream_getf(s);
+ SET_SUBTLV(exts, EXT_UNRSV_BW);
+ }
+ break;
+ case ISIS_SUBTLV_TE_METRIC:
+ if (subtlv_len != ISIS_SUBTLV_TE_METRIC_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Traffic Engineering Metric!\n");
+ } else {
+ exts->te_metric = stream_get3(s);
+ SET_SUBTLV(exts, EXT_TE_METRIC);
+ }
+ break;
+ case ISIS_SUBTLV_RAS:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Remote AS number!\n");
+ } else {
+ exts->remote_as = stream_getl(s);
+ SET_SUBTLV(exts, EXT_RMT_AS);
+ }
+ break;
+ case ISIS_SUBTLV_RIP:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Remote ASBR IP Address!\n");
+ } else {
+ stream_get(&exts->remote_ip.s_addr, s, 4);
+ SET_SUBTLV(exts, EXT_RMT_IP);
+ }
+ break;
+ /* Extended Metrics as defined in RFC 7810 */
+ case ISIS_SUBTLV_AV_DELAY:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Average Link Delay!\n");
+ } else {
+ exts->delay = stream_getl(s);
+ SET_SUBTLV(exts, EXT_DELAY);
+ }
+ break;
+ case ISIS_SUBTLV_MM_DELAY:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Min/Max Link Delay!\n");
+ } else {
+ exts->min_delay = stream_getl(s);
+ exts->max_delay = stream_getl(s);
+ SET_SUBTLV(exts, EXT_MM_DELAY);
+ }
+ break;
+ case ISIS_SUBTLV_DELAY_VAR:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Delay Variation!\n");
+ } else {
+ exts->delay_var = stream_getl(s);
+ SET_SUBTLV(exts, EXT_DELAY_VAR);
+ }
+ break;
+ case ISIS_SUBTLV_PKT_LOSS:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Link Packet Loss!\n");
+ } else {
+ exts->pkt_loss = stream_getl(s);
+ SET_SUBTLV(exts, EXT_PKT_LOSS);
+ }
+ break;
+ case ISIS_SUBTLV_RES_BW:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Unidirectional Residual Bandwidth!\n");
+ } else {
+ exts->res_bw = stream_getf(s);
+ SET_SUBTLV(exts, EXT_RES_BW);
+ }
+ break;
+ case ISIS_SUBTLV_AVA_BW:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Unidirectional Available Bandwidth!\n");
+ } else {
+ exts->ava_bw = stream_getf(s);
+ SET_SUBTLV(exts, EXT_AVA_BW);
+ }
+ break;
+ case ISIS_SUBTLV_USE_BW:
+ if (subtlv_len != ISIS_SUBTLV_DEF_SIZE) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Unidirectional Utilized Bandwidth!\n");
+ } else {
+ exts->use_bw = stream_getf(s);
+ SET_SUBTLV(exts, EXT_USE_BW);
+ }
+ break;
+ /* Segment Routing Adjacency */
+ case ISIS_SUBTLV_ADJ_SID:
+ if (subtlv_len != ISIS_SUBTLV_ADJ_SID_SIZE
+ && subtlv_len != ISIS_SUBTLV_ADJ_SID_SIZE + 1) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for Adjacency SID!\n");
+ } else {
+ struct isis_adj_sid *adj;
+
+ adj = XCALLOC(MTYPE_ISIS_SUBTLV,
+ sizeof(struct isis_adj_sid));
+ adj->flags = stream_getc(s);
+ adj->weight = stream_getc(s);
+ if (adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG) {
+ adj->sid = stream_get3(s);
+ adj->sid &= MPLS_LABEL_VALUE_MASK;
+ } else {
+ adj->sid = stream_getl(s);
+ }
+ if (mtid == ISIS_MT_IPV4_UNICAST)
+ adj->family = AF_INET;
+ if (mtid == ISIS_MT_IPV6_UNICAST)
+ adj->family = AF_INET6;
+ append_item(&exts->adj_sid,
+ (struct isis_item *)adj);
+ SET_SUBTLV(exts, EXT_ADJ_SID);
+ }
+ break;
+ case ISIS_SUBTLV_LAN_ADJ_SID:
+ if (subtlv_len != ISIS_SUBTLV_LAN_ADJ_SID_SIZE
+ && subtlv_len != ISIS_SUBTLV_LAN_ADJ_SID_SIZE + 1) {
+ sbuf_push(log, indent,
+ "TLV size does not match expected size for LAN-Adjacency SID!\n");
+ } else {
+ struct isis_lan_adj_sid *lan;
+
+ lan = XCALLOC(MTYPE_ISIS_SUBTLV,
+ sizeof(struct isis_lan_adj_sid));
+ lan->flags = stream_getc(s);
+ lan->weight = stream_getc(s);
+ stream_get(&(lan->neighbor_id), s,
+ ISIS_SYS_ID_LEN);
+ if (lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG) {
+ lan->sid = stream_get3(s);
+ lan->sid &= MPLS_LABEL_VALUE_MASK;
+ } else {
+ lan->sid = stream_getl(s);
+ }
+ if (mtid == ISIS_MT_IPV4_UNICAST)
+ lan->family = AF_INET;
+ if (mtid == ISIS_MT_IPV6_UNICAST)
+ lan->family = AF_INET6;
+ append_item(&exts->lan_sid,
+ (struct isis_item *)lan);
+ SET_SUBTLV(exts, EXT_LAN_ADJ_SID);
+ }
+ break;
+ default:
+ /* Skip unknown TLV */
+ stream_forward_getp(s, subtlv_len);
+ break;
+ }
+ sum += subtlv_len + ISIS_SUBTLV_HDR_SIZE;
+ }
+
+ return 0;
+}
+
+/* Functions for Sub-TLV 3 SR Prefix-SID */
static struct isis_item *copy_item_prefix_sid(struct isis_item *i)
{
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
@@ -127,20 +805,22 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
{
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
- sbuf_push(buf, indent, "SR Prefix-SID:\n");
- sbuf_push(buf, indent, " Flags:%s%s%s%s%s%s\n",
- sid->flags & ISIS_PREFIX_SID_READVERTISED ? " READVERTISED" : "",
- sid->flags & ISIS_PREFIX_SID_NODE ? " NODE" : "",
- sid->flags & ISIS_PREFIX_SID_NO_PHP ? " NO_PHP" : "",
- sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL ? " EXPLICIT-NULL" : "",
- sid->flags & ISIS_PREFIX_SID_VALUE ? " VALUE" : "",
- sid->flags & ISIS_PREFIX_SID_LOCAL ? " LOCAL" : "");
- sbuf_push(buf, indent, " Algorithm: %" PRIu8 "\n", sid->algorithm);
+ sbuf_push(buf, indent, "SR Prefix-SID ");
if (sid->flags & ISIS_PREFIX_SID_VALUE) {
- sbuf_push(buf, indent, "Label: %" PRIu32 "\n", sid->value);
+ sbuf_push(buf, 0, "Label: %" PRIu32 ", ", sid->value);
} else {
- sbuf_push(buf, indent, "Index: %" PRIu32 "\n", sid->value);
+ sbuf_push(buf, 0, "Index: %" PRIu32 ", ", sid->value);
}
+ sbuf_push(buf, 0, "Algorithm: %" PRIu8 ", ", sid->algorithm);
+ sbuf_push(buf, 0, "Flags:%s%s%s%s%s%s\n",
+ sid->flags & ISIS_PREFIX_SID_READVERTISED ? " READVERTISED"
+ : "",
+ sid->flags & ISIS_PREFIX_SID_NODE ? " NODE" : "",
+ sid->flags & ISIS_PREFIX_SID_NO_PHP ? " NO-PHP" : " PHP",
+ sid->flags & ISIS_PREFIX_SID_EXPLICIT_NULL ? " EXPLICIT-NULL"
+ : "",
+ sid->flags & ISIS_PREFIX_SID_VALUE ? " VALUE" : "",
+ sid->flags & ISIS_PREFIX_SID_LOCAL ? " LOCAL" : "");
}
static void free_item_prefix_sid(struct isis_item *i)
@@ -186,15 +866,17 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s,
}
sid.flags = stream_getc(s);
- if ((sid.flags & ISIS_PREFIX_SID_VALUE)
- != (sid.flags & ISIS_PREFIX_SID_LOCAL)) {
- sbuf_push(log, indent, "Flags inplausible: Local Flag needs to match Value Flag\n");
- return 0;
+ if (!!(sid.flags & ISIS_PREFIX_SID_VALUE)
+ != !!(sid.flags & ISIS_PREFIX_SID_LOCAL)) {
+ sbuf_push(log, indent, "Flags implausible: Local Flag needs to match Value Flag\n");
+ return 1;
}
sid.algorithm = stream_getc(s);
- uint8_t expected_size = (sid.flags & ISIS_PREFIX_SID_VALUE) ? 5 : 6;
+ uint8_t expected_size = (sid.flags & ISIS_PREFIX_SID_VALUE)
+ ? ISIS_SUBTLV_PREFIX_SID_SIZE
+ : ISIS_SUBTLV_PREFIX_SID_SIZE + 1;
if (len != expected_size) {
sbuf_push(log, indent,
"TLV size differs from expected size. "
@@ -205,6 +887,7 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s,
if (sid.flags & ISIS_PREFIX_SID_VALUE) {
sid.value = stream_get3(s);
+ sid.value &= MPLS_LABEL_VALUE_MASK;
} else {
sid.value = stream_getl(s);
}
@@ -276,7 +959,7 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context,
p.prefixlen = stream_getc(s);
if (p.prefixlen > 128) {
- sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv6\n",
+ sbuf_push(log, indent, "Prefixlen %u is implausible for IPv6\n",
p.prefixlen);
return 1;
}
@@ -305,7 +988,7 @@ static int unpack_subtlv_ipv6_source_prefix(enum isis_tlv_context context,
memcpy(subtlvs->source_prefix, &p, sizeof(p));
return 0;
}
-static void init_item_list(struct isis_item_list *items);
+
static struct isis_item *copy_item(enum isis_tlv_context context,
enum isis_tlv_type type,
struct isis_item *item);
@@ -703,11 +1386,8 @@ static struct isis_item *copy_item_extended_reach(struct isis_item *i)
memcpy(rv->id, r->id, 7);
rv->metric = r->metric;
- if (r->subtlvs && r->subtlv_len) {
- rv->subtlvs = XCALLOC(MTYPE_ISIS_TLV, r->subtlv_len);
- memcpy(rv->subtlvs, r->subtlvs, r->subtlv_len);
- rv->subtlv_len = r->subtlv_len;
- }
+ if (r->subtlvs)
+ rv->subtlvs = copy_item_ext_subtlvs(r->subtlvs, -1);
return (struct isis_item *)rv;
}
@@ -724,28 +1404,37 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
sbuf_push(buf, 0, "\n");
- if (r->subtlv_len && r->subtlvs)
- mpls_te_print_detail(buf, indent + 2, r->subtlvs,
- r->subtlv_len);
+ if (r->subtlvs)
+ format_item_ext_subtlvs(r->subtlvs, buf, indent + 2, mtid);
}
static void free_item_extended_reach(struct isis_item *i)
{
struct isis_extended_reach *item = (struct isis_extended_reach *)i;
- XFREE(MTYPE_ISIS_TLV, item->subtlvs);
+ if (item->subtlvs != NULL)
+ free_item_ext_subtlvs(item->subtlvs);
XFREE(MTYPE_ISIS_TLV, item);
}
static int pack_item_extended_reach(struct isis_item *i, struct stream *s)
{
struct isis_extended_reach *r = (struct isis_extended_reach *)i;
+ size_t len;
+ size_t len_pos;
- if (STREAM_WRITEABLE(s) < 11 + (unsigned)r->subtlv_len)
+ if (STREAM_WRITEABLE(s) < 11 + ISIS_SUBTLV_MAX_SIZE)
return 1;
+
stream_put(s, r->id, sizeof(r->id));
stream_put3(s, r->metric);
- stream_putc(s, r->subtlv_len);
- stream_put(s, r->subtlvs, r->subtlv_len);
+ len_pos = stream_get_endp(s);
+ /* Real length will be adjust after adding subTLVs */
+ stream_putc(s, 11);
+ if (r->subtlvs)
+ pack_item_ext_subtlvs(r->subtlvs, s);
+ /* Adjust length */
+ len = stream_get_endp(s) - len_pos - 1;
+ stream_putc_at(s, len_pos, len);
return 0;
}
@@ -780,9 +1469,6 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
rv->metric = stream_get3(s);
subtlv_len = stream_getc(s);
- format_item_extended_reach(mtid, (struct isis_item *)rv, log,
- indent + 2);
-
if ((size_t)len < ((size_t)11) + subtlv_len) {
sbuf_push(log, indent,
"Not enough data left for subtlv size %" PRIu8
@@ -795,20 +1481,14 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
subtlv_len);
if (subtlv_len) {
- size_t subtlv_start = stream_get_getp(s);
-
- if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_NE_REACH, subtlv_len, s,
- log, NULL, indent + 4, NULL)) {
+ if (unpack_item_ext_subtlvs(mtid, subtlv_len, s, log, rv,
+ indent + 4)) {
goto out;
}
-
- stream_set_getp(s, subtlv_start);
-
- rv->subtlvs = XCALLOC(MTYPE_ISIS_TLV, subtlv_len);
- stream_get(rv->subtlvs, s, subtlv_len);
- rv->subtlv_len = subtlv_len;
}
+ format_item_extended_reach(mtid, (struct isis_item *)rv, log,
+ indent + 2);
append_item(items, (struct isis_item *)rv);
return 0;
out:
@@ -1257,6 +1937,7 @@ static struct isis_item *copy_item_extended_ip_reach(struct isis_item *i)
rv->metric = r->metric;
rv->down = r->down;
rv->prefix = r->prefix;
+ rv->subtlvs = copy_subtlvs(r->subtlvs);
return (struct isis_item *)rv;
}
@@ -1348,7 +2029,7 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
rv->prefix.family = AF_INET;
rv->prefix.prefixlen = control & 0x3f;
if (rv->prefix.prefixlen > 32) {
- sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv4\n",
+ sbuf_push(log, indent, "Prefixlen %u is implausible for IPv4\n",
rv->prefix.prefixlen);
goto out;
}
@@ -1834,7 +2515,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
rv->prefix.family = AF_INET6;
rv->prefix.prefixlen = stream_getc(s);
if (rv->prefix.prefixlen > 128) {
- sbuf_push(log, indent, "Prefixlen %u is inplausible for IPv6\n",
+ sbuf_push(log, indent, "Prefixlen %u is implausible for IPv6\n",
rv->prefix.prefixlen);
goto out;
}
@@ -1848,6 +2529,7 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
}
stream_get(&rv->prefix.prefix.s6_addr, s, PSIZE(rv->prefix.prefixlen));
struct in6_addr orig_prefix = rv->prefix.prefix;
+
apply_mask_ipv6(&rv->prefix);
if (memcmp(&orig_prefix, &rv->prefix.prefix, sizeof(orig_prefix)))
sbuf_push(log, indent + 2,
@@ -1898,6 +2580,222 @@ out:
return 1;
}
+/* Functions related to TLV 242 Router Capability */
+static struct isis_router_cap *copy_tlv_router_cap(
+ const struct isis_router_cap *router_cap)
+{
+ struct isis_router_cap *rv = XMALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ if (!router_cap)
+ return NULL;
+
+ memcpy(rv, router_cap, sizeof(*rv));
+
+ return rv;
+}
+
+static void format_tlv_router_cap(const struct isis_router_cap *router_cap,
+ struct sbuf *buf, int indent)
+{
+ char addrbuf[INET_ADDRSTRLEN];
+
+ if (!router_cap)
+ return;
+
+ /* Router ID and Flags */
+ inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "Router Capability:");
+ sbuf_push(buf, indent, " %s , D:%c, S:%c\n", addrbuf,
+ router_cap->flags & ISIS_ROUTER_CAP_FLAG_D ? '1' : '0',
+ router_cap->flags & ISIS_ROUTER_CAP_FLAG_S ? '1' : '0');
+
+ /* SR Global Block */
+ if (router_cap->srgb.range_size != 0)
+ sbuf_push(buf, indent,
+ " Segment Routing: I:%s V:%s, SRGB Base: %d Range: %d\n",
+ IS_SR_IPV4(router_cap->srgb) ? "1" : "0",
+ IS_SR_IPV6(router_cap->srgb) ? "1" : "0",
+ router_cap->srgb.lower_bound,
+ router_cap->srgb.range_size);
+
+ /* SR Algorithms */
+ if (router_cap->algo[0] != SR_ALGORITHM_UNSET) {
+ sbuf_push(buf, indent, " Algorithm: %s",
+ router_cap->algo[0] == 0 ? "0: SPF"
+ : "0: Strict SPF");
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+ if (router_cap->algo[i] != SR_ALGORITHM_UNSET)
+ sbuf_push(buf, indent, " %s",
+ router_cap->algo[1] == 0
+ ? "0: SPF"
+ : "0: Strict SPF");
+ sbuf_push(buf, indent, "\n");
+ }
+
+ /* SR Node MSSD */
+ if (router_cap->msd != 0)
+ sbuf_push(buf, indent, " Node MSD: %d\n", router_cap->msd);
+}
+
+static void free_tlv_router_cap(struct isis_router_cap *router_cap)
+{
+ XFREE(MTYPE_ISIS_TLV, router_cap);
+}
+
+static int pack_tlv_router_cap(const struct isis_router_cap *router_cap,
+ struct stream *s)
+{
+ size_t tlv_len = ISIS_ROUTER_CAP_SIZE;
+ size_t len_pos;
+ uint8_t nb_algo;
+
+ if (!router_cap)
+ return 0;
+
+ /* Compute Maximum TLV size */
+ tlv_len += ISIS_SUBTLV_SID_LABEL_RANGE_SIZE
+ + ISIS_SUBTLV_HDR_SIZE
+ + ISIS_SUBTLV_ALGORITHM_SIZE
+ + ISIS_SUBTLV_NODE_MSD_SIZE;
+
+ if (STREAM_WRITEABLE(s) < (unsigned int)(2 + tlv_len))
+ return 1;
+
+ /* Add Router Capability TLV 242 with Router ID and Flags */
+ stream_putc(s, ISIS_TLV_ROUTER_CAPABILITY);
+ /* Real length will be adjusted later */
+ len_pos = stream_get_endp(s);
+ stream_putc(s, tlv_len);
+ stream_put_ipv4(s, router_cap->router_id.s_addr);
+ stream_putc(s, router_cap->flags);
+
+ /* Add SRGB if set */
+ if ((router_cap->srgb.range_size != 0)
+ && (router_cap->srgb.lower_bound != 0)) {
+ stream_putc(s, ISIS_SUBTLV_SID_LABEL_RANGE);
+ stream_putc(s, ISIS_SUBTLV_SID_LABEL_RANGE_SIZE);
+ stream_putc(s, router_cap->srgb.flags);
+ stream_put3(s, router_cap->srgb.range_size);
+ stream_putc(s, ISIS_SUBTLV_SID_LABEL);
+ stream_putc(s, ISIS_SUBTLV_SID_LABEL_SIZE);
+ stream_put3(s, router_cap->srgb.lower_bound);
+
+ /* Then SR Algorithm if set */
+ for (nb_algo = 0; nb_algo < SR_ALGORITHM_COUNT; nb_algo++)
+ if (router_cap->algo[nb_algo] == SR_ALGORITHM_UNSET)
+ break;
+ if (nb_algo > 0) {
+ stream_putc(s, ISIS_SUBTLV_ALGORITHM);
+ stream_putc(s, nb_algo);
+ for (int i = 0; i < nb_algo; i++)
+ stream_putc(s, router_cap->algo[i]);
+ }
+ /* And finish with MSD if set */
+ if (router_cap->msd != 0) {
+ stream_putc(s, ISIS_SUBTLV_NODE_MSD);
+ stream_putc(s, ISIS_SUBTLV_NODE_MSD_SIZE);
+ stream_putc(s, MSD_TYPE_BASE_MPLS_IMPOSITION);
+ stream_putc(s, router_cap->msd);
+ }
+ }
+
+ /* Adjust TLV length which depends on subTLVs presence */
+ tlv_len = stream_get_endp(s) - len_pos - 1;
+ stream_putc_at(s, len_pos, tlv_len);
+
+ return 0;
+}
+
+static int unpack_tlv_router_cap(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;
+ uint8_t type;
+ uint8_t length;
+ uint8_t subtlv_len;
+ uint8_t sid_len;
+
+ sbuf_push(log, indent, "Unpacking Router Capability TLV...\n");
+ if (tlv_len < ISIS_ROUTER_CAP_SIZE) {
+ sbuf_push(log, indent, "WARNING: Unexpected TLV size\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ if (tlvs->router_cap) {
+ sbuf_push(log, indent,
+ "WARNING: Router Capability TLV present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ /* Allocate router cap structure and initialize SR Algorithms */
+ tlvs->router_cap = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->router_cap));
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
+ tlvs->router_cap->algo[i] = SR_ALGORITHM_UNSET;
+
+ /* Get Router ID and Flags */
+ tlvs->router_cap->router_id.s_addr = stream_get_ipv4(s);
+ tlvs->router_cap->flags = stream_getc(s);
+
+ /* Parse remaining part of the TLV if present */
+ subtlv_len = tlv_len - ISIS_ROUTER_CAP_SIZE;
+ while (subtlv_len > 2) {
+ struct isis_router_cap *rc = tlvs->router_cap;
+ uint8_t msd_type;
+
+ type = stream_getc(s);
+ length = stream_getc(s);
+ switch (type) {
+ case ISIS_SUBTLV_SID_LABEL_RANGE:
+ rc->srgb.flags = stream_getc(s);
+ rc->srgb.range_size = stream_get3(s);
+ /* Skip Type and get Length of SID Label */
+ stream_getc(s);
+ sid_len = stream_getc(s);
+ if (sid_len == ISIS_SUBTLV_SID_LABEL_SIZE)
+ rc->srgb.lower_bound = stream_get3(s);
+ else
+ rc->srgb.lower_bound = stream_getl(s);
+
+ /* SRGB sanity checks. */
+ if (rc->srgb.range_size == 0
+ || (rc->srgb.lower_bound <= MPLS_LABEL_RESERVED_MAX)
+ || ((rc->srgb.lower_bound + rc->srgb.range_size - 1)
+ > MPLS_LABEL_UNRESERVED_MAX)) {
+ sbuf_push(log, indent, "Invalid label range. Reset SRGB\n");
+ rc->srgb.lower_bound = 0;
+ rc->srgb.range_size = 0;
+ }
+ break;
+ case ISIS_SUBTLV_ALGORITHM:
+ /* Only 2 algorithms are supported: SPF & Strict SPF */
+ stream_get(&rc->algo, s,
+ length > SR_ALGORITHM_COUNT
+ ? SR_ALGORITHM_COUNT
+ : length);
+ if (length > SR_ALGORITHM_COUNT)
+ stream_forward_getp(
+ s, length - SR_ALGORITHM_COUNT);
+ break;
+ case ISIS_SUBTLV_NODE_MSD:
+ msd_type = stream_getc(s);
+ rc->msd = stream_getc(s);
+ /* Only BMI-MSD type has been defined in RFC 8491 */
+ if (msd_type != MSD_TYPE_BASE_MPLS_IMPOSITION)
+ rc->msd = 0;
+ break;
+ default:
+ stream_forward_getp(s, length);
+ break;
+ }
+ subtlv_len = subtlv_len - length - 2;
+ }
+ return 0;
+}
+
/* Functions related to TLV 10 Authentication */
static struct isis_item *copy_item_auth(struct isis_item *i)
{
@@ -2318,6 +3216,39 @@ static void append_item(struct isis_item_list *dest, struct isis_item *item)
dest->count++;
}
+static void delete_item(struct isis_item_list *dest, struct isis_item *del)
+{
+ struct isis_item *item, *prev = NULL, *next;
+
+ /* Sanity Check */
+ if ((dest == NULL) || (del == NULL))
+ return;
+
+ /*
+ * TODO: delete is tricky because "dest" is a singly linked list.
+ * We need to switch a doubly linked list.
+ */
+ for (item = dest->head; item; item = next) {
+ if (item->next == del) {
+ prev = item;
+ break;
+ }
+ next = item->next;
+ }
+ if (prev)
+ prev->next = del->next;
+ if (dest->head == del)
+ dest->head = del->next;
+ if ((struct isis_item *)dest->tail == del) {
+ *dest->tail = prev;
+ if (prev)
+ dest->tail = &(*dest->tail)->next;
+ else
+ dest->tail = &dest->head;
+ }
+ dest->count--;
+}
+
static struct isis_item *last_item(struct isis_item_list *list)
{
return container_of(list->tail, struct isis_item, next);
@@ -2596,6 +3527,8 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
rv->threeway_adj = copy_tlv_threeway_adj(tlvs->threeway_adj);
+ rv->router_cap = copy_tlv_router_cap(tlvs->router_cap);
+
rv->spine_leaf = copy_tlv_spine_leaf(tlvs->spine_leaf);
return rv;
@@ -2631,6 +3564,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_router_cap(tlvs->router_cap, buf, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
&tlvs->extended_reach, buf, indent);
@@ -2717,6 +3651,7 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IPV6_REACH,
&tlvs->mt_ipv6_reach);
free_tlv_threeway_adj(tlvs->threeway_adj);
+ free_tlv_router_cap(tlvs->router_cap);
free_tlv_spine_leaf(tlvs->spine_leaf);
XFREE(MTYPE_ISIS_TLV, tlvs);
@@ -2897,6 +3832,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
fragment_tlvs->hostname =
copy_tlv_dynamic_hostname(tlvs->hostname);
+ rv = pack_tlv_router_cap(tlvs->router_cap, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ fragment_tlvs->router_cap =
+ copy_tlv_router_cap(tlvs->router_cap);
+ }
+
rv = pack_tlv_te_router_id(tlvs->te_router_id, stream);
if (rv)
return rv;
@@ -3131,6 +4074,7 @@ 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(ipv6_reach, "TLV 236 IPv6 Reachability");
+TLV_OPS(router_cap, "TLV 242 Router Capability");
ITEM_SUBTLV_OPS(prefix_sid, "Sub-TLV 3 SR Prefix-SID");
SUBTLV_OPS(ipv6_source_prefix, "Sub-TLV 22 IPv6 Source Prefix");
@@ -3144,21 +4088,22 @@ static const struct tlv_ops *tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
[ISIS_TLV_AUTH] = &tlv_auth_ops,
[ISIS_TLV_PURGE_ORIGINATOR] = &tlv_purge_originator_ops,
[ISIS_TLV_EXTENDED_REACH] = &tlv_extended_reach_ops,
- [ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
[ISIS_TLV_OLDSTYLE_IP_REACH] = &tlv_oldstyle_ip_reach_ops,
[ISIS_TLV_PROTOCOLS_SUPPORTED] = &tlv_protocols_supported_ops,
[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_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
- [ISIS_TLV_MT_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_THREE_WAY_ADJ] = &tlv_threeway_adj_ops,
[ISIS_TLV_IPV6_ADDRESS] = &tlv_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,
+ [ISIS_TLV_THREE_WAY_ADJ] = &tlv_threeway_adj_ops,
+ [ISIS_TLV_ROUTER_CAPABILITY] = &tlv_router_cap_ops,
},
[ISIS_CONTEXT_SUBTLV_NE_REACH] = {},
[ISIS_CONTEXT_SUBTLV_IP_REACH] = {
@@ -3593,6 +4538,18 @@ void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs,
tlvs->hostname = XSTRDUP(MTYPE_ISIS_TLV, hostname);
}
+/* Set Router Capability TLV parameters */
+void isis_tlvs_set_router_capability(struct isis_tlvs *tlvs,
+ const struct isis_router_cap *cap)
+{
+ XFREE(MTYPE_ISIS_TLV, tlvs->router_cap);
+ if (!cap)
+ return;
+
+ tlvs->router_cap = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->router_cap));
+ *tlvs->router_cap = *cap;
+}
+
void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
const struct in_addr *id)
{
@@ -3614,6 +4571,38 @@ void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
append_item(&tlvs->oldstyle_ip_reach, (struct isis_item *)r);
}
+void isis_tlvs_add_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_adj_sid *adj)
+{
+ append_item(&exts->adj_sid, (struct isis_item *)adj);
+ SET_SUBTLV(exts, EXT_ADJ_SID);
+}
+
+void isis_tlvs_del_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_adj_sid *adj)
+{
+ delete_item(&exts->adj_sid, (struct isis_item *)adj);
+ XFREE(MTYPE_ISIS_SUBTLV, adj);
+ if (exts->adj_sid.count == 0)
+ UNSET_SUBTLV(exts, EXT_ADJ_SID);
+}
+
+void isis_tlvs_add_lan_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_lan_adj_sid *lan)
+{
+ append_item(&exts->lan_sid, (struct isis_item *)lan);
+ SET_SUBTLV(exts, EXT_LAN_ADJ_SID);
+}
+
+void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_lan_adj_sid *lan)
+{
+ delete_item(&exts->lan_sid, (struct isis_item *)lan);
+ XFREE(MTYPE_ISIS_SUBTLV, lan);
+ if (exts->lan_sid.count == 0)
+ UNSET_SUBTLV(exts, EXT_LAN_ADJ_SID);
+}
+
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint32_t metric)
{
@@ -3668,17 +4657,14 @@ void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
uint8_t *id, uint32_t metric,
- uint8_t *subtlvs, uint8_t subtlv_len)
+ struct isis_ext_subtlvs *exts)
{
struct isis_extended_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
memcpy(r->id, id, sizeof(r->id));
r->metric = metric;
- if (subtlvs && subtlv_len) {
- r->subtlvs = XCALLOC(MTYPE_ISIS_TLV, subtlv_len);
- memcpy(r->subtlvs, subtlvs, subtlv_len);
- r->subtlv_len = subtlv_len;
- }
+ if (exts)
+ r->subtlvs = copy_item_ext_subtlvs(exts, mtid);
struct isis_item_list *l;
if (mtid == ISIS_MT_IPV4_UNICAST)
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 4954d791d8..2948728e2b 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -2,6 +2,8 @@
* IS-IS TLV Serializer/Deserializer
*
* Copyright (C) 2015,2017 Christian Franke
+
+ * Copyright (C) 2019 Olivier Dugeon - Orange Labs (for TE and SR)
*
* This file is part of FRR.
*
@@ -66,14 +68,14 @@ struct isis_lsp_entry {
};
struct isis_extended_reach;
+struct isis_ext_subtlvs;
struct isis_extended_reach {
struct isis_extended_reach *next;
uint8_t id[7];
uint32_t metric;
- uint8_t *subtlvs;
- uint8_t subtlv_len;
+ struct isis_ext_subtlvs *subtlvs;
};
struct isis_extended_ip_reach;
@@ -130,6 +132,95 @@ struct isis_threeway_adj {
uint32_t neighbor_circuit_id;
};
+/*
+ * Segment Routing subTLV's as per
+ * draft-ietf-isis-segment-routing-extension-25
+ */
+#define ISIS_SUBTLV_SRGB_FLAG_I 0x80
+#define ISIS_SUBTLV_SRGB_FLAG_V 0x40
+#define IS_SR_IPV4(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_I)
+#define IS_SR_IPV6(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_V)
+
+/* Structure aggregating SRGB info */
+struct isis_srgb {
+ uint8_t flags;
+ uint32_t range_size;
+ uint32_t lower_bound;
+};
+
+/* Prefix-SID sub-TLVs flags */
+#define ISIS_PREFIX_SID_READVERTISED 0x80
+#define ISIS_PREFIX_SID_NODE 0x40
+#define ISIS_PREFIX_SID_NO_PHP 0x20
+#define ISIS_PREFIX_SID_EXPLICIT_NULL 0x10
+#define ISIS_PREFIX_SID_VALUE 0x08
+#define ISIS_PREFIX_SID_LOCAL 0x04
+
+struct isis_prefix_sid;
+struct isis_prefix_sid {
+ struct isis_prefix_sid *next;
+
+ uint8_t flags;
+ uint8_t algorithm;
+ uint32_t value;
+};
+
+/* Adj-SID and LAN-Ajd-SID sub-TLVs flags */
+#define EXT_SUBTLV_LINK_ADJ_SID_FFLG 0x80
+#define EXT_SUBTLV_LINK_ADJ_SID_BFLG 0x40
+#define EXT_SUBTLV_LINK_ADJ_SID_VFLG 0x20
+#define EXT_SUBTLV_LINK_ADJ_SID_LFLG 0x10
+#define EXT_SUBTLV_LINK_ADJ_SID_SFLG 0x08
+#define EXT_SUBTLV_LINK_ADJ_SID_PFLG 0x04
+
+struct isis_adj_sid;
+struct isis_adj_sid {
+ struct isis_adj_sid *next;
+
+ uint8_t family;
+ uint8_t flags;
+ uint8_t weight;
+ uint32_t sid;
+};
+
+struct isis_lan_adj_sid;
+struct isis_lan_adj_sid {
+ struct isis_lan_adj_sid *next;
+
+ uint8_t family;
+ uint8_t flags;
+ uint8_t weight;
+ uint8_t neighbor_id[ISIS_SYS_ID_LEN];
+ uint32_t sid;
+};
+
+/* RFC 4971 & RFC 7981 */
+#define ISIS_ROUTER_CAP_FLAG_S 0x01
+#define ISIS_ROUTER_CAP_FLAG_D 0x02
+#define ISIS_ROUTER_CAP_SIZE 5
+
+/* Number of supported algorithm for Segment Routing.
+ * Right now only 2 have been standardized:
+ * - 0: SPF
+ * - 1: Strict SPF
+ */
+#define SR_ALGORITHM_COUNT 2
+#define SR_ALGORITHM_SPF 0
+#define SR_ALGORITHM_STRICT_SPF 1
+#define SR_ALGORITHM_UNSET 255
+
+struct isis_router_cap {
+ struct in_addr router_id;
+ uint8_t flags;
+
+ /* draft-ietf-segment-routing-extensions-25 */
+ struct isis_srgb srgb;
+ uint8_t algo[SR_ALGORITHM_COUNT];
+ /* RFC 8491 */
+#define MSD_TYPE_BASE_MPLS_IMPOSITION 0x01
+ uint8_t msd;
+};
+
struct isis_item;
struct isis_item {
struct isis_item *next;
@@ -233,26 +324,10 @@ struct isis_tlvs {
struct isis_item_list ipv6_reach;
struct isis_mt_item_list mt_ipv6_reach;
struct isis_threeway_adj *threeway_adj;
+ struct isis_router_cap *router_cap;
struct isis_spine_leaf *spine_leaf;
};
-#define ISIS_PREFIX_SID_READVERTISED 0x80
-#define ISIS_PREFIX_SID_NODE 0x40
-#define ISIS_PREFIX_SID_NO_PHP 0x20
-#define ISIS_PREFIX_SID_EXPLICIT_NULL 0x10
-#define ISIS_PREFIX_SID_VALUE 0x08
-#define ISIS_PREFIX_SID_LOCAL 0x04
-
-struct isis_prefix_sid;
-struct isis_prefix_sid {
- struct isis_prefix_sid *next;
-
- uint8_t flags;
- uint8_t algorithm;
-
- uint32_t value;
-};
-
enum isis_tlv_context {
ISIS_CONTEXT_LSP,
ISIS_CONTEXT_SUBTLV_NE_REACH,
@@ -266,11 +341,12 @@ struct isis_subtlvs {
/* draft-baker-ipv6-isis-dst-src-routing-06 */
struct prefix_ipv6 *source_prefix;
- /* draft-ietf-isis-segment-routing-extensions-16 */
+ /* draft-ietf-isis-segment-routing-extensions-25 */
struct isis_item_list prefix_sids;
};
enum isis_tlv_type {
+ /* TLVs code point */
ISIS_TLV_AREA_ADDRESSES = 1,
ISIS_TLV_OLDSTYLE_REACH = 2,
ISIS_TLV_LAN_NEIGHBORS = 6,
@@ -295,10 +371,149 @@ enum isis_tlv_type {
ISIS_TLV_IPV6_REACH = 236,
ISIS_TLV_MT_IPV6_REACH = 237,
ISIS_TLV_THREE_WAY_ADJ = 240,
+ ISIS_TLV_ROUTER_CAPABILITY = 242,
ISIS_TLV_MAX = 256,
+ /* subTLVs code point */
+ ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22,
+
+ /* RFC 5305 & RFC 6119 */
+ ISIS_SUBTLV_ADMIN_GRP = 3,
+ ISIS_SUBTLV_LOCAL_IPADDR = 6,
+ ISIS_SUBTLV_RMT_IPADDR = 8,
+ ISIS_SUBTLV_MAX_BW = 9,
+ ISIS_SUBTLV_MAX_RSV_BW = 10,
+ ISIS_SUBTLV_UNRSV_BW = 11,
+ ISIS_SUBTLV_LOCAL_IPADDR6 = 12,
+ ISIS_SUBTLV_RMT_IPADDR6 = 13,
+ ISIS_SUBTLV_TE_METRIC = 18,
+
+ /* RFC 5307 */
+ ISIS_SUBTLV_LLRI = 4,
+
+ /* RFC 5316 */
+ ISIS_SUBTLV_RAS = 24,
+ ISIS_SUBTLV_RIP = 25,
+
+ /* draft-isis-segment-routing-extension-25 */
+ ISIS_SUBTLV_SID_LABEL = 1,
+ ISIS_SUBTLV_SID_LABEL_RANGE = 2,
+ ISIS_SUBTLV_ALGORITHM = 19,
+ ISIS_SUBTLV_NODE_MSD = 23,
ISIS_SUBTLV_PREFIX_SID = 3,
- ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
+ ISIS_SUBTLV_ADJ_SID = 31,
+ ISIS_SUBTLV_LAN_ADJ_SID = 32,
+
+ /* RFC 7810 */
+ ISIS_SUBTLV_AV_DELAY = 33,
+ ISIS_SUBTLV_MM_DELAY = 34,
+ ISIS_SUBTLV_DELAY_VAR = 35,
+ ISIS_SUBTLV_PKT_LOSS = 36,
+ ISIS_SUBTLV_RES_BW = 37,
+ ISIS_SUBTLV_AVA_BW = 38,
+ ISIS_SUBTLV_USE_BW = 39,
+
+ ISIS_SUBTLV_MAX = 40
+};
+
+/* subTLVs size for TE and SR */
+enum ext_subtlv_size {
+ ISIS_SUBTLV_LLRI_SIZE = 8,
+
+ ISIS_SUBTLV_UNRSV_BW_SIZE = 32,
+ ISIS_SUBTLV_TE_METRIC_SIZE = 3,
+ ISIS_SUBTLV_IPV6_ADDR_SIZE = 16,
+
+ /* draft-isis-segment-routing-extension-25 */
+ ISIS_SUBTLV_SID_LABEL_SIZE = 3,
+ ISIS_SUBTLV_SID_LABEL_RANGE_SIZE = 9,
+ ISIS_SUBTLV_ALGORITHM_SIZE = 4,
+ ISIS_SUBTLV_NODE_MSD_SIZE = 2,
+ ISIS_SUBTLV_ADJ_SID_SIZE = 5,
+ ISIS_SUBTLV_LAN_ADJ_SID_SIZE = 11,
+ ISIS_SUBTLV_PREFIX_SID_SIZE = 5,
+
+ ISIS_SUBTLV_MM_DELAY_SIZE = 8,
+
+ ISIS_SUBTLV_HDR_SIZE = 2,
+ ISIS_SUBTLV_DEF_SIZE = 4,
+
+ ISIS_SUBTLV_MAX_SIZE = 180
+};
+
+/* Macros to manage the optional presence of EXT subTLVs */
+#define SET_SUBTLV(s, t) ((s->status) |= (t))
+#define UNSET_SUBTLV(s, t) ((s->status) &= ~(t))
+#define IS_SUBTLV(s, t) (s->status & t)
+
+#define EXT_DISABLE 0x000000
+#define EXT_ADM_GRP 0x000001
+#define EXT_LLRI 0x000002
+#define EXT_LOCAL_ADDR 0x000004
+#define EXT_NEIGH_ADDR 0x000008
+#define EXT_LOCAL_ADDR6 0x000010
+#define EXT_NEIGH_ADDR6 0x000020
+#define EXT_MAX_BW 0x000040
+#define EXT_MAX_RSV_BW 0x000080
+#define EXT_UNRSV_BW 0x000100
+#define EXT_TE_METRIC 0x000200
+#define EXT_RMT_AS 0x000400
+#define EXT_RMT_IP 0x000800
+#define EXT_ADJ_SID 0x001000
+#define EXT_LAN_ADJ_SID 0x002000
+#define EXT_DELAY 0x004000
+#define EXT_MM_DELAY 0x008000
+#define EXT_DELAY_VAR 0x010000
+#define EXT_PKT_LOSS 0x020000
+#define EXT_RES_BW 0x040000
+#define EXT_AVA_BW 0x080000
+#define EXT_USE_BW 0x100000
+
+/*
+ * This structure groups all Extended IS Reachability subTLVs.
+ *
+ * Each bit of the status field indicates if a subTLVs is valid or not.
+ * SubTLVs values use following units:
+ * - Bandwidth in bytes/sec following IEEE format,
+ * - Delay in micro-seconds with only 24 bits significant
+ * - Packet Loss in percentage of total traffic with only 24 bits (2^24 - 2)
+ *
+ * For Delay and packet Loss, upper bit (A) indicates if the value is
+ * normal (0) or anomalous (1).
+ */
+#define IS_ANORMAL(v) (v & 0x80000000)
+
+struct isis_ext_subtlvs {
+
+ uint32_t status;
+
+ uint32_t adm_group; /* Resource Class/Color - RFC 5305 */
+ /* Link Local/Remote Identifiers - RFC 5307 */
+ uint32_t local_llri;
+ uint32_t remote_llri;
+ struct in_addr local_addr; /* Local IP Address - RFC 5305 */
+ struct in_addr neigh_addr; /* Neighbor IP Address - RFC 5305 */
+ struct in6_addr local_addr6; /* Local IPv6 Address - RFC 6119 */
+ struct in6_addr neigh_addr6; /* Neighbor IPv6 Address - RFC 6119 */
+ float max_bw; /* Maximum Bandwidth - RFC 5305 */
+ float max_rsv_bw; /* Maximum Reservable Bandwidth - RFC 5305 */
+ float unrsv_bw[8]; /* Unreserved Bandwidth - RFC 5305 */
+ uint32_t te_metric; /* Traffic Engineering Metric - RFC 5305 */
+ uint32_t remote_as; /* Remote AS Number sub-TLV - RFC5316 */
+ struct in_addr remote_ip; /* IPv4 Remote ASBR ID Sub-TLV - RFC5316 */
+
+ uint32_t delay; /* Average Link Delay - RFC 8570 */
+ uint32_t min_delay; /* Low Link Delay - RFC 8570 */
+ uint32_t max_delay; /* High Link Delay - RFC 8570 */
+ uint32_t delay_var; /* Link Delay Variation i.e. Jitter - RFC 8570 */
+ uint32_t pkt_loss; /* Unidirectional Link Packet Loss - RFC 8570 */
+ float res_bw; /* Unidirectional Residual Bandwidth - RFC 8570 */
+ float ava_bw; /* Unidirectional Available Bandwidth - RFC 8570 */
+ float use_bw; /* Unidirectional Utilized Bandwidth - RFC 8570 */
+
+ /* Segment Routing Adjacency & LAN Adjacency Segment ID */
+ struct isis_item_list adj_sid;
+ struct isis_item_list lan_sid;
};
#define IS_COMPAT_MT_TLV(tlv_type) \
@@ -329,7 +544,6 @@ struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size);
#define ISIS_MT_AT_MASK 0x4000
#endif
-
void isis_tlvs_add_auth(struct isis_tlvs *tlvs, struct isis_passwd *passwd);
void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
@@ -359,6 +573,8 @@ void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id,
struct isis_lsp **last_lsp);
void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs,
const char *hostname);
+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_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
@@ -371,11 +587,21 @@ void isis_tlvs_add_ipv6_dstsrc_reach(struct isis_tlvs *tlvs, uint16_t mtid,
struct prefix_ipv6 *dest,
struct prefix_ipv6 *src,
uint32_t metric);
+struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void);
+void isis_tlvs_add_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_adj_sid *adj);
+void isis_tlvs_del_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_adj_sid *adj);
+void isis_tlvs_add_lan_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_lan_adj_sid *lan);
+void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
+ struct isis_lan_adj_sid *lan);
+
void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
uint8_t metric);
void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
uint8_t *id, uint32_t metric,
- uint8_t *subtlvs, uint8_t subtlv_len);
+ struct isis_ext_subtlvs *subtlvs);
const char *isis_threeway_state_name(enum isis_threeway_state state);
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index e8481a558b..39a2f6ef35 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -53,6 +53,8 @@
struct zclient *zclient = NULL;
+DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp))
+
/* Router-id update message from zebra. */
static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
{
@@ -82,6 +84,8 @@ static int isis_zebra_if_add(ZAPI_CALLBACK_ARGS)
isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
ifp);
+ hook_call(isis_if_new_hook, ifp);
+
return 0;
}
@@ -219,9 +223,9 @@ static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS)
return 0;
}
-static void isis_zebra_route_add_route(struct prefix *prefix,
- struct prefix_ipv6 *src_p,
- struct isis_route_info *route_info)
+void isis_zebra_route_add_route(struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
@@ -229,7 +233,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
struct listnode *node;
int count = 0;
- if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
+ if (zclient->sock < 0)
return;
memset(&api, 0, sizeof(api));
@@ -292,17 +296,15 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
api.nexthop_num = count;
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
- SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
- UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
-static void isis_zebra_route_del_route(struct prefix *prefix,
- struct prefix_ipv6 *src_p,
- struct isis_route_info *route_info)
+void isis_zebra_route_del_route(struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info)
{
struct zapi_route api;
- if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
+ if (zclient->sock < 0)
return;
memset(&api, 0, sizeof(api));
@@ -316,20 +318,6 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
}
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
- UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
-}
-
-void isis_zebra_route_update(struct prefix *prefix,
- struct prefix_ipv6 *src_p,
- struct isis_route_info *route_info)
-{
- if (zclient->sock < 0)
- return;
-
- if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
- isis_zebra_route_add_route(prefix, src_p, route_info);
- else
- isis_zebra_route_del_route(prefix, src_p, route_info);
}
static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h
index 20c10d0b23..83a32108eb 100644
--- a/isisd/isis_zebra.h
+++ b/isisd/isis_zebra.h
@@ -24,14 +24,19 @@
extern struct zclient *zclient;
+DECLARE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp));
+
void isis_zebra_init(struct thread_master *);
void isis_zebra_stop(void);
struct isis_route_info;
-void isis_zebra_route_update(struct prefix *prefix,
- struct prefix_ipv6 *src_p,
- struct isis_route_info *route_info);
+void isis_zebra_route_add_route(struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info);
+void isis_zebra_route_del_route(struct prefix *prefix,
+ struct prefix_ipv6 *src_p,
+ struct isis_route_info *route_info);
int isis_distribute_list_update(int routetype);
void isis_zebra_redistribute_set(afi_t afi, int type);
void isis_zebra_redistribute_unset(afi_t afi, int type);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 67f557ab50..029a9e0688 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -75,12 +75,13 @@ int clear_isis_neighbor_common(struct vty *, const char *id);
int isis_config_write(struct vty *);
-void isis_new(unsigned long process_id)
+void isis_new(unsigned long process_id, vrf_id_t vrf_id)
{
isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis));
/*
* Default values
*/
+ isis->vrf_id = vrf_id;
isis->max_area_addrs = 3;
isis->process_id = process_id;
isis->router_id = 0;
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 393b1d67c7..f825b6ecb4 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -58,11 +58,11 @@ extern struct zebra_privs_t isisd_privs;
/* uncomment if you are a developer in bug hunt */
/* #define EXTREME_DEBUG */
-/* #define EXTREME_DICT_DEBUG */
struct fabricd;
struct isis {
+ vrf_id_t vrf_id;
unsigned long process_id;
int sysid_set;
uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */
@@ -190,7 +190,7 @@ struct isis_area {
DECLARE_QOBJ_TYPE(isis_area)
void isis_init(void);
-void isis_new(unsigned long);
+void isis_new(unsigned long process_id, vrf_id_t vrf_id);
struct isis_area *isis_area_create(const char *);
struct isis_area *isis_area_lookup(const char *);
int isis_area_get(struct vty *vty, const char *area_tag);
diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c
index 7f2e396a7f..b234e3ebe3 100644
--- a/ldpd/l2vpn.c
+++ b/ldpd/l2vpn.c
@@ -249,7 +249,7 @@ l2vpn_pw_init(struct l2vpn_pw *pw)
l2vpn_pw_fec(pw, &fec);
lde_kernel_insert(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0,
- 0, (void *)pw);
+ 0, 0, (void *)pw);
lde_kernel_update(&fec);
}
@@ -260,7 +260,7 @@ l2vpn_pw_exit(struct l2vpn_pw *pw)
struct zapi_pw zpw;
l2vpn_pw_fec(pw, &fec);
- lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0);
+ lde_kernel_remove(&fec, AF_INET, (union ldpd_addr*)&pw->lsr_id, 0, 0, 0);
lde_kernel_update(&fec);
pw2zpw(pw, &zpw);
@@ -433,7 +433,7 @@ l2vpn_recv_pw_status(struct lde_nbr *ln, struct notify_msg *nm)
if (pw == NULL)
return;
- fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0);
+ fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id, 0, 0, 0);
if (fnh == NULL)
return;
@@ -482,7 +482,7 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
}
fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)&ln->id,
- 0, 0);
+ 0, 0, 0);
if (fnh == NULL)
continue;
diff --git a/ldpd/lde.c b/ldpd/lde.c
index ac680b47a9..006d27f6ab 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -520,7 +520,8 @@ lde_dispatch_parent(struct thread *thread)
switch (imsg.hdr.type) {
case IMSG_NETWORK_ADD:
lde_kernel_insert(&fec, kr->af, &kr->nexthop,
- kr->ifindex, kr->priority,
+ kr->ifindex, kr->route_type,
+ kr->route_instance,
kr->flags & F_CONNECTED, NULL);
break;
case IMSG_NETWORK_UPDATE:
@@ -747,7 +748,8 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
kr.ifindex = fnh->ifindex;
kr.local_label = fn->local_label;
kr.remote_label = fnh->remote_label;
- kr.priority = fnh->priority;
+ kr.route_type = fnh->route_type;
+ kr.route_instance = fnh->route_instance;
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
sizeof(kr));
@@ -761,7 +763,8 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
kr.ifindex = fnh->ifindex;
kr.local_label = fn->local_label;
kr.remote_label = fnh->remote_label;
- kr.priority = fnh->priority;
+ kr.route_type = fnh->route_type;
+ kr.route_instance = fnh->route_instance;
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
sizeof(kr));
@@ -798,7 +801,8 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
kr.ifindex = fnh->ifindex;
kr.local_label = fn->local_label;
kr.remote_label = fnh->remote_label;
- kr.priority = fnh->priority;
+ kr.route_type = fnh->route_type;
+ kr.route_instance = fnh->route_instance;
lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
sizeof(kr));
@@ -812,7 +816,8 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
kr.ifindex = fnh->ifindex;
kr.local_label = fn->local_label;
kr.remote_label = fnh->remote_label;
- kr.priority = fnh->priority;
+ kr.route_type = fnh->route_type;
+ kr.route_instance = fnh->route_instance;
lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
sizeof(kr));
diff --git a/ldpd/lde.h b/ldpd/lde.h
index 0a7d0a58fe..ce466c16b9 100644
--- a/ldpd/lde.h
+++ b/ldpd/lde.h
@@ -108,7 +108,8 @@ struct fec_nh {
union ldpd_addr nexthop;
ifindex_t ifindex;
uint32_t remote_label;
- uint8_t priority;
+ uint8_t route_type;
+ unsigned short route_instance;
uint8_t flags;
};
#define F_FEC_NH_NEW 0x01
@@ -193,11 +194,11 @@ void rt_dump(pid_t);
void fec_snap(struct lde_nbr *);
void fec_tree_clear(void);
struct fec_nh *fec_nh_find(struct fec_node *, int, union ldpd_addr *,
- ifindex_t, uint8_t);
+ ifindex_t, uint8_t, unsigned short);
void lde_kernel_insert(struct fec *, int, union ldpd_addr *,
- ifindex_t, uint8_t, int, void *);
+ ifindex_t, uint8_t, unsigned short, int, void *);
void lde_kernel_remove(struct fec *, int, union ldpd_addr *,
- ifindex_t, uint8_t);
+ ifindex_t, uint8_t, unsigned short);
void lde_kernel_update(struct fec *);
void lde_check_mapping(struct map *, struct lde_nbr *);
void lde_check_request(struct map *, struct lde_nbr *);
diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c
index 0957a5455e..eb1a6d9434 100644
--- a/ldpd/lde_lib.c
+++ b/ldpd/lde_lib.c
@@ -31,7 +31,7 @@ static int lde_nbr_is_nexthop(struct fec_node *,
static void fec_free(void *);
static struct fec_node *fec_add(struct fec *fec);
static struct fec_nh *fec_nh_add(struct fec_node *, int, union ldpd_addr *,
- ifindex_t, uint8_t);
+ ifindex_t, uint8_t, unsigned short);
static void fec_nh_del(struct fec_nh *);
RB_GENERATE(fec_tree, fec, entry, fec_compare)
@@ -275,7 +275,7 @@ fec_add(struct fec *fec)
struct fec_nh *
fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
- ifindex_t ifindex, uint8_t priority)
+ ifindex_t ifindex, uint8_t route_type, unsigned short route_instance)
{
struct fec_nh *fnh;
@@ -283,7 +283,8 @@ fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
if (fnh->af == af &&
ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 &&
fnh->ifindex == ifindex &&
- fnh->priority == priority)
+ fnh->route_type == route_type &&
+ fnh->route_instance == route_instance)
return (fnh);
return (NULL);
@@ -291,7 +292,7 @@ fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
static struct fec_nh *
fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
- ifindex_t ifindex, uint8_t priority)
+ ifindex_t ifindex, uint8_t route_type, unsigned short route_instance)
{
struct fec_nh *fnh;
@@ -303,7 +304,8 @@ fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
fnh->nexthop = *nexthop;
fnh->ifindex = ifindex;
fnh->remote_label = NO_LABEL;
- fnh->priority = priority;
+ fnh->route_type = route_type;
+ fnh->route_instance = route_instance;
LIST_INSERT_HEAD(&fn->nexthops, fnh, entry);
return (fnh);
@@ -318,7 +320,8 @@ fec_nh_del(struct fec_nh *fnh)
void
lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
- ifindex_t ifindex, uint8_t priority, int connected, void *data)
+ ifindex_t ifindex, uint8_t route_type, unsigned short route_instance,
+ int connected, void *data)
{
struct fec_node *fn;
struct fec_nh *fnh;
@@ -329,9 +332,10 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
if (data)
fn->data = data;
- fnh = fec_nh_find(fn, af, nexthop, ifindex, priority);
+ fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance);
if (fnh == NULL)
- fnh = fec_nh_add(fn, af, nexthop, ifindex, priority);
+ fnh = fec_nh_add(fn, af, nexthop, ifindex, route_type,
+ route_instance);
fnh->flags |= F_FEC_NH_NEW;
if (connected)
fnh->flags |= F_FEC_NH_CONNECTED;
@@ -339,7 +343,7 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
void
lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
- ifindex_t ifindex, uint8_t priority)
+ ifindex_t ifindex, uint8_t route_type, unsigned short route_instance)
{
struct fec_node *fn;
struct fec_nh *fnh;
@@ -348,7 +352,7 @@ lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
if (fn == NULL)
/* route lost */
return;
- fnh = fec_nh_find(fn, af, nexthop, ifindex, priority);
+ fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance);
if (fnh == NULL)
/* route lost */
return;
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 35a7d944d3..884ae159be 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -37,7 +37,7 @@
static void ifp2kif(struct interface *, struct kif *);
static void ifc2kaddr(struct interface *, struct connected *,
struct kaddr *);
-static int zebra_send_mpls_labels(int, struct kroute *);
+static int ldp_zebra_send_mpls_labels(int, struct kroute *);
static int ldp_router_id_update(ZAPI_CALLBACK_ARGS);
static int ldp_interface_add(ZAPI_CALLBACK_ARGS);
static int ldp_interface_delete(ZAPI_CALLBACK_ARGS);
@@ -106,9 +106,10 @@ pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw)
}
static int
-zebra_send_mpls_labels(int cmd, struct kroute *kr)
+ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
{
- struct stream *s;
+ struct zapi_labels zl = {};
+ struct zapi_nexthop_label *znh;
if (kr->local_label < MPLS_LABEL_RESERVED_MAX ||
kr->remote_label == NO_LABEL)
@@ -120,48 +121,65 @@ zebra_send_mpls_labels(int cmd, struct kroute *kr)
log_label(kr->local_label), log_label(kr->remote_label),
(cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete");
- /* Reset stream. */
- s = zclient->obuf;
- stream_reset(s);
+ zl.type = ZEBRA_LSP_LDP;
+ zl.local_label = kr->local_label;
- zclient_create_header(s, cmd, VRF_DEFAULT);
- stream_putc(s, ZEBRA_LSP_LDP);
- stream_putl(s, kr->af);
+ /* Set prefix. */
+ SET_FLAG(zl.message, ZAPI_LABELS_FTN);
+ zl.route.prefix.family = kr->af;
switch (kr->af) {
case AF_INET:
- stream_put_in_addr(s, &kr->prefix.v4);
- stream_putc(s, kr->prefixlen);
- stream_put_in_addr(s, &kr->nexthop.v4);
+ zl.route.prefix.u.prefix4 = kr->prefix.v4;
break;
case AF_INET6:
- stream_write(s, (uint8_t *)&kr->prefix.v6, 16);
- stream_putc(s, kr->prefixlen);
- stream_write(s, (uint8_t *)&kr->nexthop.v6, 16);
+ zl.route.prefix.u.prefix6 = kr->prefix.v6;
break;
default:
- fatalx("kr_change: unknown af");
+ fatalx("ldp_zebra_send_mpls_labels: unknown af");
}
- stream_putl(s, kr->ifindex);
- stream_putc(s, kr->priority);
- stream_putl(s, kr->local_label);
- stream_putl(s, kr->remote_label);
+ zl.route.prefix.prefixlen = kr->prefixlen;
+ zl.route.type = kr->route_type;
+ zl.route.instance = kr->route_instance;
- /* Put length at the first point of the stream. */
- stream_putw_at(s, 0, stream_get_endp(s));
+ /* Set nexthop. */
+ zl.nexthop_num = 1;
+ znh = &zl.nexthops[0];
+ switch (kr->af) {
+ case AF_INET:
+ znh->family = AF_INET;
+ znh->address.ipv4 = kr->nexthop.v4;
+ if (kr->ifindex)
+ znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ else
+ znh->type = NEXTHOP_TYPE_IPV4;
+ break;
+ case AF_INET6:
+ znh->family = AF_INET6;
+ znh->address.ipv6 = kr->nexthop.v6;
+ if (kr->ifindex)
+ znh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+ else
+ znh->type = NEXTHOP_TYPE_IPV6;
+ break;
+ default:
+ break;
+ }
+ znh->ifindex = kr->ifindex;
+ znh->label = kr->remote_label;
- return (zclient_send_message(zclient));
+ return zebra_send_mpls_labels(zclient, cmd, &zl);
}
int
kr_change(struct kroute *kr)
{
- return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr));
+ return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr));
}
int
kr_delete(struct kroute *kr)
{
- return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr));
+ return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr));
}
int
@@ -407,7 +425,8 @@ ldp_zebra_read_route(ZAPI_CALLBACK_ARGS)
break;
}
kr.prefixlen = api.prefix.prefixlen;
- kr.priority = api.distance;
+ kr.route_type = api.type;
+ kr.route_instance = api.instance;
switch (api.type) {
case ZEBRA_ROUTE_CONNECT:
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index 9113505581..bd7562e5ad 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -543,7 +543,8 @@ struct kroute {
uint32_t local_label;
uint32_t remote_label;
unsigned short ifindex;
- uint8_t priority;
+ uint8_t route_type;
+ uint8_t route_instance;
uint16_t flags;
};
diff --git a/lib/command.c b/lib/command.c
index eecca2a5f5..04f2bd95a0 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1718,16 +1718,12 @@ static int vty_write_config(struct vty *vty)
vty_out(vty, "frr defaults %s\n", DFLT_NAME);
vty_out(vty, "!\n");
- pthread_rwlock_rdlock(&running_config->lock);
- {
- for (i = 0; i < vector_active(cmdvec); i++)
- if ((node = vector_slot(cmdvec, i)) && node->func
- && (node->vtysh || vty->type != VTY_SHELL)) {
- if ((*node->func)(vty))
- vty_out(vty, "!\n");
- }
- }
- pthread_rwlock_unlock(&running_config->lock);
+ for (i = 0; i < vector_active(cmdvec); i++)
+ if ((node = vector_slot(cmdvec, i)) && node->func
+ && (node->vtysh || vty->type != VTY_SHELL)) {
+ if ((*node->func)(vty))
+ vty_out(vty, "!\n");
+ }
if (vty->type == VTY_TERM) {
vty_out(vty, "end\n");
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index 21dfc9256f..5c71fac10a 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -35,6 +35,9 @@ DEFINE_MTYPE_STATIC(LIB, PTHREAD_PRIM, "POSIX sync primitives")
static void *fpt_run(void *arg);
static int fpt_halt(struct frr_pthread *fpt, void **res);
+/* misc sigs */
+static void frr_pthread_destroy_nolock(struct frr_pthread *fpt);
+
/* default frr_pthread attributes */
struct frr_pthread_attr frr_pthread_attr_default = {
.start = fpt_run,
@@ -51,13 +54,22 @@ void frr_pthread_init(void)
{
frr_with_mutex(&frr_pthread_list_mtx) {
frr_pthread_list = list_new();
- frr_pthread_list->del = (void (*)(void *))&frr_pthread_destroy;
}
}
void frr_pthread_finish(void)
{
+ frr_pthread_stop_all();
+
frr_with_mutex(&frr_pthread_list_mtx) {
+ struct listnode *n, *nn;
+ struct frr_pthread *fpt;
+
+ for (ALL_LIST_ELEMENTS(frr_pthread_list, n, nn, fpt)) {
+ listnode_delete(frr_pthread_list, fpt);
+ frr_pthread_destroy_nolock(fpt);
+ }
+
list_delete(&frr_pthread_list);
}
}
@@ -97,10 +109,9 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
return fpt;
}
-void frr_pthread_destroy(struct frr_pthread *fpt)
+static void frr_pthread_destroy_nolock(struct frr_pthread *fpt)
{
thread_master_free(fpt->master);
-
pthread_mutex_destroy(&fpt->mtx);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
@@ -110,6 +121,15 @@ void frr_pthread_destroy(struct frr_pthread *fpt)
XFREE(MTYPE_FRR_PTHREAD, fpt);
}
+void frr_pthread_destroy(struct frr_pthread *fpt)
+{
+ frr_with_mutex(&frr_pthread_list_mtx) {
+ listnode_delete(frr_pthread_list, fpt);
+ }
+
+ frr_pthread_destroy_nolock(fpt);
+}
+
int frr_pthread_set_name(struct frr_pthread *fpt)
{
int ret = 0;
@@ -183,8 +203,11 @@ void frr_pthread_stop_all(void)
frr_with_mutex(&frr_pthread_list_mtx) {
struct listnode *n;
struct frr_pthread *fpt;
- for (ALL_LIST_ELEMENTS_RO(frr_pthread_list, n, fpt))
- frr_pthread_stop(fpt, NULL);
+ for (ALL_LIST_ELEMENTS_RO(frr_pthread_list, n, fpt)) {
+ if (atomic_load_explicit(&fpt->running,
+ memory_order_relaxed))
+ frr_pthread_stop(fpt, NULL);
+ }
}
}
diff --git a/lib/if.c b/lib/if.c
index 5f92327562..1e34ff4b84 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -207,21 +207,18 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (yang_module_find("frr-interface")) {
struct lyd_node *if_dnode;
- pthread_rwlock_wrlock(&running_config->lock);
- {
- if_dnode = yang_dnode_get(
- running_config->dnode,
- "/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
- ifp->name, old_vrf->name);
- if (if_dnode) {
- yang_dnode_change_leaf(if_dnode, vrf->name);
- running_config->version++;
- }
+ if_dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
+ ifp->name, old_vrf->name);
+ if (if_dnode) {
+ yang_dnode_change_leaf(if_dnode, vrf->name);
+ running_config->version++;
}
- pthread_rwlock_unlock(&running_config->lock);
}
}
+
/* Delete interface structure. */
void if_delete_retain(struct interface *ifp)
{
@@ -1461,6 +1458,60 @@ static int lib_interface_destroy(enum nb_event event,
}
/*
+ * XPath: /frr-interface:lib/interface
+ */
+static const void *lib_interface_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct vrf *vrf;
+ struct interface *pif = (struct interface *)list_entry;
+
+ if (list_entry == NULL) {
+ vrf = RB_MIN(vrf_name_head, &vrfs_by_name);
+ assert(vrf);
+ pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
+ } else {
+ vrf = vrf_lookup_by_id(pif->vrf_id);
+ pif = RB_NEXT(if_name_head, pif);
+ /* if no more interfaces, switch to next vrf */
+ while (pif == NULL) {
+ vrf = RB_NEXT(vrf_name_head, vrf);
+ if (!vrf)
+ return NULL;
+ pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
+ }
+ }
+
+ return pif;
+}
+
+static int lib_interface_get_keys(const void *list_entry,
+ struct yang_list_keys *keys)
+{
+ const struct interface *ifp = list_entry;
+
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
+ assert(vrf);
+
+ keys->num = 2;
+ strlcpy(keys->key[0], ifp->name, sizeof(keys->key[0]));
+ strlcpy(keys->key[1], vrf->name, sizeof(keys->key[1]));
+
+ return NB_OK;
+}
+
+static const void *lib_interface_lookup_entry(const void *parent_list_entry,
+ const struct yang_list_keys *keys)
+{
+ const char *ifname = keys->key[0];
+ const char *vrfname = keys->key[1];
+ struct vrf *vrf = vrf_lookup_by_name(vrfname);
+
+ return if_lookup_by_name(ifname, vrf->vrf_id);
+}
+
+/*
* XPath: /frr-interface:lib/interface/description
*/
static int lib_interface_description_modify(enum nb_event event,
@@ -1505,6 +1556,9 @@ const struct frr_yang_module_info frr_interface_info = {
.create = lib_interface_create,
.destroy = lib_interface_destroy,
.cli_show = cli_show_interface,
+ .get_next = lib_interface_get_next,
+ .get_keys = lib_interface_get_keys,
+ .lookup_entry = lib_interface_lookup_entry,
},
},
{
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 4301dc20ad..d4aa1f899a 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -42,6 +42,7 @@
#include "northbound_db.h"
#include "debug.h"
#include "frrcu.h"
+#include "frr_pthread.h"
DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
DEFINE_KOOH(frr_early_fini, (), ())
@@ -681,6 +682,8 @@ struct thread_master *frr_init(void)
memory_init();
log_filter_cmd_init();
+ frr_pthread_init();
+
log_ref_init();
log_ref_vty_init();
lib_error_init();
@@ -865,12 +868,7 @@ static int frr_config_read_in(struct thread *t)
/*
* Update the shared candidate after reading the startup configuration.
*/
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_replace(vty_shared_candidate_config, running_config,
- true);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ nb_config_replace(vty_shared_candidate_config, running_config, true);
return 0;
}
@@ -1076,6 +1074,7 @@ void frr_fini(void)
db_close();
#endif
log_ref_fini();
+ frr_pthread_finish();
zprivs_terminate(di->privs);
/* signal_init -> nothing needed */
thread_master_free(master);
diff --git a/lib/log.c b/lib/log.c
index f1c0fabfba..c777868736 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1041,6 +1041,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS),
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
+ DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE),
DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC),
diff --git a/lib/mpls.h b/lib/mpls.h
index d7b56c47bd..635ecc77a1 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -47,6 +47,7 @@ extern "C" {
#define MPLS_LABEL_OAM_ALERT 14 /* [RFC3429] */
#define MPLS_LABEL_EXTENSION 15 /* [RFC7274] */
#define MPLS_LABEL_MAX 1048575
+#define MPLS_LABEL_VALUE_MASK 0x000FFFFF
#define MPLS_LABEL_NONE 0xFFFFFFFF /* for internal use only */
/* Minimum and maximum label values */
@@ -125,7 +126,7 @@ enum lsp_types_t {
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
ZEBRA_LSP_BGP = 3, /* BGP LSP. */
- ZEBRA_LSP_SR = 4, /* Segment Routing LSP. */
+ ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */
ZEBRA_LSP_SHARP = 5, /* Identifier for test protocol */
};
diff --git a/lib/northbound.c b/lib/northbound.c
index a814f23e14..1b332fb1e8 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -64,6 +64,9 @@ static bool transaction_in_progress;
static int nb_callback_configuration(const enum nb_event event,
struct nb_config_change *change);
+static void nb_log_callback(const enum nb_event event,
+ enum nb_operation operation, const char *xpath,
+ const char *value);
static struct nb_transaction *nb_transaction_new(struct nb_config *config,
struct nb_config_cbs *changes,
enum nb_client client,
@@ -180,7 +183,18 @@ static int nb_node_validate_cb(const struct nb_node *nb_node,
valid = nb_operation_is_valid(operation, nb_node->snode);
- if (!valid && callback_implemented)
+ /*
+ * Add an exception for operational data callbacks. A rw list usually
+ * doesn't need any associated operational data callbacks. But if this
+ * rw list is augmented by another module which adds state nodes under
+ * it, then this list will need to have the 'get_next()', 'get_keys()'
+ * and 'lookup_entry()' callbacks. As such, never log a warning when
+ * these callbacks are implemented when they are not needed, since this
+ * depends on context (e.g. some daemons might augment "frr-interface"
+ * while others don't).
+ */
+ if (!valid && callback_implemented && operation != NB_OP_GET_NEXT
+ && operation != NB_OP_GET_KEYS && operation != NB_OP_LOOKUP_ENTRY)
flog_warn(EC_LIB_NB_CB_UNNEEDED,
"unneeded '%s' callback for '%s'",
nb_operation_name(operation), nb_node->xpath);
@@ -211,6 +225,8 @@ static unsigned int nb_node_validate_cbs(const struct nb_node *nb_node)
!!nb_node->cbs.destroy, false);
error += nb_node_validate_cb(nb_node, NB_OP_MOVE, !!nb_node->cbs.move,
false);
+ error += nb_node_validate_cb(nb_node, NB_OP_PRE_VALIDATE,
+ !!nb_node->cbs.pre_validate, true);
error += nb_node_validate_cb(nb_node, NB_OP_APPLY_FINISH,
!!nb_node->cbs.apply_finish, true);
error += nb_node_validate_cb(nb_node, NB_OP_GET_ELEM,
@@ -265,7 +281,6 @@ struct nb_config *nb_config_new(struct lyd_node *dnode)
else
config->dnode = yang_dnode_new(ly_native_ctx, true);
config->version = 0;
- pthread_rwlock_init(&config->lock, NULL);
return config;
}
@@ -274,7 +289,6 @@ void nb_config_free(struct nb_config *config)
{
if (config->dnode)
yang_dnode_free(config->dnode);
- pthread_rwlock_destroy(&config->lock);
XFREE(MTYPE_NB_CONFIG, config);
}
@@ -285,7 +299,6 @@ struct nb_config *nb_config_dup(const struct nb_config *config)
dup = XCALLOC(MTYPE_NB_CONFIG, sizeof(*dup));
dup->dnode = yang_dnode_dup(config->dnode);
dup->version = config->version;
- pthread_rwlock_init(&dup->lock, NULL);
return dup;
}
@@ -335,21 +348,23 @@ static inline int nb_config_cb_compare(const struct nb_config_cb *a,
return 1;
/*
- * Use XPath as a tie-breaker. This will naturally sort parent nodes
- * before their children.
+ * Preserve the order of the configuration changes as told by libyang.
*/
- return strcmp(a->xpath, b->xpath);
+ return a->seq - b->seq;
}
RB_GENERATE(nb_config_cbs, nb_config_cb, entry, nb_config_cb_compare);
static void nb_config_diff_add_change(struct nb_config_cbs *changes,
enum nb_operation operation,
+ uint32_t *seq,
const struct lyd_node *dnode)
{
struct nb_config_change *change;
change = XCALLOC(MTYPE_TMP, sizeof(*change));
change->cb.operation = operation;
+ change->cb.seq = *seq;
+ *seq = *seq + 1;
change->cb.nb_node = dnode->schema->priv;
yang_dnode_get_path(dnode, change->cb.xpath, sizeof(change->cb.xpath));
change->cb.dnode = dnode;
@@ -374,7 +389,7 @@ static void nb_config_diff_del_changes(struct nb_config_cbs *changes)
* configurations. Given a new subtree, calculate all new YANG data nodes,
* excluding default leafs and leaf-lists. This is a recursive function.
*/
-static void nb_config_diff_created(const struct lyd_node *dnode,
+static void nb_config_diff_created(const struct lyd_node *dnode, uint32_t *seq,
struct nb_config_cbs *changes)
{
enum nb_operation operation;
@@ -393,16 +408,17 @@ static void nb_config_diff_created(const struct lyd_node *dnode,
else
return;
- nb_config_diff_add_change(changes, operation, dnode);
+ nb_config_diff_add_change(changes, operation, seq, dnode);
break;
case LYS_CONTAINER:
case LYS_LIST:
if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
- nb_config_diff_add_change(changes, NB_OP_CREATE, dnode);
+ nb_config_diff_add_change(changes, NB_OP_CREATE, seq,
+ dnode);
/* Process child nodes recursively. */
LY_TREE_FOR (dnode->child, child) {
- nb_config_diff_created(child, changes);
+ nb_config_diff_created(child, seq, changes);
}
break;
default:
@@ -410,11 +426,11 @@ static void nb_config_diff_created(const struct lyd_node *dnode,
}
}
-static void nb_config_diff_deleted(const struct lyd_node *dnode,
+static void nb_config_diff_deleted(const struct lyd_node *dnode, uint32_t *seq,
struct nb_config_cbs *changes)
{
if (nb_operation_is_valid(NB_OP_DESTROY, dnode->schema))
- nb_config_diff_add_change(changes, NB_OP_DESTROY, dnode);
+ nb_config_diff_add_change(changes, NB_OP_DESTROY, seq, dnode);
else if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER)) {
struct lyd_node *child;
@@ -425,7 +441,7 @@ static void nb_config_diff_deleted(const struct lyd_node *dnode,
* when applicable (i.e. optional nodes).
*/
LY_TREE_FOR (dnode->child, child) {
- nb_config_diff_deleted(child, changes);
+ nb_config_diff_deleted(child, seq, changes);
}
}
}
@@ -436,6 +452,7 @@ static void nb_config_diff(const struct nb_config *config1,
struct nb_config_cbs *changes)
{
struct lyd_difflist *diff;
+ uint32_t seq = 0;
diff = lyd_diff(config1->dnode, config2->dnode,
LYD_DIFFOPT_WITHDEFAULTS);
@@ -450,15 +467,16 @@ static void nb_config_diff(const struct nb_config *config1,
switch (type) {
case LYD_DIFF_CREATED:
dnode = diff->second[i];
- nb_config_diff_created(dnode, changes);
+ nb_config_diff_created(dnode, &seq, changes);
break;
case LYD_DIFF_DELETED:
dnode = diff->first[i];
- nb_config_diff_deleted(dnode, changes);
+ nb_config_diff_deleted(dnode, &seq, changes);
break;
case LYD_DIFF_CHANGED:
dnode = diff->second[i];
- nb_config_diff_add_change(changes, NB_OP_MODIFY, dnode);
+ nb_config_diff_add_change(changes, NB_OP_MODIFY, &seq,
+ dnode);
break;
case LYD_DIFF_MOVEDAFTER1:
case LYD_DIFF_MOVEDAFTER2:
@@ -535,28 +553,17 @@ int nb_candidate_edit(struct nb_config *candidate,
bool nb_candidate_needs_update(const struct nb_config *candidate)
{
- bool ret = false;
-
- pthread_rwlock_rdlock(&running_config->lock);
- {
- if (candidate->version < running_config->version)
- ret = true;
- }
- pthread_rwlock_unlock(&running_config->lock);
+ if (candidate->version < running_config->version)
+ return true;
- return ret;
+ return false;
}
int nb_candidate_update(struct nb_config *candidate)
{
struct nb_config *updated_config;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- updated_config = nb_config_dup(running_config);
- }
- pthread_rwlock_unlock(&running_config->lock);
-
+ updated_config = nb_config_dup(running_config);
if (nb_config_merge(updated_config, candidate, true) != NB_OK)
return NB_ERR;
@@ -583,14 +590,45 @@ static int nb_candidate_validate_yang(struct nb_config *candidate)
}
/* Perform code-level validation using the northbound callbacks. */
-static int nb_candidate_validate_changes(struct nb_config *candidate,
- struct nb_config_cbs *changes)
+static int nb_candidate_validate_code(struct nb_config *candidate,
+ struct nb_config_cbs *changes)
{
struct nb_config_cb *cb;
+ struct lyd_node *root, *next, *child;
+ int ret;
+
+ /* First validate the candidate as a whole. */
+ LY_TREE_FOR (candidate->dnode, root) {
+ LY_TREE_DFS_BEGIN (root, next, child) {
+ struct nb_node *nb_node;
+
+ nb_node = child->schema->priv;
+ if (!nb_node->cbs.pre_validate)
+ goto next;
+
+ if (DEBUG_MODE_CHECK(&nb_dbg_cbs_config,
+ DEBUG_MODE_ALL)) {
+ char xpath[XPATH_MAXLEN];
+
+ yang_dnode_get_path(child, xpath,
+ sizeof(xpath));
+ nb_log_callback(NB_EV_VALIDATE,
+ NB_OP_PRE_VALIDATE, xpath,
+ NULL);
+ }
+
+ ret = (*nb_node->cbs.pre_validate)(child);
+ if (ret != NB_OK)
+ return NB_ERR_VALIDATION;
+ next:
+ LY_TREE_DFS_END(root, next, child);
+ }
+ }
+
+ /* Now validate the configuration changes. */
RB_FOREACH (cb, nb_config_cbs, changes) {
struct nb_config_change *change = (struct nb_config_change *)cb;
- int ret;
ret = nb_callback_configuration(NB_EV_VALIDATE, change);
if (ret != NB_OK)
@@ -609,13 +647,9 @@ int nb_candidate_validate(struct nb_config *candidate)
return NB_ERR_VALIDATION;
RB_INIT(nb_config_cbs, &changes);
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_diff(running_config, candidate, &changes);
- ret = nb_candidate_validate_changes(candidate, &changes);
- nb_config_diff_del_changes(&changes);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ nb_config_diff(running_config, candidate, &changes);
+ ret = nb_candidate_validate_code(candidate, &changes);
+ nb_config_diff_del_changes(&changes);
return ret;
}
@@ -635,36 +669,26 @@ int nb_candidate_commit_prepare(struct nb_config *candidate,
}
RB_INIT(nb_config_cbs, &changes);
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_diff(running_config, candidate, &changes);
- if (RB_EMPTY(nb_config_cbs, &changes)) {
- pthread_rwlock_unlock(&running_config->lock);
- return NB_ERR_NO_CHANGES;
- }
+ nb_config_diff(running_config, candidate, &changes);
+ if (RB_EMPTY(nb_config_cbs, &changes))
+ return NB_ERR_NO_CHANGES;
- if (nb_candidate_validate_changes(candidate, &changes)
- != NB_OK) {
- flog_warn(
- EC_LIB_NB_CANDIDATE_INVALID,
- "%s: failed to validate candidate configuration",
- __func__);
- nb_config_diff_del_changes(&changes);
- pthread_rwlock_unlock(&running_config->lock);
- return NB_ERR_VALIDATION;
- }
+ if (nb_candidate_validate_code(candidate, &changes) != NB_OK) {
+ flog_warn(EC_LIB_NB_CANDIDATE_INVALID,
+ "%s: failed to validate candidate configuration",
+ __func__);
+ nb_config_diff_del_changes(&changes);
+ return NB_ERR_VALIDATION;
+ }
- *transaction = nb_transaction_new(candidate, &changes, client,
- user, comment);
- if (*transaction == NULL) {
- flog_warn(EC_LIB_NB_TRANSACTION_CREATION_FAILED,
- "%s: failed to create transaction", __func__);
- nb_config_diff_del_changes(&changes);
- pthread_rwlock_unlock(&running_config->lock);
- return NB_ERR_LOCKED;
- }
+ *transaction =
+ nb_transaction_new(candidate, &changes, client, user, comment);
+ if (*transaction == NULL) {
+ flog_warn(EC_LIB_NB_TRANSACTION_CREATION_FAILED,
+ "%s: failed to create transaction", __func__);
+ nb_config_diff_del_changes(&changes);
+ return NB_ERR_LOCKED;
}
- pthread_rwlock_unlock(&running_config->lock);
return nb_transaction_process(NB_EV_PREPARE, *transaction);
}
@@ -683,11 +707,7 @@ void nb_candidate_commit_apply(struct nb_transaction *transaction,
/* Replace running by candidate. */
transaction->config->version++;
- pthread_rwlock_wrlock(&running_config->lock);
- {
- nb_config_replace(running_config, transaction->config, true);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ nb_config_replace(running_config, transaction->config, true);
/* Record transaction. */
if (save_transaction
@@ -961,52 +981,40 @@ static int nb_transaction_process(enum nb_event event,
{
struct nb_config_cb *cb;
- /*
- * Need to lock the running configuration since transaction->changes
- * can contain pointers to data nodes from the running configuration.
- */
- pthread_rwlock_rdlock(&running_config->lock);
- {
- RB_FOREACH (cb, nb_config_cbs, &transaction->changes) {
- struct nb_config_change *change =
- (struct nb_config_change *)cb;
- int ret;
+ RB_FOREACH (cb, nb_config_cbs, &transaction->changes) {
+ struct nb_config_change *change = (struct nb_config_change *)cb;
+ int ret;
+ /*
+ * Only try to release resources that were allocated
+ * successfully.
+ */
+ if (event == NB_EV_ABORT && change->prepare_ok == false)
+ break;
+
+ /* Call the appropriate callback. */
+ ret = nb_callback_configuration(event, change);
+ switch (event) {
+ case NB_EV_PREPARE:
+ if (ret != NB_OK)
+ return ret;
+ change->prepare_ok = true;
+ break;
+ case NB_EV_ABORT:
+ case NB_EV_APPLY:
/*
- * Only try to release resources that were allocated
- * successfully.
+ * At this point it's not possible to reject the
+ * transaction anymore, so any failure here can lead to
+ * inconsistencies and should be treated as a bug.
+ * Operations prone to errors, like validations and
+ * resource allocations, should be performed during the
+ * 'prepare' phase.
*/
- if (event == NB_EV_ABORT && change->prepare_ok == false)
- break;
-
- /* Call the appropriate callback. */
- ret = nb_callback_configuration(event, change);
- switch (event) {
- case NB_EV_PREPARE:
- if (ret != NB_OK) {
- pthread_rwlock_unlock(
- &running_config->lock);
- return ret;
- }
- change->prepare_ok = true;
- break;
- case NB_EV_ABORT:
- case NB_EV_APPLY:
- /*
- * At this point it's not possible to reject the
- * transaction anymore, so any failure here can
- * lead to inconsistencies and should be treated
- * as a bug. Operations prone to errors, like
- * validations and resource allocations, should
- * be performed during the 'prepare' phase.
- */
- break;
- default:
- break;
- }
+ break;
+ default:
+ break;
}
}
- pthread_rwlock_unlock(&running_config->lock);
return NB_OK;
}
@@ -1310,9 +1318,27 @@ static int nb_oper_data_iter_node(const struct lys_node *snode,
/* Update XPath. */
strlcpy(xpath, xpath_parent, sizeof(xpath));
- if (!first && snode->nodetype != LYS_USES)
- snprintf(xpath + strlen(xpath), sizeof(xpath) - strlen(xpath),
- "/%s", snode->name);
+ if (!first && snode->nodetype != LYS_USES) {
+ struct lys_node *parent;
+
+ /* Get the real parent. */
+ parent = snode->parent;
+ while (parent && parent->nodetype == LYS_USES)
+ parent = parent->parent;
+
+ /*
+ * When necessary, include the namespace of the augmenting
+ * module.
+ */
+ if (parent && parent->nodetype == LYS_AUGMENT)
+ snprintf(xpath + strlen(xpath),
+ sizeof(xpath) - strlen(xpath), "/%s:%s",
+ snode->module->name, snode->name);
+ else
+ snprintf(xpath + strlen(xpath),
+ sizeof(xpath) - strlen(xpath), "/%s",
+ snode->name);
+ }
nb_node = snode->priv;
switch (snode->nodetype) {
@@ -1550,6 +1576,7 @@ bool nb_operation_is_valid(enum nb_operation operation,
return false;
}
return true;
+ case NB_OP_PRE_VALIDATE:
case NB_OP_APPLY_FINISH:
if (!CHECK_FLAG(snode->flags, LYS_CONFIG_W))
return false;
@@ -1768,6 +1795,8 @@ const char *nb_operation_name(enum nb_operation operation)
return "destroy";
case NB_OP_MOVE:
return "move";
+ case NB_OP_PRE_VALIDATE:
+ return "pre_validate";
case NB_OP_APPLY_FINISH:
return "apply_finish";
case NB_OP_GET_ELEM:
diff --git a/lib/northbound.h b/lib/northbound.h
index ce79d907f9..fbd7771db7 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -72,6 +72,7 @@ enum nb_operation {
NB_OP_MODIFY,
NB_OP_DESTROY,
NB_OP_MOVE,
+ NB_OP_PRE_VALIDATE,
NB_OP_APPLY_FINISH,
NB_OP_GET_ELEM,
NB_OP_GET_NEXT,
@@ -199,6 +200,19 @@ struct nb_callbacks {
/*
* Optional configuration callback.
*
+ * This callback can be used to validate subsections of the
+ * configuration being committed before validating the configuration
+ * changes themselves. It's useful to perform more complex validations
+ * that depend on the relationship between multiple nodes.
+ *
+ * dnode
+ * libyang data node associated with the 'pre_validate' callback.
+ */
+ int (*pre_validate)(const struct lyd_node *dnode);
+
+ /*
+ * Optional configuration callback.
+ *
* The 'apply_finish' callbacks are called after all other callbacks
* during the apply phase (NB_EV_APPLY). These callbacks are called only
* under one of the following two cases:
@@ -435,25 +449,15 @@ enum nb_client {
/* Northbound configuration. */
struct nb_config {
- /* Configuration data. */
struct lyd_node *dnode;
-
- /* Configuration version. */
uint32_t version;
-
- /*
- * Lock protecting this structure. The use of this lock is always
- * necessary when reading or modifying the global running configuration.
- * For candidate configurations, use of this lock is optional depending
- * on the threading scheme of the northbound plugin.
- */
- pthread_rwlock_t lock;
};
/* Northbound configuration callback. */
struct nb_config_cb {
RB_ENTRY(nb_config_cb) entry;
enum nb_operation operation;
+ uint32_t seq;
char xpath[XPATH_MAXLEN];
const struct nb_node *nb_node;
const struct lyd_node *dnode;
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 884c01a457..a15fe3d1c9 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -193,13 +193,8 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
"Please check the logs for more details.\n");
/* Regenerate candidate for consistency. */
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_replace(vty->candidate_config,
- running_config, true);
- }
- pthread_rwlock_unlock(&running_config->lock);
-
+ nb_config_replace(vty->candidate_config, running_config,
+ true);
return CMD_WARNING_CONFIG_FAILED;
}
}
@@ -307,12 +302,7 @@ static int nb_cli_commit(struct vty *vty, bool force,
/* "confirm" parameter. */
if (confirmed_timeout) {
- pthread_rwlock_rdlock(&running_config->lock);
- {
- vty->confirmed_commit_rollback =
- nb_config_dup(running_config);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ vty->confirmed_commit_rollback = nb_config_dup(running_config);
vty->t_confirmed_commit_timeout = NULL;
thread_add_timer(master, nb_cli_confirmed_commit_timeout, vty,
@@ -326,13 +316,8 @@ static int nb_cli_commit(struct vty *vty, bool force,
/* Map northbound return code to CLI return code. */
switch (ret) {
case NB_OK:
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_replace(vty->candidate_config_base,
- running_config, true);
- }
- pthread_rwlock_unlock(&running_config->lock);
-
+ nb_config_replace(vty->candidate_config_base, running_config,
+ true);
vty_out(vty,
"%% Configuration committed successfully (Transaction ID #%u).\n\n",
transaction_id);
@@ -729,12 +714,7 @@ DEFPY (config_update,
return CMD_WARNING;
}
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_config_replace(vty->candidate_config_base, running_config,
- true);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ nb_config_replace(vty->candidate_config_base, running_config, true);
vty_out(vty, "%% Candidate configuration updated successfully.\n\n");
@@ -834,12 +814,8 @@ DEFPY (show_config_running,
}
}
- pthread_rwlock_rdlock(&running_config->lock);
- {
- nb_cli_show_config(vty, running_config, format, translator,
- !!with_defaults);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ nb_cli_show_config(vty, running_config, format, translator,
+ !!with_defaults);
return CMD_SUCCESS;
}
@@ -953,68 +929,57 @@ DEFPY (show_config_compare,
struct nb_config *config2, *config_transaction2 = NULL;
int ret = CMD_WARNING;
- /*
- * For simplicity, lock the running configuration regardless if it's
- * going to be used or not.
- */
- pthread_rwlock_rdlock(&running_config->lock);
- {
- if (c1_candidate)
- config1 = vty->candidate_config;
- else if (c1_running)
- config1 = running_config;
- else {
- config_transaction1 = nb_db_transaction_load(c1_tid);
- if (!config_transaction1) {
- vty_out(vty,
- "%% Transaction %u does not exist\n\n",
- (unsigned int)c1_tid);
- goto exit;
- }
- config1 = config_transaction1;
+ if (c1_candidate)
+ config1 = vty->candidate_config;
+ else if (c1_running)
+ config1 = running_config;
+ else {
+ config_transaction1 = nb_db_transaction_load(c1_tid);
+ if (!config_transaction1) {
+ vty_out(vty, "%% Transaction %u does not exist\n\n",
+ (unsigned int)c1_tid);
+ goto exit;
}
+ config1 = config_transaction1;
+ }
- if (c2_candidate)
- config2 = vty->candidate_config;
- else if (c2_running)
- config2 = running_config;
- else {
- config_transaction2 = nb_db_transaction_load(c2_tid);
- if (!config_transaction2) {
- vty_out(vty,
- "%% Transaction %u does not exist\n\n",
- (unsigned int)c2_tid);
- goto exit;
- }
- config2 = config_transaction2;
+ if (c2_candidate)
+ config2 = vty->candidate_config;
+ else if (c2_running)
+ config2 = running_config;
+ else {
+ config_transaction2 = nb_db_transaction_load(c2_tid);
+ if (!config_transaction2) {
+ vty_out(vty, "%% Transaction %u does not exist\n\n",
+ (unsigned int)c2_tid);
+ goto exit;
}
+ config2 = config_transaction2;
+ }
- if (json)
- format = NB_CFG_FMT_JSON;
- else if (xml)
- format = NB_CFG_FMT_XML;
- else
- format = NB_CFG_FMT_CMDS;
+ if (json)
+ format = NB_CFG_FMT_JSON;
+ else if (xml)
+ format = NB_CFG_FMT_XML;
+ else
+ format = NB_CFG_FMT_CMDS;
- if (translator_family) {
- translator = yang_translator_find(translator_family);
- if (!translator) {
- vty_out(vty,
- "%% Module translator \"%s\" not found\n",
- translator_family);
- goto exit;
- }
+ if (translator_family) {
+ translator = yang_translator_find(translator_family);
+ if (!translator) {
+ vty_out(vty, "%% Module translator \"%s\" not found\n",
+ translator_family);
+ goto exit;
}
-
- ret = nb_cli_show_config_compare(vty, config1, config2, format,
- translator);
- exit:
- if (config_transaction1)
- nb_config_free(config_transaction1);
- if (config_transaction2)
- nb_config_free(config_transaction2);
}
- pthread_rwlock_unlock(&running_config->lock);
+
+ ret = nb_cli_show_config_compare(vty, config1, config2, format,
+ translator);
+exit:
+ if (config_transaction1)
+ nb_config_free(config_transaction1);
+ if (config_transaction2)
+ nb_config_free(config_transaction2);
return ret;
}
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
index e9669fc7e1..2fc3c81cf2 100644
--- a/lib/northbound_confd.c
+++ b/lib/northbound_confd.c
@@ -289,11 +289,7 @@ static int frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen)
struct cdb_iter_args iter_args;
int ret;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- candidate = nb_config_dup(running_config);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ candidate = nb_config_dup(running_config);
/* Iterate over all configuration changes. */
iter_args.candidate = candidate;
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index a55da23dd1..1d6317b005 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -702,15 +702,10 @@ class NorthboundImpl final : public frr::Northbound::Service
{
struct lyd_node *dnode;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- dnode = yang_dnode_get(running_config->dnode,
- path.empty() ? NULL
- : path.c_str());
- if (dnode)
- dnode = yang_dnode_dup(dnode);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ dnode = yang_dnode_get(running_config->dnode,
+ path.empty() ? NULL : path.c_str());
+ if (dnode)
+ dnode = yang_dnode_dup(dnode);
return dnode;
}
@@ -817,11 +812,7 @@ class NorthboundImpl final : public frr::Northbound::Service
struct candidate *candidate = &_candidates[candidate_id];
candidate->id = candidate_id;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- candidate->config = nb_config_dup(running_config);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ candidate->config = nb_config_dup(running_config);
candidate->transaction = NULL;
return candidate;
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 77183282ba..b94c939763 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -256,11 +256,7 @@ static int frr_sr_config_change_cb_verify(sr_session_ctx_t *session,
return ret;
}
- pthread_rwlock_rdlock(&running_config->lock);
- {
- candidate = nb_config_dup(running_config);
- }
- pthread_rwlock_unlock(&running_config->lock);
+ candidate = nb_config_dup(running_config);
while ((ret = sr_get_change_next(session, it, &sr_op, &sr_old_val,
&sr_new_val))
diff --git a/lib/routemap.c b/lib/routemap.c
index fc15183bf9..580d898448 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -478,11 +478,6 @@ int generic_match_add(struct vty *vty, struct route_map_index *index,
ret = route_map_add_match(index, command, arg, type);
switch (ret) {
- case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_ADDED) {
- route_map_upd8_dependency(type, arg, index->map->name);
- }
- break;
case RMAP_RULE_MISSING:
vty_out(vty, "%% [%s] Can't find rule.\n", frr_protonameinst);
return CMD_WARNING_CONFIG_FAILED;
@@ -493,7 +488,7 @@ int generic_match_add(struct vty *vty, struct route_map_index *index,
frr_protonameinst);
return CMD_WARNING_CONFIG_FAILED;
break;
- case RMAP_DUPLICATE_RULE:
+ case RMAP_COMPILE_SUCCESS:
/*
* Nothing to do here move along
*/
@@ -526,7 +521,7 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
}
- ret = route_map_delete_match(index, command, dep_name);
+ ret = route_map_delete_match(index, command, dep_name, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% [%s] Can't find rule.\n", frr_protonameinst);
@@ -539,10 +534,6 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
- route_map_upd8_dependency(type, dep_name, rmap_name);
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
@@ -573,7 +564,6 @@ int generic_set_add(struct vty *vty, struct route_map_index *index,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
break;
}
@@ -598,7 +588,6 @@ int generic_set_delete(struct vty *vty, struct route_map_index *index,
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
break;
}
@@ -1410,6 +1399,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
struct route_map_rule_cmd *cmd;
void *compile;
int8_t delete_rmap_event_type = 0;
+ const char *rule_key;
/* First lookup rule for add match statement. */
cmd = route_map_lookup_match(match_name);
@@ -1423,6 +1413,12 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
return RMAP_COMPILE_ERROR;
} else
compile = NULL;
+ /* use the compiled results if applicable */
+ if (compile && cmd->func_get_rmap_rule_key)
+ rule_key = (*cmd->func_get_rmap_rule_key)
+ (compile);
+ else
+ rule_key = match_arg;
/* If argument is completely same ignore it. */
for (rule = index->match_list.head; rule; rule = next) {
@@ -1436,7 +1432,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
if (cmd->func_free)
(*cmd->func_free)(compile);
- return RMAP_DUPLICATE_RULE;
+ return RMAP_COMPILE_SUCCESS;
}
/* Remove the dependency of the route-map on the rule
@@ -1447,7 +1443,7 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
get_route_map_delete_event(type);
route_map_upd8_dependency(
delete_rmap_event_type,
- rule->rule_str,
+ rule_key,
index->map->name);
}
@@ -1473,6 +1469,8 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
route_map_notify_dependencies(index->map->name,
RMAP_EVENT_CALL_ADDED);
}
+ if (type != RMAP_EVENT_MATCH_ADDED)
+ route_map_upd8_dependency(type, rule_key, index->map->name);
return RMAP_COMPILE_SUCCESS;
}
@@ -1480,10 +1478,12 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
/* Delete specified route match rule. */
enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
const char *match_name,
- const char *match_arg)
+ const char *match_arg,
+ route_map_event_t type)
{
struct route_map_rule *rule;
struct route_map_rule_cmd *cmd;
+ const char *rule_key;
cmd = route_map_lookup_match(match_name);
if (cmd == NULL)
@@ -1492,7 +1492,6 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
for (rule = index->match_list.head; rule; rule = rule->next)
if (rule->cmd == cmd && (rulecmp(rule->rule_str, match_arg) == 0
|| match_arg == NULL)) {
- route_map_rule_delete(&index->match_list, rule);
/* Execute event hook. */
if (route_map_master.event_hook) {
(*route_map_master.event_hook)(index->map->name);
@@ -1500,6 +1499,17 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
index->map->name,
RMAP_EVENT_CALL_ADDED);
}
+ if (cmd->func_get_rmap_rule_key)
+ rule_key = (*cmd->func_get_rmap_rule_key)
+ (rule->value);
+ else
+ rule_key = match_arg;
+
+ if (type != RMAP_EVENT_MATCH_DELETED && rule_key)
+ route_map_upd8_dependency(type, rule_key,
+ index->map->name);
+
+ route_map_rule_delete(&index->match_list, rule);
return RMAP_COMPILE_SUCCESS;
}
/* Can't find matched rule. */
diff --git a/lib/routemap.h b/lib/routemap.h
index 40525987e9..e6eccd4b29 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -123,6 +123,9 @@ struct route_map_rule_cmd {
/* Free allocated value by func_compile (). */
void (*func_free)(void *);
+
+ /** To get the rule key after Compilation **/
+ void *(*func_get_rmap_rule_key)(void *val);
};
/* Route map apply error. */
@@ -135,8 +138,6 @@ enum rmap_compile_rets {
/* Route map rule can't compile */
RMAP_COMPILE_ERROR,
- /* Route map rule is duplicate */
- RMAP_DUPLICATE_RULE
};
/* Route map rule list. */
@@ -228,7 +229,8 @@ extern enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
/* Delete specified route match rule. */
extern enum rmap_compile_rets
route_map_delete_match(struct route_map_index *index,
- const char *match_name, const char *match_arg);
+ const char *match_name, const char *match_arg,
+ route_map_event_t type);
extern const char *route_map_get_match_arg(struct route_map_index *index,
const char *match_name);
diff --git a/lib/vrf.c b/lib/vrf.c
index 575e96bae4..4c6df797ad 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -199,9 +199,14 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
/* Set name */
if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
+ /* update the vrf name */
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
+ strlcpy(vrf->data.l.netns_name,
+ name, NS_NAMSIZ);
strlcpy(vrf->name, name, sizeof(vrf->name));
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
+ if (vrf->vrf_id == VRF_DEFAULT)
+ vrf_set_default_name(vrf->name, false);
} else if (name && vrf->name[0] == '\0') {
strlcpy(vrf->name, name, sizeof(vrf->name));
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
@@ -870,7 +875,8 @@ void vrf_set_default_name(const char *default_name, bool force)
def_vrf->vrf_id);
return;
}
-
+ if (strmatch(vrf_default_name, default_name))
+ return;
snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
if (def_vrf) {
if (force)
diff --git a/lib/vty.c b/lib/vty.c
index deb9391bd5..502d2c9d04 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2582,22 +2582,17 @@ int vty_config_enter(struct vty *vty, bool private_config, bool exclusive)
vty->private_config = private_config;
vty->xpath_index = 0;
- pthread_rwlock_rdlock(&running_config->lock);
- {
- if (private_config) {
- vty->candidate_config = nb_config_dup(running_config);
+ if (private_config) {
+ vty->candidate_config = nb_config_dup(running_config);
+ vty->candidate_config_base = nb_config_dup(running_config);
+ vty_out(vty,
+ "Warning: uncommitted changes will be discarded on exit.\n\n");
+ } else {
+ vty->candidate_config = vty_shared_candidate_config;
+ if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL)
vty->candidate_config_base =
nb_config_dup(running_config);
- vty_out(vty,
- "Warning: uncommitted changes will be discarded on exit.\n\n");
- } else {
- vty->candidate_config = vty_shared_candidate_config;
- if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL)
- vty->candidate_config_base =
- nb_config_dup(running_config);
- }
}
- pthread_rwlock_unlock(&running_config->lock);
return CMD_SUCCESS;
}
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index 0558383823..50225f35a0 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -782,6 +782,60 @@ void yang_get_default_string_buf(char *buf, size_t size, const char *xpath_fmt,
}
/*
+ * Derived type: IP prefix.
+ */
+void yang_str2prefix(const char *value, union prefixptr prefix)
+{
+ (void)str2prefix(value, prefix.p);
+ apply_mask(prefix.p);
+}
+
+struct yang_data *yang_data_new_prefix(const char *xpath,
+ union prefixconstptr prefix)
+{
+ char value_str[PREFIX2STR_BUFFER];
+
+ (void)prefix2str(prefix.p, value_str, sizeof(value_str));
+ return yang_data_new(xpath, value_str);
+}
+
+void yang_dnode_get_prefix(union prefixptr prefix, const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ const struct lyd_node_leaf_list *dleaf;
+
+ assert(dnode);
+ if (xpath_fmt) {
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+ dnode = yang_dnode_get(dnode, xpath);
+ YANG_DNODE_GET_ASSERT(dnode, xpath);
+ }
+
+ dleaf = (const struct lyd_node_leaf_list *)dnode;
+ assert(dleaf->value_type == LY_TYPE_STRING);
+ (void)str2prefix(dleaf->value_str, prefix.p);
+}
+
+void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...)
+{
+ char xpath[XPATH_MAXLEN];
+ const char *value;
+ va_list ap;
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ value = yang_get_default_value(xpath);
+ yang_str2prefix(value, var);
+}
+
+/*
* Derived type: ipv4.
*/
void yang_str2ipv4(const char *value, struct in_addr *addr)
@@ -1000,3 +1054,56 @@ void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...)
value = yang_get_default_value(xpath);
yang_str2ipv6p(value, var);
}
+
+/*
+ * Derived type: ip.
+ */
+void yang_str2ip(const char *value, struct ipaddr *ip)
+{
+ (void)str2ipaddr(value, ip);
+}
+
+struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr)
+{
+ size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
+ char value_str[sz];
+
+ ipaddr2str(addr, value_str, sizeof(value_str));
+ return yang_data_new(xpath, value_str);
+}
+
+void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ const struct lyd_node_leaf_list *dleaf;
+
+ assert(dnode);
+ if (xpath_fmt) {
+ va_list ap;
+ char xpath[XPATH_MAXLEN];
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+ dnode = yang_dnode_get(dnode, xpath);
+ YANG_DNODE_GET_ASSERT(dnode, xpath);
+ }
+
+ dleaf = (const struct lyd_node_leaf_list *)dnode;
+ assert(dleaf->value_type == LY_TYPE_STRING);
+ (void)str2ipaddr(dleaf->value_str, addr);
+}
+
+void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
+{
+ char xpath[XPATH_MAXLEN];
+ const char *value;
+ va_list ap;
+
+ va_start(ap, xpath_fmt);
+ vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
+ va_end(ap);
+
+ value = yang_get_default_value(xpath);
+ yang_str2ip(value, var);
+}
diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h
index 5203a033ad..1a30ff3686 100644
--- a/lib/yang_wrappers.h
+++ b/lib/yang_wrappers.h
@@ -114,6 +114,16 @@ extern const char *yang_get_default_string(const char *xpath_fmt, ...);
extern void yang_get_default_string_buf(char *buf, size_t size,
const char *xpath_fmt, ...);
+/* ip prefix */
+extern void yang_str2prefix(const char *value, union prefixptr prefix);
+extern struct yang_data *yang_data_new_prefix(const char *xpath,
+ union prefixconstptr prefix);
+extern void yang_dnode_get_prefix(union prefixptr prefix,
+ const struct lyd_node *dnode,
+ const char *xpath_fmt, ...);
+extern void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt,
+ ...);
+
/* ipv4 */
extern void yang_str2ipv4(const char *value, struct in_addr *addr);
extern struct yang_data *yang_data_new_ipv4(const char *xpath,
@@ -154,4 +164,12 @@ extern void yang_dnode_get_ipv6p(union prefixptr prefix,
extern void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt,
...);
+/* ip */
+extern void yang_str2ip(const char *value, struct ipaddr *addr);
+extern struct yang_data *yang_data_new_ip(const char *xpath,
+ const struct ipaddr *addr);
+extern void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
+ const char *xpath_fmt, ...);
+extern void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...);
+
#endif /* _FRR_NORTHBOUND_WRAPPERS_H_ */
diff --git a/lib/zclient.c b/lib/zclient.c
index f809704f86..92a495ac61 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2451,6 +2451,143 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
return zclient_send_message(zclient);
}
+int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
+ struct zapi_labels *zl)
+{
+ if (zapi_labels_encode(zclient->obuf, cmd, zl) < 0)
+ return -1;
+ return zclient_send_message(zclient);
+}
+
+int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
+{
+ struct zapi_nexthop_label *znh;
+
+ stream_reset(s);
+
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+ stream_putc(s, zl->message);
+ stream_putc(s, zl->type);
+ stream_putl(s, zl->local_label);
+
+ if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
+ stream_putw(s, zl->route.prefix.family);
+ stream_put_prefix(s, &zl->route.prefix);
+ stream_putc(s, zl->route.type);
+ stream_putw(s, zl->route.instance);
+ }
+
+ if (zl->nexthop_num > MULTIPATH_NUM) {
+ flog_err(
+ EC_LIB_ZAPI_ENCODE,
+ "%s: label %u: can't encode %u nexthops (maximum is %u)",
+ __func__, zl->local_label, zl->nexthop_num,
+ MULTIPATH_NUM);
+ return -1;
+ }
+ stream_putw(s, zl->nexthop_num);
+
+ for (int i = 0; i < zl->nexthop_num; i++) {
+ znh = &zl->nexthops[i];
+
+ stream_putc(s, znh->type);
+ stream_putw(s, znh->family);
+ switch (znh->family) {
+ case AF_INET:
+ stream_put_in_addr(s, &znh->address.ipv4);
+ break;
+ case AF_INET6:
+ stream_write(s, (uint8_t *)&znh->address.ipv6, 16);
+ break;
+ default:
+ break;
+ }
+ stream_putl(s, znh->ifindex);
+ stream_putl(s, znh->label);
+ }
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
+int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
+{
+ struct zapi_nexthop_label *znh;
+
+ memset(zl, 0, sizeof(*zl));
+
+ /* Get data. */
+ STREAM_GETC(s, zl->message);
+ STREAM_GETC(s, zl->type);
+ STREAM_GETL(s, zl->local_label);
+
+ if (CHECK_FLAG(zl->message, ZAPI_LABELS_FTN)) {
+ size_t psize;
+
+ STREAM_GETW(s, zl->route.prefix.family);
+ STREAM_GETC(s, zl->route.prefix.prefixlen);
+
+ psize = PSIZE(zl->route.prefix.prefixlen);
+ switch (zl->route.prefix.family) {
+ case AF_INET:
+ if (zl->route.prefix.prefixlen > IPV4_MAX_BITLEN) {
+ zlog_debug(
+ "%s: Specified prefix length %d is greater than a v4 address can support",
+ __PRETTY_FUNCTION__,
+ zl->route.prefix.prefixlen);
+ return -1;
+ }
+ STREAM_GET(&zl->route.prefix.u.prefix4.s_addr, s,
+ psize);
+ break;
+ case AF_INET6:
+ if (zl->route.prefix.prefixlen > IPV6_MAX_BITLEN) {
+ zlog_debug(
+ "%s: Specified prefix length %d is greater than a v6 address can support",
+ __PRETTY_FUNCTION__,
+ zl->route.prefix.prefixlen);
+ return -1;
+ }
+ STREAM_GET(&zl->route.prefix.u.prefix6, s, psize);
+ break;
+ default:
+ flog_err(EC_LIB_ZAPI_ENCODE,
+ "%s: Specified family %u is not v4 or v6",
+ __PRETTY_FUNCTION__, zl->route.prefix.family);
+ return -1;
+ }
+
+ STREAM_GETC(s, zl->route.type);
+ STREAM_GETW(s, zl->route.instance);
+ }
+
+ STREAM_GETW(s, zl->nexthop_num);
+ for (int i = 0; i < zl->nexthop_num; i++) {
+ znh = &zl->nexthops[i];
+
+ STREAM_GETC(s, znh->type);
+ STREAM_GETW(s, znh->family);
+ switch (znh->family) {
+ case AF_INET:
+ STREAM_GET(&znh->address.ipv4.s_addr, s,
+ IPV4_MAX_BYTELEN);
+ break;
+ case AF_INET6:
+ STREAM_GET(&znh->address.ipv6, s, 16);
+ break;
+ default:
+ break;
+ }
+ STREAM_GETL(s, znh->ifindex);
+ STREAM_GETL(s, znh->label);
+ }
+
+ return 0;
+stream_failure:
+ return -1;
+}
int zebra_send_pw(struct zclient *zclient, int command, struct zapi_pw *pw)
{
diff --git a/lib/zclient.h b/lib/zclient.h
index 81e454d192..eb3c97b111 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -126,6 +126,7 @@ typedef enum {
ZEBRA_INTERFACE_LINK_PARAMS,
ZEBRA_MPLS_LABELS_ADD,
ZEBRA_MPLS_LABELS_DELETE,
+ ZEBRA_MPLS_LABELS_REPLACE,
ZEBRA_IPMR_ROUTE_STATS,
ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_LABEL_MANAGER_CONNECT_ASYNC,
@@ -395,6 +396,28 @@ struct zapi_route {
uint32_t tableid;
};
+struct zapi_nexthop_label {
+ enum nexthop_types_t type;
+ int family;
+ union g_addr address;
+ ifindex_t ifindex;
+ mpls_label_t label;
+};
+
+struct zapi_labels {
+ uint8_t message;
+#define ZAPI_LABELS_FTN 0x01
+ enum lsp_types_t type;
+ mpls_label_t local_label;
+ struct {
+ struct prefix prefix;
+ uint8_t type;
+ unsigned short instance;
+ } route;
+ uint16_t nexthop_num;
+ struct zapi_nexthop_label nexthops[MULTIPATH_NUM];
+};
+
struct zapi_pw {
char ifname[IF_NAMESIZE];
ifindex_t ifindex;
@@ -625,6 +648,12 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
+extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
+ struct zapi_labels *zl);
+extern int zapi_labels_encode(struct stream *s, int cmd,
+ struct zapi_labels *zl);
+extern int zapi_labels_decode(struct stream *s, struct zapi_labels *zl);
+
extern int zebra_send_pw(struct zclient *zclient, int command,
struct zapi_pw *pw);
extern void zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_status *pw);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 4d1c085081..7914412e87 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1593,7 +1593,6 @@ static int route_map_command_status(struct vty *vty, enum rmap_compile_rets ret)
return CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- case RMAP_DUPLICATE_RULE:
break;
}
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 40c6123810..95dafff84e 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -136,7 +136,7 @@ static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
ospf6_abr_originate_summary(route);
}
-static struct ospf6 *ospf6_create(void)
+static struct ospf6 *ospf6_create(vrf_id_t vrf_id)
{
struct ospf6 *o;
@@ -144,6 +144,7 @@ static struct ospf6 *ospf6_create(void)
/* initialize */
monotime(&o->starttime);
+ o->vrf_id = vrf_id;
o->area_list = list_new();
o->area_list->cmp = ospf6_area_cmp;
o->lsdb = ospf6_lsdb_create(o);
@@ -325,7 +326,7 @@ DEFUN_NOSH (router_ospf6,
OSPF6_STR)
{
if (ospf6 == NULL) {
- ospf6 = ospf6_create();
+ ospf6 = ospf6_create(VRF_DEFAULT);
if (ospf6->router_id == 0)
ospf6_router_id_update();
}
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 381027dcff..ba41fca65b 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -31,6 +31,9 @@ struct ospf6_master {
/* OSPFv3 top level data structure */
struct ospf6 {
+ /* The relevant vrf_id */
+ vrf_id_t vrf_id;
+
/* my router id */
uint32_t router_id;
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 36bb8d49b5..bee7bbb21d 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -216,16 +216,6 @@ int main(int argc, char **argv)
/* OSPF errors init */
ospf_error_init();
- /* Need to initialize the default ospf structure, so the interface mode
- commands can be duly processed if they are received before 'router
- ospf',
- when quagga(ospfd) is restarted */
- if (!ospf_get_instance(instance)) {
- flog_err(EC_OSPF_INIT_FAIL, "OSPF instance init failed: %s",
- strerror(errno));
- exit(1);
- }
-
frr_config_fork();
frr_run(master);
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index 6947393a60..ff2039bec8 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -608,26 +608,8 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
/* Send MPLS Label entry to Zebra for installation or deletion */
static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
{
- struct stream *s;
-
- /* Reset stream. */
- s = zclient->obuf;
- stream_reset(s);
-
- zclient_create_header(s, cmd, VRF_DEFAULT);
- stream_putc(s, ZEBRA_LSP_SR);
- /* OSPF Segment Routing currently support only IPv4 */
- stream_putl(s, nhlfe.prefv4.family);
- stream_put_in_addr(s, &nhlfe.prefv4.prefix);
- stream_putc(s, nhlfe.prefv4.prefixlen);
- stream_put_in_addr(s, &nhlfe.nexthop);
- stream_putl(s, nhlfe.ifindex);
- stream_putc(s, OSPF_SR_PRIORITY_DEFAULT);
- stream_putl(s, nhlfe.label_in);
- stream_putl(s, nhlfe.label_out);
-
- /* Put length at the first point of the stream. */
- stream_putw_at(s, 0, stream_get_endp(s));
+ struct zapi_labels zl = {};
+ struct zapi_nexthop_label *znh;
if (IS_DEBUG_OSPF_SR)
zlog_debug(" |- %s LSP %u/%u for %s/%u via %u",
@@ -636,70 +618,39 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
inet_ntoa(nhlfe.prefv4.prefix),
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
- return zclient_send_message(zclient);
-}
-
-/* Request zebra to install/remove FEC in FIB */
-static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe)
-{
- struct zapi_route api;
- struct zapi_nexthop *api_nh;
-
- /* Support only IPv4 */
- if (nhlfe.prefv4.family != AF_INET)
- return -1;
-
- memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
- api.type = ZEBRA_ROUTE_OSPF;
- api.safi = SAFI_UNICAST;
- memcpy(&api.prefix, &nhlfe.prefv4, sizeof(struct prefix_ipv4));
-
- if (cmd == ZEBRA_ROUTE_ADD) {
- /* Metric value. */
- SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
- api.metric = OSPF_SR_DEFAULT_METRIC;
- /* Nexthop */
- SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
- api_nh = &api.nexthops[0];
- IPV4_ADDR_COPY(&api_nh->gate.ipv4, &nhlfe.nexthop);
- api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- api_nh->ifindex = nhlfe.ifindex;
- /* MPLS labels */
- SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
- api_nh->labels[0] = nhlfe.label_out;
- api_nh->label_num = 1;
- api_nh->vrf_id = VRF_DEFAULT;
- api.nexthop_num = 1;
- }
-
- if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- %s FEC %u for %s/%u via %u",
- cmd == ZEBRA_ROUTE_ADD ? "Add" : "Delete",
- nhlfe.label_out, inet_ntoa(nhlfe.prefv4.prefix),
- nhlfe.prefv4.prefixlen, nhlfe.ifindex);
-
- return zclient_route_send(cmd, zclient, &api);
+ zl.type = ZEBRA_LSP_OSPF_SR;
+ zl.local_label = nhlfe.label_in;
+
+ SET_FLAG(zl.message, ZAPI_LABELS_FTN);
+ zl.route.prefix.family = nhlfe.prefv4.family;
+ zl.route.prefix.prefixlen = nhlfe.prefv4.prefixlen;
+ zl.route.prefix.u.prefix4 = nhlfe.prefv4.prefix;
+ zl.route.type = ZEBRA_ROUTE_OSPF;
+ zl.route.instance = 0;
+
+ zl.nexthop_num = 1;
+ znh = &zl.nexthops[0];
+ znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ znh->family = AF_INET;
+ znh->address.ipv4 = nhlfe.nexthop;
+ znh->ifindex = nhlfe.ifindex;
+ znh->label = nhlfe.label_out;
+
+ return zebra_send_mpls_labels(zclient, cmd, &zl);
}
/* Add new NHLFE entry for SID */
static inline void add_sid_nhlfe(struct sr_nhlfe nhlfe)
{
- if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
+ if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0))
ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, nhlfe);
- if (nhlfe.label_out != MPLS_LABEL_IMPLICIT_NULL)
- ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_ADD, nhlfe);
- }
}
/* Remove NHLFE entry for SID */
static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe)
{
- if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0)) {
+ if ((nhlfe.label_in != 0) && (nhlfe.label_out != 0))
ospf_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, nhlfe);
- if (nhlfe.label_out != MPLS_LABEL_IMPLICIT_NULL)
- ospf_zebra_send_mpls_ftn(ZEBRA_ROUTE_DELETE, nhlfe);
- }
}
/* Update NHLFE entry for SID */
diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h
index 4d3f5f441a..df923e970f 100644
--- a/ospfd/ospf_sr.h
+++ b/ospfd/ospf_sr.h
@@ -27,9 +27,6 @@
#ifndef _FRR_OSPF_SR_H
#define _FRR_OSPF_SR_H
-/* Default Route priority for OSPF Segment Routing */
-#define OSPF_SR_PRIORITY_DEFAULT 10
-
/* macros and constants for segment routing */
#define SET_RANGE_SIZE_MASK 0xffffff00
#define GET_RANGE_SIZE_MASK 0x00ffffff
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index e48a5b4d36..f4de255877 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -2158,7 +2158,7 @@ static int ospf_vrf_disable(struct vrf *vrf)
void ospf_vrf_init(void)
{
vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
- ospf_vrf_delete, NULL);
+ ospf_vrf_delete, ospf_vrf_enable);
}
void ospf_vrf_terminate(void)
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index 57e8cf5742..359f869c42 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -682,29 +682,119 @@ struct pbr_nht_individual {
uint32_t valid;
};
-static void pbr_nht_individual_nexthop_update_lookup(struct hash_bucket *b,
- void *data)
+static bool
+pbr_nht_individual_nexthop_gw_update(struct pbr_nexthop_cache *pnhc,
+ const struct pbr_nht_individual *pnhi)
{
- struct pbr_nexthop_cache *pnhc = b->data;
- struct pbr_nht_individual *pnhi = data;
- char buf[PREFIX_STRLEN];
- bool old_valid;
+ bool is_valid = pnhc->valid;
- old_valid = pnhc->valid;
+ if (!pnhi->nhr) /* It doesn't care about non-nexthop updates */
+ goto done;
switch (pnhi->nhr->prefix.family) {
case AF_INET:
if (pnhc->nexthop->gate.ipv4.s_addr
- == pnhi->nhr->prefix.u.prefix4.s_addr)
- pnhc->valid = !!pnhi->nhr->nexthop_num;
+ != pnhi->nhr->prefix.u.prefix4.s_addr)
+ goto done; /* Unrelated change */
break;
case AF_INET6:
if (memcmp(&pnhc->nexthop->gate.ipv6,
&pnhi->nhr->prefix.u.prefix6, 16)
- == 0)
- pnhc->valid = !!pnhi->nhr->nexthop_num;
+ != 0)
+ goto done; /* Unrelated change */
+ break;
+ }
+
+ if (!pnhi->nhr->nexthop_num) {
+ is_valid = false;
+ goto done;
+ }
+
+ if (pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
+ || pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+
+ /* GATEWAY_IFINDEX type shouldn't resolve to group */
+ if (pnhi->nhr->nexthop_num > 1) {
+ is_valid = false;
+ goto done;
+ }
+
+ /* If whatever we resolved to wasn't on the interface we
+ * specified. (i.e. not a connected route), its invalid.
+ */
+ if (pnhi->nhr->nexthops[0].ifindex != pnhc->nexthop->ifindex) {
+ is_valid = false;
+ goto done;
+ }
+ }
+
+ is_valid = true;
+
+done:
+ pnhc->valid = is_valid;
+
+ return pnhc->valid;
+}
+
+static bool pbr_nht_individual_nexthop_interface_update(
+ struct pbr_nexthop_cache *pnhc, const struct pbr_nht_individual *pnhi)
+{
+ bool is_valid = pnhc->valid;
+
+ if (!pnhi->ifp) /* It doesn't care about non-interface updates */
+ goto done;
+
+ if (pnhc->nexthop->ifindex
+ != pnhi->ifp->ifindex) /* Un-related interface */
+ goto done;
+
+ is_valid = !!if_is_up(pnhi->ifp);
+
+done:
+ pnhc->valid = is_valid;
+
+ return pnhc->valid;
+}
+
+/* Given this update either from interface or nexthop tracking, re-validate this
+ * nexthop.
+ *
+ * If the update is un-related, the subroutines shoud just return their cached
+ * valid state.
+ */
+static void
+pbr_nht_individual_nexthop_update(struct pbr_nexthop_cache *pnhc,
+ const struct pbr_nht_individual *pnhi)
+{
+ assert(pnhi->nhr || pnhi->ifp); /* Either nexthop or interface update */
+
+ switch (pnhc->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ pbr_nht_individual_nexthop_interface_update(pnhc, pnhi);
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ pbr_nht_individual_nexthop_gw_update(pnhc, pnhi);
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ pnhc->valid = true;
break;
}
+}
+
+static void pbr_nht_individual_nexthop_update_lookup(struct hash_bucket *b,
+ void *data)
+{
+ struct pbr_nexthop_cache *pnhc = b->data;
+ struct pbr_nht_individual *pnhi = data;
+ char buf[PREFIX_STRLEN];
+ bool old_valid;
+
+ old_valid = pnhc->valid;
+
+ pbr_nht_individual_nexthop_update(pnhc, pnhi);
DEBUGD(&pbr_dbg_nht, "\tFound %s: old: %d new: %d",
prefix2str(&pnhi->nhr->prefix, buf, sizeof(buf)), old_valid,
@@ -736,7 +826,7 @@ pbr_nexthop_group_cache_to_nexthop_group(struct nexthop_group *nhg,
static void pbr_nht_nexthop_update_lookup(struct hash_bucket *b, void *data)
{
struct pbr_nexthop_group_cache *pnhgc = b->data;
- struct pbr_nht_individual pnhi;
+ struct pbr_nht_individual pnhi = {};
struct nexthop_group nhg = {};
bool old_valid;
@@ -778,9 +868,7 @@ pbr_nht_individual_nexthop_interface_update_lookup(struct hash_backet *b,
old_valid = pnhc->valid;
- if (pnhc->nexthop->type == NEXTHOP_TYPE_IFINDEX
- && pnhc->nexthop->ifindex == pnhi->ifp->ifindex)
- pnhc->valid = !!if_is_up(pnhi->ifp);
+ pbr_nht_individual_nexthop_update(pnhc, pnhi);
DEBUGD(&pbr_dbg_nht, "\tFound %s: old: %d new: %d", pnhi->ifp->name,
old_valid, pnhc->valid);
@@ -793,7 +881,7 @@ static void pbr_nht_nexthop_interface_update_lookup(struct hash_backet *b,
void *data)
{
struct pbr_nexthop_group_cache *pnhgc = b->data;
- struct pbr_nht_individual pnhi;
+ struct pbr_nht_individual pnhi = {};
bool old_valid;
old_valid = pnhgc->valid;
diff --git a/qpb/subdir.am b/qpb/subdir.am
index 75a733f8fc..1864ba7369 100644
--- a/qpb/subdir.am
+++ b/qpb/subdir.am
@@ -10,9 +10,12 @@ qpb_libfrr_pb_la_SOURCES = \
qpb/qpb.c \
qpb/qpb_allocator.c \
# end
+
+if HAVE_PROTOBUF
nodist_qpb_libfrr_pb_la_SOURCES = \
qpb/qpb.pb-c.c \
# end
+endif
noinst_HEADERS += \
qpb/linear_allocator.h \
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index fa0a6d8a0a..b3f9ac7630 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -656,6 +656,9 @@ fi
%files pythontools
+%{_sbindir}/generate_support_bundle.py
+%{_sbindir}/generate_support_bundle.pyc
+%{_sbindir}/generate_support_bundle.pyo
%{_sbindir}/frr-reload.py
%{_sbindir}/frr-reload.pyc
%{_sbindir}/frr-reload.pyo
diff --git a/ripd/ripd.c b/ripd/ripd.c
index ad373aebdf..1b5a582cb1 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -3641,6 +3641,37 @@ static int rip_vrf_enable(struct vrf *vrf)
int socket;
rip = rip_lookup_by_vrf_name(vrf->name);
+ if (!rip) {
+ char *old_vrf_name = NULL;
+
+ rip = (struct rip *)vrf->info;
+ if (!rip)
+ return 0;
+ /* update vrf name */
+ if (rip->vrf_name)
+ old_vrf_name = rip->vrf_name;
+ rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf->name);
+ /*
+ * HACK: Change the RIP VRF in the running configuration directly,
+ * bypassing the northbound layer. This is necessary to avoid deleting
+ * the RIP and readding it in the new VRF, which would have
+ * several implications.
+ */
+ if (yang_module_find("frr-ripd") && old_vrf_name) {
+ struct lyd_node *rip_dnode;
+
+ rip_dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-ripd:ripd/instance[vrf='%s']/vrf",
+ old_vrf_name);
+ if (rip_dnode) {
+ yang_dnode_change_leaf(rip_dnode, vrf->name);
+ running_config->version++;
+ }
+ }
+ if (old_vrf_name)
+ XFREE(MTYPE_RIP_VRF_NAME, old_vrf_name);
+ }
if (!rip || rip->enabled)
return 0;
@@ -3682,7 +3713,7 @@ static int rip_vrf_disable(struct vrf *vrf)
void rip_vrf_init(void)
{
vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete,
- NULL);
+ rip_vrf_enable);
}
void rip_vrf_terminate(void)
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 49f7dda646..ef4e474737 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -2776,7 +2776,39 @@ static int ripng_vrf_enable(struct vrf *vrf)
int socket;
ripng = ripng_lookup_by_vrf_name(vrf->name);
- if (!ripng || ripng->enabled)
+ if (!ripng) {
+ char *old_vrf_name = NULL;
+
+ ripng = (struct ripng *)vrf->info;
+ if (!ripng)
+ return 0;
+ /* update vrf name */
+ if (ripng->vrf_name)
+ old_vrf_name = ripng->vrf_name;
+ ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf->name);
+ /*
+ * HACK: Change the RIPng VRF in the running configuration directly,
+ * bypassing the northbound layer. This is necessary to avoid deleting
+ * the RIPng and readding it in the new VRF, which would have
+ * several implications.
+ */
+ if (yang_module_find("frr-ripngd") && old_vrf_name) {
+ struct lyd_node *ripng_dnode;
+
+ ripng_dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-ripngd:ripngd/instance[vrf='%s']/vrf",
+ old_vrf_name);
+ if (ripng_dnode) {
+ yang_dnode_change_leaf(ripng_dnode, vrf->name);
+ running_config->version++;
+ }
+ }
+ if (old_vrf_name)
+ XFREE(MTYPE_RIPNG_VRF_NAME, old_vrf_name);
+ }
+
+ if (ripng->enabled)
return 0;
if (IS_RIPNG_DEBUG_EVENT)
@@ -2784,13 +2816,11 @@ static int ripng_vrf_enable(struct vrf *vrf)
vrf->vrf_id);
/* Activate the VRF RIPng instance. */
- if (!ripng->enabled) {
- socket = ripng_make_socket(vrf);
- if (socket < 0)
- return -1;
+ socket = ripng_make_socket(vrf);
+ if (socket < 0)
+ return -1;
- ripng_instance_enable(ripng, vrf, socket);
- }
+ ripng_instance_enable(ripng, vrf, socket);
return 0;
}
@@ -2817,7 +2847,7 @@ static int ripng_vrf_disable(struct vrf *vrf)
void ripng_vrf_init(void)
{
vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
- ripng_vrf_delete, NULL);
+ ripng_vrf_delete, ripng_vrf_enable);
}
void ripng_vrf_terminate(void)
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 9dd25fbdd1..abb64aad3f 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -27,6 +27,7 @@
#include "static_memory.h"
#include "static_vrf.h"
#include "static_routes.h"
+#include "static_zebra.h"
#include "static_vty.h"
static void zebra_stable_node_cleanup(struct route_table *table,
@@ -76,6 +77,8 @@ static int static_vrf_new(struct vrf *vrf)
static int static_vrf_enable(struct vrf *vrf)
{
+ static_zebra_vrf_register(vrf);
+
static_fixup_vrf_ids(vrf->info);
/*
@@ -89,6 +92,7 @@ static int static_vrf_enable(struct vrf *vrf)
static int static_vrf_disable(struct vrf *vrf)
{
+ static_zebra_vrf_unregister(vrf);
return 0;
}
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 1965c2968e..2944cdad32 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -526,3 +526,17 @@ void static_zebra_init(void)
static_nht_hash_cmp,
"Static Nexthop Tracking hash");
}
+
+void static_zebra_vrf_register(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+ zclient_send_reg_requests(zclient, vrf->vrf_id);
+}
+
+void static_zebra_vrf_unregister(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+ zclient_send_dereg_requests(zclient, vrf->vrf_id);
+}
diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h
index 15f5410b81..962dc3908f 100644
--- a/staticd/static_zebra.h
+++ b/staticd/static_zebra.h
@@ -28,4 +28,7 @@ extern void static_zebra_route_add(struct route_node *rn,
struct static_route *si_changed,
vrf_id_t vrf_id, safi_t safi, bool install);
extern void static_zebra_init(void);
+extern void static_zebra_vrf_register(struct vrf *vrf);
+extern void static_zebra_vrf_unregister(struct vrf *vrf);
+
#endif
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index b2612892f9..b5db36703a 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -1379,6 +1379,7 @@ int main(void)
i = 0;
+ frr_pthread_init();
bgp_pthreads_init();
bgp_pth_ka->running = true;
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index 968f9ac445..db1cf0611d 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -916,6 +916,7 @@ int main(void)
vrf_init(NULL, NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
+ frr_pthread_init();
bgp_pthreads_init();
bgp_pth_ka->running = true;
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 8e1b62ac15..e5d3030ed1 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -1391,6 +1391,7 @@ static void bgp_startup(void)
bgp_master_init(master);
bgp_option_set(BGP_OPT_NO_LISTEN);
vrf_init(NULL, NULL, NULL, NULL, NULL);
+ frr_pthread_init();
bgp_init(0);
bgp_pthreads_run();
}
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
index 6f8bc2218e..46e45e5ee0 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_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py b/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
index bee5115323..d6753e9b23 100644
--- a/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
+++ b/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
@@ -39,6 +39,7 @@ import sys
import json
import time
import pytest
+import functools
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, '../'))
@@ -88,21 +89,42 @@ def test_bgp_maximum_prefix_invalid():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
+ router = tgen.gears['r2']
+
def _bgp_converge(router):
- while True:
- output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
- if output['192.168.255.1']['bgpState'] == 'Established':
- if output['192.168.255.1']['addressFamilyInfo']['ipv4Unicast']['acceptedPrefixCounter'] == 3:
- return True
+ output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ expected = {
+ '192.168.255.1': {
+ 'bgpState': 'Established',
+ 'addressFamilyInfo': {
+ 'ipv4Unicast': {
+ 'acceptedPrefixCounter': 3
+ }
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
def _bgp_aggregate_address_has_metric(router):
- output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp 172.16.255.0/24 json"))
- if output['paths'][0]['med'] == 123:
- return True
- return False
+ output = json.loads(router.vtysh_cmd("show ip bgp 172.16.255.0/24 json"))
+ expected = {
+ 'paths': [
+ {
+ 'med': 123
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, 'Failed to see bgp convergence in "{}"'.format(router)
+
+ test_func = functools.partial(_bgp_aggregate_address_has_metric, router)
+ success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
- if _bgp_converge('r2'):
- assert _bgp_aggregate_address_has_metric('r2') == True
+ assert result is None, 'Failed to see applied metric for aggregated prefix in "{}"'.format(router)
if __name__ == '__main__':
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref-1 b/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref-1
deleted file mode 100644
index f244122f1a..0000000000
--- a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref-1
+++ /dev/null
@@ -1,5 +0,0 @@
-xx as to xx via inet 10.0.1.2 dev r1-eth0 proto xx
-xx as to xx via inet 10.0.1.2 dev r1-eth0 proto xx
-xx via inet 10.0.1.2 dev r1-eth0 proto xx
-xx via inet 10.0.1.2 dev r1-eth0 proto xx
-xx via inet 10.0.1.2 dev r1-eth0 proto xx
diff --git a/tests/topotests/ldp-topo1/r1/show_ipv4_route.ref-1 b/tests/topotests/ldp-topo1/r1/show_ipv4_route.ref-1
deleted file mode 100644
index ff99ff9866..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_ipv4_route.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
-O 1.1.1.1/32 [110/0] is directly connected, lo
-O>* 2.2.2.2/32 [110/10] via 10.0.1.2, r1-eth0
-O>* 3.3.3.3/32 [110/20] via 10.0.1.2, r1-eth0, label xxx
-O>* 4.4.4.4/32 [110/20] via 10.0.1.2, r1-eth0, label xxx
-O 10.0.1.0/24 [110/10] is directly connected, r1-eth0
-O>* 10.0.2.0/24 [110/20] via 10.0.1.2, r1-eth0
-O>* 10.0.3.0/24 [110/20] via 10.0.1.2, r1-eth0
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_binding.ref-1 b/tests/topotests/ldp-topo1/r1/show_mpls_ldp_binding.ref-1
deleted file mode 100644
index ff72a1c0b7..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_binding.ref-1
+++ /dev/null
@@ -1,42 +0,0 @@
-1.1.1.1/32
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
-2.2.2.2/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
-3.3.3.3/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
-4.4.4.4/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
-10.0.1.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
-10.0.2.0/24
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
-10.0.3.0/24
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_discovery.ref-1 b/tests/topotests/ldp-topo1/r1/show_mpls_ldp_discovery.ref-1
deleted file mode 100644
index 38522e162e..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_discovery.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
-Local LDP Identifier: 1.1.1.1:0
-Discovery Sources:
- Interfaces:
- r1-eth0: xmit/recv
- LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
- Hold time: 15 sec
- Targeted Hellos:
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_interface.ref-1 b/tests/topotests/ldp-topo1/r1/show_mpls_ldp_interface.ref-1
deleted file mode 100644
index 0fb15d2da7..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_interface.ref-1
+++ /dev/null
@@ -1,2 +0,0 @@
-AF Interface State Uptime Hello Timers ac
-ipv4 r1-eth0 ACTIVE xx:xx:xx 5/15 1
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_neighbor.ref-1 b/tests/topotests/ldp-topo1/r1/show_mpls_ldp_neighbor.ref-1
deleted file mode 100644
index 3df98bfae5..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_ldp_neighbor.ref-1
+++ /dev/null
@@ -1,8 +0,0 @@
-Peer LDP Identifier: 2.2.2.2:0
- TCP connection: 1.1.1.1:xxx - 2.2.2.2:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r1-eth0
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref b/tests/topotests/ldp-topo1/r1/show_mpls_table.ref
index 61cb9eec82..7e24359af3 100644
--- a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref
+++ b/tests/topotests/ldp-topo1/r1/show_mpls_table.ref
@@ -1,8 +1,8 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.2 XX
- XX LDP 10.0.1.2 XX
- XX LDP 10.0.1.2 implicit-null
- XX LDP 10.0.1.2 implicit-null
- XX LDP 10.0.1.2 implicit-null
+ Inbound Label Type Nexthop Outbound Label
+ -----------------------------------------------
+ XX LDP 10.0.1.2 XX
+ XX LDP 10.0.1.2 XX
+ XX LDP 10.0.1.2 implicit-null
+ XX LDP 10.0.1.2 implicit-null
+ XX LDP 10.0.1.2 implicit-null
+
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-1 b/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-1
deleted file mode 100644
index 912a082019..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-1
+++ /dev/null
@@ -1,8 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 XX
- XX LDP 10.0.1.2 XX
diff --git a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-no-impl-null b/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-no-impl-null
deleted file mode 100644
index 912a082019..0000000000
--- a/tests/topotests/ldp-topo1/r1/show_mpls_table.ref-no-impl-null
+++ /dev/null
@@ -1,8 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 3
- XX LDP 10.0.1.2 XX
- XX LDP 10.0.1.2 XX
diff --git a/tests/topotests/ldp-topo1/r2/show_ipv4_route.ref-1 b/tests/topotests/ldp-topo1/r2/show_ipv4_route.ref-1
deleted file mode 100644
index eaec2f16b9..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_ipv4_route.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
-O>* 1.1.1.1/32 [110/10] via 10.0.1.1, r2-eth0
-O 2.2.2.2/32 [110/0] is directly connected, lo
-O>* 3.3.3.3/32 [110/10] via 10.0.2.3, r2-eth1
-O>* 4.4.4.4/32 [110/10] via 10.0.2.4, r2-eth1
-O 10.0.1.0/24 [110/10] is directly connected, r2-eth0
-O 10.0.2.0/24 [110/10] is directly connected, r2-eth1
-O 10.0.3.0/24 [110/10] is directly connected, r2-eth2
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_binding.ref-1 b/tests/topotests/ldp-topo1/r2/show_mpls_ldp_binding.ref-1
deleted file mode 100644
index 54ee39080a..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_binding.ref-1
+++ /dev/null
@@ -1,56 +0,0 @@
-1.1.1.1/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 imp-null
- 3.3.3.3 xxx
- 4.4.4.4 xxx
-2.2.2.2/32
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 xxx
- 3.3.3.3 xxx
- 4.4.4.4 xxx
-3.3.3.3/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 xxx
- 3.3.3.3 imp-null
- 4.4.4.4 xxx
-4.4.4.4/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 xxx
- 3.3.3.3 xxx
- 4.4.4.4 imp-null
-10.0.1.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 imp-null
- 3.3.3.3 xxx
- 4.4.4.4 xxx
-10.0.2.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 xxx
- 3.3.3.3 imp-null
- 4.4.4.4 imp-null
-10.0.3.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 1.1.1.1 xxx
- 3.3.3.3 imp-null
- 4.4.4.4 xxx
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_discovery.ref-1 b/tests/topotests/ldp-topo1/r2/show_mpls_ldp_discovery.ref-1
deleted file mode 100644
index b1bebd7c46..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_discovery.ref-1
+++ /dev/null
@@ -1,12 +0,0 @@
-Local LDP Identifier: 2.2.2.2:0
-Discovery Sources:
- Interfaces:
- r2-eth0: xmit/recv
- LDP Id: 1.1.1.1:0, Transport address: 1.1.1.1
- Hold time: 15 sec
- r2-eth1: xmit/recv
- LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
- Hold time: 15 sec
- LDP Id: 4.4.4.4:0, Transport address: 4.4.4.4
- Hold time: 15 sec
- Targeted Hellos:
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_interface.ref-1 b/tests/topotests/ldp-topo1/r2/show_mpls_ldp_interface.ref-1
deleted file mode 100644
index f9fc98408c..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_interface.ref-1
+++ /dev/null
@@ -1,3 +0,0 @@
-AF Interface State Uptime Hello Timers ac
-ipv4 r2-eth0 ACTIVE xx:xx:xx 5/15 1
-ipv4 r2-eth1 ACTIVE xx:xx:xx 5/15 2
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_neighbor.ref-1 b/tests/topotests/ldp-topo1/r2/show_mpls_ldp_neighbor.ref-1
deleted file mode 100644
index a70e2f48c6..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_ldp_neighbor.ref-1
+++ /dev/null
@@ -1,26 +0,0 @@
-Peer LDP Identifier: 1.1.1.1:0
- TCP connection: 2.2.2.2:xxx - 1.1.1.1:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r2-eth0
-
-Peer LDP Identifier: 3.3.3.3:0
- TCP connection: 2.2.2.2:xxx - 3.3.3.3:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r2-eth1
-
-Peer LDP Identifier: 4.4.4.4:0
- TCP connection: 2.2.2.2:xxx - 4.4.4.4:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r2-eth1
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref b/tests/topotests/ldp-topo1/r2/show_mpls_table.ref
index 46420ccd11..df05a6b31a 100644
--- a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref
+++ b/tests/topotests/ldp-topo1/r2/show_mpls_table.ref
@@ -1,7 +1,7 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.1 implicit-null
- XX LDP 10.0.2.3 implicit-null
- XX LDP 10.0.2.4 implicit-null
- XX LDP 10.0.3.3 implicit-null
+ Inbound Label Type Nexthop Outbound Label
+ -----------------------------------------------
+ XX LDP 10.0.1.1 implicit-null
+ XX LDP 10.0.2.3 implicit-null
+ XX LDP 10.0.2.4 implicit-null
+ XX LDP 10.0.3.3 implicit-null
+
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-1 b/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-1
deleted file mode 100644
index ba244e76ec..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.1 3
- XX LDP 10.0.2.3 3
- XX LDP 10.0.2.4 3
- XX LDP 10.0.3.3 3
diff --git a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-no-impl-null b/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-no-impl-null
deleted file mode 100644
index ba244e76ec..0000000000
--- a/tests/topotests/ldp-topo1/r2/show_mpls_table.ref-no-impl-null
+++ /dev/null
@@ -1,7 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.1.1 3
- XX LDP 10.0.2.3 3
- XX LDP 10.0.2.4 3
- XX LDP 10.0.3.3 3
diff --git a/tests/topotests/ldp-topo1/r3/show_ipv4_route.ref-1 b/tests/topotests/ldp-topo1/r3/show_ipv4_route.ref-1
deleted file mode 100644
index c8a29400b2..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_ipv4_route.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
-O>* 1.1.1.1/32 [110/20] via 10.0.2.2, r3-eth0, label xxx
-O>* 2.2.2.2/32 [110/10] via 10.0.2.2, r3-eth0
-O 3.3.3.3/32 [110/0] is directly connected, lo
-O>* 4.4.4.4/32 [110/10] via 10.0.2.4, r3-eth0
-O>* 10.0.1.0/24 [110/20] via 10.0.2.2, r3-eth0
-O 10.0.2.0/24 [110/10] is directly connected, r3-eth0
-O 10.0.3.0/24 [110/10] is directly connected, r3-eth1
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_binding.ref-1 b/tests/topotests/ldp-topo1/r3/show_mpls_ldp_binding.ref-1
deleted file mode 100644
index e04d2b7e4a..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_binding.ref-1
+++ /dev/null
@@ -1,49 +0,0 @@
-1.1.1.1/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 4.4.4.4 xxx
-2.2.2.2/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 4.4.4.4 xxx
-3.3.3.3/32
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 4.4.4.4 xxx
-4.4.4.4/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 4.4.4.4 imp-null
-10.0.1.0/24
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 4.4.4.4 xxx
-10.0.2.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 4.4.4.4 imp-null
-10.0.3.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 4.4.4.4 xxx
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_discovery.ref-1 b/tests/topotests/ldp-topo1/r3/show_mpls_ldp_discovery.ref-1
deleted file mode 100644
index 5e299fff9c..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_discovery.ref-1
+++ /dev/null
@@ -1,9 +0,0 @@
-Local LDP Identifier: 3.3.3.3:0
-Discovery Sources:
- Interfaces:
- r3-eth0: xmit/recv
- LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
- Hold time: 15 sec
- LDP Id: 4.4.4.4:0, Transport address: 4.4.4.4
- Hold time: 15 sec
- Targeted Hellos:
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_interface.ref-1 b/tests/topotests/ldp-topo1/r3/show_mpls_ldp_interface.ref-1
deleted file mode 100644
index 243811e3a9..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_interface.ref-1
+++ /dev/null
@@ -1,2 +0,0 @@
-AF Interface State Uptime Hello Timers ac
-ipv4 r3-eth0 ACTIVE xx:xx:xx 5/15 2
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_neighbor.ref-1 b/tests/topotests/ldp-topo1/r3/show_mpls_ldp_neighbor.ref-1
deleted file mode 100644
index ee1983ac29..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_ldp_neighbor.ref-1
+++ /dev/null
@@ -1,17 +0,0 @@
-Peer LDP Identifier: 2.2.2.2:0
- TCP connection: 3.3.3.3:xxx - 2.2.2.2:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r3-eth0
-
-Peer LDP Identifier: 4.4.4.4:0
- TCP connection: 3.3.3.3:xxx - 4.4.4.4:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r3-eth0
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref b/tests/topotests/ldp-topo1/r3/show_mpls_table.ref
index c367f240f4..3978895613 100644
--- a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref
+++ b/tests/topotests/ldp-topo1/r3/show_mpls_table.ref
@@ -1,10 +1,10 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.2 implicit-null
- XX LDP 10.0.2.2 implicit-null
- XX LDP 10.0.2.4 implicit-null
- XX LDP 10.0.3.2 XX
- XX LDP 10.0.3.2 implicit-null
- XX LDP 10.0.3.2 implicit-null
+ Inbound Label Type Nexthop Outbound Label
+ -----------------------------------------------
+ XX LDP 10.0.2.2 XX
+ XX LDP 10.0.2.2 implicit-null
+ XX LDP 10.0.2.2 implicit-null
+ XX LDP 10.0.2.4 implicit-null
+ XX LDP 10.0.3.2 XX
+ XX LDP 10.0.3.2 implicit-null
+ XX LDP 10.0.3.2 implicit-null
+
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-1 b/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-1
deleted file mode 100644
index 9198969bd5..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-1
+++ /dev/null
@@ -1,10 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.4 3
- XX LDP 10.0.3.2 3
- XX LDP 10.0.3.2 3
- XX LDP 10.0.3.2 XX
diff --git a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-no-impl-null b/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-no-impl-null
deleted file mode 100644
index 9198969bd5..0000000000
--- a/tests/topotests/ldp-topo1/r3/show_mpls_table.ref-no-impl-null
+++ /dev/null
@@ -1,10 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.4 3
- XX LDP 10.0.3.2 3
- XX LDP 10.0.3.2 3
- XX LDP 10.0.3.2 XX
diff --git a/tests/topotests/ldp-topo1/r4/show_ipv4_route.ref-1 b/tests/topotests/ldp-topo1/r4/show_ipv4_route.ref-1
deleted file mode 100644
index df2a2b585f..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_ipv4_route.ref-1
+++ /dev/null
@@ -1,7 +0,0 @@
-O>* 1.1.1.1/32 [110/20] via 10.0.2.2, r4-eth0, label xxx
-O>* 2.2.2.2/32 [110/10] via 10.0.2.2, r4-eth0
-O>* 3.3.3.3/32 [110/10] via 10.0.2.3, r4-eth0
-O 4.4.4.4/32 [110/0] is directly connected, lo
-O>* 10.0.1.0/24 [110/20] via 10.0.2.2, r4-eth0
-O 10.0.2.0/24 [110/10] is directly connected, r4-eth0
-O>* 10.0.3.0/24 [110/20] via 10.0.2.2, r4-eth0
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_binding.ref-1 b/tests/topotests/ldp-topo1/r4/show_mpls_ldp_binding.ref-1
deleted file mode 100644
index 3d55805d7c..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_binding.ref-1
+++ /dev/null
@@ -1,49 +0,0 @@
-1.1.1.1/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 3.3.3.3 xxx
-2.2.2.2/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 xxx
-3.3.3.3/32
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 3.3.3.3 imp-null
-4.4.4.4/32
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 xxx
- 3.3.3.3 xxx
-10.0.1.0/24
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 xxx
-10.0.2.0/24
- Local binding: label: imp-null
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 imp-null
-10.0.3.0/24
- Local binding: label: xxx
- Remote bindings:
- Peer Label
- ----------------- ---------
- 2.2.2.2 imp-null
- 3.3.3.3 imp-null
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_discovery.ref-1 b/tests/topotests/ldp-topo1/r4/show_mpls_ldp_discovery.ref-1
deleted file mode 100644
index 3ebddd606a..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_discovery.ref-1
+++ /dev/null
@@ -1,9 +0,0 @@
-Local LDP Identifier: 4.4.4.4:0
-Discovery Sources:
- Interfaces:
- r4-eth0: xmit/recv
- LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
- Hold time: 15 sec
- LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
- Hold time: 15 sec
- Targeted Hellos:
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_interface.ref-1 b/tests/topotests/ldp-topo1/r4/show_mpls_ldp_interface.ref-1
deleted file mode 100644
index dd57656f15..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_interface.ref-1
+++ /dev/null
@@ -1,2 +0,0 @@
-AF Interface State Uptime Hello Timers ac
-ipv4 r4-eth0 ACTIVE xx:xx:xx 5/15 2
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_neighbor.ref-1 b/tests/topotests/ldp-topo1/r4/show_mpls_ldp_neighbor.ref-1
deleted file mode 100644
index fb0e7d7dfa..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_ldp_neighbor.ref-1
+++ /dev/null
@@ -1,17 +0,0 @@
-Peer LDP Identifier: 2.2.2.2:0
- TCP connection: 4.4.4.4:xxx - 2.2.2.2:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r4-eth0
-
-Peer LDP Identifier: 3.3.3.3:0
- TCP connection: 4.4.4.4:xxx - 3.3.3.3:xxx
- Session Holdtime: 180 sec
- State: OPERATIONAL; Downstream-Unsolicited
- Up time: xx:xx:xx
- LDP Discovery Sources:
- IPv4:
- Interface: r4-eth0
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref b/tests/topotests/ldp-topo1/r4/show_mpls_table.ref
index 9f86cd67cc..174dcebd4d 100644
--- a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref
+++ b/tests/topotests/ldp-topo1/r4/show_mpls_table.ref
@@ -1,9 +1,9 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.2 implicit-null
- XX LDP 10.0.2.2 implicit-null
- XX LDP 10.0.2.2 implicit-null
- XX LDP 10.0.2.3 implicit-null
- XX LDP 10.0.2.3 implicit-null
+ Inbound Label Type Nexthop Outbound Label
+ -----------------------------------------------
+ XX LDP 10.0.2.2 XX
+ XX LDP 10.0.2.2 implicit-null
+ XX LDP 10.0.2.2 implicit-null
+ XX LDP 10.0.2.2 implicit-null
+ XX LDP 10.0.2.3 implicit-null
+ XX LDP 10.0.2.3 implicit-null
+
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-1 b/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-1
deleted file mode 100644
index b8cf5a2702..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-1
+++ /dev/null
@@ -1,9 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.3 3
- XX LDP 10.0.2.3 3
diff --git a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-no-impl-null b/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-no-impl-null
deleted file mode 100644
index b8cf5a2702..0000000000
--- a/tests/topotests/ldp-topo1/r4/show_mpls_table.ref-no-impl-null
+++ /dev/null
@@ -1,9 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 3
- XX LDP 10.0.2.2 XX
- XX LDP 10.0.2.3 3
- XX LDP 10.0.2.3 3
diff --git a/tests/topotests/ldp-topo1/test_ldp_topo1.py b/tests/topotests/ldp-topo1/test_ldp_topo1.py
index 409a5f54c8..f02f4c4e21 100755
--- a/tests/topotests/ldp-topo1/test_ldp_topo1.py
+++ b/tests/topotests/ldp-topo1/test_ldp_topo1.py
@@ -77,12 +77,6 @@ from lib import topotest
fatal_error = ""
-# Expected version of CLI Output - Appendix to filename
-# empty string = current, latest output (default)
-# "-1" ... "-NNN" previous versions (incrementing with each version)
-cli_version = ""
-
-
#####################################################
##
## Network Topology Definition
@@ -164,7 +158,6 @@ def teardown_module(module):
def test_router_running():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -179,35 +172,12 @@ def test_router_running():
fatal_error = net['r%s' % i].checkRouterRunning()
assert fatal_error == "", fatal_error
- # Detect CLI Version
- # At this time, there are only 2 possible outputs, so simple check
- output = net['r1'].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
-
- # Check if old or new format of CLI Output. Default is to current format
- #
- # Old (v1) output looks like this:
- # Local LDP Identifier: 1.1.1.1:0
- # Discovery Sources:
- # Interfaces:
- # r1-eth0: xmit/recv
- # LDP Id: 2.2.2.2:0, Transport address: 2.2.2.2
- # Hold time: 15 sec
- # Targeted Hellos:
- #
- # Current (v0) output looks like this:
- # AF ID Type Source Holdtime
- # ipv4 2.2.2.2 Link r1-eth0 15
- pattern = re.compile("^Local LDP Identifier.*")
- if pattern.match(output):
- cli_version = "-1"
-
# For debugging after starting FRR/Quagga daemons, uncomment the next line
# CLI(net)
def test_mpls_interfaces():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -220,7 +190,7 @@ def test_mpls_interfaces():
print("******************************************\n")
failures = 0
for i in range(1, 5):
- refTableFile = '%s/r%s/show_mpls_ldp_interface.ref%s' % (thisDir, i, cli_version)
+ refTableFile = '%s/r%s/show_mpls_ldp_interface.ref'
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -263,7 +233,6 @@ def test_mpls_interfaces():
def test_mpls_ldp_neighbor_establish():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -279,22 +248,22 @@ def test_mpls_ldp_neighbor_establish():
# Look for any node not yet converged
for i in range(1, 5):
established = net['r%s' % i].cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null').rstrip()
- if cli_version != "-1":
- # On current version, we need to make sure they all turn to OPERATIONAL on all lines
- #
- lines = ('\n'.join(established.splitlines()) + '\n').splitlines(1)
- # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
- header = r'^AF.*'
- operational = r'^ip.*OPERATIONAL.*'
- found_operational = 0
- for j in range(1, len(lines)):
- if (not re.search(header, lines[j])) and (not re.search(operational, lines[j])):
- established = "" # Empty string shows NOT established
- if re.search(operational, lines[j]):
- found_operational += 1
- if found_operational < 1:
- # Need at least one operational neighbor
+
+ # On current version, we need to make sure they all turn to OPERATIONAL on all lines
+ #
+ lines = ('\n'.join(established.splitlines()) + '\n').splitlines(1)
+ # Check all lines to be either table header (starting with ^AF or show OPERATIONAL)
+ header = r'^AF.*'
+ operational = r'^ip.*OPERATIONAL.*'
+ found_operational = 0
+ for j in range(1, len(lines)):
+ if (not re.search(header, lines[j])) and (not re.search(operational, lines[j])):
established = "" # Empty string shows NOT established
+ if re.search(operational, lines[j]):
+ found_operational += 1
+ if found_operational < 1:
+ # Need at least one operational neighbor
+ established = "" # Empty string shows NOT established
if not established:
print('Waiting for r%s' %i)
sys.stdout.flush()
@@ -326,7 +295,6 @@ def test_mpls_ldp_neighbor_establish():
def test_mpls_ldp_discovery():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -339,7 +307,7 @@ def test_mpls_ldp_discovery():
print("******************************************\n")
failures = 0
for i in range(1, 5):
- refTableFile = '%s/r%s/show_mpls_ldp_discovery.ref%s' % (thisDir, i, cli_version)
+ refTableFile = '%s/r%s/show_mpls_ldp_discovery.ref'
if os.path.isfile(refTableFile):
# Actual output from router
actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp discovery" 2> /dev/null').rstrip()
@@ -381,7 +349,6 @@ def test_mpls_ldp_discovery():
def test_mpls_ldp_neighbor():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -394,7 +361,7 @@ def test_mpls_ldp_neighbor():
print("******************************************\n")
failures = 0
for i in range(1, 5):
- refTableFile = '%s/r%s/show_mpls_ldp_neighbor.ref%s' % (thisDir, i, cli_version)
+ refTableFile = '%s/r%s/show_mpls_ldp_neighbor.ref'
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -405,17 +372,8 @@ def test_mpls_ldp_neighbor():
actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp neighbor" 2> /dev/null').rstrip()
# Mask out changing parts in output
- if cli_version == "-1":
- # Mask out Timer in Uptime
- actual = re.sub(r"Up time: [0-9][0-9]:[0-9][0-9]:[0-9][0-9]", "Up time: xx:xx:xx", actual)
- # Mask out Port numbers in TCP connection
- actual = re.sub(r"TCP connection: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]):[0-9]+ - ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]):[0-9]+",
- r"TCP connection: \1:xxx - \2:xxx", actual)
- else:
- # Current Version
- #
- # Mask out Timer in Uptime
- actual = re.sub(r"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]", r"\1xx:xx:xx", actual)
+ # Mask out Timer in Uptime
+ actual = re.sub(r"(ipv4 [0-9\.]+ +OPERATIONAL [0-9\.]+ +)[0-9][0-9]:[0-9][0-9]:[0-9][0-9]", r"\1xx:xx:xx", actual)
# Fix newlines (make them all the same)
actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
@@ -446,7 +404,6 @@ def test_mpls_ldp_neighbor():
def test_mpls_ldp_binding():
global fatal_error
global net
- global cli_version
# Skip this test for now until proper sorting of the output
# is implemented
@@ -463,7 +420,7 @@ def test_mpls_ldp_binding():
print("******************************************\n")
failures = 0
for i in range(1, 5):
- refTableFile = '%s/r%s/show_mpls_ldp_binding.ref%s' % (thisDir, i, cli_version)
+ refTableFile = '%s/r%s/show_mpls_ldp_binding.ref'
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -474,16 +431,9 @@ def test_mpls_ldp_binding():
actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp binding" 2> /dev/null').rstrip()
# Mask out changing parts in output
- if cli_version == "-1":
- # Mask out label
- actual = re.sub(r"label: [0-9]+", "label: xxx", actual)
- actual = re.sub(r"(\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[ ]+)[0-9]+", r"\1xxx", actual)
- else:
- # Current Version
- #
- # Mask out label
- actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
- actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
+ # Mask out label
+ actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
+ actual = re.sub(r"(ipv4 [0-9\./]+ +[0-9\.]+ +[a-z\-]+ +)[0-9][0-9] (.*)", r"\1xxx\2", actual)
# Fix newlines (make them all the same)
actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
@@ -527,7 +477,6 @@ def test_mpls_ldp_binding():
def test_zebra_ipv4_routingTable():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -540,7 +489,7 @@ def test_zebra_ipv4_routingTable():
print("******************************************\n")
failures = 0
for i in range(1, 5):
- refTableFile = '%s/r%s/show_ipv4_route.ref%s' % (thisDir, i, cli_version)
+ refTableFile = '%s/r%s/show_ipv4_route.ref'
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -562,9 +511,6 @@ def test_zebra_ipv4_routingTable():
# now fix newlines of expected (make them all the same)
expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
- # Add missing comma before label (for old version)
- actual = re.sub(r"([0-9]) label ", r"\1, label ", actual)
-
# Fix newlines (make them all the same)
actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
@@ -594,7 +540,6 @@ def test_zebra_ipv4_routingTable():
def test_mpls_table():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
@@ -607,23 +552,16 @@ def test_mpls_table():
print("******************************************\n")
failures = 0
- version = cli_version
- if (version == ""):
- # check for new output without implicit-null
- output = net['r1'].cmd('vtysh -c "show mpls table" 2> /dev/null').rstrip()
- if 'LDP 10.0.1.2 3' in output:
- version = "-no-impl-null"
-
for i in range(1, 5):
- refTableFile = '%s/r%s/show_mpls_table.ref%s' % (thisDir, i, version)
+ refTableFile = '%s/r%s/show_mpls_table.ref'
if os.path.isfile(refTableFile):
# Read expected result from file
- expected = open(refTableFile).read().rstrip()
+ expected = open(refTableFile).read()
# Fix newlines (make them all the same)
expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
# Actual output from router
- actual = net['r%s' % i].cmd('vtysh -c "show mpls table" 2> /dev/null').rstrip()
+ actual = net['r%s' % i].cmd('vtysh -c "show mpls table" 2> /dev/null')
# Fix inconsistent Label numbers at beginning of line
actual = re.sub(r"(\s+)[0-9]+(\s+LDP)", r"\1XX\2", actual)
@@ -672,7 +610,6 @@ def test_mpls_table():
def test_linux_mpls_routes():
global fatal_error
global net
- global cli_version
# Skip if previous fatal error condition is raised
if (fatal_error != ""):
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref
deleted file mode 100644
index fb193265be..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "neighbors":[
- {
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
-
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index 7c4d0ab58c..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1"
- }
- ],
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index 2270c3fdde..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "2.2.2.2":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1"
- },
- "3.3.3.3":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref
deleted file mode 100644
index 1376579757..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "neighbors":[
- {
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index a982c1cbd3..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2"
- }
- ],
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index 18ffbc2f8a..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "1.1.1.1":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2"
- },
- "3.3.3.3":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref
deleted file mode 100644
index 41de304b2b..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "neighbors":[
- {
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index d7e0e42405..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3"
- }
- ],
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index b0669742ab..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "1.1.1.1":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3"
- },
- "2.2.2.2":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
index 0948c2e41b..ce651c50cd 100755
--- a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
+++ b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
@@ -144,9 +144,6 @@ def setup_module(mod):
)
tgen.start_router()
- for router in router_list.values():
- if router.has_version('<', '3'):
- tgen.set_error('unsupported version')
def teardown_module(mod):
"Teardown the pytest environment"
@@ -180,30 +177,8 @@ def test_ospf_convergence():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- # Old output (before FRR PR1383) didn't show a list of neighbors.
- # Check for dict object and compare to old output if this is the case
- tgen = get_topogen()
- router = tgen.gears['r1']
- output = router.vtysh_cmd("show ip ospf neighbor json", isjson=True)
-
- # We could have either old format (without "neighbors" and direct list
- # of IP's or new format from PR1659 with "neighbors".
- # Trying old formats first and fall back to new format
- #
- # New format: neighbors have dict instead of list of dicts (PR1723).
- if output.has_key('neighbors'):
- if isinstance(output['neighbors'], dict):
- reffile = "show_ip_ospf_neighbor.json"
- else:
- reffile = "show_ip_ospf_neighbor.ref"
- else:
- if isinstance(output["2.2.2.2"], dict):
- reffile = "show_ip_ospf_neighbor.ref-old-nolist"
- else:
- reffile = "show_ip_ospf_neighbor.ref-no-neigh"
-
for rname in ['r1', 'r2', 'r3']:
- router_compare_json_output(rname, "show ip ospf neighbor json", reffile)
+ router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json")
def test_rib():
logger.info("Test: verify RIB")
diff --git a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json
index 254c137acd..6b1fe76b6e 100644
--- a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json
+++ b/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json
@@ -4,7 +4,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -17,7 +17,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -30,7 +30,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8300,
"distance":150,
"installed":true,
@@ -43,7 +43,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8400,
"distance":150,
"installed":true,
@@ -56,7 +56,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -69,7 +69,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
diff --git a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json
index 0d73a409ed..79965d280a 100644
--- a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json
+++ b/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json
@@ -4,7 +4,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":20100,
"distance":150,
"installed":true,
@@ -17,7 +17,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -30,7 +30,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":10400,
"distance":150,
"installed":true,
@@ -43,7 +43,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -56,7 +56,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -69,7 +69,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -82,7 +82,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -95,7 +95,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -108,7 +108,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
diff --git a/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json
index b15f90afd1..ceb2f7a0e5 100644
--- a/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json
+++ b/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json
@@ -4,7 +4,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8100,
"distance":150,
"installed":true,
@@ -17,7 +17,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -30,7 +30,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8400,
"distance":150,
"installed":true,
@@ -43,7 +43,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -56,7 +56,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
diff --git a/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json
index d1238517f5..d7f54b224d 100644
--- a/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json
+++ b/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json
@@ -4,7 +4,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8100,
"distance":150,
"installed":true,
@@ -17,7 +17,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -30,7 +30,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":8300,
"distance":150,
"installed":true,
@@ -43,7 +43,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -56,7 +56,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
@@ -69,7 +69,7 @@
"installed":true,
"nexthops":[
{
- "type":"SR",
+ "type":"SR (OSPF)",
"outLabel":3,
"distance":150,
"installed":true,
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index ade5bfd501..b65f93856f 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -1,6 +1,6 @@
# Skip pytests example directory
[pytest]
-norecursedirs = .git example-test example-topojson-test lib docker
+norecursedirs = .git example-test example-topojson-test lib docker bgp-ecmp-topo2
[topogen]
# Default configuration values
diff --git a/tools/etc/frr/support_bundle_commands.conf b/tools/etc/frr/support_bundle_commands.conf
index d52824ff07..8845df5fc7 100644
--- a/tools/etc/frr/support_bundle_commands.conf
+++ b/tools/etc/frr/support_bundle_commands.conf
@@ -28,6 +28,7 @@ show bgp ipv6 update-groups advertised-routes
show bgp ipv6 update-groups packet-queue
show bgp ipv6 update-groups statistics
show ip bgp statistics
+show bgp martian next-hop
show bgp evpn route
CMD_LIST_END
@@ -37,14 +38,17 @@ PROC_NAME:zebra
CMD_LIST_START
show zebra
show zebra client summary
-show ip route
-
+show ip zebra route dump json
+show ipv6 zebra route dump json
+show ip nht vrf all
show route-map
show memory
-show interface
+show interface vrf all
show vrf
+show zebra fpm stats
show error all
show work-queues
+show debugging hashtable
show running-config
show thread cpu
show thread poll
diff --git a/tools/generate_support_bundle.py b/tools/generate_support_bundle.py
index 118ca113a5..c9ca9c3d0d 100644..100755
--- a/tools/generate_support_bundle.py
+++ b/tools/generate_support_bundle.py
@@ -1,3 +1,5 @@
+#!/usr/bin/python
+
########################################################
### Python Script to generate the FRR support bundle ###
########################################################
diff --git a/tools/subdir.am b/tools/subdir.am
index 7713bb1ade..c637db6eb1 100644
--- a/tools/subdir.am
+++ b/tools/subdir.am
@@ -16,6 +16,7 @@ sbin_SCRIPTS += \
\
tools/frrcommon.sh \
tools/frrinit.sh \
+ tools/generate_support_bundle.py \
tools/watchfrr.sh \
# end
@@ -35,6 +36,7 @@ EXTRA_DIST += \
tools/frr-reload \
tools/frr-reload.py \
tools/frr.service \
+ tools/generate_support_bundle.py \
tools/multiple-bgpd.sh \
tools/rrcheck.pl \
tools/rrlookup.pl \
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index a762e9555c..08126f6885 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2422,6 +2422,53 @@ DEFUN (vtysh_show_error_code,
return CMD_SUCCESS;
}
+/* Northbound. */
+DEFUN (show_yang_operational_data,
+ show_yang_operational_data_cmd,
+ "show yang operational-data XPATH$xpath\
+ [{\
+ format <json$json|xml$xml>\
+ |translate WORD$translator_family\
+ }]" DAEMONS_LIST,
+ SHOW_STR
+ "YANG information\n"
+ "Show YANG operational data\n"
+ "XPath expression specifying the YANG data path\n"
+ "Set the output format\n"
+ "JavaScript Object Notation\n"
+ "Extensible Markup Language\n"
+ "Translate operational data\n"
+ "YANG module translator\n"
+ DAEMONS_STR)
+{
+ int idx_protocol = argc - 1;
+ char *fcmd = argv_concat(argv, argc - 1, 0);
+ int ret = vtysh_client_execute_name(argv[idx_protocol]->text, fcmd);
+ XFREE(MTYPE_TMP, fcmd);
+ return ret;
+}
+
+DEFUNSH(VTYSH_ALL, debug_nb,
+ debug_nb_cmd,
+ "[no] debug northbound\
+ [<\
+ callbacks$cbs [{configuration$cbs_cfg|state$cbs_state|rpc$cbs_rpc}]\
+ |notifications$notifications\
+ |events$events\
+ >]",
+ NO_STR
+ DEBUG_STR
+ "Northbound debugging\n"
+ "Callbacks\n"
+ "Configuration\n"
+ "State\n"
+ "RPC\n"
+ "Notifications\n"
+ "Events\n")
+{
+ return CMD_SUCCESS;
+}
+
/* Memory */
DEFUN (vtysh_show_memory,
vtysh_show_memory_cmd,
@@ -2548,10 +2595,11 @@ DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd,
}
DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
- "no log facility [FACILITY]", NO_STR
+ "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
+ NO_STR
"Logging control\n"
"Reset syslog facility to default (daemon)\n"
- "Syslog facility\n")
+ LOG_FACILITY_DESC)
{
return CMD_SUCCESS;
}
@@ -4017,6 +4065,11 @@ void vtysh_init_vty(void)
install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd);
install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
+ /* northbound */
+ install_element(VIEW_NODE, &show_yang_operational_data_cmd);
+ install_element(ENABLE_NODE, &debug_nb_cmd);
+ install_element(CONFIG_NODE, &debug_nb_cmd);
+
/* misc lib show commands */
install_element(VIEW_NODE, &vtysh_show_memory_cmd);
install_element(VIEW_NODE, &vtysh_show_modules_cmd);
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 3ec2eb239d..e56c6fbf4e 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -406,7 +406,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
== 0
|| strncmp(line, "frr", strlen("frr")) == 0
|| strncmp(line, "agentx", strlen("agentx")) == 0
- || strncmp(line, "no log", strlen("no log")) == 0)
+ || strncmp(line, "no log", strlen("no log")) == 0
+ || strncmp(line, "no ip prefix-list", strlen("no ip prefix-list")) == 0
+ || strncmp(line, "no ipv6 prefix-list", strlen("no ipv6 prefix-list")) == 0)
config_add_line_uniq(config_top, line);
else
config_add_line(config_top, line);
diff --git a/watchfrr/subdir.am b/watchfrr/subdir.am
index c27491e55c..30f606c202 100644
--- a/watchfrr/subdir.am
+++ b/watchfrr/subdir.am
@@ -19,3 +19,6 @@ watchfrr_watchfrr_SOURCES = \
watchfrr/watchfrr_errors.c \
watchfrr/watchfrr_vty.c \
# end
+
+watchfrr/watchfrr_vty_clippy.c: $(CLIPPY_DEPS)
+watchfrr/watchfrr_vty.$(OBJEXT): watchfrr/watchfrr_vty_clippy.c
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index c17d381730..a6a910a1db 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -159,6 +159,15 @@ struct daemon {
struct thread *t_write;
struct daemon *next;
struct restart_info restart;
+
+ /*
+ * For a given daemon, if we've turned on ignore timeouts
+ * ignore the timeout value and assume everything is ok
+ * This is for daemon debugging w/ gdb after we have started
+ * FRR and realize we have something that needs to be looked
+ * at
+ */
+ bool ignore_timeout;
};
#define OPTION_MINRESTART 2000
@@ -191,6 +200,25 @@ static void phase_check(void);
static void restart_done(struct daemon *dmn);
static const char *progname;
+
+void watchfrr_set_ignore_daemon(struct vty *vty, const char *dname, bool ignore)
+{
+ struct daemon *dmn;
+
+ for (dmn = gs.daemons; dmn; dmn = dmn->next) {
+ if (strncmp(dmn->name, dname, strlen(dmn->name)) == 0)
+ break;
+ }
+
+ if (dmn) {
+ dmn->ignore_timeout = ignore;
+ vty_out(vty, "%s switching to %s\n", dmn->name,
+ ignore ? "ignore" : "watch");
+ } else
+ vty_out(vty, "%s is not configured for running at the moment",
+ dname);
+}
+
static void printhelp(FILE *target)
{
fprintf(target,
@@ -533,7 +561,9 @@ static int wakeup_init(struct thread *t_wakeup)
static void restart_done(struct daemon *dmn)
{
if (dmn->state != DAEMON_DOWN) {
- zlog_warn("wtf?");
+ zlog_warn(
+ "Daemon: %s: is in %s state but expected it to be in DAEMON_DOWN state",
+ dmn->name, state_str[dmn->state]);
return;
}
if (dmn->t_wakeup)
@@ -961,6 +991,8 @@ static int wakeup_no_answer(struct thread *t_wakeup)
dmn->t_wakeup = NULL;
dmn->state = DAEMON_UNRESPONSIVE;
+ if (dmn->ignore_timeout)
+ return 0;
flog_err(EC_WATCHFRR_CONNECTION,
"%s state -> unresponsive : no response yet to ping "
"sent %ld seconds ago",
@@ -1014,7 +1046,8 @@ void watchfrr_status(struct vty *vty)
(long)gs.restart.pid);
for (dmn = gs.daemons; dmn; dmn = dmn->next) {
- vty_out(vty, " %-20s %s\n", dmn->name, state_str[dmn->state]);
+ vty_out(vty, " %-20s %s%s", dmn->name, state_str[dmn->state],
+ dmn->ignore_timeout ? "/Ignoring Timeout\n" : "\n");
if (dmn->restart.pid)
vty_out(vty, " restart running, pid %ld\n",
(long)dmn->restart.pid);
diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h
index c5f54769bd..ba6e94960f 100644
--- a/watchfrr/watchfrr.h
+++ b/watchfrr/watchfrr.h
@@ -41,4 +41,6 @@ extern void watchfrr_status(struct vty *vty);
*/
extern bool check_all_up(void);
+extern void watchfrr_set_ignore_daemon(struct vty *vty, const char *dname,
+ bool ignore);
#endif /* FRR_WATCHFRR_H */
diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c
index 9b844d67f2..c06cb89382 100644
--- a/watchfrr/watchfrr_vty.c
+++ b/watchfrr/watchfrr_vty.c
@@ -134,6 +134,23 @@ DEFUN (show_watchfrr,
return CMD_SUCCESS;
}
+#ifndef VTYSH_EXTRACT_PL
+#include "watchfrr/watchfrr_vty_clippy.c"
+#endif
+
+DEFPY (watchfrr_ignore_daemon,
+ watchfrr_ignore_daemon_cmd,
+ "[no] watchfrr ignore DAEMON$dname",
+ NO_STR
+ "Watchfrr Specific sub-command\n"
+ "Ignore a specified daemon when it does not respond to echo request\n"
+ "The daemon to ignore\n")
+{
+ watchfrr_set_ignore_daemon(vty, dname, no ? false : true );
+
+ return CMD_SUCCESS;
+}
+
void integrated_write_sigchld(int status)
{
uint8_t reply[4] = {0, 0, 0, CMD_WARNING};
@@ -168,6 +185,9 @@ void watchfrr_vty_init(void)
integrated_write_pid = -1;
install_element(ENABLE_NODE, &config_write_integrated_cmd);
install_element(ENABLE_NODE, &show_debugging_watchfrr_cmd);
+
+ install_element(ENABLE_NODE, &watchfrr_ignore_daemon_cmd);
+
install_element(CONFIG_NODE, &show_debugging_watchfrr_cmd);
install_element(VIEW_NODE, &show_watchfrr_cmd);
}
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 3313dc2f20..faa880eff4 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -61,6 +61,13 @@ module frr-isisd {
"This type defines IS-IS level of an object.";
}
+ typedef extended-circuit-id {
+ type uint32;
+ description
+ "This type defines the extended circuit ID
+ associated with an interface.";
+ }
+
typedef network-type {
type enumeration {
enum "unknown" {
@@ -95,6 +102,20 @@ module frr-isisd {
pattern, An example LSP ID is 0143.0438.AeF0.02-01";
}
+ typedef snpa {
+ type string {
+ length "0 .. 20";
+ }
+ description
+ "This type defines the Subnetwork Point
+ of Attachment (SNPA) format.
+ The SNPA should be encoded according to the rules
+ specified for the particular type of subnetwork
+ being used. As an example, for an ethernet subnetwork,
+ the SNPA is encoded as a MAC address like
+ '00aa.bbcc.ddee'.";
+ }
+
typedef system-id {
type string {
pattern "[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}";
@@ -275,6 +296,399 @@ module frr-isisd {
}
}
+ grouping interface-config {
+ description "Interface configuration grouping";
+
+ leaf area-tag {
+ type string;
+ mandatory true;
+ description
+ "Area-tag associated to this circuit.";
+ }
+
+ leaf ipv4-routing {
+ type boolean;
+ default "false";
+ description
+ "Routing IS-IS IPv4 traffic over this circuit.";
+ }
+
+ leaf ipv6-routing {
+ type boolean;
+ default "false";
+ description
+ "Routing IS-IS IPv6 traffic over this circuit.";
+ }
+
+ leaf circuit-type {
+ type level;
+ default "level-1-2";
+ description
+ "IS-type of this circuit.";
+ }
+
+ leaf bfd-monitoring {
+ type boolean;
+ default false;
+ description "Monitor IS-IS peers on this circuit.";
+ }
+
+ container csnp-interval {
+ description
+ "Complete Sequence Number PDU (CSNP) generation interval.";
+ leaf level-1 {
+ type uint16 {
+ range "1..600";
+ }
+ units "seconds";
+ default "10";
+ description
+ "CNSP interval for level-1";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "1..600";
+ }
+ units "seconds";
+ default "10";
+ description
+ "CNSP interval for level-2";
+ }
+ }
+
+ container psnp-interval {
+ description
+ "Partial Sequence Number PDU (PSNP) generation interval.";
+ leaf level-1 {
+ type uint16 {
+ range "1..120";
+ }
+ units "seconds";
+ default "2";
+ description
+ "PNSP interval for level-1";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "1..120";
+ }
+ units "seconds";
+ default "2";
+ description
+ "PCNSP interval for level-2";
+ }
+ }
+
+ container hello {
+ description
+ "Parameters related to IS-IS hello PDUs.";
+ leaf padding {
+ type boolean;
+ default "true";
+ description
+ "Add padding to IS-IS hello PDUs.";
+ }
+
+ container interval {
+ description
+ "Interval between consecutive hello messages.";
+ leaf level-1 {
+ type uint32 {
+ range "1..600";
+ }
+ units "seconds";
+ default "3";
+ description
+ "Holding time for level-1; interval will depend on multiplier.";
+ }
+
+ leaf level-2 {
+ type uint32 {
+ range "1..600";
+ }
+ units "seconds";
+ default "3";
+ description
+ "Holding time for level-2; interval will depend on multiplier.";
+ }
+ }
+
+ container multiplier {
+ description
+ "Multiplier for the hello messages holding time.";
+ leaf level-1 {
+ type uint16 {
+ range "2..100";
+ }
+ default "10";
+ description
+ "Multiplier for the hello holding time.";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "2..100";
+ }
+ default "10";
+ description
+ "Multiplier for the hello holding time.";
+ }
+ }
+ }
+
+ container metric {
+ description
+ "Default metric for this IS-IS circuit.";
+ leaf level-1 {
+ type uint32 {
+ range "0..16777215";
+ }
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ default "10";
+ description
+ "Default level-1 metric for this IS-IS circuit.";
+ }
+
+ leaf level-2 {
+ type uint32 {
+ range "0..16777215";
+ }
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ default "10";
+ description
+ "Default level-2 metric for this IS-IS circuit.";
+ }
+ }
+
+ container priority {
+ description
+ "Priority for Designated Router election.";
+ leaf level-1 {
+ type uint8 {
+ range "0..127";
+ }
+ default "64";
+ description
+ "Level-1 priority for this IS-IS circuit.";
+ }
+
+ leaf level-2 {
+ type uint8 {
+ range "0..127";
+ }
+ default "64";
+ description
+ "Level-2 priority for this IS-IS circuit.";
+ }
+ }
+
+ leaf network-type {
+ type network-type;
+ default "broadcast";
+ must "(. = \"point-to-point\") or (. = \"broadcast\")";
+ description
+ "Explicitly configured type of IS-IS circuit (broadcast or point-to-point).";
+ }
+
+ leaf passive {
+ type boolean;
+ default "false";
+ description
+ "Interface is in passive mode.";
+ }
+
+ container password {
+ presence "Present if a password is set for this IS interface.";
+ uses isis-password;
+ }
+
+ leaf disable-three-way-handshake {
+ type boolean;
+ default "false";
+ description
+ "Disables three-way handshake when creating new adjacencies.";
+ }
+
+ container multi-topology {
+ description
+ "IS-IS topologies configured on this circuit.";
+ leaf ipv4-unicast {
+ type boolean;
+ default "true";
+ description
+ "IPv4 unicast topology.";
+ }
+
+ leaf ipv4-multicast {
+ type boolean;
+ default "true";
+ description
+ "IPv4 multicast topology.";
+ }
+
+ leaf ipv4-management {
+ type boolean;
+ default "true";
+ description
+ "IPv4 management topology.";
+ }
+
+ leaf ipv6-unicast {
+ type boolean;
+ default "true";
+ description
+ "IPv6 unicast topology.";
+ }
+
+ leaf ipv6-multicast {
+ type boolean;
+ default "true";
+ description
+ "IPv6 multicast topology.";
+ }
+
+ leaf ipv6-management {
+ type boolean;
+ default "true";
+ description
+ "IPv6 management topology.";
+ }
+
+ leaf ipv6-dstsrc {
+ type boolean;
+ default "true";
+ description
+ "IPv6 destination-source topology.";
+ }
+ }
+ }
+
+ grouping adjacency-state {
+ container adjacencies {
+ config false;
+ list adjacency {
+ leaf neighbor-sys-type {
+ type level;
+ description
+ "Level capability of neighboring system";
+ }
+ leaf neighbor-sysid {
+ type system-id;
+ description
+ "The system-id of the neighbor";
+ }
+ leaf neighbor-extended-circuit-id {
+ type extended-circuit-id;
+ description
+ "Circuit ID of the neighbor";
+ }
+ leaf neighbor-snpa {
+ type snpa;
+ description
+ "SNPA of the neighbor";
+ }
+ leaf hold-timer {
+ type uint16;
+ units seconds;
+ description
+ "The holding time in seconds for this
+ adjacency. This value is based on
+ received hello PDUs and the elapsed
+ time since receipt.";
+ }
+ leaf neighbor-priority {
+ type uint8 {
+ range "0 .. 127";
+ }
+ description
+ "Priority of the neighboring IS for becoming
+ the DIS.";
+ }
+ leaf state {
+ type adj-state-type;
+ description
+ "This leaf describes the state of the interface.";
+ }
+
+ description
+ "List of operational adjacencies.";
+ }
+ description
+ "This container lists the adjacencies of
+ the local node.";
+ }
+ description
+ "Adjacency state";
+ }
+
+ grouping event-counters {
+ container event-counters {
+ config false;
+ leaf adjacency-changes {
+ type uint32;
+ description
+ "The number of times an adjacency state change has
+ occurred on this interface.";
+ }
+ leaf adjacency-number {
+ type uint32;
+ description
+ "The number of adjacencies on this interface.";
+ }
+ leaf init-fails {
+ type uint32;
+ description
+ "The number of times initialization of this
+ interface has failed. This counts events such
+ as PPP NCP failures. Failures to form an
+ adjacency are counted by adjacency-rejects.";
+ }
+ leaf adjacency-rejects {
+ type uint32;
+ description
+ "The number of times an adjacency has been
+ rejected on this interface.";
+ }
+ leaf id-len-mismatch {
+ type uint32;
+ description
+ "The number of times an IS-IS PDU with an ID
+ field length different from that for this
+ system has been received on this interface.";
+ }
+ leaf max-area-addresses-mismatch {
+ type uint32;
+ description
+ "The number of times an IS-IS PDU has been
+ received on this interface with the
+ max area address field differing from that of
+ this system.";
+ }
+ leaf authentication-type-fails {
+ type uint32;
+ description
+ "Number of authentication type mismatches.";
+ }
+ leaf authentication-fails {
+ type uint32;
+ description
+ "Number of authentication key failures.";
+ }
+ description "IS-IS interface event counters.";
+ }
+ description
+ "Grouping for IS-IS interface event counters";
+ }
+
+ grouping interface-state {
+ description
+ "IS-IS interface operational state.";
+ uses adjacency-state;
+ uses event-counters;
+ }
+
grouping notification-instance-hdr {
description
"Instance specific IS-IS notification data grouping";
@@ -313,7 +727,7 @@ module frr-isisd {
}
leaf extended-circuit-id {
- type uint32;
+ type extended-circuit-id;
description
"Eextended circuit-id of the interface.";
}
@@ -733,270 +1147,8 @@ module frr-isisd {
presence "Present if an IS-IS circuit is defined for this interface.";
description
"IS-IS interface parameters.";
- leaf area-tag {
- type string;
- mandatory true;
- description
- "Area-tag associated to this circuit.";
- }
-
- leaf ipv4-routing {
- type boolean;
- default "false";
- description
- "Routing IS-IS IPv4 traffic over this circuit.";
- }
-
- leaf ipv6-routing {
- type boolean;
- default "false";
- description
- "Routing IS-IS IPv6 traffic over this circuit.";
- }
-
- leaf circuit-type {
- type level;
- default "level-1-2";
- description
- "IS-type of this circuit.";
- }
-
- leaf bfd-monitoring {
- type boolean;
- default false;
- description "Monitor IS-IS peers on this circuit.";
- }
-
- container csnp-interval {
- description
- "Complete Sequence Number PDU (CSNP) generation interval.";
- leaf level-1 {
- type uint16 {
- range "1..600";
- }
- units "seconds";
- default "10";
- description
- "CNSP interval for level-1";
- }
-
- leaf level-2 {
- type uint16 {
- range "1..600";
- }
- units "seconds";
- default "10";
- description
- "CNSP interval for level-2";
- }
- }
-
- container psnp-interval {
- description
- "Partial Sequence Number PDU (PSNP) generation interval.";
- leaf level-1 {
- type uint16 {
- range "1..120";
- }
- units "seconds";
- default "2";
- description
- "PNSP interval for level-1";
- }
-
- leaf level-2 {
- type uint16 {
- range "1..120";
- }
- units "seconds";
- default "2";
- description
- "PCNSP interval for level-2";
- }
- }
-
- container hello {
- description
- "Parameters related to IS-IS hello PDUs.";
- leaf padding {
- type boolean;
- default "true";
- description
- "Add padding to IS-IS hello PDUs.";
- }
-
- container interval {
- description
- "Interval between consecutive hello messages.";
- leaf level-1 {
- type uint32 {
- range "1..600";
- }
- units "seconds";
- default "3";
- description
- "Holding time for level-1; interval will depend on multiplier.";
- }
-
- leaf level-2 {
- type uint32 {
- range "1..600";
- }
- units "seconds";
- default "3";
- description
- "Holding time for level-2; interval will depend on multiplier.";
- }
- }
-
- container multiplier {
- description
- "Multiplier for the hello messages holding time.";
- leaf level-1 {
- type uint16 {
- range "2..100";
- }
- default "10";
- description
- "Multiplier for the hello holding time.";
- }
-
- leaf level-2 {
- type uint16 {
- range "2..100";
- }
- default "10";
- description
- "Multiplier for the hello holding time.";
- }
- }
- }
-
- container metric {
- description
- "Default metric for this IS-IS circuit.";
- leaf level-1 {
- type uint32 {
- range "0..16777215";
- }
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
- default "10";
- description
- "Default level-1 metric for this IS-IS circuit.";
- }
-
- leaf level-2 {
- type uint32 {
- range "0..16777215";
- }
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
- default "10";
- description
- "Default level-2 metric for this IS-IS circuit.";
- }
- }
-
- container priority {
- description
- "Priority for Designated Router election.";
- leaf level-1 {
- type uint8 {
- range "0..127";
- }
- default "64";
- description
- "Level-1 priority for this IS-IS circuit.";
- }
-
- leaf level-2 {
- type uint8 {
- range "0..127";
- }
- default "64";
- description
- "Level-2 priority for this IS-IS circuit.";
- }
- }
-
- leaf network-type {
- type network-type;
- default "broadcast";
- must "(. = \"point-to-point\") or (. = \"broadcast\")";
- description
- "Explicitly configured type of IS-IS circuit (broadcast or point-to-point).";
- }
-
- leaf passive {
- type boolean;
- default "false";
- description
- "Interface is in passive mode.";
- }
-
- container password {
- presence "Present if a password is set for this IS interface.";
- uses isis-password;
- }
-
- leaf disable-three-way-handshake {
- type boolean;
- default "false";
- description
- "Disables three-way handshake when creating new adjacencies.";
- }
-
- container multi-topology {
- description
- "IS-IS topologies configured on this circuit.";
- leaf ipv4-unicast {
- type boolean;
- default "true";
- description
- "IPv4 unicast topology.";
- }
-
- leaf ipv4-multicast {
- type boolean;
- default "true";
- description
- "IPv4 multicast topology.";
- }
-
- leaf ipv4-management {
- type boolean;
- default "true";
- description
- "IPv4 management topology.";
- }
-
- leaf ipv6-unicast {
- type boolean;
- default "true";
- description
- "IPv6 unicast topology.";
- }
-
- leaf ipv6-multicast {
- type boolean;
- default "true";
- description
- "IPv6 multicast topology.";
- }
-
- leaf ipv6-management {
- type boolean;
- default "true";
- description
- "IPv6 management topology.";
- }
-
- leaf ipv6-dstsrc {
- type boolean;
- default "true";
- description
- "IPv6 destination-source topology.";
- }
- }
+ uses interface-config;
+ uses interface-state;
}
}
diff --git a/yang/libyang_plugins/frr_user_types.c b/yang/libyang_plugins/frr_user_types.c
index 4814f5bc1d..48cdceccf4 100644
--- a/yang/libyang_plugins/frr_user_types.c
+++ b/yang/libyang_plugins/frr_user_types.c
@@ -20,6 +20,7 @@
#include <zebra.h>
#include "prefix.h"
+#include "ipaddr.h"
#include <libyang/user_types.h>
@@ -53,6 +54,21 @@ static int ipv6_address_store_clb(const char *type_name, const char *value_str,
return 0;
}
+static int ip_address_store_clb(const char *type_name, const char *value_str,
+ lyd_val *value, char **err_msg)
+{
+ value->ptr = malloc(sizeof(struct ipaddr));
+ if (!value->ptr)
+ return 1;
+
+ if (str2ipaddr(value_str, value->ptr)) {
+ free(value->ptr);
+ return 1;
+ }
+
+ return 0;
+}
+
static int ipv4_prefix_store_clb(const char *type_name, const char *value_str,
lyd_val *value, char **err_msg)
{
@@ -83,6 +99,21 @@ static int ipv6_prefix_store_clb(const char *type_name, const char *value_str,
return 0;
}
+static int ip_prefix_store_clb(const char *type_name, const char *value_str,
+ lyd_val *value, char **err_msg)
+{
+ value->ptr = malloc(sizeof(struct prefix));
+ if (!value->ptr)
+ return 1;
+
+ if (str2prefix(value_str, value->ptr) == 0) {
+ free(value->ptr);
+ return 1;
+ }
+
+ return 0;
+}
+
struct lytype_plugin_list frr_user_types[] = {
{"ietf-inet-types", "2013-07-15", "ipv4-address",
ipv4_address_store_clb, free},
@@ -92,9 +123,13 @@ struct lytype_plugin_list frr_user_types[] = {
ipv6_address_store_clb, free},
{"ietf-inet-types", "2013-07-15", "ipv6-address-no-zone",
ipv6_address_store_clb, free},
+ {"ietf-inet-types", "2013-07-15", "ip-address", ip_address_store_clb,
+ free},
{"ietf-inet-types", "2013-07-15", "ipv4-prefix", ipv4_prefix_store_clb,
free},
{"ietf-inet-types", "2013-07-15", "ipv6-prefix", ipv6_prefix_store_clb,
free},
+ {"ietf-inet-types", "2013-07-15", "ip-prefix", ip_prefix_store_clb,
+ free},
{NULL, NULL, NULL, NULL, NULL} /* terminating item */
};
diff --git a/zebra/connected.c b/zebra/connected.c
index 6b92945c63..87cf8c8f20 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -385,7 +385,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
return;
break;
default:
- zlog_info("Unknown AFI: %s", afi2str(afi));
+ zlog_warn("Unknown AFI: %s", afi2str(afi));
break;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index c71b95f753..08fa77923d 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1032,7 +1032,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* addr is primary key, SOL if we don't have one */
if (addr == NULL) {
- zlog_debug("%s: NULL address", __func__);
+ zlog_debug("%s: Local Interface Address is NULL for %s",
+ __func__, ifp->name);
return -1;
}
diff --git a/zebra/interface.c b/zebra/interface.c
index 6486c01430..bb808e1852 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -2034,13 +2034,13 @@ DEFUN (link_params_enable,
/* This command could be issue at startup, when activate MPLS TE */
/* on a new interface or after a ON / OFF / ON toggle */
/* In all case, TE parameters are reset to their default factory */
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
zlog_debug(
"Link-params: enable TE link parameters on interface %s",
ifp->name);
if (!if_link_params_get(ifp)) {
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
zlog_debug(
"Link-params: failed to init TE link parameters %s",
ifp->name);
@@ -2063,8 +2063,9 @@ DEFUN (no_link_params_enable,
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
- ifp->name);
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
+ zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
+ ifp->name);
if_link_params_free(ifp);
diff --git a/zebra/main.c b/zebra/main.c
index 657d1247e9..99607c0d78 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -36,7 +36,6 @@
#include "vrf.h"
#include "libfrr.h"
#include "routemap.h"
-#include "frr_pthread.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_errors.h"
@@ -375,9 +374,6 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
- /* Initialize pthread library */
- frr_pthread_init();
-
/* Zebra related initialize. */
zebra_router_init();
zserv_init();
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 1ae2ba92b0..227226b5f9 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -119,7 +119,7 @@ static void zebra_redistribute(struct zserv *client, int type,
srcdest_rnode_prefixes(rn, &dst_p, &src_p);
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
"%s: client %s %s(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d",
__func__,
@@ -149,7 +149,8 @@ static void zebra_redistribute(struct zserv *client, int type,
/* 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,
- struct route_entry *re, struct route_entry *prev_re)
+ const struct route_entry *re,
+ const struct route_entry *prev_re)
{
struct listnode *node, *nnode;
struct zserv *client;
@@ -200,7 +201,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
send_redistribute = 1;
if (send_redistribute) {
- if (IS_ZEBRA_DEBUG_EVENT) {
+ if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
"%s: client %s %s(%u), type=%d, distance=%d, metric=%d",
__func__,
@@ -226,54 +227,99 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
}
}
+/*
+ * During a route delete, where 'new_re' is NULL, redist a delete to all
+ * clients registered for the type of 'old_re'.
+ * During a route update, redist a delete to any clients who will not see
+ * an update when the new route is installed. There are cases when a client
+ * 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,
- struct route_entry *re)
+ const struct route_entry *old_re,
+ const struct route_entry *new_re)
{
struct listnode *node, *nnode;
struct zserv *client;
- char buf[INET6_ADDRSTRLEN];
int afi;
+ char buf[PREFIX_STRLEN];
+ vrf_id_t vrfid;
+
+ if (old_re)
+ vrfid = old_re->vrf_id;
+ else if (new_re)
+ vrfid = new_re->vrf_id;
+ else
+ return;
if (IS_ZEBRA_DEBUG_RIB) {
- inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug("%u:%s/%d: Redist delete re %p (%s)",
- re->vrf_id, buf, p->prefixlen, re,
- zebra_route_string(re->type));
+ zlog_debug(
+ "%u:%s: Redist del: re %p (%s), new re %p (%s)",
+ vrfid, prefix2str(p, buf, sizeof(buf)),
+ old_re,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Add DISTANCE_INFINITY check. */
- if (re->distance == DISTANCE_INFINITY)
+ if (old_re && (old_re->distance == DISTANCE_INFINITY))
return;
afi = family2afi(p->family);
if (!afi) {
flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
"%s: Unknown AFI/SAFI prefix received\n",
- __FUNCTION__);
+ __func__);
return;
}
+ /* Skip invalid (e.g. linklocal) prefix */
if (!zebra_check_addr(p)) {
- if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug("Redist delete filter prefix %s",
- prefix2str(p, buf, sizeof(buf)));
+ if (IS_ZEBRA_DEBUG_RIB) {
+ zlog_debug(
+ "%u:%s: Redist del old: skipping invalid prefix",
+ vrfid, prefix2str(p, buf, sizeof(buf)));
+ }
return;
}
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
- if ((is_default_prefix(p)
- && vrf_bitmap_check(client->redist_default[afi],
- re->vrf_id))
- || vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL],
- re->vrf_id)
- || (re->instance
- && redist_check_instance(
- &client->mi_redist[afi][re->type],
- re->instance))
- || vrf_bitmap_check(client->redist[afi][re->type],
- re->vrf_id)) {
+ if (new_re) {
+ /* Skip this client if it will receive an update for the
+ * 'new' re
+ */
+ if (is_default_prefix(p)
+ && vrf_bitmap_check(client->redist_default[afi],
+ new_re->vrf_id))
+ continue;
+ else if (vrf_bitmap_check(
+ client->redist[afi][ZEBRA_ROUTE_ALL],
+ new_re->vrf_id))
+ continue;
+ else if (new_re->instance
+ && redist_check_instance(
+ &client->mi_redist[afi][new_re->type],
+ new_re->instance))
+ continue;
+ else if (vrf_bitmap_check(
+ client->redist[afi][new_re->type],
+ new_re->vrf_id))
+ continue;
+ }
+
+ /* Send a delete for the 'old' re to any subscribed client. */
+ if (old_re
+ && ((old_re->instance
+ && redist_check_instance(
+ &client->mi_redist[afi]
+ [old_re->type],
+ old_re->instance))
+ || vrf_bitmap_check(
+ client->redist[afi][old_re->type],
+ old_re->vrf_id))) {
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, p, src_p, re);
+ client, p, src_p, old_re);
}
}
}
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 30ff6bcd09..2685458f96 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -42,11 +42,19 @@ extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
extern void redistribute_update(const struct prefix *p,
const struct prefix *src_p,
- struct route_entry *re,
- struct route_entry *prev_re);
-extern void redistribute_delete(const struct prefix *p,
- const struct prefix *src_p,
- struct route_entry *re);
+ const struct route_entry *re,
+ const struct route_entry *prev_re);
+/*
+ * During a route delete, where 'new_re' is NULL, redist a delete to all
+ * clients registered for the type of 'old_re'.
+ * During a route update, redist a delete to any clients who will not see
+ * an update when the new route is installed. There are cases when a client
+ * 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,
+ 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 *);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 91a3024038..43e44cad16 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1440,6 +1440,7 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
int llalen, ns_id_t ns_id)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -1460,6 +1461,8 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
req.ndm.ndm_ifindex = ifindex;
req.ndm.ndm_type = RTN_UNICAST;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
@@ -1930,6 +1933,7 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
int cmd)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -1950,6 +1954,8 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
@@ -2297,6 +2303,7 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
static enum zebra_dplane_result
netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -2330,6 +2337,8 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
else
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_LLADDR,
dplane_ctx_mac_get_addr(ctx), 6);
req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
@@ -2748,6 +2757,7 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
int cmd)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -2782,6 +2792,8 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
req.ndm.ndm_type = RTN_UNICAST;
req.ndm.ndm_flags = flags;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
if (mac)
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index 8cc5b52b34..711c4e0877 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -54,6 +54,7 @@
*/
static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
{
+ uint8_t protocol = RTPROT_ZEBRA;
int family;
int bytelen;
struct {
@@ -78,6 +79,9 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
req.frh.family = family;
req.frh.action = FR_ACT_TO_TBL;
+ addattr_l(&req.n, sizeof(req),
+ FRA_PROTOCOL, &protocol, sizeof(protocol));
+
/* rule's pref # */
addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index fa6a2f62ec..ffdc4dc512 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -516,7 +516,8 @@ 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, struct route_entry *re)
+ const struct prefix *src_p,
+ const struct route_entry *re)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
@@ -1749,88 +1750,146 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
}
-static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
+/*
+ * Handle request to create an MPLS LSP.
+ *
+ * A single message can fully specify an LSP with multiple nexthops.
+ *
+ * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
+ * updated to use the received label(s).
+ */
+static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- enum lsp_types_t type;
- struct prefix prefix;
- enum nexthop_types_t gtype;
- union g_addr gate;
- ifindex_t ifindex;
- mpls_label_t in_label, out_label;
- uint8_t distance;
+ struct zapi_labels zl;
/* Get input stream. */
s = msg;
+ if (zapi_labels_decode(s, &zl) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_labels sent",
+ __PRETTY_FUNCTION__);
+ return;
+ }
- /* Get data. */
- STREAM_GETC(s, type);
- STREAM_GETL(s, prefix.family);
- switch (prefix.family) {
- case AF_INET:
- STREAM_GET(&prefix.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN);
- STREAM_GETC(s, prefix.prefixlen);
- if (prefix.prefixlen > IPV4_MAX_BITLEN) {
- zlog_debug(
- "%s: Specified prefix length %d is greater than a v4 address can support",
- __PRETTY_FUNCTION__, prefix.prefixlen);
- return;
- }
- STREAM_GET(&gate.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
- break;
- case AF_INET6:
- STREAM_GET(&prefix.u.prefix6, s, 16);
- STREAM_GETC(s, prefix.prefixlen);
- if (prefix.prefixlen > IPV6_MAX_BITLEN) {
- zlog_debug(
- "%s: Specified prefix length %d is greater than a v6 address can support",
- __PRETTY_FUNCTION__, prefix.prefixlen);
- return;
- }
- STREAM_GET(&gate.ipv6, s, 16);
- break;
- default:
- zlog_debug("%s: Specified AF %d is not supported for this call",
- __PRETTY_FUNCTION__, prefix.family);
+ if (!mpls_enabled)
return;
+
+ for (int i = 0; i < zl.nexthop_num; i++) {
+ struct zapi_nexthop_label *znh;
+
+ znh = &zl.nexthops[i];
+ mpls_lsp_install(zvrf, zl.type, zl.local_label, znh->label,
+ znh->type, &znh->address, znh->ifindex);
+
+ if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
+ mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
+ znh->type, &znh->address, znh->ifindex,
+ zl.route.type, zl.route.instance,
+ znh->label);
}
- STREAM_GETL(s, ifindex);
- STREAM_GETC(s, distance);
- STREAM_GETL(s, in_label);
- STREAM_GETL(s, out_label);
+}
- switch (prefix.family) {
- case AF_INET:
- if (ifindex)
- gtype = NEXTHOP_TYPE_IPV4_IFINDEX;
- else
- gtype = NEXTHOP_TYPE_IPV4;
- break;
- case AF_INET6:
- if (ifindex)
- gtype = NEXTHOP_TYPE_IPV6_IFINDEX;
- else
- gtype = NEXTHOP_TYPE_IPV6;
- break;
- default:
+/*
+ * Handle request to delete an MPLS LSP.
+ *
+ * An LSP is identified by its type and local label. When the received message
+ * doesn't contain any nexthop, the whole LSP is deleted. Otherwise, only the
+ * listed LSP nexthops (aka NHLFEs) are deleted.
+ *
+ * When the optional ZAPI_LABELS_FTN flag is set, the labels of the specified
+ * FEC (route) nexthops are deleted.
+ */
+static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ struct zapi_labels zl;
+
+ /* Get input stream. */
+ s = msg;
+ if (zapi_labels_decode(s, &zl) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_labels sent",
+ __PRETTY_FUNCTION__);
return;
}
if (!mpls_enabled)
return;
- if (hdr->command == ZEBRA_MPLS_LABELS_ADD) {
- mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate,
- ifindex);
- mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex,
- distance, out_label);
- } else if (hdr->command == ZEBRA_MPLS_LABELS_DELETE) {
- mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex);
- mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex,
- distance, out_label);
+ if (zl.nexthop_num > 0) {
+ for (int i = 0; i < zl.nexthop_num; i++) {
+ struct zapi_nexthop_label *znh;
+
+ znh = &zl.nexthops[i];
+ mpls_lsp_uninstall(zvrf, zl.type, zl.local_label,
+ znh->type, &znh->address,
+ znh->ifindex);
+
+ if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
+ mpls_ftn_update(0, zvrf, zl.type,
+ &zl.route.prefix, znh->type,
+ &znh->address, znh->ifindex,
+ zl.route.type,
+ zl.route.instance, znh->label);
+ }
+ } else {
+ mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
+
+ if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
+ mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
+ zl.route.type, zl.route.instance);
+ }
+}
+
+/*
+ * Handle request to add an MPLS LSP or change an existing one.
+ *
+ * A single message can fully specify an LSP with multiple nexthops.
+ *
+ * When the optional ZAPI_LABELS_FTN flag is set, the specified FEC (route) is
+ * updated to use the received label(s).
+ *
+ * NOTE: zebra will use route replace semantics (make-before-break) to update
+ * the LSP in the forwarding plane if that's supported by the underlying
+ * platform.
+ */
+static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ struct zapi_labels zl;
+
+ /* Get input stream. */
+ s = msg;
+ if (zapi_labels_decode(s, &zl) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_labels sent",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ if (!mpls_enabled)
+ return;
+
+ mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
+ if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
+ mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
+ zl.route.type, zl.route.instance);
+
+ for (int i = 0; i < zl.nexthop_num; i++) {
+ struct zapi_nexthop_label *znh;
+
+ znh = &zl.nexthops[i];
+ mpls_lsp_install(zvrf, zl.type, zl.local_label, znh->label,
+ znh->type, &znh->address, znh->ifindex);
+
+ if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) {
+ mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
+ znh->type, &znh->address, znh->ifindex,
+ zl.route.type, zl.route.instance,
+ znh->label);
+ }
}
-stream_failure:
- return;
}
/* Send response to a table manager connect request to client */
@@ -2455,8 +2514,9 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_INTERFACE_ENABLE_RADV] = NULL,
[ZEBRA_INTERFACE_DISABLE_RADV] = NULL,
#endif
- [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels,
- [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels,
+ [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,
+ [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete,
+ [ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,
[ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats,
[ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request,
[ZEBRA_LABEL_MANAGER_CONNECT_ASYNC] = zread_label_manager_request,
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index 884edfef04..996a255ff4 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -65,7 +65,8 @@ extern int zsend_interface_update(int cmd, struct zserv *client,
extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
const struct prefix *p,
const struct prefix *src_p,
- struct route_entry *re);
+ const struct route_entry *re);
+
extern int zsend_router_id_update(struct zserv *zclient, struct prefix *p,
vrf_id_t vrf_id);
extern int zsend_interface_vrf_update(struct zserv *zclient,
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 4144c0afe0..5d88d4eeb4 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -711,7 +711,6 @@ static void zfpm_connection_down(const char *detail)
* Start thread to clean up state after the connection goes down.
*/
assert(!zfpm_g->t_conn_down);
- zfpm_debug("Starting conn_down thread");
zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter);
zfpm_g->t_conn_down = NULL;
thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0,
@@ -806,8 +805,6 @@ static int zfpm_read_cb(struct thread *thread)
goto done;
}
- zfpm_debug("Read out a full fpm message");
-
/*
* Just throw it away for now.
*/
@@ -1249,7 +1246,7 @@ static int zfpm_connect_cb(struct thread *t)
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
- zfpm_debug("Failed to create socket for connect(): %s",
+ zlog_err("Failed to create socket for connect(): %s",
strerror(errno));
zfpm_g->stats.connect_no_sock++;
return 0;
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 5214f1f22d..8088ec1bfe 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -34,6 +34,7 @@
#include "routemap.h"
#include "stream.h"
#include "nexthop.h"
+#include "termtable.h"
#include "lib/json.h"
#include "zebra/rib.h"
@@ -124,6 +125,9 @@ static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp,
static int snhlfe_del(zebra_snhlfe_t *snhlfe);
static int snhlfe_del_all(zebra_slsp_t *slsp);
static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size);
+static void mpls_lsp_uninstall_all_type(struct hash_bucket *bucket, void *ctxt);
+static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
+ int afi, enum lsp_types_t lsp_type);
/* Static functions */
@@ -1111,6 +1115,7 @@ static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size)
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, size);
break;
case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, size);
break;
case NEXTHOP_TYPE_IFINDEX:
@@ -2294,6 +2299,42 @@ static int zebra_mpls_cleanup_fecs_for_client(struct zserv *client)
return 0;
}
+struct lsp_uninstall_args {
+ struct hash *lsp_table;
+ enum lsp_types_t type;
+};
+
+/*
+ * Cleanup MPLS labels registered by this client.
+ */
+static int zebra_mpls_cleanup_zclient_labels(struct zserv *client)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ struct lsp_uninstall_args args;
+
+ zvrf = vrf->info;
+ if (!zvrf)
+ continue;
+
+ /* Cleanup LSPs. */
+ args.lsp_table = zvrf->lsp_table;
+ args.type = lsp_type_from_re_type(client->proto);
+ hash_iterate(zvrf->lsp_table, mpls_lsp_uninstall_all_type,
+ &args);
+
+ /* Cleanup FTNs. */
+ mpls_ftn_uninstall_all(zvrf, AFI_IP,
+ lsp_type_from_re_type(client->proto));
+ mpls_ftn_uninstall_all(zvrf, AFI_IP6,
+ lsp_type_from_re_type(client->proto));
+ }
+
+ return 0;
+}
+
/*
* Return FEC (if any) to which this label is bound.
* Note: Only works for per-prefix binding and when the label is not
@@ -2542,8 +2583,8 @@ static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
*/
int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
struct prefix *prefix, enum nexthop_types_t gtype,
- union g_addr *gate, ifindex_t ifindex, uint8_t distance,
- mpls_label_t out_label)
+ union g_addr *gate, ifindex_t ifindex, uint8_t route_type,
+ unsigned short route_instance, mpls_label_t out_label)
{
struct route_table *table;
struct route_node *rn;
@@ -2562,7 +2603,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
RNODE_FOREACH_RE (rn, re) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
continue;
- if (re->distance == distance)
+ if (re->type == route_type && re->instance == route_instance)
break;
}
@@ -2617,6 +2658,42 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
return 0;
}
+int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ unsigned short route_instance)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct route_entry *re;
+ struct nexthop *nexthop;
+
+ /* Lookup table. */
+ table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST,
+ zvrf_id(zvrf));
+ if (!table)
+ return -1;
+
+ /* Lookup existing route */
+ rn = route_node_get(table, prefix);
+ RNODE_FOREACH_RE (rn, re) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+ continue;
+ if (re->type == route_type && re->instance == route_instance)
+ break;
+ }
+ if (re == NULL)
+ return -1;
+
+ for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
+ nexthop_del_labels(nexthop);
+
+ SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
+ SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+ rib_queue_add(rn);
+
+ return 0;
+}
+
/*
* Install/update a NHLFE for an LSP in the forwarding table. This may be
* a new LSP entry or a new NHLFE for an existing in-label or an update of
@@ -2749,12 +2826,34 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
return 0;
}
+int mpls_lsp_uninstall_all_vrf(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ mpls_label_t in_label)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return -1;
+
+ /* If entry is not present, exit. */
+ tmp_ile.in_label = in_label;
+ lsp = hash_lookup(lsp_table, &tmp_ile);
+ if (!lsp)
+ return 0;
+
+ return mpls_lsp_uninstall_all(lsp_table, lsp, type);
+}
+
/*
- * Uninstall all LDP NHLFEs for a particular LSP forwarding entry.
+ * Uninstall all NHLFEs for a particular LSP forwarding entry.
* If no other NHLFEs exist, the entry would be deleted.
*/
-void mpls_ldp_lsp_uninstall_all(struct hash_bucket *bucket, void *ctxt)
+static void mpls_lsp_uninstall_all_type(struct hash_bucket *bucket, void *ctxt)
{
+ struct lsp_uninstall_args *args = ctxt;
zebra_lsp_t *lsp;
struct hash *lsp_table;
@@ -2762,17 +2861,19 @@ void mpls_ldp_lsp_uninstall_all(struct hash_bucket *bucket, void *ctxt)
if (!lsp->nhlfe_list)
return;
- lsp_table = ctxt;
+ lsp_table = args->lsp_table;
if (!lsp_table)
return;
- mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_LDP);
+ mpls_lsp_uninstall_all(lsp_table, lsp, args->type);
}
/*
- * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family.
+ * Uninstall all FEC-To-NHLFE (FTN) bindings of the given address-family and
+ * LSP type.
*/
-void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi)
+static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
+ int afi, enum lsp_types_t lsp_type)
{
struct route_table *table;
struct route_node *rn;
@@ -2790,7 +2891,7 @@ void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi)
RNODE_FOREACH_RE (rn, re) {
for (nexthop = re->ng.nexthop; nexthop;
nexthop = nexthop->next) {
- if (nexthop->nh_label_type != ZEBRA_LSP_LDP)
+ if (nexthop->nh_label_type != lsp_type)
continue;
nexthop_del_labels(nexthop);
@@ -3047,7 +3148,6 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json = NULL;
zebra_lsp_t *lsp = NULL;
zebra_nhlfe_t *nhlfe = NULL;
- struct nexthop *nexthop = NULL;
struct listnode *node = NULL;
struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp);
@@ -3063,15 +3163,23 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
} else {
- vty_out(vty, " Inbound Outbound\n");
- vty_out(vty, " Label Type Nexthop Label\n");
- vty_out(vty, "-------- ------- --------------- --------\n");
+ struct ttable *tt;
+
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Inbound Label|Type|Nexthop|Outbound Label");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ ttable_rowseps(tt, 0, BOTTOM, true, '-');
for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) {
for (nhlfe = lsp->nhlfe_list; nhlfe;
nhlfe = nhlfe->next) {
- vty_out(vty, "%8d %7s ", lsp->ile.in_label,
- nhlfe_type2str(nhlfe->type));
+ struct nexthop *nexthop;
+ const char *out_label_str;
+ char nh_buf[NEXTHOP_STRLEN];
+
nexthop = nhlfe->nexthop;
switch (nexthop->type) {
@@ -3081,45 +3189,47 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
zns = zebra_ns_lookup(NS_DEFAULT);
ifp = if_lookup_by_index_per_ns(
- zns,
- nexthop->ifindex);
- if (ifp)
- vty_out(vty, "%15s", ifp->name);
- else
- vty_out(vty, "%15s", "Null");
-
+ zns, nexthop->ifindex);
+ snprintf(nh_buf, sizeof(nh_buf), "%s",
+ ifp ? ifp->name : "Null");
break;
}
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out(vty, "%15s",
- inet_ntoa(nexthop->gate.ipv4));
+ inet_ntop(AF_INET, &nexthop->gate.ipv4,
+ nh_buf, sizeof(nh_buf));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- vty_out(vty, "%15s",
- inet_ntop(AF_INET6,
- &nexthop->gate.ipv6,
- buf, BUFSIZ));
+ inet_ntop(AF_INET6, &nexthop->gate.ipv6,
+ nh_buf, sizeof(nh_buf));
break;
default:
break;
}
if (nexthop->type != NEXTHOP_TYPE_IFINDEX)
- vty_out(vty, " %8s\n",
- mpls_label2str(
- nexthop->nh_label
- ->num_labels,
- &nexthop->nh_label
- ->label[0],
- buf, BUFSIZ, 1));
+ out_label_str = mpls_label2str(
+ nexthop->nh_label->num_labels,
+ &nexthop->nh_label->label[0],
+ buf, BUFSIZ, 1);
else
- vty_out(vty, "\n");
+ out_label_str = "-";
+
+ ttable_add_row(tt, "%u|%s|%s|%s",
+ lsp->ile.in_label,
+ nhlfe_type2str(nhlfe->type),
+ nh_buf, out_label_str);
}
}
- vty_out(vty, "\n");
+ /* Dump the generated table. */
+ if (tt->nrows > 1) {
+ char *table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ }
+ ttable_del(tt);
}
list_delete(&lsp_list);
@@ -3289,4 +3399,5 @@ void zebra_mpls_init(void)
mpls_enabled = 1;
hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
+ hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels);
}
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index d983221cb5..157f43ca98 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -269,8 +269,15 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
*/
int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
struct prefix *prefix, enum nexthop_types_t gtype,
- union g_addr *gate, ifindex_t ifindex, uint8_t distance,
- mpls_label_t out_label);
+ union g_addr *gate, ifindex_t ifindex, uint8_t route_type,
+ unsigned short route_instance, mpls_label_t out_label);
+
+/*
+ * Uninstall all NHLFEs bound to a single FEC.
+ */
+int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ unsigned short route_instance);
/*
* Install/update a NHLFE for an LSP in the forwarding table. This may be
@@ -291,15 +298,10 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
union g_addr *gate, ifindex_t ifindex);
/*
- * Uninstall all LDP NHLFEs for a particular LSP forwarding entry.
- * If no other NHLFEs exist, the entry would be deleted.
- */
-void mpls_ldp_lsp_uninstall_all(struct hash_bucket *bucket, void *ctxt);
-
-/*
- * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family.
+ * Uninstall all NHLFEs for a particular LSP forwarding entry.
*/
-void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi);
+int mpls_lsp_uninstall_all_vrf(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ mpls_label_t in_label);
/*
* Uninstall all Segment Routing NHLFEs for a particular LSP forwarding entry.
@@ -426,7 +428,7 @@ static inline uint8_t lsp_distance(enum lsp_types_t type)
return (route_distance(ZEBRA_ROUTE_BGP));
case ZEBRA_LSP_NONE:
case ZEBRA_LSP_SHARP:
- case ZEBRA_LSP_SR:
+ case ZEBRA_LSP_OSPF_SR:
return 150;
}
@@ -448,8 +450,12 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
switch (re_type) {
case ZEBRA_ROUTE_STATIC:
return ZEBRA_LSP_STATIC;
+ case ZEBRA_ROUTE_LDP:
+ return ZEBRA_LSP_LDP;
case ZEBRA_ROUTE_BGP:
return ZEBRA_LSP_BGP;
+ case ZEBRA_ROUTE_OSPF:
+ return ZEBRA_LSP_OSPF_SR;
case ZEBRA_ROUTE_SHARP:
return ZEBRA_LSP_SHARP;
default:
@@ -469,7 +475,7 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
return ZEBRA_ROUTE_LDP;
case ZEBRA_LSP_BGP:
return ZEBRA_ROUTE_BGP;
- case ZEBRA_LSP_SR:
+ case ZEBRA_LSP_OSPF_SR:
return ZEBRA_ROUTE_OSPF;
case ZEBRA_LSP_NONE:
return ZEBRA_ROUTE_KERNEL;
@@ -496,8 +502,8 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
return "LDP";
case ZEBRA_LSP_BGP:
return "BGP";
- case ZEBRA_LSP_SR:
- return "SR";
+ case ZEBRA_LSP_OSPF_SR:
+ return "SR (OSPF)";
case ZEBRA_LSP_SHARP:
return "SHARP";
case ZEBRA_LSP_NONE:
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 157c67fa62..5428b6eaef 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -691,7 +691,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
srcdest_rnode_prefixes(rn, &p, &src_p);
- redistribute_delete(p, src_p, re);
+ redistribute_delete(p, src_p, re, NULL);
UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
}
}
@@ -1248,8 +1248,17 @@ static void rib_process(struct route_node *rn)
SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED);
if (old_selected) {
- if (!new_selected)
- redistribute_delete(p, src_p, old_selected);
+ /*
+ * If we're removing the old entry, we should tell
+ * redist subscribers about that *if* they aren't
+ * going to see a redist for the new entry.
+ */
+ if (!new_selected || CHECK_FLAG(old_selected->status,
+ ROUTE_ENTRY_REMOVED))
+ redistribute_delete(p, src_p,
+ old_selected,
+ new_selected);
+
if (old_selected != new_selected)
UNSET_FLAG(old_selected->flags,
ZEBRA_FLAG_SELECTED);
@@ -2026,7 +2035,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);
+ redistribute_delete(dest_pfx, src_pfx, re, NULL);
zebra_rib_evaluate_rn_nexthops(
rn, zebra_router_get_next_sequence());
@@ -2088,14 +2097,6 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
return 1;
}
-
-/*
- * Perform next-hop tracking processing after RIB updates.
- */
-static void do_nht_processing(void)
-{
-}
-
/* Dispatch the meta queue by picking, processing and unlocking the next RN from
* a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
* data
@@ -3294,9 +3295,6 @@ static int rib_process_dplane_results(struct thread *thread)
} while (1);
- /* Check for nexthop tracking processing after finishing with results */
- do_nht_processing();
-
return 0;
}
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 666ebb70e8..5df5d94f4b 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -337,7 +337,7 @@ static void addr2hostprefix(int af, const union g_addr *addr,
break;
default:
memset(prefix, 0, sizeof(*prefix));
- zlog_debug("%s: unknown address family %d", __func__, af);
+ zlog_warn("%s: unknown address family %d", __func__, af);
break;
}
}
@@ -916,7 +916,8 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
table = get_rnh_table(vrfid, afi, type);
if (!table) {
- zlog_debug("print_rnhs: rnh table not found");
+ if (IS_ZEBRA_DEBUG_NHT)
+ zlog_debug("print_rnhs: rnh table not found");
return;
}
@@ -1198,13 +1199,6 @@ static int zebra_client_cleanup_rnh(struct zserv *client)
RNH_IMPORT_CHECK_TYPE);
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client,
RNH_IMPORT_CHECK_TYPE);
- if (client->proto == ZEBRA_ROUTE_LDP) {
- hash_iterate(zvrf->lsp_table,
- mpls_ldp_lsp_uninstall_all,
- zvrf->lsp_table);
- mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP);
- mpls_ldp_ftn_uninstall_all(zvrf, AFI_IP6);
- }
}
}
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 88d2091394..364f5755d8 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -78,11 +78,6 @@ static int zebra_route_match_add(struct vty *vty, const char *command,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_ADDED) {
- route_map_upd8_dependency(type, arg, index->map->name);
- }
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
@@ -116,7 +111,7 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
}
- ret = route_map_delete_match(index, command, arg);
+ ret = route_map_delete_match(index, command, arg, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% Zebra Can't find rule.\n");
@@ -127,10 +122,6 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
- if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
- route_map_upd8_dependency(type, dep_name, rmap_name);
- break;
- case RMAP_DUPLICATE_RULE:
/*
* Nothing to do here
*/
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 72d0b6866d..4f1868311c 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -92,7 +92,7 @@ static int zebra_vrf_new(struct vrf *vrf)
struct zebra_vrf *zvrf;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id);
+ zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id);
zvrf = zebra_vrf_alloc();
vrf->info = zvrf;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 7984481093..15f0398ca4 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -394,6 +394,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_labels = NULL;
time_t uptime;
struct tm *tm;
+ struct vrf *vrf = NULL;
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop_group *nhg;
@@ -422,9 +423,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_int_add(json_route, "instance",
re->instance);
- if (re->vrf_id)
+ if (re->vrf_id) {
json_object_int_add(json_route, "vrfId", re->vrf_id);
+ vrf = vrf_lookup_by_id(re->vrf_id);
+ json_object_string_add(json_route, "vrfName",
+ vrf->name);
+ }
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
@@ -565,9 +570,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if ((nexthop->vrf_id != re->vrf_id)
&& (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
- struct vrf *vrf =
- vrf_lookup_by_id(nexthop->vrf_id);
-
+ vrf = vrf_lookup_by_id(nexthop->vrf_id);
json_object_string_add(json_nexthop, "vrf",
vrf->name);
}