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>
This commit is contained in:
Olivier Dugeon 2021-06-30 17:23:56 +02:00
parent 0536fea8d2
commit 173f8887cc
23 changed files with 619 additions and 118 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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),

View File

@ -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) {

View File

@ -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" \

View File

@ -566,6 +566,14 @@ const struct frr_yang_module_info frr_isisd_info = {
.modify = isis_instance_mpls_te_router_address_modify,
},
},
{
.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 = {

View File

@ -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);

View File

@ -1929,6 +1929,57 @@ int isis_instance_mpls_te_router_address_destroy(
return NB_OK;
}
/*
* 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
*/

View File

@ -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);

View File

@ -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)) {

View File

@ -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]);

View File

@ -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);
}

View File

@ -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;
struct isis_circuit *circuit = adj->circuit;
/* Update MPLS TE Remote IP address parameter if possible */
if (!IS_MPLS_TE(circuit->area->mta) || !IS_EXT_TE(circuit->ext))
/* Sanity Check */
if (!adj || !adj->circuit)
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);
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:
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 */

View File

@ -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. */

View File

@ -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));
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->ipv6_address_count; oc++) {
memset(&adj->ipv6_addresses[oc], 0,
sizeof(adj->ipv6_addresses[oc]));
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);

View File

@ -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,

View File

@ -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 {