]> git.puffer.fish Git - matthieu/frr.git/commitdiff
[ospfd] Add support for oversized LSAs.
authorpaul <paul>
Wed, 18 Jan 2006 15:07:38 +0000 (15:07 +0000)
committerpaul <paul>
Wed, 18 Jan 2006 15:07:38 +0000 (15:07 +0000)
2006-01-18 Juergen Kammer <j.kammer@eurodata.de>

* ospf_lsa.c: (ospf_router_lsa_new) dont take reference to the
  stream data until it is constructed, data reference is
  volatile due to the potential resize in link_info_set

2006-01-18 Paul Jakma <paul.jakma@sun.com>

* ospf_lsa.c: (link_info_set) Resize the stream if required and
  possible. Return number of links added.
  (lsa_link_*_set) use return value from previous.
* ospf_lsa.h: Add OSPF_ROUTER_LSA_LINK_SIZE define.

ospfd/ChangeLog
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h

index a13ed6f974e35d49b76c1883bc9af0f3d4e40c4a..e5f833782af76d57ddc96ca130d6dc3a03bee101 100644 (file)
@@ -1,3 +1,16 @@
+2006-01-18 Juergen Kammer <j.kammer@eurodata.de>
+
+       * ospf_lsa.c: (ospf_router_lsa_new) dont take reference to the
+         stream data until it is constructed, data reference is
+         volatile due to the potential resize in link_info_set
+
+2006-01-18 Paul Jakma <paul.jakma@sun.com>
+
+       * ospf_lsa.c: (link_info_set) Resize the stream if required and
+         possible. Return number of links added.
+         (lsa_link_*_set) use return value from previous.
+       * ospf_lsa.h: Add OSPF_ROUTER_LSA_LINK_SIZE define.
+         
 2006-01-17 Paul Jakma <paul.jakma@sun.com>
 
        * ospf_packet.c: (ospf_verify_header) print out the types
index ff018fd4c9523ef61a0853ed6c1fc701b812764f..89e4d53588882f623ed87237b0387988205bb144 100644 (file)
@@ -497,16 +497,49 @@ ospf_link_cost (struct ospf_interface *oi)
 }
 
 /* Set a link information. */
-static void
+static char
 link_info_set (struct stream *s, struct in_addr id,
               struct in_addr data, u_char type, u_char tos, u_int16_t cost)
 {
+  /* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits
+   * vast majority of cases. Some rare routers with lots of links need more.
+   * we try accomodate those here.
+   */
+  if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE)
+    {
+      size_t ret = OSPF_MAX_LSA_SIZE;
+      
+      /* Can we enlarge the stream still? */
+      if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE)
+        {
+          /* we futz the size here for simplicity, really we need to account
+           * for just:
+           * IP Header - (sizeof (struct ip))
+           * OSPF Header - OSPF_HEADER_SIZE
+           * LSA Header - OSPF_LSA_HEADER_SIZE
+           * MD5 auth data, if MD5 is configured - OSPF_AUTH_MD5_SIZE.
+           *
+           * Simpler just to subtract OSPF_MAX_LSA_SIZE though.
+           */
+          ret = stream_resize (s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
+        }
+      
+      if (ret == OSPF_MAX_LSA_SIZE)
+        {
+          zlog_warn ("%s: Out of space in LSA stream, left %ld, size %ld",
+                     __func__, STREAM_REMAIN (s), STREAM_SIZE (s));
+          return 0;
+        }
+    }
+  
   /* TOS based routing is not supported. */
   stream_put_ipv4 (s, id.s_addr);              /* Link ID. */
   stream_put_ipv4 (s, data.s_addr);            /* Link Data. */
   stream_putc (s, type);                       /* Link Type. */
   stream_putc (s, tos);                                /* TOS = 0. */
   stream_putw (s, cost);                       /* Link Cost. */
+  
+  return 1;
 }
 
 /* Describe Point-to-Point link. */
@@ -526,9 +559,8 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
       {
        /* For unnumbered point-to-point networks, the Link Data field
           should specify the interface's MIB-II ifIndex value. */
-       link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                      LSA_LINK_TYPE_POINTOPOINT, 0, cost);
-       links++;
+       links += link_info_set (s, nbr->router_id, oi->address->u.prefix4,
+                               LSA_LINK_TYPE_POINTOPOINT, 0, cost);
       }
 
   if (CONNECTED_DEST_HOST(oi->connected))
@@ -541,7 +573,8 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
       
       id.s_addr = oi->connected->destination->u.prefix4.s_addr;
       mask.s_addr = 0xffffffff;
-      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+      links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
+                              oi->output_cost);
     }
   else
     {
@@ -549,10 +582,9 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
         network regardless of the state of the neighbor */
       masklen2ip (oi->address->prefixlen, &mask);
       id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
-      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+      links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 
+                              oi->output_cost);
     }
-  links++;
-
   return links;
 }
 
@@ -569,8 +601,8 @@ lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
     {
       masklen2ip (oi->address->prefixlen, &mask);
       id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
-      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
-      return 1;
+      return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
+                            oi->output_cost);
     }
 
   dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
@@ -579,17 +611,17 @@ lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
             IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
       ospf_nbr_count (oi, NSM_Full) > 0)
     {
-      link_info_set (s, DR (oi), oi->address->u.prefix4,
-                    LSA_LINK_TYPE_TRANSIT, 0, cost);
+      return link_info_set (s, DR (oi), oi->address->u.prefix4,
+                            LSA_LINK_TYPE_TRANSIT, 0, cost);
     }
   /* Describe type 3 link. */
   else
     {
       masklen2ip (oi->address->prefixlen, &mask);
       id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
-      link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
+      return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
+                            oi->output_cost);
     }
-  return 1;
 }
 
 static int
@@ -603,8 +635,7 @@ lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
 
   mask.s_addr = 0xffffffff;
   id.s_addr = oi->address->u.prefix4.s_addr;
-  link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
-  return 1;
+  return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
 }
 
 /* Describe Virtual Link. */
@@ -618,9 +649,8 @@ lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
     if ((nbr = ospf_nbr_lookup_ptop (oi)))
       if (nbr->state == NSM_Full)
        {
-         link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                        LSA_LINK_TYPE_VIRTUALLINK, 0, cost);
-         return 1;
+         return link_info_set (s, nbr->router_id, oi->address->u.prefix4,
+                               LSA_LINK_TYPE_VIRTUALLINK, 0, cost);
        }
 
   return 0;
@@ -643,8 +673,7 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
 
   mask.s_addr = 0xffffffff;
   id.s_addr = oi->address->u.prefix4.s_addr;
-  link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
-  links++;
+  links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
 
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
     zlog_debug ("PointToMultipoint: running ptomultip_set");
@@ -657,9 +686,8 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
        if (nbr->state == NSM_Full)
 
          {
-           link_info_set (s, nbr->router_id, oi->address->u.prefix4,
-                          LSA_LINK_TYPE_POINTOPOINT, 0, cost);
-           links++;
+           links += link_info_set (s, nbr->router_id, oi->address->u.prefix4,
+                                   LSA_LINK_TYPE_POINTOPOINT, 0, cost);
             if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
              zlog_debug ("PointToMultipoint: set link to %s",
                         inet_ntoa(oi->address->u.prefix4));
@@ -816,8 +844,6 @@ ospf_router_lsa_new (struct ospf_area *area)
   
   /* Create a stream for LSA. */
   s = stream_new (OSPF_MAX_LSA_SIZE);
-  lsah = (struct lsa_header *) STREAM_DATA (s);
-
   /* Set LSA common header fields. */
   lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area),
                  OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
@@ -827,6 +853,7 @@ ospf_router_lsa_new (struct ospf_area *area)
 
   /* Set length. */
   length = stream_get_endp (s);
+  lsah = (struct lsa_header *) STREAM_DATA (s);
   lsah->length = htons (length);
 
   /* Now, create OSPF LSA instance. */
index 42c08828335c580505b87d99658c07d8e8898c26..9e480dee5736cf379c02838c7a5d7d0b7bf6e4a3 100644 (file)
@@ -47,8 +47,9 @@
 #define OSPF_OPAQUE_AREA_LSA        10
 #define OSPF_OPAQUE_AS_LSA          11
 
-#define OSPF_LSA_HEADER_SIZE   20U
-#define OSPF_MAX_LSA_SIZE      1500U
+#define OSPF_LSA_HEADER_SIZE        20U
+#define OSPF_ROUTER_LSA_LINK_SIZE    12U
+#define OSPF_MAX_LSA_SIZE         1500U
 
 /* AS-external-LSA refresh method. */
 #define LSA_REFRESH_IF_CHANGED 0