summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Dugeon <olivier.dugeon@orange.com>2021-06-30 17:23:56 +0200
committerOlivier Dugeon <olivier.dugeon@orange.com>2021-11-30 15:22:28 +0100
commit173f8887cc3716985bfe4b84bdf2228194716f7d (patch)
tree6bf71295b47e814980e8620feba04e6950d7ed18
parentMerge pull request #10146 from ton31337/fix/acl_bmp (diff)
downloadfrr-173f8887cc3716985bfe4b84bdf2228194716f7d.tar.xz
frr-173f8887cc3716985bfe4b84bdf2228194716f7d.zip
isisd: Add support for RFC6119 (IPv6 TE in IS-IS)
- Add advertisement of Global IPv6 address in IIH pdu - Add new CLI to set IPv6 Router ID - Add advertisement of IPv6 Router ID - Correctly advertise IPv6 local and neighbor addresses in Extended IS and MT Reachability TLVs - Correct output of Neighbor IPv6 address in 'show isis database detail' - Manage IPv6 addresses advertisement and corresponiding Adjacency SID when IS-IS is not using Multi-Topology by introducing a new ISIS_MT_DISABLE value for mtid (== 4096 i.e. first reserved flag set to 1) Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
-rw-r--r--doc/user/isisd.rst4
-rw-r--r--isisd/isis_adjacency.c23
-rw-r--r--isisd/isis_adjacency.h12
-rw-r--r--isisd/isis_bfd.c11
-rw-r--r--isisd/isis_circuit.c10
-rw-r--r--isisd/isis_cli.c39
-rw-r--r--isisd/isis_lfa.c5
-rw-r--r--isisd/isis_lsp.c16
-rw-r--r--isisd/isis_mt.c11
-rw-r--r--isisd/isis_mt.h2
-rw-r--r--isisd/isis_nb.c8
-rw-r--r--isisd/isis_nb.h7
-rw-r--r--isisd/isis_nb_config.c51
-rw-r--r--isisd/isis_pdu.c5
-rw-r--r--isisd/isis_route.c4
-rw-r--r--isisd/isis_snmp.c7
-rw-r--r--isisd/isis_sr.c18
-rw-r--r--isisd/isis_te.c139
-rw-r--r--isisd/isis_te.h3
-rw-r--r--isisd/isis_tlvs.c349
-rw-r--r--isisd/isis_tlvs.h8
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin176859 -> 245481 bytes
-rw-r--r--yang/frr-isisd.yang5
23 files changed, 619 insertions, 118 deletions
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index 4a711a8fe..2bba3b975 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -330,6 +330,10 @@ Traffic Engineering
Configure stable IP address for MPLS-TE.
+.. clicmd:: mpls-te router-address ipv6 <X:X::X:X>
+
+ Configure stable IPv6 address for MPLS-TE.
+
.. clicmd:: show isis mpls-te interface
.. clicmd:: show isis mpls-te interface INTERFACE
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index f5e8a790b..ea05824f0 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -168,7 +168,7 @@ void isis_delete_adj(void *arg)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
- XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs);
adj_mt_finish(adj);
list_delete(&adj->adj_sids);
@@ -414,11 +414,11 @@ void isis_adj_print(struct isis_adjacency *adj)
zlog_debug("%pI4", &adj->ipv4_addresses[i]);
}
- if (adj->ipv6_address_count) {
+ if (adj->ll_ipv6_count) {
zlog_debug("IPv6 Address(es):");
- for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
char buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &adj->ipv6_addresses[i], buf,
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i], buf,
sizeof(buf));
zlog_debug("%s", buf);
}
@@ -577,12 +577,21 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
vty_out(vty, " %pI4\n",
&adj->ipv4_addresses[i]);
}
- if (adj->ipv6_address_count) {
+ if (adj->ll_ipv6_count) {
vty_out(vty, " IPv6 Address(es):\n");
- for (unsigned int i = 0; i < adj->ipv6_address_count;
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &adj->ll_ipv6_addrs[i],
+ buf, sizeof(buf));
+ vty_out(vty, " %s\n", buf);
+ }
+ }
+ if (adj->global_ipv6_count) {
+ vty_out(vty, " Global IPv6 Address(es):\n");
+ for (unsigned int i = 0; i < adj->global_ipv6_count;
i++) {
char buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &adj->ipv6_addresses[i],
+ inet_ntop(AF_INET6, &adj->global_ipv6_addrs[i],
buf, sizeof(buf));
vty_out(vty, " %s\n", buf);
}
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index 4aa553e30..af70775a8 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -88,8 +88,10 @@ struct isis_adjacency {
struct in_addr *ipv4_addresses;
unsigned int ipv4_address_count;
struct in_addr router_address;
- struct in6_addr *ipv6_addresses;
- unsigned int ipv6_address_count;
+ struct in6_addr *ll_ipv6_addrs; /* Link local IPv6 neighbor address */
+ unsigned int ll_ipv6_count;
+ struct in6_addr *global_ipv6_addrs; /* Global IPv6 neighbor address */
+ unsigned int global_ipv6_count;
struct in6_addr router_address6;
uint8_t prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
int circuit_t; /* from hello PDU hdr */
@@ -127,9 +129,11 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
enum isis_adj_usage adj_usage);
DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj));
DECLARE_HOOK(isis_adj_ip_enabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
DECLARE_HOOK(isis_adj_ip_disabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
void isis_log_adj_change(struct isis_adjacency *adj,
enum isis_adj_state old_state,
enum isis_adj_state new_state, const char *reason);
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index a7548e2f1..1f50fb934 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -81,7 +81,7 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj)
*/
if (circuit->ipv6_router
&& (listcount(circuit->ipv6_link) == 0
- || adj->ipv6_address_count == 0)) {
+ || adj->ll_ipv6_count == 0)) {
if (IS_DEBUG_BFD)
zlog_debug(
"ISIS-BFD: skipping BFD initialization on adjacency with %s because IPv6 is enabled but not ready",
@@ -93,9 +93,9 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj)
* If IS-IS is enabled for both IPv4 and IPv6 on the circuit, prefer
* creating a BFD session over IPv6.
*/
- if (circuit->ipv6_router && adj->ipv6_address_count) {
+ if (circuit->ipv6_router && adj->ll_ipv6_count) {
family = AF_INET6;
- dst_ip.ipv6 = adj->ipv6_addresses[0];
+ dst_ip.ipv6 = adj->ll_ipv6_addrs[0];
local_ips = circuit->ipv6_link;
if (!local_ips || list_isempty(local_ips)) {
if (IS_DEBUG_BFD)
@@ -181,10 +181,11 @@ void isis_bfd_circuit_cmd(struct isis_circuit *circuit)
}
}
-static int bfd_handle_adj_ip_enabled(struct isis_adjacency *adj, int family)
+static int bfd_handle_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
- if (family != AF_INET6)
+ if (family != AF_INET6 || global)
return 0;
if (adj->bfd_session)
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index a91bbd0b9..0ad6190ba 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -335,8 +335,16 @@ void isis_circuit_add_addr(struct isis_circuit *circuit,
if (IN6_IS_ADDR_LINKLOCAL(&ipv6->prefix))
listnode_add(circuit->ipv6_link, ipv6);
- else
+ else {
listnode_add(circuit->ipv6_non_link, ipv6);
+ /* Update Local IPv6 address param. if MPLS TE is on */
+ if (circuit->ext && circuit->area
+ && IS_MPLS_TE(circuit->area->mta)) {
+ IPV6_ADDR_COPY(&circuit->ext->local_addr6,
+ &ipv6->prefix);
+ SET_SUBTLV(circuit->ext, EXT_LOCAL_ADDR6);
+ }
+ }
if (circuit->area)
lsp_regenerate_schedule(circuit->area, circuit->is_type,
0);
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index bf03d0a05..b6f798bb2 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -1140,6 +1140,43 @@ void cli_show_isis_mpls_te_router_addr(struct vty *vty,
yang_dnode_get_string(dnode, NULL));
}
+/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/router-address-v6
+ */
+DEFPY_YANG(isis_mpls_te_router_addr_v6, isis_mpls_te_router_addr_v6_cmd,
+ "mpls-te router-address ipv6 X:X::X:X",
+ MPLS_TE_STR
+ "Stable IP address of the advertising router\n"
+ "IPv6 address\n"
+ "MPLS-TE router address in IPv6 address format\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_MODIFY,
+ ipv6_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(no_isis_mpls_te_router_addr_v6, no_isis_mpls_te_router_addr_v6_cmd,
+ "no mpls-te router-address ipv6 [X:X::X:X]",
+ NO_STR MPLS_TE_STR
+ "Delete IP address of the advertising router\n"
+ "IPv6 address\n"
+ "MPLS-TE router address in IPv6 address format\n")
+{
+ nb_cli_enqueue_change(vty, "./mpls-te/router-address-v6", NB_OP_DESTROY,
+ NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+void cli_show_isis_mpls_te_router_addr_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " mpls-te router-address ipv6 %s\n",
+ yang_dnode_get_string(dnode, NULL));
+}
+
DEFPY_YANG(isis_mpls_te_inter_as, isis_mpls_te_inter_as_cmd,
"[no] mpls-te inter-as [level-1|level-1-2|level-2-only]",
NO_STR MPLS_TE_STR
@@ -3125,6 +3162,8 @@ void isis_cli_init(void)
install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd);
install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd);
install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_cmd);
+ install_element(ISIS_NODE, &isis_mpls_te_router_addr_v6_cmd);
+ install_element(ISIS_NODE, &no_isis_mpls_te_router_addr_v6_cmd);
install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd);
install_element(ISIS_NODE, &isis_default_originate_cmd);
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index e033c28fe..84aac24d5 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -1443,9 +1443,8 @@ static mpls_label_t rlfa_nexthop_label(struct isis_spftree *spftree,
}
break;
case AF_INET6:
- for (unsigned int j = 0; j < adj->ipv6_address_count;
- j++) {
- struct in6_addr addr = adj->ipv6_addresses[j];
+ for (unsigned int j = 0; j < adj->ll_ipv6_count; j++) {
+ struct in6_addr addr = adj->ll_ipv6_addrs[j];
if (!IPV6_ADDR_SAME(
&addr,
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index e3de6f08c..94353a5bc 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -1067,6 +1067,14 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
area->area_tag);
}
+ if (IS_MPLS_TE(area->mta)
+ && !IN6_IS_ADDR_UNSPECIFIED(&area->mta->router_id_ipv6)) {
+ lsp_debug("ISIS (%s): Adding IPv6 TE Router ID tlv.",
+ area->area_tag);
+ isis_tlvs_set_te_router_id_ipv6(lsp->tlvs,
+ &area->mta->router_id_ipv6);
+ }
+
lsp_debug("ISIS (%s): Adding circuit specific information.",
area->area_tag);
@@ -1601,6 +1609,7 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
struct list *adj_list;
struct listnode *node;
struct isis_area *area = circuit->area;
+ uint16_t mtid;
lsp_clear_data(lsp);
lsp->tlvs = isis_alloc_tlvs();
@@ -1630,8 +1639,11 @@ static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit,
LSP_PSEUDO_ID(ne_id));
}
if (circuit->area->newmetric) {
- isis_tlvs_add_extended_reach(lsp->tlvs, ISIS_MT_IPV4_UNICAST,
- ne_id, 0, NULL);
+ if (area_is_mt(circuit->area))
+ mtid = ISIS_MT_IPV4_UNICAST;
+ else
+ mtid = ISIS_MT_DISABLE;
+ isis_tlvs_add_extended_reach(lsp->tlvs, mtid, ne_id, 0, NULL);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor (self)",
area->area_tag, sysid_print(ne_id),
diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c
index c024549fc..f937bdf55 100644
--- a/isisd/isis_mt.c
+++ b/isisd/isis_mt.c
@@ -515,6 +515,17 @@ static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
uint8_t *id, uint32_t metric,
struct isis_ext_subtlvs *ext)
{
+ /* Check if MT is enable for this area */
+ if (!area_is_mt(area)) {
+ lsp_debug(
+ "ISIS (%s): Adding %s.%02x as te-style neighbor (MT disable)",
+ area->area_tag, sysid_print(id), LSP_PSEUDO_ID(id));
+ isis_tlvs_add_extended_reach(tlvs, ISIS_MT_DISABLE, id, metric,
+ ext);
+ return;
+ }
+
+ /* Process Multi-Topology */
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
if (mt_set[i] == ISIS_MT_IPV4_UNICAST) {
diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h
index fd9ee133c..2952a2f17 100644
--- a/isisd/isis_mt.h
+++ b/isisd/isis_mt.h
@@ -33,6 +33,8 @@
#define ISIS_MT_IPV6_MULTICAST 4
#define ISIS_MT_IPV6_MGMT 5
#define ISIS_MT_IPV6_DSTSRC 3996 /* FIXME: IANA */
+/* Use first Reserved Flag to indicate that there is no MT Topology active */
+#define ISIS_MT_DISABLE 4096
#define ISIS_MT_NAMES \
"<ipv4-unicast" \
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index f62a8d481..57d013b3d 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -567,6 +567,14 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-isisd:isis/instance/mpls-te/router-address-v6",
+ .cbs = {
+ .cli_show = cli_show_isis_mpls_te_router_addr_ipv6,
+ .destroy = isis_instance_mpls_te_router_address_ipv6_destroy,
+ .modify = isis_instance_mpls_te_router_address_ipv6_modify,
+ },
+ },
+ {
.xpath = "/frr-isisd:isis/instance/segment-routing/enabled",
.cbs = {
.modify = isis_instance_segment_routing_enabled_modify,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index ee7904163..11167096c 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -211,6 +211,10 @@ int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args);
int isis_instance_mpls_te_router_address_modify(struct nb_cb_modify_args *args);
int isis_instance_mpls_te_router_address_destroy(
struct nb_cb_destroy_args *args);
+int isis_instance_mpls_te_router_address_ipv6_modify(
+ struct nb_cb_modify_args *args);
+int isis_instance_mpls_te_router_address_ipv6_destroy(
+ struct nb_cb_destroy_args *args);
int lib_interface_isis_create(struct nb_cb_create_args *args);
int lib_interface_isis_destroy(struct nb_cb_destroy_args *args);
int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args);
@@ -463,6 +467,9 @@ void cli_show_isis_mpls_te(struct vty *vty, const struct lyd_node *dnode,
void cli_show_isis_mpls_te_router_addr(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
+void cli_show_isis_mpls_te_router_addr_ipv6(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_def_origin_ipv4(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 3674d6937..bf043c4f4 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -1930,6 +1930,57 @@ int isis_instance_mpls_te_router_address_destroy(
}
/*
+ * XPath: /frr-isisd:isis/instance/mpls-te/router-address-v6
+ */
+int isis_instance_mpls_te_router_address_ipv6_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct in6_addr value;
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ /* only proceed if MPLS-TE is enabled */
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ yang_dnode_get_ipv6(&value, args->dnode, NULL);
+ /* Update Area IPv6 Router ID if different */
+ if (!IPV6_ADDR_SAME(&area->mta->router_id_ipv6, &value)) {
+ IPV6_ADDR_COPY(&area->mta->router_id_ipv6, &value);
+
+ /* And re-schedule LSP update */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+ }
+
+ return NB_OK;
+}
+
+int isis_instance_mpls_te_router_address_ipv6_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct isis_area *area;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ area = nb_running_get_entry(args->dnode, NULL, true);
+ /* only proceed if MPLS-TE is enabled */
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ /* Reset Area Router ID */
+ IPV6_ADDR_COPY(&area->mta->router_id_ipv6, &in6addr_any);
+
+ /* And re-schedule LSP update */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-isisd:isis/instance/segment-routing/enabled
*/
int isis_instance_segment_routing_enabled_modify(
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 7256fcbbc..0814f3eea 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -1971,6 +1971,11 @@ int send_hello(struct isis_circuit *circuit, int level)
if (circuit->ipv6_router && circuit->ipv6_link)
isis_tlvs_add_ipv6_addresses(tlvs, circuit->ipv6_link);
+ /* RFC6119 section 4 define TLV 233 to provide Global IPv6 address */
+ if (circuit->ipv6_router && circuit->ipv6_non_link)
+ isis_tlvs_add_global_ipv6_addresses(tlvs,
+ circuit->ipv6_non_link);
+
if (isis_pack_tlvs(tlvs, circuit->snd_stream, len_pointer,
circuit->pad_hellos, false)) {
isis_free_tlvs(tlvs);
diff --git a/isisd/isis_route.c b/isisd/isis_route.c
index bf0079d81..764a0b0cd 100644
--- a/isisd/isis_route.c
+++ b/isisd/isis_route.c
@@ -145,8 +145,8 @@ void adjinfo2nexthop(int family, struct list *nexthops,
}
break;
case AF_INET6:
- for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
- ip.ipv6 = adj->ipv6_addresses[i];
+ for (unsigned int i = 0; i < adj->ll_ipv6_count; i++) {
+ ip.ipv6 = adj->ll_ipv6_addrs[i];
if (!nexthoplookup(nexthops, AF_INET6, &ip,
adj->circuit->interface->ifindex)) {
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
index c530eb916..319977f41 100644
--- a/isisd/isis_snmp.c
+++ b/isisd/isis_snmp.c
@@ -1186,14 +1186,13 @@ static int isis_snmp_adj_helper(struct isis_adjacency *adj, int data_id,
break;
case ISIS_SNMP_ADJ_DATA_IP_ADDR:
- if (data_off
- >= (adj->ipv4_address_count + adj->ipv6_address_count))
+ if (data_off >= (adj->ipv4_address_count + adj->ll_ipv6_count))
return 0;
if (data_off >= adj->ipv4_address_count) {
- data = (uint8_t *)&adj->ipv6_addresses
+ data = (uint8_t *)&adj->ll_ipv6_addrs
[data_off - adj->ipv4_address_count];
- data_len = sizeof(adj->ipv6_addresses[0]);
+ data_len = sizeof(adj->ll_ipv6_addrs[0]);
} else {
data = (uint8_t *)&adj->ipv4_addresses[data_off];
data_len = sizeof(adj->ipv4_addresses[0]);
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 54e31f004..18a727add 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -661,10 +661,10 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup,
nexthop.ipv4 = adj->ipv4_addresses[0];
break;
case AF_INET6:
- if (!circuit->ipv6_router || !adj->ipv6_address_count)
+ if (!circuit->ipv6_router || !adj->ll_ipv6_count)
return;
- nexthop.ipv6 = adj->ipv6_addresses[0];
+ nexthop.ipv6 = adj->ll_ipv6_addrs[0];
break;
default:
flog_err(EC_LIB_DEVELOPMENT,
@@ -880,12 +880,14 @@ static int sr_adj_state_change(struct isis_adjacency *adj)
*
* @param adj IS-IS Adjacency
* @param family Inet Family (IPv4 or IPv6)
+ * @param global Indicate if it concerns the Local or Global IPv6 addresses
*
* @return 0
*/
-static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family)
+static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
- if (!adj->circuit->area->srdb.enabled)
+ if (!adj->circuit->area->srdb.enabled || global)
return 0;
sr_adj_sid_add(adj, family);
@@ -899,15 +901,17 @@ static int sr_adj_ip_enabled(struct isis_adjacency *adj, int family)
*
* @param adj IS-IS Adjacency
* @param family Inet Family (IPv4 or IPv6)
+ * @param global Indicate if it concerns the Local or Global IPv6 addresses
*
* @return 0
*/
-static int sr_adj_ip_disabled(struct isis_adjacency *adj, int family)
+static int sr_adj_ip_disabled(struct isis_adjacency *adj, int family,
+ bool global)
{
struct sr_adjacency *sra;
struct listnode *node, *nnode;
- if (!adj->circuit->area->srdb.enabled)
+ if (!adj->circuit->area->srdb.enabled || global)
return 0;
for (ALL_LIST_ELEMENTS(adj->adj_sids, node, nnode, sra))
@@ -1148,7 +1152,7 @@ int isis_sr_start(struct isis_area *area)
for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
if (adj->ipv4_address_count > 0)
sr_adj_sid_add(adj, AF_INET);
- if (adj->ipv6_address_count > 0)
+ if (adj->ll_ipv6_count > 0)
sr_adj_sid_add(adj, AF_INET6);
}
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 8daa2b36b..348894fed 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -248,29 +248,99 @@ void isis_link_params_update(struct isis_circuit *circuit,
return;
}
-static int isis_link_update_adj_hook(struct isis_adjacency *adj)
+static int isis_mpls_te_adj_ip_enabled(struct isis_adjacency *adj, int family,
+ bool global)
{
+ struct isis_circuit *circuit;
+ struct isis_ext_subtlvs *ext;
+
+ /* Sanity Check */
+ if (!adj || !adj->circuit)
+ return 0;
+
+ circuit = adj->circuit;
- struct isis_circuit *circuit = adj->circuit;
+ /* Check that MPLS TE is enabled */
+ if (!IS_MPLS_TE(circuit->area->mta) || !circuit->ext)
+ return 0;
+
+ ext = circuit->ext;
- /* Update MPLS TE Remote IP address parameter if possible */
- if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext))
+ /* Update MPLS TE IP address parameters if possible */
+ if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(ext))
return 0;
- /* IPv4 first */
- if (adj->ipv4_address_count > 0) {
- IPV4_ADDR_COPY(&circuit->ext->neigh_addr,
- &adj->ipv4_addresses[0]);
- SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR);
+ /* Determine nexthop IP address */
+ switch (family) {
+ case AF_INET:
+ if (!circuit->ip_router || !adj->ipv4_address_count)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ else {
+ IPV4_ADDR_COPY(&ext->neigh_addr,
+ &adj->ipv4_addresses[0]);
+ SET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ }
+ break;
+ case AF_INET6:
+ if (!global)
+ return 0;
+
+ if (!circuit->ipv6_router || !adj->global_ipv6_count)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ else {
+ IPV6_ADDR_COPY(&ext->neigh_addr6,
+ &adj->global_ipv6_addrs[0]);
+ SET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ }
+ break;
+ default:
+ return 0;
}
- /* and IPv6 */
- if (adj->ipv6_address_count > 0) {
- IPV6_ADDR_COPY(&circuit->ext->neigh_addr6,
- &adj->ipv6_addresses[0]);
- SET_SUBTLV(circuit->ext, EXT_NEIGH_ADDR6);
+ /* Update LSP */
+ lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
+
+ return 0;
+}
+
+static int isis_mpls_te_adj_ip_disabled(struct isis_adjacency *adj, int family,
+ bool global)
+{
+ struct isis_circuit *circuit;
+ struct isis_ext_subtlvs *ext;
+
+ /* Sanity Check */
+ if (!adj || !adj->circuit || !adj->circuit->ext)
+ return 0;
+
+ circuit = adj->circuit;
+
+ /* Check that MPLS TE is enabled */
+ if (!IS_MPLS_TE(circuit->area->mta) || !circuit->ext)
+ return 0;
+
+ ext = circuit->ext;
+
+ /* Update MPLS TE IP address parameters if possible */
+ if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(ext))
+ return 0;
+
+ /* Determine nexthop IP address */
+ switch (family) {
+ case AF_INET:
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR);
+ break;
+ case AF_INET6:
+ if (global)
+ UNSET_SUBTLV(ext, EXT_NEIGH_ADDR6);
+ break;
+ default:
+ return 0;
}
+ /* Update LSP */
+ lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
+
return 0;
}
@@ -302,6 +372,25 @@ int isis_mpls_te_update(struct interface *ifp)
/* Followings are vty command functions */
#ifndef FABRICD
+static void show_router_id(struct vty *vty, struct isis_area *area)
+{
+ bool no_match = true;
+
+ vty_out(vty, "Area %s:\n", area->area_tag);
+ if (area->mta->router_id.s_addr != 0) {
+ vty_out(vty, " MPLS-TE IPv4 Router-Address: %pI4\n",
+ &area->mta->router_id);
+ no_match = false;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED(&area->mta->router_id_ipv6)) {
+ vty_out(vty, " MPLS-TE IPv6 Router-Address: %pI6\n",
+ &area->mta->router_id_ipv6);
+ no_match = false;
+ }
+ if (no_match)
+ vty_out(vty, " N/A\n");
+}
+
DEFUN(show_isis_mpls_te_router,
show_isis_mpls_te_router_cmd,
"show " PROTO_NAME " [vrf <NAME|all>] mpls-te router",
@@ -331,15 +420,7 @@ DEFUN(show_isis_mpls_te_router,
if (!IS_MPLS_TE(area->mta))
continue;
- vty_out(vty, "Area %s:\n",
- area->area_tag);
- if (ntohs(area->mta->router_id.s_addr)
- != 0)
- vty_out(vty,
- " MPLS-TE Router-Address: %pI4\n",
- &area->mta->router_id);
- else
- vty_out(vty, " N/A\n");
+ show_router_id(vty, area);
}
}
return 0;
@@ -352,13 +433,7 @@ DEFUN(show_isis_mpls_te_router,
if (!IS_MPLS_TE(area->mta))
continue;
- vty_out(vty, "Area %s:\n", area->area_tag);
- if (ntohs(area->mta->router_id.s_addr) != 0)
- vty_out(vty,
- " MPLS-TE Router-Address: %pI4\n",
- &area->mta->router_id);
- else
- vty_out(vty, " N/A\n");
+ show_router_id(vty, area);
}
}
}
@@ -536,8 +611,8 @@ void isis_mpls_te_init(void)
/* Register Circuit and Adjacency hook */
hook_register(isis_if_new_hook, isis_mpls_te_update);
- hook_register(isis_adj_state_change_hook, isis_link_update_adj_hook);
-
+ hook_register(isis_adj_ip_enabled_hook, isis_mpls_te_adj_ip_enabled);
+ hook_register(isis_adj_ip_disabled_hook, isis_mpls_te_adj_ip_disabled);
#ifndef FABRICD
/* Register new VTY commands */
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index 2a6911d50..e69ae4072 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -101,8 +101,9 @@ struct mpls_te_area {
interas_mode_t inter_as;
struct in_addr interas_areaid;
- /* MPLS_TE router ID */
+ /* MPLS_TE IPv4 & IPv6 Router IDs */
struct in_addr router_id;
+ struct in6_addr router_id_ipv6;
};
/* Prototypes. */
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index a66d3b00f..9a442e037 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -99,6 +99,7 @@ static const struct pack_order_entry pack_order[] = {
PACK_ENTRY(OLDSTYLE_IP_REACH_EXT, ISIS_ITEMS, oldstyle_ip_reach_ext),
PACK_ENTRY(IPV4_ADDRESS, ISIS_ITEMS, ipv4_address),
PACK_ENTRY(IPV6_ADDRESS, ISIS_ITEMS, ipv6_address),
+ PACK_ENTRY(GLOBAL_IPV6_ADDRESS, ISIS_ITEMS, global_ipv6_address),
PACK_ENTRY(EXTENDED_IP_REACH, ISIS_ITEMS, extended_ip_reach),
PACK_ENTRY(MT_IP_REACH, ISIS_MT_ITEMS, mt_ip_reach),
PACK_ENTRY(IPV6_REACH, ISIS_ITEMS, ipv6_reach),
@@ -128,27 +129,41 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
}
/*
- * mtid parameter is used to determine if Adjacency is related to IPv4 or IPv6.
- * A negative value could be used to skip copy of Adjacency SID.
+ * mtid parameter is used to determine if Adjacency is related to IPv4 or IPv6
+ * Multi-Topology. Special 4096 value i.e. first R flag set is used to indicate
+ * that MT is disabled i.e. IS-IS is working with a Single Topology.
*/
static struct isis_ext_subtlvs *
-copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, int16_t mtid)
+copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
{
struct isis_ext_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
struct isis_adj_sid *adj;
struct isis_lan_adj_sid *lan;
+ /* Copy the Extended IS main part */
memcpy(rv, exts, sizeof(struct isis_ext_subtlvs));
+
+ /* Disable IPv4 / IPv6 advertisement in function of MTID */
+ if (mtid == ISIS_MT_IPV4_UNICAST) {
+ UNSET_SUBTLV(rv, EXT_LOCAL_ADDR6);
+ UNSET_SUBTLV(rv, EXT_NEIGH_ADDR6);
+ }
+ if (mtid == ISIS_MT_IPV6_UNICAST) {
+ UNSET_SUBTLV(rv, EXT_LOCAL_ADDR);
+ UNSET_SUBTLV(rv, EXT_NEIGH_ADDR);
+ }
+
+ /* Prepare (LAN)-Adjacency Segment Routing ID*/
init_item_list(&rv->adj_sid);
init_item_list(&rv->lan_sid);
UNSET_SUBTLV(rv, EXT_ADJ_SID);
UNSET_SUBTLV(rv, EXT_LAN_ADJ_SID);
- /* Copy Adj SID and LAN Adj SID list for IPv4 if needed */
+ /* Copy Adj SID list for IPv4 & IPv6 in function of MT ID */
for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj != NULL;
adj = adj->next) {
- if ((mtid != -1)
+ if ((mtid != ISIS_MT_DISABLE)
&& (((mtid == ISIS_MT_IPV4_UNICAST)
&& (adj->family != AF_INET))
|| ((mtid == ISIS_MT_IPV6_UNICAST)
@@ -166,9 +181,10 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, int16_t mtid)
SET_SUBTLV(rv, EXT_ADJ_SID);
}
+ /* Same for LAN Adj SID */
for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head; lan != NULL;
lan = lan->next) {
- if ((mtid != -1)
+ if ((mtid != ISIS_MT_DISABLE)
&& (((mtid == ISIS_MT_IPV4_UNICAST)
&& (lan->family != AF_INET))
|| ((mtid == ISIS_MT_IPV6_UNICAST)
@@ -196,8 +212,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
uint16_t mtid)
{
- char ibuf[PREFIX2STR_BUFFER];
-
/* Standard metrics */
if (IS_SUBTLV(exts, EXT_ADM_GRP))
sbuf_push(buf, indent, "Administrative Group: 0x%x\n",
@@ -212,16 +226,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
sbuf_push(buf, indent, "Local Interface IP Address(es): %pI4\n",
&exts->local_addr);
if (IS_SUBTLV(exts, EXT_NEIGH_ADDR))
- sbuf_push(buf, indent, "Remote Interface IP Address(es): %pI4\n",
+ sbuf_push(buf, indent,
+ "Remote Interface IP Address(es): %pI4\n",
&exts->neigh_addr);
if (IS_SUBTLV(exts, EXT_LOCAL_ADDR6))
- sbuf_push(buf, indent, "Local Interface IPv6 Address(es): %s\n",
- inet_ntop(AF_INET6, &exts->local_addr6, ibuf,
- PREFIX2STR_BUFFER));
+ sbuf_push(buf, indent,
+ "Local Interface IPv6 Address(es): %pI6\n",
+ &exts->local_addr6);
if (IS_SUBTLV(exts, EXT_NEIGH_ADDR6))
- sbuf_push(buf, indent, "Remote Interface IPv6 Address(es): %s\n",
- inet_ntop(AF_INET6, &exts->local_addr6, ibuf,
- PREFIX2STR_BUFFER));
+ sbuf_push(buf, indent,
+ "Remote Interface IPv6 Address(es): %pI6\n",
+ &exts->neigh_addr6);
if (IS_SUBTLV(exts, EXT_MAX_BW))
sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n",
exts->max_bw);
@@ -289,11 +304,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
for (adj = (struct isis_adj_sid *)exts->adj_sid.head; adj;
adj = adj->next) {
- if (((mtid == ISIS_MT_IPV4_UNICAST)
- && (adj->family != AF_INET))
- || ((mtid == ISIS_MT_IPV6_UNICAST)
- && (adj->family != AF_INET6)))
- continue;
sbuf_push(
buf, indent,
"Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n",
@@ -319,10 +329,6 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
for (lan = (struct isis_lan_adj_sid *)exts->lan_sid.head;
lan; lan = lan->next) {
- if (((mtid == ISIS_MT_IPV4_UNICAST)
- && (lan->family != AF_INET))
- || ((mtid == ISIS_MT_IPV6_UNICAST)
- && (lan->family != AF_INET6)))
continue;
sbuf_push(buf, indent,
"Lan-Adjacency-SID: %u, Weight: %hhu, Flags: F:%c B:%c, V:%c, L:%c, S:%c, P:%c\n"
@@ -1839,12 +1845,12 @@ static int pack_item_ipv6_address(struct isis_item *i, struct stream *s,
{
struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
- if (STREAM_WRITEABLE(s) < 16) {
- *min_len = 16;
+ if (STREAM_WRITEABLE(s) < IPV6_MAX_BYTELEN) {
+ *min_len = IPV6_MAX_BYTELEN;
return 1;
}
- stream_put(s, &a->addr, 16);
+ stream_put(s, &a->addr, IPV6_MAX_BYTELEN);
return 0;
}
@@ -1865,7 +1871,7 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
}
struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
- stream_get(&rv->addr, s, 16);
+ stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
format_item_ipv6_address(mtid, (struct isis_item *)rv, log, indent + 2);
append_item(&tlvs->ipv6_address, (struct isis_item *)rv);
@@ -1873,6 +1879,70 @@ static int unpack_item_ipv6_address(uint16_t mtid, uint8_t len,
}
+/* Functions related to TLV 233 Global IPv6 Interface addresses */
+static struct isis_item *copy_item_global_ipv6_address(struct isis_item *i)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+
+ rv->addr = a->addr;
+ return (struct isis_item *)rv;
+}
+
+static void format_item_global_ipv6_address(uint16_t mtid, struct isis_item *i,
+ struct sbuf *buf, int indent)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+ char addrbuf[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n", addrbuf);
+}
+
+static void free_item_global_ipv6_address(struct isis_item *i)
+{
+ XFREE(MTYPE_ISIS_TLV, i);
+}
+
+static int pack_item_global_ipv6_address(struct isis_item *i, struct stream *s,
+ size_t *min_len)
+{
+ struct isis_ipv6_address *a = (struct isis_ipv6_address *)i;
+
+ if (STREAM_WRITEABLE(s) < IPV6_MAX_BYTELEN) {
+ *min_len = IPV6_MAX_BYTELEN;
+ return 1;
+ }
+
+ stream_put(s, &a->addr, IPV6_MAX_BYTELEN);
+
+ return 0;
+}
+
+static int unpack_item_global_ipv6_address(uint16_t mtid, uint8_t len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpack Global IPv6 Interface address...\n");
+ if (len < IPV6_MAX_BYTELEN) {
+ sbuf_push(
+ log, indent,
+ "Not enough data left.(Expected 16 bytes of IPv6 address, got %hhu)\n",
+ len);
+ return 1;
+ }
+
+ struct isis_ipv6_address *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ stream_get(&rv->addr, s, IPV6_MAX_BYTELEN);
+
+ format_item_global_ipv6_address(mtid, (struct isis_item *)rv, log,
+ indent + 2);
+ append_item(&tlvs->global_ipv6_address, (struct isis_item *)rv);
+ return 0;
+}
+
/* Functions related to TLV 229 MT Router information */
static struct isis_item *copy_item_mt_router_info(struct isis_item *i)
{
@@ -2273,6 +2343,77 @@ static int unpack_tlv_dynamic_hostname(enum isis_tlv_context context,
return 0;
}
+/* Functions related to TLV 140 IPv6 TE Router ID */
+
+static struct in6_addr *copy_tlv_te_router_id_ipv6(const struct in6_addr *id)
+{
+ if (!id)
+ return NULL;
+
+ struct in6_addr *rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
+ memcpy(rv, id, sizeof(*rv));
+ return rv;
+}
+
+static void format_tlv_te_router_id_ipv6(const struct in6_addr *id,
+ struct sbuf *buf, int indent)
+{
+ if (!id)
+ return;
+
+ char addrbuf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, id, addrbuf, sizeof(addrbuf));
+ sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
+}
+
+static void free_tlv_te_router_id_ipv6(struct in6_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, id);
+}
+
+static int pack_tlv_te_router_id_ipv6(const struct in6_addr *id,
+ struct stream *s)
+{
+ if (!id)
+ return 0;
+
+ if (STREAM_WRITEABLE(s) < (unsigned)(2 + sizeof(*id)))
+ return 1;
+
+ stream_putc(s, ISIS_TLV_TE_ROUTER_ID_IPV6);
+ stream_putc(s, IPV6_MAX_BYTELEN);
+ stream_put(s, id, IPV6_MAX_BYTELEN);
+ return 0;
+}
+
+static int unpack_tlv_te_router_id_ipv6(enum isis_tlv_context context,
+ uint8_t tlv_type, uint8_t tlv_len,
+ struct stream *s, struct sbuf *log,
+ void *dest, int indent)
+{
+ struct isis_tlvs *tlvs = dest;
+
+ sbuf_push(log, indent, "Unpacking IPv6 TE Router ID TLV...\n");
+ if (tlv_len != IPV6_MAX_BYTELEN) {
+ sbuf_push(log, indent, "WARNING: Length invalid\n");
+ return 1;
+ }
+
+ if (tlvs->te_router_id_ipv6) {
+ sbuf_push(
+ log, indent,
+ "WARNING: IPv6 TE Router ID present multiple times.\n");
+ stream_forward_getp(s, tlv_len);
+ return 0;
+ }
+
+ tlvs->te_router_id_ipv6 = XCALLOC(MTYPE_ISIS_TLV, IPV6_MAX_BYTELEN);
+ stream_get(tlvs->te_router_id_ipv6, s, IPV6_MAX_BYTELEN);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, log, indent + 2);
+ return 0;
+}
+
+
/* Functions related to TLV 150 Spine-Leaf-Extension */
static struct isis_spine_leaf *copy_tlv_spine_leaf(
@@ -3640,6 +3781,7 @@ struct isis_tlvs *isis_alloc_tlvs(void)
init_item_list(&result->oldstyle_ip_reach_ext);
init_item_list(&result->ipv4_address);
init_item_list(&result->ipv6_address);
+ init_item_list(&result->global_ipv6_address);
init_item_list(&result->extended_ip_reach);
RB_INIT(isis_mt_item_list, &result->mt_ip_reach);
init_item_list(&result->ipv6_reach);
@@ -3696,8 +3838,14 @@ struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs)
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS, &tlvs->ipv6_address,
&rv->ipv6_address);
+ copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address, &rv->global_ipv6_address);
+
rv->te_router_id = copy_tlv_te_router_id(tlvs->te_router_id);
+ rv->te_router_id_ipv6 =
+ copy_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
+
copy_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach, &rv->extended_ip_reach);
@@ -3751,6 +3899,7 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
format_tlv_dynamic_hostname(tlvs->hostname, buf, indent);
format_tlv_te_router_id(tlvs->te_router_id, buf, indent);
+ format_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, buf, indent);
format_tlv_router_cap(tlvs->router_cap, buf, indent);
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_REACH,
@@ -3771,6 +3920,9 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, int indent)
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
&tlvs->ipv6_address, buf, indent);
+ format_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address, buf, indent);
+
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach, buf, indent);
@@ -3828,7 +3980,10 @@ void isis_free_tlvs(struct isis_tlvs *tlvs)
&tlvs->ipv4_address);
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_IPV6_ADDRESS,
&tlvs->ipv6_address);
+ free_items(ISIS_CONTEXT_LSP, ISIS_TLV_GLOBAL_IPV6_ADDRESS,
+ &tlvs->global_ipv6_address);
free_tlv_te_router_id(tlvs->te_router_id);
+ free_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
free_items(ISIS_CONTEXT_LSP, ISIS_TLV_EXTENDED_IP_REACH,
&tlvs->extended_ip_reach);
free_mt_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_IP_REACH,
@@ -4035,6 +4190,14 @@ static int pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
copy_tlv_te_router_id(tlvs->te_router_id);
}
+ rv = pack_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6, stream);
+ if (rv)
+ return rv;
+ if (fragment_tlvs) {
+ fragment_tlvs->te_router_id_ipv6 =
+ copy_tlv_te_router_id_ipv6(tlvs->te_router_id_ipv6);
+ }
+
rv = pack_tlv_threeway_adj(tlvs->threeway_adj, stream);
if (rv)
return rv;
@@ -4255,10 +4418,12 @@ ITEM_TLV_OPS(ipv4_address, "TLV 132 IPv4 Interface Address");
TLV_OPS(te_router_id, "TLV 134 TE Router ID");
ITEM_TLV_OPS(extended_ip_reach, "TLV 135 Extended IP Reachability");
TLV_OPS(dynamic_hostname, "TLV 137 Dynamic Hostname");
+TLV_OPS(te_router_id_ipv6, "TLV 140 IPv6 TE Router ID");
TLV_OPS(spine_leaf, "TLV 150 Spine Leaf Extensions");
ITEM_TLV_OPS(mt_router_info, "TLV 229 MT Router Information");
TLV_OPS(threeway_adj, "TLV 240 P2P Three-Way Adjacency");
ITEM_TLV_OPS(ipv6_address, "TLV 232 IPv6 Interface Address");
+ITEM_TLV_OPS(global_ipv6_address, "TLV 233 Global IPv6 Interface Address");
ITEM_TLV_OPS(ipv6_reach, "TLV 236 IPv6 Reachability");
TLV_OPS(router_cap, "TLV 242 Router Capability");
@@ -4279,12 +4444,14 @@ static const struct tlv_ops *const tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
[ISIS_TLV_OLDSTYLE_IP_REACH_EXT] = &tlv_oldstyle_ip_reach_ops,
[ISIS_TLV_IPV4_ADDRESS] = &tlv_ipv4_address_ops,
[ISIS_TLV_TE_ROUTER_ID] = &tlv_te_router_id_ops,
+ [ISIS_TLV_TE_ROUTER_ID_IPV6] = &tlv_te_router_id_ipv6_ops,
[ISIS_TLV_EXTENDED_IP_REACH] = &tlv_extended_ip_reach_ops,
[ISIS_TLV_DYNAMIC_HOSTNAME] = &tlv_dynamic_hostname_ops,
[ISIS_TLV_SPINE_LEAF_EXT] = &tlv_spine_leaf_ops,
[ISIS_TLV_MT_REACH] = &tlv_extended_reach_ops,
[ISIS_TLV_MT_ROUTER_INFO] = &tlv_mt_router_info_ops,
[ISIS_TLV_IPV6_ADDRESS] = &tlv_ipv6_address_ops,
+ [ISIS_TLV_GLOBAL_IPV6_ADDRESS] = &tlv_global_ipv6_address_ops,
[ISIS_TLV_MT_IP_REACH] = &tlv_extended_ip_reach_ops,
[ISIS_TLV_IPV6_REACH] = &tlv_ipv6_reach_ops,
[ISIS_TLV_MT_IPV6_REACH] = &tlv_ipv6_reach_ops,
@@ -4427,6 +4594,26 @@ void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
}
}
+void isis_tlvs_add_global_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses)
+{
+ struct listnode *node;
+ struct prefix_ipv6 *ip_addr;
+ unsigned int addr_count = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(addresses, node, ip_addr)) {
+ if (addr_count >= 15)
+ break;
+
+ struct isis_ipv6_address *a =
+ XCALLOC(MTYPE_ISIS_TLV, sizeof(*a));
+
+ a->addr = ip_addr->prefix;
+ append_item(&tlvs->global_ipv6_address, (struct isis_item *)a);
+ addr_count++;
+ }
+}
+
typedef bool (*auth_validator_func)(struct isis_passwd *passwd,
struct stream *stream,
struct isis_auth *auth, bool is_lsp);
@@ -4606,10 +4793,12 @@ static void tlvs_protocols_supported_to_adj(struct isis_tlvs *tlvs,
memcpy(adj->nlpids.nlpids, reduced.nlpids, reduced.count);
}
-DEFINE_HOOK(isis_adj_ip_enabled_hook, (struct isis_adjacency *adj, int family),
- (adj, family));
+DEFINE_HOOK(isis_adj_ip_enabled_hook,
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
DEFINE_HOOK(isis_adj_ip_disabled_hook,
- (struct isis_adjacency *adj, int family), (adj, family));
+ (struct isis_adjacency * adj, int family, bool global),
+ (adj, family, global));
static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
struct isis_adjacency *adj,
@@ -4620,7 +4809,7 @@ static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
if (adj->ipv4_address_count == 0 && tlvs->ipv4_address.count > 0)
ipv4_enabled = true;
else if (adj->ipv4_address_count > 0 && tlvs->ipv4_address.count == 0)
- hook_call(isis_adj_ip_disabled_hook, adj, AF_INET);
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET, false);
if (adj->ipv4_address_count != tlvs->ipv4_address.count) {
uint32_t oc = adj->ipv4_address_count;
@@ -4654,7 +4843,7 @@ static void tlvs_ipv4_addresses_to_adj(struct isis_tlvs *tlvs,
}
if (ipv4_enabled)
- hook_call(isis_adj_ip_enabled_hook, adj, AF_INET);
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET, false);
}
static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
@@ -4663,23 +4852,23 @@ static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
{
bool ipv6_enabled = false;
- if (adj->ipv6_address_count == 0 && tlvs->ipv6_address.count > 0)
+ if (adj->ll_ipv6_count == 0 && tlvs->ipv6_address.count > 0)
ipv6_enabled = true;
- else if (adj->ipv6_address_count > 0 && tlvs->ipv6_address.count == 0)
- hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6);
+ else if (adj->ll_ipv6_count > 0 && tlvs->ipv6_address.count == 0)
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6, false);
- if (adj->ipv6_address_count != tlvs->ipv6_address.count) {
- uint32_t oc = adj->ipv6_address_count;
+ if (adj->ll_ipv6_count != tlvs->ipv6_address.count) {
+ uint32_t oc = adj->ll_ipv6_count;
*changed = true;
- adj->ipv6_address_count = tlvs->ipv6_address.count;
- adj->ipv6_addresses = XREALLOC(
- MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses,
- adj->ipv6_address_count * sizeof(*adj->ipv6_addresses));
-
- for (; oc < adj->ipv6_address_count; oc++) {
- memset(&adj->ipv6_addresses[oc], 0,
- sizeof(adj->ipv6_addresses[oc]));
+ adj->ll_ipv6_count = tlvs->ipv6_address.count;
+ adj->ll_ipv6_addrs = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs,
+ adj->ll_ipv6_count * sizeof(*adj->ll_ipv6_addrs));
+
+ for (; oc < adj->ll_ipv6_count; oc++) {
+ memset(&adj->ll_ipv6_addrs[oc], 0,
+ sizeof(adj->ll_ipv6_addrs[oc]));
}
}
@@ -4691,16 +4880,65 @@ static void tlvs_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
else
addr = addr->next;
- if (!memcmp(&adj->ipv6_addresses[i], &addr->addr,
+ if (!memcmp(&adj->ll_ipv6_addrs[i], &addr->addr,
sizeof(addr->addr)))
continue;
*changed = true;
- adj->ipv6_addresses[i] = addr->addr;
+ adj->ll_ipv6_addrs[i] = addr->addr;
}
if (ipv6_enabled)
- hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6);
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6, false);
+}
+
+
+static void tlvs_global_ipv6_addresses_to_adj(struct isis_tlvs *tlvs,
+ struct isis_adjacency *adj,
+ bool *changed)
+{
+ bool global_ipv6_enabled = false;
+
+ if (adj->global_ipv6_count == 0 && tlvs->global_ipv6_address.count > 0)
+ global_ipv6_enabled = true;
+ else if (adj->global_ipv6_count > 0
+ && tlvs->global_ipv6_address.count == 0)
+ hook_call(isis_adj_ip_disabled_hook, adj, AF_INET6, true);
+
+ if (adj->global_ipv6_count != tlvs->global_ipv6_address.count) {
+ uint32_t oc = adj->global_ipv6_count;
+
+ *changed = true;
+ adj->global_ipv6_count = tlvs->global_ipv6_address.count;
+ adj->global_ipv6_addrs = XREALLOC(
+ MTYPE_ISIS_ADJACENCY_INFO, adj->global_ipv6_addrs,
+ adj->global_ipv6_count
+ * sizeof(*adj->global_ipv6_addrs));
+
+ for (; oc < adj->global_ipv6_count; oc++) {
+ memset(&adj->global_ipv6_addrs[oc], 0,
+ sizeof(adj->global_ipv6_addrs[oc]));
+ }
+ }
+
+ struct isis_ipv6_address *addr = NULL;
+ for (unsigned int i = 0; i < tlvs->global_ipv6_address.count; i++) {
+ if (!addr)
+ addr = (struct isis_ipv6_address *)
+ tlvs->global_ipv6_address.head;
+ else
+ addr = addr->next;
+
+ if (!memcmp(&adj->global_ipv6_addrs[i], &addr->addr,
+ sizeof(addr->addr)))
+ continue;
+
+ *changed = true;
+ adj->global_ipv6_addrs[i] = addr->addr;
+ }
+
+ if (global_ipv6_enabled)
+ hook_call(isis_adj_ip_enabled_hook, adj, AF_INET6, true);
}
void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
@@ -4712,6 +4950,7 @@ void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
tlvs_protocols_supported_to_adj(tlvs, adj, changed);
tlvs_ipv4_addresses_to_adj(tlvs, adj, changed);
tlvs_ipv6_addresses_to_adj(tlvs, adj, changed);
+ tlvs_global_ipv6_addresses_to_adj(tlvs, adj, changed);
}
bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa)
@@ -4793,6 +5032,16 @@ void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
memcpy(tlvs->te_router_id, id, sizeof(*id));
}
+void isis_tlvs_set_te_router_id_ipv6(struct isis_tlvs *tlvs,
+ const struct in6_addr *id)
+{
+ XFREE(MTYPE_ISIS_TLV, tlvs->te_router_id_ipv6);
+ if (!id)
+ return;
+ tlvs->te_router_id_ipv6 = XCALLOC(MTYPE_ISIS_TLV, sizeof(*id));
+ memcpy(tlvs->te_router_id_ipv6, id, sizeof(*id));
+}
+
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint8_t metric)
{
@@ -4922,7 +5171,7 @@ void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
r->subtlvs = copy_item_ext_subtlvs(exts, mtid);
struct isis_item_list *l;
- if (mtid == ISIS_MT_IPV4_UNICAST)
+ if ((mtid == ISIS_MT_IPV4_UNICAST) || (mtid == ISIS_MT_DISABLE))
l = &tlvs->extended_reach;
else
l = isis_get_mt_items(&tlvs->mt_reach, mtid);
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 0438d13ae..38470ef85 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -324,9 +324,11 @@ struct isis_tlvs {
struct isis_item_list oldstyle_ip_reach_ext;
struct isis_item_list ipv4_address;
struct isis_item_list ipv6_address;
+ struct isis_item_list global_ipv6_address;
struct isis_item_list mt_router_info;
bool mt_router_info_empty;
struct in_addr *te_router_id;
+ struct in6_addr *te_router_id_ipv6;
struct isis_item_list extended_ip_reach;
struct isis_mt_item_list mt_ip_reach;
char *hostname;
@@ -372,10 +374,12 @@ enum isis_tlv_type {
ISIS_TLV_TE_ROUTER_ID = 134,
ISIS_TLV_EXTENDED_IP_REACH = 135,
ISIS_TLV_DYNAMIC_HOSTNAME = 137,
+ ISIS_TLV_TE_ROUTER_ID_IPV6 = 140,
ISIS_TLV_SPINE_LEAF_EXT = 150,
ISIS_TLV_MT_REACH = 222,
ISIS_TLV_MT_ROUTER_INFO = 229,
ISIS_TLV_IPV6_ADDRESS = 232,
+ ISIS_TLV_GLOBAL_IPV6_ADDRESS = 233,
ISIS_TLV_MT_IP_REACH = 235,
ISIS_TLV_IPV6_REACH = 236,
ISIS_TLV_MT_IPV6_REACH = 237,
@@ -575,6 +579,8 @@ void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
+void isis_tlvs_add_global_ipv6_addresses(struct isis_tlvs *tlvs,
+ struct list *addresses);
int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
struct stream *stream, bool is_lsp);
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
@@ -594,6 +600,8 @@ void isis_tlvs_set_router_capability(struct isis_tlvs *tlvs,
const struct isis_router_cap *cap);
void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
const struct in_addr *id);
+void isis_tlvs_set_te_router_id_ipv6(struct isis_tlvs *tlvs,
+ const struct in6_addr *id);
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint8_t metric);
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
index b50c5683b..accc906bf 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/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 5997e8866..7a67a739e 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -1481,6 +1481,11 @@ module frr-isisd {
description
"Stable IP address of the advertising router.";
}
+ leaf router-address-v6 {
+ type inet:ipv6-address;
+ description
+ "Stable IPv6 address of the advertising router.";
+ }
}
container segment-routing {