summaryrefslogtreecommitdiffstats
path: root/isisd/isis_pdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_pdu.c')
-rw-r--r--isisd/isis_pdu.c177
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,