diff options
Diffstat (limited to 'isisd/isis_pdu.c')
-rw-r--r-- | isisd/isis_pdu.c | 177 |
1 files changed, 110 insertions, 67 deletions
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 0cd43a7..6f410d3 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -111,6 +111,7 @@ struct iih_info { bool v6_usable; struct isis_tlvs *tlvs; + int calculated_type; }; static int process_p2p_hello(struct iih_info *iih) @@ -151,6 +152,76 @@ static int process_p2p_hello(struct iih_info *iih) struct isis_adjacency *adj = iih->circuit->u.p2p.neighbor; /* If an adjacency exists, check it is with the source of the hello * packets */ + if (((iih->circuit->area->is_type == IS_LEVEL_1) && + ((iih->circuit->is_type_config == IS_LEVEL_1_AND_2) || + (iih->circuit->is_type_config == IS_LEVEL_1))) || + ((iih->circuit->area->is_type == IS_LEVEL_1_AND_2) && + (iih->circuit->is_type_config == IS_LEVEL_1) && + ((iih->circ_type == IS_LEVEL_1) || + (iih->circ_type == IS_LEVEL_1_AND_2))) || + ((iih->circuit->area->is_type == IS_LEVEL_1_AND_2) && + (iih->circuit->is_type_config == IS_LEVEL_1_AND_2) && + (iih->circ_type == IS_LEVEL_1))) { + if (!isis_tlvs_area_addresses_match(iih->tlvs, + iih->circuit->area + ->area_addrs)) { + if (IS_DEBUG_ADJ_PACKETS) { + zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s, cir id %u, length %u", + iih->circuit->area->area_tag, + iih->circuit->interface->name, + circuit_t2string( + iih->circuit->is_type), + iih->circuit->circuit_id, + iih->pdu_len); + } + + return ISIS_WARNING; + } + + iih->calculated_type = IS_LEVEL_1; + + } + + else if (((iih->circuit->area->is_type == IS_LEVEL_2) && + ((iih->circuit->is_type_config == IS_LEVEL_1_AND_2) || + (iih->circuit->is_type_config == IS_LEVEL_2))) || + ((iih->circuit->area->is_type == IS_LEVEL_1_AND_2) && + (iih->circuit->is_type_config == IS_LEVEL_2) && + ((iih->circ_type == IS_LEVEL_2) || + (iih->circ_type == IS_LEVEL_1_AND_2))) || + ((iih->circuit->area->is_type == IS_LEVEL_1_AND_2) && + (iih->circuit->is_type_config == IS_LEVEL_1_AND_2) && + (iih->circ_type == IS_LEVEL_2))) { + iih->calculated_type = IS_LEVEL_2; + } + + else if ((iih->circuit->area->is_type == IS_LEVEL_1_AND_2) && + (iih->circuit->is_type_config == IS_LEVEL_1_AND_2) && + (iih->circ_type == IS_LEVEL_1_AND_2)) { + iih->calculated_type = IS_LEVEL_1_AND_2; + + if (!isis_tlvs_area_addresses_match(iih->tlvs, + iih->circuit->area + ->area_addrs)) { + iih->calculated_type = IS_LEVEL_2; + } + } + + else { + if (IS_DEBUG_ADJ_PACKETS) { + if (IS_DEBUG_ADJ_PACKETS) { + zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s, cir id %u, length %u", + iih->circuit->area->area_tag, + iih->circuit->interface->name, + circuit_t2string( + iih->circuit->is_type), + iih->circuit->circuit_id, + iih->pdu_len); + } + } + return ISIS_WARNING; + } + if (adj) { if (memcmp(iih->sys_id, adj->sysid, ISIS_SYS_ID_LEN)) { zlog_debug( @@ -160,12 +231,13 @@ static int process_p2p_hello(struct iih_info *iih) return ISIS_OK; } } - if (!adj || adj->level != iih->circ_type) { + if (!adj || adj->level != iih->calculated_type) { if (!adj) { - adj = isis_new_adj(iih->sys_id, NULL, iih->circ_type, - iih->circuit); + adj = isis_new_adj(iih->sys_id, NULL, + iih->calculated_type, iih->circuit); + } else { - adj->level = iih->circ_type; + adj->level = iih->calculated_type; } iih->circuit->u.p2p.neighbor = adj; /* Build lsp with the new neighbor entry when a new @@ -174,7 +246,7 @@ static int process_p2p_hello(struct iih_info *iih) * when an adjacency is up. This will result in the new * adjacency entry getting added to the lsp tlv neighbor list. */ - adj->circuit_t = iih->circ_type; + adj->circuit_t = iih->calculated_type; isis_adj_state_change(&adj, ISIS_ADJ_INITIALIZING, NULL); adj->sys_type = ISIS_SYSTYPE_UNKNOWN; } @@ -205,45 +277,35 @@ static int process_p2p_hello(struct iih_info *iih) /* 8.2.5.2 a) a match was detected */ if (isis_tlvs_area_addresses_match(iih->tlvs, iih->circuit->area->area_addrs)) { - /* 8.2.5.2 a) 2) If the system is L1 - table 5 */ - if (iih->circuit->area->is_type == IS_LEVEL_1) { + /* 8.2.5.2 a) 2) If the calculated type is L1 - table 5 */ + if (iih->calculated_type == IS_LEVEL_1) { switch (iih->circ_type) { case IS_LEVEL_1: + isis_adj_process_threeway(adj, tw_adj, + iih->calculated_type); + break; case IS_LEVEL_1_AND_2: - if (adj->adj_state != ISIS_ADJ_UP - || adj->adj_usage == ISIS_ADJ_LEVEL1) { + if ((adj->adj_state != ISIS_ADJ_UP) || + (adj->adj_usage == ISIS_ADJ_LEVEL1) || + (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL1); - } - break; - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP) { - /* (7) reject - wrong system type event - */ - zlog_warn("wrongSystemType"); - return ISIS_WARNING; - } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { - /* (6) down - wrong system */ - isis_adj_state_change(&adj, - ISIS_ADJ_DOWN, - "Wrong System"); + iih->calculated_type); } break; } } - /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ - if (iih->circuit->area->is_type == IS_LEVEL_1_AND_2) { + /* 8.2.5.2 a) 3) If the calculated type is L1L2 - table 6 */ + if (iih->calculated_type == IS_LEVEL_1_AND_2) { switch (iih->circ_type) { case IS_LEVEL_1: if (adj->adj_state != ISIS_ADJ_UP || adj->adj_usage == ISIS_ADJ_LEVEL1) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL1); - } else if ((adj->adj_usage - == ISIS_ADJ_LEVEL1AND2) - || (adj->adj_usage - == ISIS_ADJ_LEVEL2)) { + iih->calculated_type); + } else if ((adj->adj_usage == ISIS_ADJ_LEVEL2) || + (adj->adj_usage == + ISIS_ADJ_LEVEL1AND2)) { /* (8) down - wrong system */ isis_adj_state_change(&adj, ISIS_ADJ_DOWN, @@ -254,10 +316,10 @@ static int process_p2p_hello(struct iih_info *iih) if (adj->adj_state != ISIS_ADJ_UP || adj->adj_usage == ISIS_ADJ_LEVEL2) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL2); - } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) - || (adj->adj_usage - == ISIS_ADJ_LEVEL1AND2)) { + iih->calculated_type); + } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || + (adj->adj_usage == + ISIS_ADJ_LEVEL1AND2)) { /* (8) down - wrong system */ isis_adj_state_change(&adj, ISIS_ADJ_DOWN, @@ -268,10 +330,9 @@ static int process_p2p_hello(struct iih_info *iih) if (adj->adj_state != ISIS_ADJ_UP || adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL1AND2); - } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) - || (adj->adj_usage - == ISIS_ADJ_LEVEL2)) { + iih->calculated_type); + } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || + (adj->adj_usage == ISIS_ADJ_LEVEL2)) { /* (8) down - wrong system */ isis_adj_state_change(&adj, ISIS_ADJ_DOWN, @@ -282,44 +343,26 @@ static int process_p2p_hello(struct iih_info *iih) } /* 8.2.5.2 a) 4) If the system is L2 - table 7 */ - if (iih->circuit->area->is_type == IS_LEVEL_2) { + if (iih->calculated_type == IS_LEVEL_2) { switch (iih->circ_type) { - case IS_LEVEL_1: - if (adj->adj_state != ISIS_ADJ_UP) { - /* (5) reject - wrong system type event - */ - zlog_warn("wrongSystemType"); - return ISIS_WARNING; - } else if ((adj->adj_usage - == ISIS_ADJ_LEVEL1AND2) - || (adj->adj_usage - == ISIS_ADJ_LEVEL2)) { - /* (6) down - wrong system */ - isis_adj_state_change(&adj, - ISIS_ADJ_DOWN, - "Wrong System"); - } - break; case IS_LEVEL_1_AND_2: - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP - || adj->adj_usage == ISIS_ADJ_LEVEL2) { + if (adj->adj_state != ISIS_ADJ_UP || + adj->adj_usage == ISIS_ADJ_LEVEL2 || + adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL2); - } else if (adj->adj_usage - == ISIS_ADJ_LEVEL1AND2) { - /* (6) down - wrong system */ - isis_adj_state_change(&adj, - ISIS_ADJ_DOWN, - "Wrong System"); + iih->calculated_type); } break; + case IS_LEVEL_2: + isis_adj_process_threeway(adj, tw_adj, + iih->calculated_type); + break; } } } /* 8.2.5.2 b) if no match was detected */ else if (listcount(iih->circuit->area->area_addrs) > 0) { - if (iih->circuit->area->is_type == IS_LEVEL_1) { + if (iih->calculated_type == IS_LEVEL_1) { /* 8.2.5.2 b) 1) is_type L1 and adj is not up */ if (adj->adj_state != ISIS_ADJ_UP) { isis_adj_state_change(&adj, ISIS_ADJ_DOWN, @@ -359,7 +402,7 @@ static int process_p2p_hello(struct iih_info *iih) if (adj->adj_state != ISIS_ADJ_UP || adj->adj_usage == ISIS_ADJ_LEVEL2) { isis_adj_process_threeway(adj, tw_adj, - ISIS_ADJ_LEVEL2); + iih->calculated_type); } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { /* (7) down - wrong system */ isis_adj_state_change(&adj, |