Annotation of embedaddon/quagga/ospf6d/ospf6_flood.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2003 Yasuhiro Ohara
        !             3:  *
        !             4:  * This file is part of GNU Zebra.
        !             5:  *
        !             6:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2, or (at your option) any
        !             9:  * later version.
        !            10:  *
        !            11:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            14:  * General Public License for more details.
        !            15:  *
        !            16:  * You should have received a copy of the GNU General Public License
        !            17:  * along with GNU Zebra; see the file COPYING.  If not, write to the 
        !            18:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
        !            19:  * Boston, MA 02111-1307, USA.  
        !            20:  */
        !            21: 
        !            22: #include <zebra.h>
        !            23: 
        !            24: #include "log.h"
        !            25: #include "thread.h"
        !            26: #include "linklist.h"
        !            27: #include "vty.h"
        !            28: #include "command.h"
        !            29: 
        !            30: #include "ospf6d.h"
        !            31: #include "ospf6_proto.h"
        !            32: #include "ospf6_lsa.h"
        !            33: #include "ospf6_lsdb.h"
        !            34: #include "ospf6_message.h"
        !            35: #include "ospf6_route.h"
        !            36: #include "ospf6_spf.h"
        !            37: 
        !            38: #include "ospf6_top.h"
        !            39: #include "ospf6_area.h"
        !            40: #include "ospf6_interface.h"
        !            41: #include "ospf6_neighbor.h"
        !            42: 
        !            43: #include "ospf6_flood.h"
        !            44: 
        !            45: unsigned char conf_debug_ospf6_flooding;
        !            46: 
        !            47: struct ospf6_lsdb *
        !            48: ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
        !            49: {
        !            50:   struct ospf6_lsdb *lsdb = NULL;
        !            51:   switch (OSPF6_LSA_SCOPE (lsa->header->type))
        !            52:     {
        !            53:     case OSPF6_SCOPE_LINKLOCAL:
        !            54:       lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
        !            55:       break;
        !            56:     case OSPF6_SCOPE_AREA:
        !            57:       lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
        !            58:       break;
        !            59:     case OSPF6_SCOPE_AS:
        !            60:       lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
        !            61:       break;
        !            62:     default:
        !            63:       assert (0);
        !            64:       break;
        !            65:     }
        !            66:   return lsdb;
        !            67: }
        !            68: 
        !            69: struct ospf6_lsdb *
        !            70: ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
        !            71: {
        !            72:   struct ospf6_lsdb *lsdb_self = NULL;
        !            73:   switch (OSPF6_LSA_SCOPE (lsa->header->type))
        !            74:     {
        !            75:     case OSPF6_SCOPE_LINKLOCAL:
        !            76:       lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
        !            77:       break;
        !            78:     case OSPF6_SCOPE_AREA:
        !            79:       lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
        !            80:       break;
        !            81:     case OSPF6_SCOPE_AS:
        !            82:       lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
        !            83:       break;
        !            84:     default:
        !            85:       assert (0);
        !            86:       break;
        !            87:     }
        !            88:   return lsdb_self;
        !            89: }
        !            90: 
        !            91: void
        !            92: ospf6_lsa_originate (struct ospf6_lsa *lsa)
        !            93: {
        !            94:   struct ospf6_lsa *old;
        !            95:   struct ospf6_lsdb *lsdb_self;
        !            96: 
        !            97:   /* find previous LSA */
        !            98:   old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !            99:                            lsa->header->adv_router, lsa->lsdb);
        !           100: 
        !           101:   /* if the new LSA does not differ from previous,
        !           102:      suppress this update of the LSA */
        !           103:   if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
        !           104:     {
        !           105:       if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
        !           106:         zlog_debug ("Suppress updating LSA: %s", lsa->name);
        !           107:       ospf6_lsa_delete (lsa);
        !           108:       return;
        !           109:     }
        !           110: 
        !           111:   /* store it in the LSDB for self-originated LSAs */
        !           112:   lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
        !           113:   ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
        !           114: 
        !           115:   lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
        !           116:                                    LS_REFRESH_TIME);
        !           117: 
        !           118:   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
        !           119:       IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
        !           120:     {
        !           121:       zlog_debug ("LSA Originate:");
        !           122:       ospf6_lsa_header_print (lsa);
        !           123:     }
        !           124: 
        !           125:   if (old)
        !           126:     ospf6_flood_clear (old);
        !           127:   ospf6_flood (NULL, lsa);
        !           128:   ospf6_install_lsa (lsa);
        !           129: }
        !           130: 
        !           131: void
        !           132: ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
        !           133:                              struct ospf6 *process)
        !           134: {
        !           135:   lsa->lsdb = process->lsdb;
        !           136:   ospf6_lsa_originate (lsa);
        !           137: }
        !           138: 
        !           139: void
        !           140: ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
        !           141:                           struct ospf6_area *oa)
        !           142: {
        !           143:   lsa->lsdb = oa->lsdb;
        !           144:   ospf6_lsa_originate (lsa);
        !           145: }
        !           146: 
        !           147: void
        !           148: ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
        !           149:                                struct ospf6_interface *oi)
        !           150: {
        !           151:   lsa->lsdb = oi->lsdb;
        !           152:   ospf6_lsa_originate (lsa);
        !           153: }
        !           154: 
        !           155: void
        !           156: ospf6_lsa_purge (struct ospf6_lsa *lsa)
        !           157: {
        !           158:   struct ospf6_lsa *self;
        !           159:   struct ospf6_lsdb *lsdb_self;
        !           160: 
        !           161:   /* remove it from the LSDB for self-originated LSAs */
        !           162:   lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
        !           163:   self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           164:                             lsa->header->adv_router, lsdb_self);
        !           165:   if (self)
        !           166:     {
        !           167:       THREAD_OFF (self->expire);
        !           168:       THREAD_OFF (self->refresh);
        !           169:       ospf6_lsdb_remove (self, lsdb_self);
        !           170:     }
        !           171: 
        !           172:   ospf6_lsa_premature_aging (lsa);
        !           173: }
        !           174: 
        !           175: 
        !           176: void
        !           177: ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
        !           178: {
        !           179:   /* The LSA must be the original one (see the description
        !           180:      in ospf6_decrement_retrans_count () below) */
        !           181:   lsa->retrans_count++;
        !           182: }
        !           183: 
        !           184: void
        !           185: ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
        !           186: {
        !           187:   struct ospf6_lsdb *lsdb;
        !           188:   struct ospf6_lsa *orig;
        !           189: 
        !           190:   /* The LSA must be on the retrans-list of a neighbor. It means
        !           191:      the "lsa" is a copied one, and we have to decrement the
        !           192:      retransmission count of the original one (instead of this "lsa"'s).
        !           193:      In order to find the original LSA, first we have to find
        !           194:      appropriate LSDB that have the original LSA. */
        !           195:   lsdb = ospf6_get_scoped_lsdb (lsa);
        !           196: 
        !           197:   /* Find the original LSA of which the retrans_count should be decremented */
        !           198:   orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           199:                             lsa->header->adv_router, lsdb);
        !           200:   if (orig)
        !           201:     {
        !           202:       orig->retrans_count--;
        !           203:       assert (orig->retrans_count >= 0);
        !           204:     }
        !           205: }
        !           206: 
        !           207: /* RFC2328 section 13.2 Installing LSAs in the database */
        !           208: void
        !           209: ospf6_install_lsa (struct ospf6_lsa *lsa)
        !           210: {
        !           211:   struct ospf6_lsa *old;
        !           212:   struct timeval now;
        !           213: 
        !           214:   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
        !           215:       IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
        !           216:     zlog_debug ("Install LSA: %s", lsa->name);
        !           217: 
        !           218:   /* Remove the old instance from all neighbors' Link state
        !           219:      retransmission list (RFC2328 13.2 last paragraph) */
        !           220:   old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           221:                            lsa->header->adv_router, lsa->lsdb);
        !           222:   if (old)
        !           223:     {
        !           224:       THREAD_OFF (old->expire);
        !           225:       ospf6_flood_clear (old);
        !           226:     }
        !           227: 
        !           228:   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
        !           229:   if (! OSPF6_LSA_IS_MAXAGE (lsa))
        !           230:     lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
        !           231:                                     MAXAGE + lsa->birth.tv_sec - now.tv_sec);
        !           232:   else
        !           233:     lsa->expire = NULL;
        !           234: 
        !           235:   /* actually install */
        !           236:   lsa->installed = now;
        !           237:   ospf6_lsdb_add (lsa, lsa->lsdb);
        !           238: 
        !           239:   return;
        !           240: }
        !           241: 
        !           242: /* RFC2740 section 3.5.2. Sending Link State Update packets */
        !           243: /* RFC2328 section 13.3 Next step in the flooding procedure */
        !           244: static void
        !           245: ospf6_flood_interface (struct ospf6_neighbor *from,
        !           246:                        struct ospf6_lsa *lsa, struct ospf6_interface *oi)
        !           247: {
        !           248:   struct listnode *node, *nnode;
        !           249:   struct ospf6_neighbor *on;
        !           250:   struct ospf6_lsa *req;
        !           251:   int retrans_added = 0;
        !           252:   int is_debug = 0;
        !           253: 
        !           254:   if (IS_OSPF6_DEBUG_FLOODING ||
        !           255:       IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
        !           256:     {
        !           257:       is_debug++;
        !           258:       zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name);
        !           259:     }
        !           260: 
        !           261:   /* (1) For each neighbor */
        !           262:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
        !           263:     {
        !           264:       if (is_debug)
        !           265:         zlog_debug ("To neighbor %s", on->name);
        !           266: 
        !           267:       /* (a) if neighbor state < Exchange, examin next */
        !           268:       if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
        !           269:         {
        !           270:           if (is_debug)
        !           271:             zlog_debug ("Neighbor state less than ExChange, next neighbor");
        !           272:           continue;
        !           273:         }
        !           274: 
        !           275:       /* (b) if neighbor not yet Full, check request-list */
        !           276:       if (on->state != OSPF6_NEIGHBOR_FULL)
        !           277:         {
        !           278:           if (is_debug)
        !           279:             zlog_debug ("Neighbor not yet Full");
        !           280: 
        !           281:           req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           282:                                    lsa->header->adv_router, on->request_list);
        !           283:           if (req == NULL)
        !           284:             {
        !           285:               if (is_debug)
        !           286:                 zlog_debug ("Not on request-list for this neighbor");
        !           287:               /* fall through */
        !           288:             }
        !           289:           else
        !           290:             {
        !           291:               /* If new LSA less recent, examin next neighbor */
        !           292:               if (ospf6_lsa_compare (lsa, req) > 0)
        !           293:                 {
        !           294:                   if (is_debug)
        !           295:                     zlog_debug ("Requesting is newer, next neighbor");
        !           296:                   continue;
        !           297:                 }
        !           298: 
        !           299:               /* If the same instance, delete from request-list and
        !           300:                  examin next neighbor */
        !           301:               if (ospf6_lsa_compare (lsa, req) == 0)
        !           302:                 {
        !           303:                   if (is_debug)
        !           304:                     zlog_debug ("Requesting the same, remove it, next neighbor");
        !           305:                   ospf6_lsdb_remove (req, on->request_list);
        !           306:                   continue;
        !           307:                 }
        !           308: 
        !           309:               /* If the new LSA is more recent, delete from request-list */
        !           310:               if (ospf6_lsa_compare (lsa, req) < 0)
        !           311:                 {
        !           312:                   if (is_debug)
        !           313:                     zlog_debug ("Received is newer, remove requesting");
        !           314:                   ospf6_lsdb_remove (req, on->request_list);
        !           315:                   /* fall through */
        !           316:                 }
        !           317:             }
        !           318:         }
        !           319: 
        !           320:       /* (c) If the new LSA was received from this neighbor,
        !           321:          examin next neighbor */
        !           322:       if (from == on)
        !           323:         {
        !           324:           if (is_debug)
        !           325:             zlog_debug ("Received is from the neighbor, next neighbor");
        !           326:           continue;
        !           327:         }
        !           328: 
        !           329:       /* (d) add retrans-list, schedule retransmission */
        !           330:       if (is_debug)
        !           331:         zlog_debug ("Add retrans-list of this neighbor");
        !           332:       ospf6_increment_retrans_count (lsa);
        !           333:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
        !           334:       if (on->thread_send_lsupdate == NULL)
        !           335:         on->thread_send_lsupdate =
        !           336:           thread_add_timer (master, ospf6_lsupdate_send_neighbor,
        !           337:                             on, on->ospf6_if->rxmt_interval);
        !           338:       retrans_added++;
        !           339:     }
        !           340: 
        !           341:   /* (2) examin next interface if not added to retrans-list */
        !           342:   if (retrans_added == 0)
        !           343:     {
        !           344:       if (is_debug)
        !           345:         zlog_debug ("No retransmission scheduled, next interface");
        !           346:       return;
        !           347:     }
        !           348: 
        !           349:   /* (3) If the new LSA was received on this interface,
        !           350:      and it was from DR or BDR, examin next interface */
        !           351:   if (from && from->ospf6_if == oi &&
        !           352:       (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
        !           353:     {
        !           354:       if (is_debug)
        !           355:         zlog_debug ("Received is from the I/F's DR or BDR, next interface");
        !           356:       return;
        !           357:     }
        !           358: 
        !           359:   /* (4) If the new LSA was received on this interface,
        !           360:      and the interface state is BDR, examin next interface */
        !           361:   if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
        !           362:     {
        !           363:       if (is_debug)
        !           364:         zlog_debug ("Received is from the I/F, itself BDR, next interface");
        !           365:       return;
        !           366:     }
        !           367: 
        !           368:   /* (5) flood the LSA out the interface. */
        !           369:   if (is_debug)
        !           370:     zlog_debug ("Schedule flooding for the interface");
        !           371:   if (if_is_broadcast (oi->interface))
        !           372:     {
        !           373:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
        !           374:       if (oi->thread_send_lsupdate == NULL)
        !           375:         oi->thread_send_lsupdate =
        !           376:           thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
        !           377:     }
        !           378:   else
        !           379:     {
        !           380:       /* reschedule retransmissions to all neighbors */
        !           381:       for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
        !           382:         {
        !           383:           THREAD_OFF (on->thread_send_lsupdate);
        !           384:           on->thread_send_lsupdate =
        !           385:             thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
        !           386:         }
        !           387:     }
        !           388: }
        !           389: 
        !           390: static void
        !           391: ospf6_flood_area (struct ospf6_neighbor *from,
        !           392:                   struct ospf6_lsa *lsa, struct ospf6_area *oa)
        !           393: {
        !           394:   struct listnode *node, *nnode;
        !           395:   struct ospf6_interface *oi;
        !           396: 
        !           397:   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
        !           398:     {
        !           399:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
        !           400:           oi != OSPF6_INTERFACE (lsa->lsdb->data))
        !           401:         continue;
        !           402: 
        !           403: #if 0
        !           404:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
        !           405:           ospf6_is_interface_virtual_link (oi))
        !           406:         continue;
        !           407: #endif/*0*/
        !           408: 
        !           409:       ospf6_flood_interface (from, lsa, oi);
        !           410:     }
        !           411: }
        !           412: 
        !           413: static void
        !           414: ospf6_flood_process (struct ospf6_neighbor *from,
        !           415:                      struct ospf6_lsa *lsa, struct ospf6 *process)
        !           416: {
        !           417:   struct listnode *node, *nnode;
        !           418:   struct ospf6_area *oa;
        !           419: 
        !           420:   for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa))
        !           421:     {
        !           422:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
        !           423:           oa != OSPF6_AREA (lsa->lsdb->data))
        !           424:         continue;
        !           425:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
        !           426:           oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
        !           427:         continue;
        !           428: 
        !           429:       if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
        !           430:           IS_AREA_STUB (oa))
        !           431:         continue;
        !           432: 
        !           433:       ospf6_flood_area (from, lsa, oa);
        !           434:     }
        !           435: }
        !           436: 
        !           437: void
        !           438: ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
        !           439: {
        !           440:   ospf6_flood_process (from, lsa, ospf6);
        !           441: }
        !           442: 
        !           443: static void
        !           444: ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
        !           445: {
        !           446:   struct listnode *node, *nnode;
        !           447:   struct ospf6_neighbor *on;
        !           448:   struct ospf6_lsa *rem;
        !           449: 
        !           450:   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
        !           451:     {
        !           452:       rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           453:                                lsa->header->adv_router, on->retrans_list);
        !           454:       if (rem && ! ospf6_lsa_compare (rem, lsa))
        !           455:         {
        !           456:           if (IS_OSPF6_DEBUG_FLOODING ||
        !           457:               IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
        !           458:             zlog_debug ("Remove %s from retrans_list of %s",
        !           459:                        rem->name, on->name);
        !           460:           ospf6_decrement_retrans_count (rem);
        !           461:           ospf6_lsdb_remove (rem, on->retrans_list);
        !           462:         }
        !           463:     }
        !           464: }
        !           465: 
        !           466: static void
        !           467: ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
        !           468: {
        !           469:   struct listnode *node, *nnode;
        !           470:   struct ospf6_interface *oi;
        !           471: 
        !           472:   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
        !           473:     {
        !           474:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
        !           475:           oi != OSPF6_INTERFACE (lsa->lsdb->data))
        !           476:         continue;
        !           477: 
        !           478: #if 0
        !           479:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
        !           480:           ospf6_is_interface_virtual_link (oi))
        !           481:         continue;
        !           482: #endif/*0*/
        !           483: 
        !           484:       ospf6_flood_clear_interface (lsa, oi);
        !           485:     }
        !           486: }
        !           487: 
        !           488: static void
        !           489: ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
        !           490: {
        !           491:   struct listnode *node, *nnode;
        !           492:   struct ospf6_area *oa;
        !           493: 
        !           494:   for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa))
        !           495:     {
        !           496:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
        !           497:           oa != OSPF6_AREA (lsa->lsdb->data))
        !           498:         continue;
        !           499:       if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
        !           500:           oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
        !           501:         continue;
        !           502: 
        !           503:       if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
        !           504:           IS_AREA_STUB (oa))
        !           505:         continue;
        !           506: 
        !           507:       ospf6_flood_clear_area (lsa, oa);
        !           508:     }
        !           509: }
        !           510: 
        !           511: void
        !           512: ospf6_flood_clear (struct ospf6_lsa *lsa)
        !           513: {
        !           514:   ospf6_flood_clear_process (lsa, ospf6);
        !           515: }
        !           516: 
        !           517: 
        !           518: /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
        !           519: static void
        !           520: ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
        !           521:                                 struct ospf6_neighbor *from)
        !           522: {
        !           523:   struct ospf6_interface *oi;
        !           524:   int is_debug = 0;
        !           525: 
        !           526:   if (IS_OSPF6_DEBUG_FLOODING ||
        !           527:       IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
        !           528:     is_debug++;
        !           529: 
        !           530:   assert (from && from->ospf6_if);
        !           531:   oi = from->ospf6_if;
        !           532: 
        !           533:   /* LSA has been flood back out receiving interface.
        !           534:      No acknowledgement sent. */
        !           535:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
        !           536:     {
        !           537:       if (is_debug)
        !           538:         zlog_debug ("No acknowledgement (BDR & FloodBack)");
        !           539:       return;
        !           540:     }
        !           541: 
        !           542:   /* LSA is more recent than database copy, but was not flooded
        !           543:      back out receiving interface. Delayed acknowledgement sent
        !           544:      if advertisement received from Designated Router,
        !           545:      otherwide do nothing. */
        !           546:   if (ismore_recent < 0)
        !           547:     {
        !           548:       if (oi->drouter == from->router_id)
        !           549:         {
        !           550:           if (is_debug)
        !           551:             zlog_debug ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
        !           552:           /* Delayed acknowledgement */
        !           553:           ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
        !           554:           if (oi->thread_send_lsack == NULL)
        !           555:             oi->thread_send_lsack =
        !           556:               thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
        !           557:         }
        !           558:       else
        !           559:         {
        !           560:           if (is_debug)
        !           561:             zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)");
        !           562:         }
        !           563:       return;
        !           564:     }
        !           565: 
        !           566:   /* LSA is a duplicate, and was treated as an implied acknowledgement.
        !           567:      Delayed acknowledgement sent if advertisement received from
        !           568:      Designated Router, otherwise do nothing */
        !           569:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
        !           570:       CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
        !           571:     {
        !           572:       if (oi->drouter == from->router_id)
        !           573:         {
        !           574:           if (is_debug)
        !           575:             zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
        !           576:           /* Delayed acknowledgement */
        !           577:           ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
        !           578:           if (oi->thread_send_lsack == NULL)
        !           579:             oi->thread_send_lsack =
        !           580:               thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
        !           581:         }
        !           582:       else
        !           583:         {
        !           584:           if (is_debug)
        !           585:             zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
        !           586:         }
        !           587:       return;
        !           588:     }
        !           589: 
        !           590:   /* LSA is a duplicate, and was not treated as an implied acknowledgement.
        !           591:      Direct acknowledgement sent */
        !           592:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
        !           593:       ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
        !           594:     {
        !           595:       if (is_debug)
        !           596:         zlog_debug ("Direct acknowledgement (BDR & Duplicate)");
        !           597:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
        !           598:       if (from->thread_send_lsack == NULL)
        !           599:         from->thread_send_lsack =
        !           600:           thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
        !           601:       return;
        !           602:     }
        !           603: 
        !           604:   /* LSA's LS age is equal to Maxage, and there is no current instance
        !           605:      of the LSA in the link state database, and none of router's
        !           606:      neighbors are in states Exchange or Loading */
        !           607:   /* Direct acknowledgement sent, but this case is handled in
        !           608:      early of ospf6_receive_lsa () */
        !           609: }
        !           610: 
        !           611: static void
        !           612: ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
        !           613:                                 struct ospf6_neighbor *from)
        !           614: {
        !           615:   struct ospf6_interface *oi;
        !           616:   int is_debug = 0;
        !           617: 
        !           618:   if (IS_OSPF6_DEBUG_FLOODING ||
        !           619:       IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
        !           620:     is_debug++;
        !           621: 
        !           622:   assert (from && from->ospf6_if);
        !           623:   oi = from->ospf6_if;
        !           624: 
        !           625:   /* LSA has been flood back out receiving interface.
        !           626:      No acknowledgement sent. */
        !           627:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
        !           628:     {
        !           629:       if (is_debug)
        !           630:         zlog_debug ("No acknowledgement (AllOther & FloodBack)");
        !           631:       return;
        !           632:     }
        !           633: 
        !           634:   /* LSA is more recent than database copy, but was not flooded
        !           635:      back out receiving interface. Delayed acknowledgement sent. */
        !           636:   if (ismore_recent < 0)
        !           637:     {
        !           638:       if (is_debug)
        !           639:         zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)");
        !           640:       /* Delayed acknowledgement */
        !           641:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
        !           642:       if (oi->thread_send_lsack == NULL)
        !           643:         oi->thread_send_lsack =
        !           644:           thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
        !           645:       return;
        !           646:     }
        !           647: 
        !           648:   /* LSA is a duplicate, and was treated as an implied acknowledgement.
        !           649:      No acknowledgement sent. */
        !           650:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
        !           651:       CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
        !           652:     {
        !           653:       if (is_debug)
        !           654:         zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
        !           655:       return;
        !           656:     }
        !           657: 
        !           658:   /* LSA is a duplicate, and was not treated as an implied acknowledgement.
        !           659:      Direct acknowledgement sent */
        !           660:   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
        !           661:       ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
        !           662:     {
        !           663:       if (is_debug)
        !           664:         zlog_debug ("Direct acknowledgement (AllOther & Duplicate)");
        !           665:       ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
        !           666:       if (from->thread_send_lsack == NULL)
        !           667:         from->thread_send_lsack =
        !           668:           thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
        !           669:       return;
        !           670:     }
        !           671: 
        !           672:   /* LSA's LS age is equal to Maxage, and there is no current instance
        !           673:      of the LSA in the link state database, and none of router's
        !           674:      neighbors are in states Exchange or Loading */
        !           675:   /* Direct acknowledgement sent, but this case is handled in
        !           676:      early of ospf6_receive_lsa () */
        !           677: }
        !           678: 
        !           679: static void
        !           680: ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
        !           681:                        struct ospf6_neighbor *from)
        !           682: {
        !           683:   struct ospf6_interface *oi;
        !           684: 
        !           685:   assert (from && from->ospf6_if);
        !           686:   oi = from->ospf6_if;
        !           687: 
        !           688:   if (oi->state == OSPF6_INTERFACE_BDR)
        !           689:     ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
        !           690:   else
        !           691:     ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
        !           692: }
        !           693: 
        !           694: /* RFC2328 section 13 (4):
        !           695:    if MaxAge LSA and if we have no instance, and no neighbor
        !           696:    is in states Exchange or Loading
        !           697:    returns 1 if match this case, else returns 0 */
        !           698: static int
        !           699: ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
        !           700: {
        !           701:   struct ospf6_neighbor *on;
        !           702:   struct ospf6_interface *oi;
        !           703:   struct ospf6_area *oa;
        !           704:   struct ospf6 *process = NULL;
        !           705:   struct listnode *i, *j, *k;
        !           706:   int count = 0;
        !           707: 
        !           708:   if (! OSPF6_LSA_IS_MAXAGE (lsa))
        !           709:     return 0;
        !           710: 
        !           711:   if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
        !           712:                          lsa->header->adv_router, lsa->lsdb))
        !           713:     return 0;
        !           714: 
        !           715:   process = from->ospf6_if->area->ospf6;
        !           716: 
        !           717:   for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa))
        !           718:     for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
        !           719:       for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on))
        !           720:         if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
        !           721:             on->state == OSPF6_NEIGHBOR_LOADING)
        !           722:           count++;
        !           723: 
        !           724:   if (count == 0)
        !           725:     return 1;
        !           726:   return 0;
        !           727: }
        !           728: 
        !           729: /* RFC2328 section 13 The Flooding Procedure */
        !           730: void
        !           731: ospf6_receive_lsa (struct ospf6_neighbor *from,
        !           732:                    struct ospf6_lsa_header *lsa_header)
        !           733: {
        !           734:   struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
        !           735:   int ismore_recent;
        !           736:   unsigned short cksum;
        !           737:   int is_debug = 0;
        !           738: 
        !           739:   ismore_recent = 1;
        !           740:   assert (from);
        !           741: 
        !           742:   /* make lsa structure for received lsa */
        !           743:   new = ospf6_lsa_create (lsa_header);
        !           744: 
        !           745:   if (IS_OSPF6_DEBUG_FLOODING ||
        !           746:       IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type))
        !           747:     {
        !           748:       is_debug++;
        !           749:       zlog_debug ("LSA Receive from %s", from->name);
        !           750:       ospf6_lsa_header_print (new);
        !           751:     }
        !           752: 
        !           753:   /* (1) LSA Checksum */
        !           754:   cksum = ntohs (new->header->checksum);
        !           755:   if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
        !           756:     {
        !           757:       if (is_debug)
        !           758:         zlog_debug ("Wrong LSA Checksum, discard");
        !           759:       ospf6_lsa_delete (new);
        !           760:       return;
        !           761:     }
        !           762: 
        !           763:   /* (2) Examine the LSA's LS type. 
        !           764:      RFC2470 3.5.1. Receiving Link State Update packets  */
        !           765:   if (IS_AREA_STUB (from->ospf6_if->area) &&
        !           766:       OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
        !           767:     {
        !           768:       if (is_debug)
        !           769:         zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
        !           770:       ospf6_lsa_delete (new);
        !           771:       return;
        !           772:     }
        !           773: 
        !           774:   /* (3) LSA which have reserved scope is discarded
        !           775:      RFC2470 3.5.1. Receiving Link State Update packets  */
        !           776:   /* Flooding scope check. LSAs with unknown scope are discarded here.
        !           777:      Set appropriate LSDB for the LSA */
        !           778:   switch (OSPF6_LSA_SCOPE (new->header->type))
        !           779:     {
        !           780:     case OSPF6_SCOPE_LINKLOCAL:
        !           781:       new->lsdb = from->ospf6_if->lsdb;
        !           782:       break;
        !           783:     case OSPF6_SCOPE_AREA:
        !           784:       new->lsdb = from->ospf6_if->area->lsdb;
        !           785:       break;
        !           786:     case OSPF6_SCOPE_AS:
        !           787:       new->lsdb = from->ospf6_if->area->ospf6->lsdb;
        !           788:       break;
        !           789:     default:
        !           790:       if (is_debug)
        !           791:         zlog_debug ("LSA has reserved scope, discard");
        !           792:       ospf6_lsa_delete (new);
        !           793:       return;
        !           794:     }
        !           795: 
        !           796:   /* (4) if MaxAge LSA and if we have no instance, and no neighbor
        !           797:          is in states Exchange or Loading */
        !           798:   if (ospf6_is_maxage_lsa_drop (new, from))
        !           799:     {
        !           800:       /* log */
        !           801:       if (is_debug)
        !           802:         zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
        !           803: 
        !           804:       /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
        !           805:       ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
        !           806:       if (from->thread_send_lsack == NULL)
        !           807:         from->thread_send_lsack =
        !           808:           thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
        !           809: 
        !           810:       /* b) Discard */
        !           811:       ospf6_lsa_delete (new);
        !           812:       return;
        !           813:     }
        !           814: 
        !           815:   /* (5) */
        !           816:   /* lookup the same database copy in lsdb */
        !           817:   old = ospf6_lsdb_lookup (new->header->type, new->header->id,
        !           818:                            new->header->adv_router, new->lsdb);
        !           819:   if (old)
        !           820:     {
        !           821:       ismore_recent = ospf6_lsa_compare (new, old);
        !           822:       if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
        !           823:         {
        !           824:           if (is_debug)
        !           825:             zlog_debug ("Received is duplicated LSA");
        !           826:           SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
        !           827:         }
        !           828:     }
        !           829: 
        !           830:   /* if no database copy or received is more recent */
        !           831:   if (old == NULL || ismore_recent < 0)
        !           832:     {
        !           833:       /* in case we have no database copy */
        !           834:       ismore_recent = -1;
        !           835: 
        !           836:       /* (a) MinLSArrival check */
        !           837:       if (old)
        !           838:         {
        !           839:           struct timeval now, res;
        !           840:           quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
        !           841:           timersub (&now, &old->installed, &res);
        !           842:           if (res.tv_sec < MIN_LS_ARRIVAL)
        !           843:             {
        !           844:               if (is_debug)
        !           845:                 zlog_debug ("LSA can't be updated within MinLSArrival, discard");
        !           846:               ospf6_lsa_delete (new);
        !           847:               return;   /* examin next lsa */
        !           848:             }
        !           849:         }
        !           850: 
        !           851:       quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received);
        !           852: 
        !           853:       if (is_debug)
        !           854:         zlog_debug ("Flood, Install, Possibly acknowledge the received LSA");
        !           855: 
        !           856:       /* (b) immediately flood and (c) remove from all retrans-list */
        !           857:       /* Prevent self-originated LSA to be flooded. this is to make
        !           858:       reoriginated instance of the LSA not to be rejected by other routers
        !           859:       due to MinLSArrival. */
        !           860:       if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
        !           861:         ospf6_flood (from, new);
        !           862: 
        !           863:       /* (c) Remove the current database copy from all neighbors' Link
        !           864:              state retransmission lists. */
        !           865:       /* XXX, flood_clear ? */
        !           866: 
        !           867:       /* (d), installing lsdb, which may cause routing
        !           868:               table calculation (replacing database copy) */
        !           869:       ospf6_install_lsa (new);
        !           870: 
        !           871:       /* (e) possibly acknowledge */
        !           872:       ospf6_acknowledge_lsa (new, ismore_recent, from);
        !           873: 
        !           874:       /* (f) Self Originated LSA, section 13.4 */
        !           875:       if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
        !           876:         {
        !           877:           /* Self-originated LSA (newer than ours) is received from
        !           878:              another router. We have to make a new instance of the LSA
        !           879:              or have to flush this LSA. */
        !           880:           if (is_debug)
        !           881:             {
        !           882:               zlog_debug ("Newer instance of the self-originated LSA");
        !           883:               zlog_debug ("Schedule reorigination");
        !           884:             }
        !           885:           new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
        !           886:         }
        !           887: 
        !           888:       return;
        !           889:     }
        !           890: 
        !           891:   /* (6) if there is instance on sending neighbor's request list */
        !           892:   if (ospf6_lsdb_lookup (new->header->type, new->header->id,
        !           893:                          new->header->adv_router, from->request_list))
        !           894:     {
        !           895:       /* if no database copy, should go above state (5) */
        !           896:       assert (old);
        !           897: 
        !           898:       if (is_debug)
        !           899:         {
        !           900:           zlog_debug ("Received is not newer, on the neighbor's request-list");
        !           901:           zlog_debug ("BadLSReq, discard the received LSA");
        !           902:         }
        !           903: 
        !           904:       /* BadLSReq */
        !           905:       thread_add_event (master, bad_lsreq, from, 0);
        !           906: 
        !           907:       ospf6_lsa_delete (new);
        !           908:       return;
        !           909:     }
        !           910: 
        !           911:   /* (7) if neither one is more recent */
        !           912:   if (ismore_recent == 0)
        !           913:     {
        !           914:       if (is_debug)
        !           915:         zlog_debug ("The same instance as database copy (neither recent)");
        !           916: 
        !           917:       /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
        !           918:       rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
        !           919:                                new->header->adv_router, from->retrans_list);
        !           920:       if (rem)
        !           921:         {
        !           922:           if (is_debug)
        !           923:             {
        !           924:               zlog_debug ("It is on the neighbor's retrans-list.");
        !           925:               zlog_debug ("Treat as an Implied acknowledgement");
        !           926:             }
        !           927:           SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
        !           928:           ospf6_decrement_retrans_count (rem);
        !           929:           ospf6_lsdb_remove (rem, from->retrans_list);
        !           930:         }
        !           931: 
        !           932:       if (is_debug)
        !           933:         zlog_debug ("Possibly acknowledge and then discard");
        !           934: 
        !           935:       /* (b) possibly acknowledge */
        !           936:       ospf6_acknowledge_lsa (new, ismore_recent, from);
        !           937: 
        !           938:       ospf6_lsa_delete (new);
        !           939:       return;
        !           940:     }
        !           941: 
        !           942:   /* (8) previous database copy is more recent */
        !           943:     {
        !           944:       assert (old);
        !           945: 
        !           946:       /* If database copy is in 'Seqnumber Wrapping',
        !           947:          simply discard the received LSA */
        !           948:       if (OSPF6_LSA_IS_MAXAGE (old) &&
        !           949:           old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
        !           950:         {
        !           951:           if (is_debug)
        !           952:             {
        !           953:               zlog_debug ("The LSA is in Seqnumber Wrapping");
        !           954:               zlog_debug ("MaxAge & MaxSeqNum, discard");
        !           955:             }
        !           956:           ospf6_lsa_delete (new);
        !           957:           return;
        !           958:         }
        !           959: 
        !           960:       /* Otherwise, Send database copy of this LSA to this neighbor */
        !           961:         {
        !           962:           if (is_debug)
        !           963:             {
        !           964:               zlog_debug ("Database copy is more recent.");
        !           965:               zlog_debug ("Send back directly and then discard");
        !           966:             }
        !           967: 
        !           968:           /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
        !           969: 
        !           970:           ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
        !           971:           if (from->thread_send_lsupdate == NULL)
        !           972:             from->thread_send_lsupdate =
        !           973:               thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
        !           974:           ospf6_lsa_delete (new);
        !           975:           return;
        !           976:         }
        !           977:       return;
        !           978:     }
        !           979: }
        !           980: 
        !           981: 
        !           982: DEFUN (debug_ospf6_flooding,
        !           983:        debug_ospf6_flooding_cmd,
        !           984:        "debug ospf6 flooding",
        !           985:        DEBUG_STR
        !           986:        OSPF6_STR
        !           987:        "Debug OSPFv3 flooding function\n"
        !           988:       )
        !           989: {
        !           990:   OSPF6_DEBUG_FLOODING_ON ();
        !           991:   return CMD_SUCCESS;
        !           992: }
        !           993: 
        !           994: DEFUN (no_debug_ospf6_flooding,
        !           995:        no_debug_ospf6_flooding_cmd,
        !           996:        "no debug ospf6 flooding",
        !           997:        NO_STR
        !           998:        DEBUG_STR
        !           999:        OSPF6_STR
        !          1000:        "Debug OSPFv3 flooding function\n"
        !          1001:       )
        !          1002: {
        !          1003:   OSPF6_DEBUG_FLOODING_OFF ();
        !          1004:   return CMD_SUCCESS;
        !          1005: }
        !          1006: 
        !          1007: int
        !          1008: config_write_ospf6_debug_flood (struct vty *vty)
        !          1009: {
        !          1010:   if (IS_OSPF6_DEBUG_FLOODING)
        !          1011:     vty_out (vty, "debug ospf6 flooding%s", VNL);
        !          1012:   return 0;
        !          1013: }
        !          1014: 
        !          1015: void
        !          1016: install_element_ospf6_debug_flood (void)
        !          1017: {
        !          1018:   install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd);
        !          1019:   install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
        !          1020:   install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd);
        !          1021:   install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd);
        !          1022: }
        !          1023: 
        !          1024: 
        !          1025: 
        !          1026: 
        !          1027: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>