📄 ospf6_flood.c
字号:
ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); else ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);}/* RFC2328 section 13 (4): if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading returns 1 if match this case, else returns 0 */static intospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from){ struct ospf6_neighbor *on; struct ospf6_interface *oi; struct ospf6_area *oa; struct ospf6 *process = NULL; listnode i, j, k; int count = 0; if (! OSPF6_LSA_IS_MAXAGE (lsa)) return 0; if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, lsa->header->adv_router, lsa->lsdb)) return 0; process = from->ospf6_if->area->ospf6; for (i = listhead (process->area_list); i; nextnode (i)) { oa = OSPF6_AREA (getdata (i)); for (j = listhead (oa->if_list); j; nextnode (j)) { oi = OSPF6_INTERFACE (getdata (j)); for (k = listhead (oi->neighbor_list); k; nextnode (k)) { on = OSPF6_NEIGHBOR (getdata (k)); if (on->state == OSPF6_NEIGHBOR_EXCHANGE || on->state == OSPF6_NEIGHBOR_LOADING) count++; } } } if (count == 0) return 1; return 0;}/* RFC2328 section 13 The Flooding Procedure */voidospf6_receive_lsa (struct ospf6_neighbor *from, struct ospf6_lsa_header *lsa_header){ struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; int ismore_recent; unsigned short cksum; int is_debug = 0; ismore_recent = 1; assert (from); /* make lsa structure for received lsa */ new = ospf6_lsa_create (lsa_header); if (IS_OSPF6_DEBUG_FLOODING || IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) { is_debug++; zlog_info ("LSA Receive from %s", from->name); ospf6_lsa_header_print (new); } /* (1) LSA Checksum */ cksum = ntohs (new->header->checksum); if (ntohs (ospf6_lsa_checksum (new->header)) != cksum) { if (is_debug) zlog_info ("Wrong LSA Checksum, discard"); ospf6_lsa_delete (new); return; } /* (2) Examine the LSA's LS type. RFC2470 3.5.1. Receiving Link State Update packets */ if (IS_AREA_STUB (from->ospf6_if->area) && OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) { if (is_debug) zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); ospf6_lsa_delete (new); return; } /* (3) LSA which have reserved scope is discarded RFC2470 3.5.1. Receiving Link State Update packets */ /* Flooding scope check. LSAs with unknown scope are discarded here. Set appropriate LSDB for the LSA */ switch (OSPF6_LSA_SCOPE (new->header->type)) { case OSPF6_SCOPE_LINKLOCAL: new->lsdb = from->ospf6_if->lsdb; break; case OSPF6_SCOPE_AREA: new->lsdb = from->ospf6_if->area->lsdb; break; case OSPF6_SCOPE_AS: new->lsdb = from->ospf6_if->area->ospf6->lsdb; break; default: if (is_debug) zlog_info ("LSA has reserved scope, discard"); ospf6_lsa_delete (new); return; } /* (4) if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading */ if (ospf6_is_maxage_lsa_drop (new, from)) { /* log */ if (is_debug) zlog_info ("Drop MaxAge LSA with direct acknowledgement."); /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); /* b) Discard */ ospf6_lsa_delete (new); return; } /* (5) */ /* lookup the same database copy in lsdb */ old = ospf6_lsdb_lookup (new->header->type, new->header->id, new->header->adv_router, new->lsdb); if (old) { ismore_recent = ospf6_lsa_compare (new, old); if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) { if (is_debug) zlog_info ("Received is duplicated LSA"); SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); } } /* if no database copy or received is more recent */ if (old == NULL || ismore_recent < 0) { /* in case we have no database copy */ ismore_recent = -1; /* (a) MinLSArrival check */ if (old) { struct timeval now, res; gettimeofday (&now, (struct timezone *) NULL); timersub (&now, &old->installed, &res); if (res.tv_sec < MIN_LS_ARRIVAL) { if (is_debug) zlog_info ("LSA can't be updated within MinLSArrival, discard"); ospf6_lsa_delete (new); return; /* examin next lsa */ } } gettimeofday (&new->received, (struct timezone *) NULL); if (is_debug) zlog_info ("Flood, Install, Possibly acknowledge the received LSA"); /* (b) immediately flood and (c) remove from all retrans-list */ /* Prevent self-originated LSA to be flooded. this is to make reoriginated instance of the LSA not to be rejected by other routers due to MinLSArrival. */ if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) ospf6_flood (from, new); /* (c) Remove the current database copy from all neighbors' Link state retransmission lists. */ /* XXX, flood_clear ? */ /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ ospf6_install_lsa (new); /* (e) possibly acknowledge */ ospf6_acknowledge_lsa (new, ismore_recent, from); /* (f) Self Originated LSA, section 13.4 */ if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) { /* Self-originated LSA (newer than ours) is received from another router. We have to make a new instance of the LSA or have to flush this LSA. */ if (is_debug) { zlog_info ("Newer instance of the self-originated LSA"); zlog_info ("Schedule reorigination"); } new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0); } return; } /* (6) if there is instance on sending neighbor's request list */ if (ospf6_lsdb_lookup (new->header->type, new->header->id, new->header->adv_router, from->request_list)) { /* if no database copy, should go above state (5) */ assert (old); if (is_debug) { zlog_info ("Received is not newer, on the neighbor's request-list"); zlog_info ("BadLSReq, discard the received LSA"); } /* BadLSReq */ thread_add_event (master, bad_lsreq, from, 0); ospf6_lsa_delete (new); return; } /* (7) if neither one is more recent */ if (ismore_recent == 0) { if (is_debug) zlog_info ("The same instance as database copy (neither recent)"); /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ rem = ospf6_lsdb_lookup (new->header->type, new->header->id, new->header->adv_router, from->retrans_list); if (rem) { if (is_debug) { zlog_info ("It is on the neighbor's retrans-list."); zlog_info ("Treat as an Implied acknowledgement"); } SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); ospf6_decrement_retrans_count (rem); ospf6_lsdb_remove (rem, from->retrans_list); } if (is_debug) zlog_info ("Possibly acknowledge and then discard"); /* (b) possibly acknowledge */ ospf6_acknowledge_lsa (new, ismore_recent, from); ospf6_lsa_delete (new); return; } /* (8) previous database copy is more recent */ { assert (old); /* If database copy is in 'Seqnumber Wrapping', simply discard the received LSA */ if (OSPF6_LSA_IS_MAXAGE (old) && old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER)) { if (is_debug) { zlog_info ("The LSA is in Seqnumber Wrapping"); zlog_info ("MaxAge & MaxSeqNum, discard"); } ospf6_lsa_delete (new); return; } /* Otherwise, Send database copy of this LSA to this neighbor */ { if (is_debug) { zlog_info ("Database copy is more recent."); zlog_info ("Send back directly and then discard"); } /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); if (from->thread_send_lsupdate == NULL) from->thread_send_lsupdate = thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0); ospf6_lsa_delete (new); return; } return; }}DEFUN (debug_ospf6_flooding, debug_ospf6_flooding_cmd, "debug ospf6 flooding", DEBUG_STR OSPF6_STR "Debug OSPFv3 flooding function\n" ){ OSPF6_DEBUG_FLOODING_ON (); return CMD_SUCCESS;}DEFUN (no_debug_ospf6_flooding, no_debug_ospf6_flooding_cmd, "no debug ospf6 flooding", NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 flooding function\n" ){ OSPF6_DEBUG_FLOODING_OFF (); return CMD_SUCCESS;}intconfig_write_ospf6_debug_flood (struct vty *vty){ if (IS_OSPF6_DEBUG_FLOODING) vty_out (vty, "debug ospf6 flooding%s", VNL); return 0;}voidinstall_element_ospf6_debug_flood (){ install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd); install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd); install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -