]> git.proxmox.com Git - mirror_frr.git/commitdiff
ospf6d: Divide LSupdate to keep size small
authorChirag Shah <chirag@cumulusnetworks.com>
Wed, 18 Oct 2017 04:54:29 +0000 (21:54 -0700)
committerChirag Shah <chirag@cumulusnetworks.com>
Fri, 20 Oct 2017 21:48:13 +0000 (14:48 -0700)
Within OSPFv3 area, Disect Router LSA and
Intra-prefix LSA in order to keep LSA size Small.
Each LSA has unique Link State ID assigned.

Intra-Area-Prefix LSA:
Spread prefixes across multiple intra-area-prefix-LSAs.

Ticket:CM-18069
Testing Done:
Tested 92 ospf6 enabled (point-to-point) interfaces
between two routers.
92 adajancy comes up with Full Neighborship.
Validated 'show ipv6 ospf6 database router detail' &
'show ipv6 ospf6 database intra-prefix detail', each adv-router
has two distinct LSA of such catgory.

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
ospf6d/ospf6_area.c
ospf6d/ospf6_intra.c

index b1267862466b589882a75100f4fe136e6b953291..6bbab46ad88072eeaf04502e7ec5fdf4347e4090 100644 (file)
@@ -234,6 +234,7 @@ struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df)
        oa->summary_prefix->scope = oa;
        oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
        oa->summary_router->scope = oa;
+       oa->router_lsa_size_limit = 1024 + 256;
 
        /* set default options */
        if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) {
index a2caeccb86ed49e6cce55f088205a3b4e885d268..b5a0a9209bb8a7f8edb9262e66aaefee79253563 100644 (file)
@@ -52,6 +52,7 @@ unsigned char conf_debug_ospf6_brouter = 0;
 u_int32_t conf_debug_ospf6_brouter_specific_router_id;
 u_int32_t conf_debug_ospf6_brouter_specific_area_id;
 
+#define MAX_LSA_PAYLOAD   (1024 + 256)
 /******************************/
 /* RFC2740 3.4.3.1 Router-LSA */
 /******************************/
@@ -214,8 +215,7 @@ int ospf6_router_lsa_originate(struct thread *thread)
        ospf6_router_lsa_options_set(oa, router_lsa);
 
        /* describe links for each interfaces */
-       lsdesc = (struct ospf6_router_lsdesc
-                         *)((caddr_t)router_lsa
+       lsdesc = (struct ospf6_router_lsdesc *)((caddr_t)router_lsa
                             + sizeof(struct ospf6_router_lsa));
 
        for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
@@ -248,6 +248,41 @@ int ospf6_router_lsa_originate(struct thread *thread)
                                return 0;
                        }
 
+                       /* Fill LSA Header */
+                       lsa_header->age = 0;
+                       lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
+                       lsa_header->id = htonl(link_state_id);
+                       lsa_header->adv_router = oa->ospf6->router_id;
+                       lsa_header->seqnum =
+                               ospf6_new_ls_seqnum(lsa_header->type,
+                                                   lsa_header->id,
+                                   lsa_header->adv_router, oa->lsdb);
+                       lsa_header->length =
+                               htons((caddr_t)lsdesc - (caddr_t)buffer);
+
+                       /* LSA checksum */
+                       ospf6_lsa_checksum(lsa_header);
+
+                       /* create LSA */
+                       lsa = ospf6_lsa_create(lsa_header);
+
+                       /* Originate */
+                       ospf6_lsa_originate_area(lsa, oa);
+
+                       /* Reset Buffer to fill next Router LSA */
+                       memset(buffer, 0, sizeof(buffer));
+                       lsa_header = (struct ospf6_lsa_header *)buffer;
+                       router_lsa =
+                               (struct ospf6_router_lsa *)((caddr_t)lsa_header
+                                           + sizeof(struct ospf6_lsa_header));
+
+                       ospf6_router_lsa_options_set(oa, router_lsa);
+
+                       /* describe links for each interfaces */
+                       lsdesc = (struct ospf6_router_lsdesc *)
+                               ((caddr_t)router_lsa +
+                                sizeof(struct ospf6_router_lsa));
+
                        link_state_id++;
                }
 
@@ -861,7 +896,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
 
        char buffer[OSPF6_MAX_LSASIZE];
        struct ospf6_lsa_header *lsa_header;
-       struct ospf6_lsa *old, *lsa;
+       struct ospf6_lsa *old, *lsa, *old_next = NULL;
 
        struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
        struct ospf6_interface *oi;
@@ -873,6 +908,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
        unsigned short prefix_num = 0;
        char buf[PREFIX2STR_BUFFER];
        struct ospf6_route_table *route_advertise;
+       int ls_id = 0;
 
        oa = (struct ospf6_area *)THREAD_ARG(thread);
        oa->thread_intra_prefix_lsa = NULL;
@@ -882,8 +918,22 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
                                oa->ospf6->router_id, oa->lsdb);
 
        if (!IS_AREA_ENABLED(oa)) {
-               if (old)
+               if (old) {
                        ospf6_lsa_purge(old);
+                       /* find previous LSA */
+                       old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id),
+                                       oa->ospf6->router_id, oa->lsdb);
+
+                       while (old_next) {
+                               ospf6_lsa_purge(old_next);
+                               old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id),
+                                       oa->ospf6->router_id, oa->lsdb);
+                       }
+               }
                return 0;
        }
 
@@ -895,8 +945,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
        /* prepare buffer */
        memset(buffer, 0, sizeof(buffer));
        lsa_header = (struct ospf6_lsa_header *)buffer;
-       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
-                                   *)((caddr_t)lsa_header
+       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)((caddr_t)lsa_header
                                       + sizeof(struct ospf6_lsa_header));
 
        /* Fill Intra-Area-Prefix-LSA */
@@ -945,8 +994,23 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
        }
 
        if (route_advertise->count == 0) {
-               if (old)
+               if (old) {
+                       ls_id = 0;
                        ospf6_lsa_purge(old);
+                       /* find previous LSA */
+                       old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id),
+                                       oa->ospf6->router_id, oa->lsdb);
+
+                       while (old_next) {
+                               ospf6_lsa_purge(old_next);
+                               old_next = ospf6_lsdb_lookup(
+                                       htons(OSPF6_LSTYPE_INTRA_PREFIX),
+                                       htonl(++ls_id),
+                                       oa->ospf6->router_id, oa->lsdb);
+                       }
+               }
                ospf6_route_table_delete(route_advertise);
                return 0;
        }
@@ -957,13 +1021,58 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
                                     + sizeof(struct ospf6_intra_prefix_lsa));
        for (route = ospf6_route_head(route_advertise); route;
             route = ospf6_route_best_next(route)) {
+               if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) {
+
+                       intra_prefix_lsa->prefix_num = htons(prefix_num);
+
+                       /* Fill LSA Header */
+                       lsa_header->age = 0;
+                       lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
+                       lsa_header->id = htonl(ls_id++);
+                       lsa_header->adv_router = oa->ospf6->router_id;
+                       lsa_header->seqnum =
+                               ospf6_new_ls_seqnum(lsa_header->type,
+                                                   lsa_header->id,
+                                                   lsa_header->adv_router,
+                                                   oa->lsdb);
+                       lsa_header->length = htons((caddr_t)op -
+                                                  (caddr_t)lsa_header);
+
+                       /* LSA checksum */
+                       ospf6_lsa_checksum(lsa_header);
+
+                       /* Create LSA */
+                       lsa = ospf6_lsa_create(lsa_header);
+
+                       /* Originate */
+                       ospf6_lsa_originate_area(lsa, oa);
+
+                       /* Prepare next buffer */
+                       memset(buffer, 0, sizeof(buffer));
+                       lsa_header = (struct ospf6_lsa_header *)buffer;
+                       intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+                                       ((caddr_t)lsa_header
+                                      + sizeof(struct ospf6_lsa_header));
+
+                       /* Fill Intra-Area-Prefix-LSA */
+                       intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
+                       intra_prefix_lsa->ref_id = htonl(0);
+                       intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
+
+                       /* Put next set of prefixes to advertise */
+                       prefix_num = 0;
+                       op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
+                                    + sizeof(struct ospf6_intra_prefix_lsa));
+               }
+
                op->prefix_length = route->prefix.prefixlen;
                op->prefix_options = route->path.prefix_options;
                op->prefix_metric = htons(route->path.cost);
                memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
                       OSPF6_PREFIX_SPACE(op->prefix_length));
-               op = OSPF6_PREFIX_NEXT(op);
                prefix_num++;
+
+               op = OSPF6_PREFIX_NEXT(op);
        }
 
        ospf6_route_table_delete(route_advertise);
@@ -980,7 +1089,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
        /* Fill LSA Header */
        lsa_header->age = 0;
        lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
-       lsa_header->id = htonl(0);
+       lsa_header->id = htonl(ls_id++);
        lsa_header->adv_router = oa->ospf6->router_id;
        lsa_header->seqnum =
                ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,