]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #1738 from chiragshah6/ospfv3_dev
authorOlivier Dugeon <olivier.dugeon@orange.com>
Thu, 15 Feb 2018 16:17:38 +0000 (17:17 +0100)
committerGitHub <noreply@github.com>
Thu, 15 Feb 2018 16:17:38 +0000 (17:17 +0100)
ospf6d: Handle Premature Aging of LSAs

13 files changed:
ospf6d/ospf6_asbr.c
ospf6d/ospf6_flood.c
ospf6d/ospf6_flood.h
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_intra.h
ospf6d/ospf6_lsa.c
ospf6d/ospf6_lsa.h
ospf6d/ospf6_lsdb.c
ospf6d/ospf6_message.c
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_top.c
ospf6d/ospf6_top.h

index 02f8eb0b09ca6f2cd1b7e7accab7fb4d4fe1b497..11f9e7c7b6e4dfc2dfcdde6268a4a96e1d596525 100644 (file)
@@ -148,6 +148,32 @@ static void ospf6_as_external_lsa_originate(struct ospf6_route *route)
        ospf6_lsa_originate_process(lsa, ospf6);
 }
 
+int ospf6_orig_as_external_lsa(struct thread *thread)
+{
+       struct ospf6_interface *oi;
+       struct ospf6_lsa *lsa;
+       uint32_t type, adv_router;
+
+       oi = (struct ospf6_interface *)THREAD_ARG(thread);
+       oi->thread_as_extern_lsa = NULL;
+
+       if (oi->state == OSPF6_INTERFACE_DOWN)
+               return 0;
+
+       type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
+       adv_router = oi->area->ospf6->router_id;
+       for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
+               if (IS_OSPF6_DEBUG_ASBR)
+                       zlog_debug("%s: Send update of AS-External LSA %s seq 0x%x",
+                                  __PRETTY_FUNCTION__, lsa->name,
+                                  ntohl(lsa->header->seqnum));
+
+               ospf6_flood_interface(NULL, lsa, oi);
+       }
+
+       return 0;
+}
+
 static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
 {
        struct ospf6_as_external_lsa *external;
index 42716fbc7fda9a65617449007345be013677381b..17733d6099fc257e0a3effaf295b1f1df07b8616 100644 (file)
@@ -192,10 +192,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 +233,13 @@ 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,7 +249,7 @@ 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,
+void ospf6_flood_interface(struct ospf6_neighbor *from,
                                  struct ospf6_lsa *lsa,
                                  struct ospf6_interface *oi)
 {
@@ -343,15 +346,24 @@ 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 +818,17 @@ 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 +982,34 @@ 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 +1017,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
        }
 }
 
-
 DEFUN (debug_ospf6_flooding,
        debug_ospf6_flooding_cmd,
        "debug ospf6 flooding",
index 610eefc803b43047e1b21901692ff7bb3dc3b647..f5d33e2843aa3269a24e56c0fd6f20aab0ccb15b 100644 (file)
@@ -58,5 +58,10 @@ extern void ospf6_install_lsa(struct ospf6_lsa *lsa);
 
 extern int config_write_ospf6_debug_flood(struct vty *vty);
 extern void install_element_ospf6_debug_flood(void);
+extern void ospf6_flood_interface(struct ospf6_neighbor *from,
+                                 struct ospf6_lsa *lsa,
+                                 struct ospf6_interface *oi);
+extern int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
+                                           struct ospf6_lsa *lsa);
 
 #endif /* OSPF6_FLOOD_H */
index fc6c46c7e75d417f87dc199198fcc734acd77d45..5eaf6177025321e1928380b2d8dbdc6bd32dab8e 100644 (file)
@@ -301,6 +301,7 @@ void ospf6_interface_disable(struct ospf6_interface *oi)
        THREAD_OFF(oi->thread_network_lsa);
        THREAD_OFF(oi->thread_link_lsa);
        THREAD_OFF(oi->thread_intra_prefix_lsa);
+       THREAD_OFF(oi->thread_as_extern_lsa);
 }
 
 static struct in6_addr *
@@ -532,6 +533,7 @@ static void ospf6_interface_state_change(u_char next_state,
                OSPF6_NETWORK_LSA_EXECUTE(oi);
                OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
                OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
+               OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
        } else if (prev_state == OSPF6_INTERFACE_DR
                   || next_state == OSPF6_INTERFACE_DR) {
                OSPF6_NETWORK_LSA_SCHEDULE(oi);
index b67d9a9f2e6f55167f56159e3d577e3702db3118..9b9952beb68317f6215cd96d844bd60e632f089e 100644 (file)
@@ -108,6 +108,7 @@ struct ospf6_interface {
        struct thread *thread_network_lsa;
        struct thread *thread_link_lsa;
        struct thread *thread_intra_prefix_lsa;
+       struct thread *thread_as_extern_lsa;
 
        struct ospf6_route_table *route_connected;
 
index b511a92005342e302a81ae646d1997825e101b24..2ae17f07004b58472a4b1d5c76fd0e54ef9b10a1 100644 (file)
@@ -185,11 +185,21 @@ struct ospf6_intra_prefix_lsa {
                                0, &(oi)->thread_intra_prefix_lsa);            \
        } while (0)
 
+#define OSPF6_AS_EXTERN_LSA_SCHEDULE(oi)                                      \
+       do {                                                                   \
+               if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE))          \
+                       thread_add_event(                                      \
+                               master,                                        \
+                               ospf6_orig_as_external_lsa, oi,                \
+                               0, &(oi)->thread_as_extern_lsa);               \
+       } while (0)
+
 #define OSPF6_NETWORK_LSA_EXECUTE(oi)                                          \
        do {                                                                   \
                THREAD_OFF((oi)->thread_network_lsa);                          \
                thread_execute(master, ospf6_network_lsa_originate, oi, 0);    \
        } while (0)
+
 #define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi)                             \
        do {                                                                   \
                THREAD_OFF((oi)->thread_intra_prefix_lsa);                     \
@@ -198,6 +208,11 @@ struct ospf6_intra_prefix_lsa {
                               0);                                             \
        } while (0)
 
+#define OSPF6_AS_EXTERN_LSA_EXECUTE(oi)                                        \
+       do {                                                                   \
+               THREAD_OFF((oi)->thread_as_extern_lsa);                        \
+               thread_execute(master, ospf6_orig_as_external_lsa, oi, 0);     \
+       } while (0)
 
 /* Function Prototypes */
 extern char *ospf6_router_lsdesc_lookup(u_char type, u_int32_t interface_id,
@@ -215,7 +230,7 @@ extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *);
 extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *);
 extern void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa);
 extern void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa);
-
+extern int ospf6_orig_as_external_lsa(struct thread *thread);
 extern void ospf6_intra_route_calculation(struct ospf6_area *oa);
 extern void ospf6_intra_brouter_calculation(struct ospf6_area *oa);
 
index cca4616c163323b6385d967e5d93d2639c7770e9..4a1ba992e3de38770ff0d7dd805389acfdcc492f 100644 (file)
@@ -706,6 +706,37 @@ int ospf6_lsa_refresh(struct thread *thread)
        return 0;
 }
 
+void ospf6_flush_self_originated_lsas_now(void)
+{
+       struct listnode *node;
+       struct ospf6_area *oa;
+       struct ospf6_lsa *lsa;
+       const struct route_node *end = NULL;
+       uint32_t type, adv_router;
+
+       ospf6->inst_shutdown = 1;
+
+       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
+               end = ospf6_lsdb_head(oa->lsdb_self, 0, 0,
+                                     ospf6->router_id, &lsa);
+               while (lsa) {
+                       /* RFC 2328 (14.1):  Set MAXAGE */
+                       lsa->header->age = htons(OSPF_LSA_MAXAGE);
+                       /* Flood MAXAGE LSA*/
+                       ospf6_flood(NULL, lsa);
+
+                       lsa = ospf6_lsdb_next(end, lsa);
+               }
+       }
+
+       type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
+       adv_router = ospf6->router_id;
+       for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
+               /* RFC 2328 (14.1):  Set MAXAGE */
+               lsa->header->age = htons(OSPF_LSA_MAXAGE);
+               ospf6_flood(NULL, lsa);
+       }
+}
 
 /* Fletcher Checksum -- Refer to RFC1008. */
 
index db446a328734f4ec95aec29afbbea974f01252bb..369b381faaed5f131b35a1a641ac4952c36624d9 100644 (file)
@@ -253,5 +253,6 @@ extern void ospf6_lsa_terminate(void);
 extern int config_write_ospf6_debug_lsa(struct vty *vty);
 extern void install_element_ospf6_debug_lsa(void);
 extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
+extern void ospf6_flush_self_originated_lsas_now(void);
 
 #endif /* OSPF6_LSA_H */
index 418f858a3256a6684b240248a00d404289864fd7..152702391b6a3891dc92cf3318da419829a2c15c 100644 (file)
@@ -334,6 +334,7 @@ int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
                }
                if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
                        zlog_debug("Remove MaxAge %s", lsa->name);
+
                if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) {
                        UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
                        /*
index d76438ea5033aae81e6c89259946a5bbfdc7bd09..fe74ddc982ec00eab1310f27411a8db299080325 100644 (file)
@@ -2163,6 +2163,40 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
        return 0;
 }
 
+int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
+                                    struct ospf6_lsa *lsa)
+{
+       struct ospf6_header *oh;
+       struct ospf6_lsupdate *lsupdate;
+       u_char *p;
+       int lsa_cnt = 0;
+
+       memset(sendbuf, 0, iobuflen);
+       oh = (struct ospf6_header *)sendbuf;
+       lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
+                                            + sizeof(struct ospf6_header));
+
+       p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
+       ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
+       memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header));
+       p += OSPF6_LSA_SIZE(lsa->header);
+       lsa_cnt++;
+
+       oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+       oh->length = htons(p - sendbuf);
+       lsupdate->lsa_number = htonl(lsa_cnt);
+
+       if (IS_OSPF6_DEBUG_FLOODING ||
+           IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+               zlog_debug("%s: Send lsupdate with lsa %s (age %u)",
+                  __PRETTY_FUNCTION__, lsa->name,
+                  ntohs(lsa->header->age));
+
+       ospf6_send_lsupdate(on, NULL, oh);
+
+       return 0;
+}
+
 int ospf6_lsupdate_send_interface(struct thread *thread)
 {
        struct ospf6_interface *oi;
index bde89f54a604b1be465f297c4d6caefec7d75d80..35d0b0a6462918af0861e457f05280b1947abb20 100644 (file)
@@ -189,6 +189,11 @@ static void ospf6_neighbor_state_change(u_char next_state,
                        OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if);
                }
                OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area);
+
+               if (prev_state == OSPF6_NEIGHBOR_LOADING &&
+                   next_state == OSPF6_NEIGHBOR_FULL) {
+                       OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if);
+               }
        }
 
        if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE
index 749873bcf8c753dae2232b3d2125e0b97df36b3c..db39420548c1785792bdca46b2ced064e0224978 100644 (file)
@@ -180,6 +180,8 @@ void ospf6_delete(struct ospf6 *o)
        struct ospf6_area *oa;
 
        QOBJ_UNREG(o);
+
+       ospf6_flush_self_originated_lsas_now();
        ospf6_disable(ospf6);
 
        for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
index b39c25ba84c46472f9d4ba5dbd1e446a3f6bb830..8f99cc33f42a9a5aae5dc09719b4aedf6285f973 100644 (file)
@@ -94,6 +94,10 @@ struct ospf6 {
 
        struct route_table *distance_table;
 
+       /* Used during ospf instance going down send LSDB
+        * update to neighbors immediatly */
+       uint8_t inst_shutdown;
+
        QOBJ_FIELDS
 };
 DECLARE_QOBJ_TYPE(ospf6)