diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index fea99ec907..e3643868d3 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -415,6 +415,12 @@ isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t)); vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); vty_out (vty, "%s", VTY_NEWLINE); + if (adj->mt_count != 1 || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) + { + vty_out (vty, " Topologies:%s", VTY_NEWLINE); + for (unsigned int i = 0; i < adj->mt_count; i++) + vty_out (vty, " %s%s", isis_mtid2str(adj->mt_set[i]), VTY_NEWLINE); + } vty_out (vty, " SNPA: %s", snpa_print (adj->snpa)); if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index 552365ad10..d15da1d27a 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -415,7 +415,7 @@ tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable, if (!tlvs->mt_router_info) { /* Other end does not have MT enabled */ - if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST) + if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST && v4_usable) adj_mt_set(adj, intersect_count++, ISIS_MT_IPV4_UNICAST); } else @@ -425,7 +425,27 @@ tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable, for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node, info)) { if (mt_settings[i]->mtid == info->mtid) - adj_mt_set(adj, intersect_count++, info->mtid); + { + bool usable; + switch (info->mtid) + { + case ISIS_MT_IPV4_UNICAST: + case ISIS_MT_IPV4_MGMT: + case ISIS_MT_IPV4_MULTICAST: + usable = v4_usable; + break; + case ISIS_MT_IPV6_UNICAST: + case ISIS_MT_IPV6_MGMT: + case ISIS_MT_IPV6_MULTICAST: + usable = v6_usable; + break; + default: + usable = true; + break; + } + if (usable) + adj_mt_set(adj, intersect_count++, info->mtid); + } } } } diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 9e90acf2e0..5232666bda 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -62,11 +62,6 @@ #define PNBBY 8 #endif /* PNBBY */ -/* Utility mask array. */ -static const u_char maskbit[] = { - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff -}; - /* * HELPER FUNCS */ @@ -93,69 +88,6 @@ area_match (struct list *left, struct list *right) return 0; /* mismatch */ } -/* - * Check if ip2 is in the ip1's network (function like Prefix.h:prefix_match() ) - * param ip1 the IS interface ip address structure - * param ip2 the IIH's ip address - * return 0 the IIH's IP is not in the IS's subnetwork - * 1 the IIH's IP is in the IS's subnetwork - */ -static int -ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2) -{ - u_char *addr1, *addr2; - int shift, offset, offsetloop; - int len; - - addr1 = (u_char *) & ip1->prefix.s_addr; - addr2 = (u_char *) & ip2->s_addr; - len = ip1->prefixlen; - - shift = len % PNBBY; - offsetloop = offset = len / PNBBY; - - while (offsetloop--) - if (addr1[offsetloop] != addr2[offsetloop]) - return 0; - - if (shift) - if (maskbit[shift] & (addr1[offset] ^ addr2[offset])) - return 0; - - return 1; /* match */ -} - -/* - * Compares two set of ip addresses - * param left the local interface's ip addresses - * param right the iih interface's ip address - * return 0 no match; - * 1 match; - */ -static int -ip_match (struct list *left, struct list *right) -{ - struct prefix_ipv4 *ip1; - struct in_addr *ip2; - struct listnode *node1, *node2; - - if ((left == NULL) || (right == NULL)) - return 0; - - for (ALL_LIST_ELEMENTS_RO (left, node1, ip1)) - { - for (ALL_LIST_ELEMENTS_RO (right, node2, ip2)) - { - if (ip_same_subnet (ip1, ip2)) - { - return 1; /* match */ - } - } - - } - return 0; -} - /* * Checks whether we should accept a PDU of given level */ @@ -517,16 +449,14 @@ process_p2p_hello (struct isis_circuit *circuit) } /* - * check if it's own interface ip match iih ip addrs + * check if both ends have an IPv4 address */ - if (found & TLVFLAG_IPV4_ADDR) + if (circuit->ip_addrs && listcount(circuit->ip_addrs) + && tlvs.ipv4_addrs && listcount(tlvs.ipv4_addrs)) { - if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) - v4_usable = 1; - else - zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " - "in P2P IIH from %s\n", circuit->interface->name); + v4_usable = 1; } + if (found & TLVFLAG_IPV6_ADDR) { /* TBA: check that we have a linklocal ourselves? */ @@ -1116,16 +1046,14 @@ process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa) } /* - * check if it's own interface ip match iih ip addrs + * check if both ends have an IPv4 address */ - if (found & TLVFLAG_IPV4_ADDR) + if (circuit->ip_addrs && listcount(circuit->ip_addrs) + && tlvs.ipv4_addrs && listcount(tlvs.ipv4_addrs)) { - if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) - v4_usable = 1; - else - zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " - "in LAN IIH from %s\n", circuit->interface->name); + v4_usable = 1; } + if (found & TLVFLAG_IPV6_ADDR) { /* TBA: check that we have a linklocal ourselves? */ diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index d85f08f50b..43dffdc863 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -940,7 +940,9 @@ isis_spf_preload_tent (struct isis_spftree *spftree, switch (adj->sys_type) { case ISIS_SYSTYPE_ES: - isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, + memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID (lsp_id) = 0; + isis_spf_add_local (spftree, VTYPE_ES, lsp_id, adj, circuit->te_metric[spftree->level - 1], parent); break; @@ -1017,7 +1019,9 @@ isis_spf_preload_tent (struct isis_spftree *spftree, switch (adj->sys_type) { case ISIS_SYSTYPE_ES: - isis_spf_add_local (spftree, VTYPE_ES, adj->sysid, adj, + memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID (lsp_id) = 0; + isis_spf_add_local (spftree, VTYPE_ES, lsp_id, adj, circuit->te_metric[spftree->level - 1], parent); break; diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 1658ca3733..9cae5f9a5c 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -1284,6 +1284,13 @@ DEFUN (circuit_topology, return CMD_ERR_NO_MATCH; const char *arg = argv[2]->arg; uint16_t mtid = isis_str2mtid(arg); + + if (circuit->area && circuit->area->oldmetric) + { + vty_out (vty, "Multi topology IS-IS can only be used with wide metrics%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == (uint16_t)-1) { vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); @@ -1306,6 +1313,13 @@ DEFUN (no_circuit_topology, return CMD_ERR_NO_MATCH; const char *arg = argv[3]->arg; uint16_t mtid = isis_str2mtid(arg); + + if (circuit->area && circuit->area->oldmetric) + { + vty_out (vty, "Multi topology IS-IS can only be used with wide metrics%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == (uint16_t)-1) { vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); @@ -1371,6 +1385,12 @@ DEFUN (metric_style, return CMD_SUCCESS; } + if (area_is_mt(area)) + { + vty_out (vty, "Narrow metrics cannot be used while multi topology IS-IS is active%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + ret = validate_metric_style_narrow (vty, area); if (ret != CMD_SUCCESS) return ret; @@ -1393,6 +1413,12 @@ DEFUN (no_metric_style, VTY_DECLVAR_CONTEXT (isis_area, area); int ret; + if (area_is_mt(area)) + { + vty_out (vty, "Narrow metrics cannot be used while multi topology IS-IS is active%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + ret = validate_metric_style_narrow (vty, area); if (ret != CMD_SUCCESS) return ret; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index e7bd99c3e8..3b128a689d 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -300,8 +300,9 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix, /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { - stream_putc (stream, NEXTHOP_TYPE_IPV4); + stream_putc (stream, NEXTHOP_TYPE_IPV4_IFINDEX); stream_put_in_addr (stream, &nexthop->ip); + stream_putl (stream, nexthop->ifindex); } else { diff --git a/isisd/isisd.c b/isisd/isisd.c index 179e430986..d11044377f 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1669,6 +1669,13 @@ DEFUN (isis_topology, const char *arg = argv[1]->arg; uint16_t mtid = isis_str2mtid(arg); + + if (area->oldmetric) + { + vty_out (vty, "Multi topology IS-IS can only be used with wide metrics%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == (uint16_t)-1) { vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); @@ -1697,6 +1704,13 @@ DEFUN (no_isis_topology, const char *arg = argv[2]->arg; uint16_t mtid = isis_str2mtid(arg); + + if (area->oldmetric) + { + vty_out (vty, "Multi topology IS-IS can only be used with wide metrics%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == (uint16_t)-1) { vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE);