]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospf6d/ospf6_flood.c
Merge pull request #3502 from donaldsharp/socket_to_me_baby
[mirror_frr.git] / ospf6d / ospf6_flood.c
index 42716fbc7fda9a65617449007345be013677381b..0828c2beb659348d24b47305d0ae9f8f1f87a2ac 100644 (file)
@@ -156,6 +156,28 @@ void ospf6_lsa_purge(struct ospf6_lsa *lsa)
        ospf6_lsa_premature_aging(lsa);
 }
 
+/* Puring Multi Link-State IDs LSAs:
+ * Same Advertising Router with Multiple Link-State IDs
+ * LSAs, purging require to traverse all Link-State IDs
+ */
+void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, struct ospf6_lsa *lsa)
+{
+       int ls_id = 0;
+       struct ospf6_lsa *lsa_next;
+       uint16_t type;
+
+       type = lsa->header->type;
+
+       ospf6_lsa_purge(lsa);
+
+       lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
+                                    oa->ospf6->router_id, oa->lsdb);
+       while (lsa_next) {
+               ospf6_lsa_purge(lsa_next);
+               lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id),
+                                            oa->ospf6->router_id, oa->lsdb);
+       }
+}
 
 void ospf6_increment_retrans_count(struct ospf6_lsa *lsa)
 {
@@ -192,10 +214,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
        struct timeval now;
        struct ospf6_lsa *old;
 
-       if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
-           || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
-               zlog_debug("Install LSA: %s", lsa->name);
-
        /* Remove the old instance from all neighbors' Link state
           retransmission list (RFC2328 13.2 last paragraph) */
        old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id,
@@ -237,6 +255,12 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
                ospf6_lsa_checksum(lsa->header);
        }
 
+       if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)
+           || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type))
+               zlog_debug("%s Install LSA: %s age %d seqnum %x in LSDB.",
+                          __PRETTY_FUNCTION__, lsa->name,
+                          ntohs(lsa->header->age), ntohl(lsa->header->seqnum));
+
        /* actually install */
        lsa->installed = now;
        ospf6_lsdb_add(lsa, lsa->lsdb);
@@ -246,9 +270,8 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
 
 /* RFC2740 section 3.5.2. Sending Link State Update packets */
 /* RFC2328 section 13.3 Next step in the flooding procedure */
-static void ospf6_flood_interface(struct ospf6_neighbor *from,
-                                 struct ospf6_lsa *lsa,
-                                 struct ospf6_interface *oi)
+void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
+                          struct ospf6_interface *oi)
 {
        struct listnode *node, *nnode;
        struct ospf6_neighbor *on;
@@ -307,6 +330,8 @@ static void ospf6_flood_interface(struct ospf6_neighbor *from,
                                                zlog_debug(
                                                        "Requesting the same, remove it, next neighbor");
                                        if (req == on->last_ls_req) {
+                                               /* sanity check refcount */
+                                               assert(req->lock >= 2);
                                                ospf6_lsa_unlock(req);
                                                on->last_ls_req = NULL;
                                        }
@@ -326,8 +351,9 @@ static void ospf6_flood_interface(struct ospf6_neighbor *from,
                                                ospf6_lsa_unlock(req);
                                                on->last_ls_req = NULL;
                                        }
-                                       ospf6_lsdb_remove(req,
-                                                         on->request_list);
+                                       if (req)
+                                               ospf6_lsdb_remove(req,
+                                                       on->request_list);
                                        ospf6_check_nbr_loading(on);
                                        /* fall through */
                                }
@@ -343,15 +369,25 @@ static void ospf6_flood_interface(struct ospf6_neighbor *from,
                        continue;
                }
 
-               /* (d) add retrans-list, schedule retransmission */
-               if (is_debug)
-                       zlog_debug("Add retrans-list of this neighbor");
-               ospf6_increment_retrans_count(lsa);
-               ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
-               thread_add_timer(master, ospf6_lsupdate_send_neighbor, on,
-                                on->ospf6_if->rxmt_interval,
-                                &on->thread_send_lsupdate);
-               retrans_added++;
+               if (ospf6->inst_shutdown) {
+                       if (is_debug)
+                               zlog_debug(
+                                       "%s: Send LSA %s (age %d) update now",
+                                       __PRETTY_FUNCTION__, lsa->name,
+                                       ntohs(lsa->header->age));
+                       ospf6_lsupdate_send_neighbor_now(on, lsa);
+                       continue;
+               } else {
+                       /* (d) add retrans-list, schedule retransmission */
+                       if (is_debug)
+                               zlog_debug("Add retrans-list of this neighbor");
+                       ospf6_increment_retrans_count(lsa);
+                       ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
+                       thread_add_timer(master, ospf6_lsupdate_send_neighbor,
+                                        on, on->ospf6_if->rxmt_interval,
+                                        &on->thread_send_lsupdate);
+                       retrans_added++;
+               }
        }
 
        /* (2) examin next interface if not added to retrans-list */
@@ -806,6 +842,18 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
                                zlog_debug("Received is duplicated LSA");
                        SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE);
                }
+               if (old->header->adv_router
+                           == from->ospf6_if->area->ospf6->router_id
+                   && OSPF6_LSA_IS_MAXAGE(new)) {
+                       ospf6_acknowledge_lsa(new, ismore_recent, from);
+                       ospf6_lsa_delete(new);
+                       if (is_debug)
+                               zlog_debug(
+                                       "%s: Received is self orig MAXAGE LSA %s, discard (ismore_recent %d)",
+                                       __PRETTY_FUNCTION__, old->name,
+                                       ismore_recent);
+                       return;
+               }
        }
 
        /* if no database copy or received is more recent */
@@ -959,12 +1007,33 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
                                        "Send back directly and then discard");
                        }
 
+                       /* Neighbor router sent recent age for LSA,
+                        * Router could be restarted while current copy is
+                        * MAXAGEd and not removed.*/
+                       if (OSPF6_LSA_IS_MAXAGE(old)
+                           && !OSPF6_LSA_IS_MAXAGE(new)) {
+
+                               if (is_debug)
+                                       zlog_debug(
+                                               "%s: Current copy of LSA %s is MAXAGE, but new has recent Age.",
+                                               old->name, __PRETTY_FUNCTION__);
+
+                               ospf6_lsa_purge(old);
+                               if (new->header->adv_router
+                                   != from->ospf6_if->area->ospf6->router_id)
+                                       ospf6_flood(from, new);
+
+                               ospf6_install_lsa(new);
+                               return;
+                       }
+
                        /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
 
                        ospf6_lsdb_add(ospf6_lsa_copy(old),
                                       from->lsupdate_list);
                        thread_add_event(master, ospf6_lsupdate_send_neighbor,
                                         from, 0, &from->thread_send_lsupdate);
+
                        ospf6_lsa_delete(new);
                        return;
                }
@@ -972,7 +1041,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
        }
 }
 
-
 DEFUN (debug_ospf6_flooding,
        debug_ospf6_flooding_cmd,
        "debug ospf6 flooding",