📄 ospf6_dbex.c
字号:
/* * Copyright (C) 1999 Yasuhiro Ohara * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include "ospf6d.h"/* check validity and put lsa in reqestlist if needed. *//* returns -1 if SeqNumMismatch required. */intospf6_dbex_check_dbdesc_lsa_header (struct ospf6_lsa_header *lsa_header, struct ospf6_neighbor *from){ struct ospf6_lsa *received = NULL; struct ospf6_lsa *have = NULL; received = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header); /* case when received is AS-External though neighbor belongs stub area */ if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && ospf6_area_is_stub (from->ospf6_interface->area)) { zlog_err ("DbDesc %s receive from %s", from->str, received->str); zlog_err (" E-bit mismatch: %s", received->str); ospf6_lsa_delete (received); return -1; } /* if already have newer database copy, check next LSA */ have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, lsa_header->advrtr, ospf6_lsa_get_scope (lsa_header->type, from->ospf6_interface)); if (! have) { /* if we don't have database copy, add request */ if (IS_OSPF6_DUMP_DBEX) zlog_info ("Have no database copy, Request"); ospf6_neighbor_request_add (received, from); } else if (have) { /* if database copy is less recent, add request */ if (ospf6_lsa_check_recent (received, have) < 0) { if (IS_OSPF6_DUMP_DBEX) zlog_info ("Database copy less recent, Request"); ospf6_neighbor_request_add (received, from); } } return 0;}/* Direct acknowledgement */static voidospf6_dbex_acknowledge_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n){ struct iovec directack[MAXIOVLIST]; assert (lsa); if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: [%s:%s] direct ack %s ", o6n->str, o6n->ospf6_interface->interface->name, lsa->str); /* clear pointers to fragments of packet for direct acknowledgement */ iov_clear (directack, MAXIOVLIST); /* set pointer of LSA to send */ OSPF6_MESSAGE_ATTACH (directack, lsa->header, sizeof (struct ospf6_lsa_header)); /* age update and add InfTransDelay */ ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); /* send unicast packet to neighbor's ipaddress */ ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, directack, &o6n->hisaddr, o6n->ospf6_interface->if_id);}/* Delayed acknowledgement */voidospf6_dbex_acknowledge_delayed (struct ospf6_lsa *lsa, struct ospf6_interface *o6i){ assert (o6i); if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: [%s] delayed ack %s", o6i->interface->name, lsa->str); /* attach delayed acknowledge list */ ospf6_lsa_age_current (lsa); ospf6_interface_delayed_ack_add (lsa, o6i); /* if not yet, schedule delayed acknowledge RxmtInterval later. timers should be *less than* RxmtInterval or needless retrans will ensue */ if (o6i->thread_send_lsack_delayed == NULL) o6i->thread_send_lsack_delayed = thread_add_timer (master, ospf6_send_lsack_delayed, o6i, o6i->rxmt_interval - 1); return;}/* 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_dbex_is_maxage_to_be_dropped (struct ospf6_lsa *received, struct ospf6_neighbor *from){ int count; if (! IS_LSA_MAXAGE (received)) return 0; if (ospf6_lsdb_lookup (received->header->type, received->header->id, received->header->adv_router, ospf6_lsa_get_scope (received->header->type, from->ospf6_interface))) return 0; if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (received->header->type))) { count = 0; (*from->ospf6_interface->foreach_nei) (from->ospf6_interface, &count, NBS_EXCHANGE, ospf6_count_state); (*from->ospf6_interface->foreach_nei) (from->ospf6_interface, &count, NBS_LOADING, ospf6_count_state); if (count) return 0; } else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (received->header->type))) { count = 0; (*from->ospf6_interface->area->foreach_nei) (from->ospf6_interface->area, &count, NBS_EXCHANGE, ospf6_count_state); (*from->ospf6_interface->area->foreach_nei) (from->ospf6_interface->area, &count, NBS_LOADING, ospf6_count_state); if (count) return 0; } else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (received->header->type))) { count = 0; (*from->ospf6_interface->area->ospf6->foreach_nei) (from->ospf6_interface->area->ospf6, &count, NBS_EXCHANGE, ospf6_count_state); (*from->ospf6_interface->area->ospf6->foreach_nei) (from->ospf6_interface->area->ospf6, &count, NBS_LOADING, ospf6_count_state); if (count) return 0; } return 1;}static voidospf6_dbex_remove_retrans (void *arg, int val, void *obj){ struct ospf6_lsa *rem; struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj; struct ospf6_lsa *lsa = (struct ospf6_lsa *) arg; rem = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id, lsa->header->adv_router, nei->retrans_list); if (rem) { ospf6_neighbor_retrans_remove (rem, nei); ospf6_maxage_remover (); }}voidospf6_dbex_remove_from_all_retrans_list (struct ospf6_lsa *lsa){ struct ospf6_interface *o6i; struct ospf6_area *o6a; if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa->header->type))) { o6i = lsa->scope; (*o6i->foreach_nei) (o6i, lsa, 0, ospf6_dbex_remove_retrans); } else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa->header->type))) { o6a = lsa->scope; (*o6a->foreach_nei) (o6a, lsa, 0, ospf6_dbex_remove_retrans); } else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa->header->type))) { (*ospf6->foreach_nei) (ospf6, lsa, 0, ospf6_dbex_remove_retrans); }}/* RFC2328 section 13 */voidospf6_dbex_receive_lsa (struct ospf6_lsa_header *lsa_header, struct ospf6_neighbor *from){ struct ospf6_lsa *received, *have, *rem; struct timeval now; int ismore_recent, acktype; unsigned short cksum; struct ospf6_lsa_slot *slot; received = have = (struct ospf6_lsa *)NULL; ismore_recent = -1; recent_reason = "no instance"; zlog_info ("Receive LSA (header -> %p)", lsa_header); /* make lsa structure for received lsa */ received = ospf6_lsa_create (lsa_header); /* set LSA scope */ if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type))) received->scope = from->ospf6_interface; else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa_header->type))) received->scope = from->ospf6_interface->area; else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa_header->type))) received->scope = from->ospf6_interface->area->ospf6; /* (1) LSA Checksum */ cksum = ntohs (lsa_header->checksum); if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum) { if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: received %s from %s%%%s" ": wrong checksum, drop", received->str, from->str, from->ospf6_interface->interface->name); ospf6_lsa_delete (received); return; } /* (3) Ebit Missmatch: AS-External-LSA */ if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && ospf6_area_is_stub (from->ospf6_interface->area)) { if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: received %s from %s%%%s" ": E-bit mismatch, drop", received->str, from->str, from->ospf6_interface->interface->name); ospf6_lsa_delete (received); return; } /* (4) if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading */ if (ospf6_dbex_is_maxage_to_be_dropped (received, from)) { /* log */ if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: received %s from %s%%%s" ": MaxAge, no instance, no neighbor exchange, drop", received->str, from->str, from->ospf6_interface->interface->name); /* a) Acknowledge back to neighbor (13.5) */ /* Direct Acknowledgement */ ospf6_dbex_acknowledge_direct (received, from); /* b) Discard */ ospf6_lsa_delete (received); return; } /* (5) */ /* lookup the same database copy in lsdb */ have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, lsa_header->advrtr, ospf6_lsa_get_scope (lsa_header->type, from->ospf6_interface)); if (have) { ismore_recent = ospf6_lsa_check_recent (received, have); if (ntohl (received->header->seqnum) == ntohl (have->header->seqnum)) SET_FLAG (received->flag, OSPF6_LSA_FLAG_DUPLICATE); } /* if no database copy or received is more recent */ if (!have || ismore_recent < 0) { /* in case we have no database copy */ ismore_recent = -1; /* (a) MinLSArrival check */ gettimeofday (&now, (struct timezone *)NULL); if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL) { //if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d " "within MinLSArrival, drop: %ld.%06ld", from->str, received->str, ntohl (received->header->seqnum), ntohs (received->header->age), now.tv_sec, now.tv_usec); /* this will do free this lsa */ ospf6_lsa_delete (received); return; /* examin next lsa */ } //if (IS_OSPF6_DUMP_DBEX) zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d: " "%ld.%06ld", from->str, received->str, ntohl (received->header->seqnum), ntohs (received->header->age), now.tv_sec, now.tv_usec); /* (b) immediately flood */ ospf6_dbex_flood (received, from);#if 0 /* Because New LSDB do not permit two LSA having the same identifier exist in a LSDB list, above ospf6_dbex_flood() will remove the old instance automatically. thus bellow is not needed. */ /* (c) remove database copy from all neighbor's retranslist */ if (have) ospf6_dbex_remove_from_all_retrans_list (have);#endif /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ ospf6_lsdb_install (received); /* (e) possibly acknowledge */ acktype = ack_type (received, ismore_recent, from);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -