]> git.proxmox.com Git - mirror_frr.git/commitdiff
Marker merge for 'RE-0.99.17.6'
authorPaul Jakma <paul@quagga.net>
Sun, 8 Jan 2012 14:47:06 +0000 (14:47 +0000)
committerPaul Jakma <paul@quagga.net>
Sun, 8 Jan 2012 14:47:27 +0000 (14:47 +0000)
This marker merge (i.e. an 'ours' strategy merge) is a placeholder to show
that all commits in Quagga-RE stable, to its release RE-0.99.17.6 tag, have
been reviewed and merged into 'master'.

72 files changed:
README.NetBSD
bgpd/bgp_advertise.c
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_clist.c
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h
bgpd/bgp_main.c
bgpd/bgp_network.c
bgpd/bgp_nexthop.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_table.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
configure.ac
lib/command.c
lib/distribute.c
lib/hash.c
lib/hash.h
lib/if.c
lib/if_rmap.c
lib/memory.c
lib/memtypes.c
lib/prefix.c
lib/prefix.h
lib/sockunion.c
lib/sockunion.h
lib/table.c
lib/thread.c
lib/thread.h
lib/vty.c
lib/workqueue.c
lib/zclient.c
ospf6d/ospf6_main.c
ospf6d/ospf6_zebra.c
ospfd/ospf_abr.c
ospfd/ospf_api.c
ospfd/ospf_apiserver.c
ospfd/ospf_apiserver.h
ospfd/ospf_asbr.c
ospfd/ospf_ase.c
ospfd/ospf_flood.c
ospfd/ospf_flood.h
ospfd/ospf_interface.c
ospfd/ospf_interface.h
ospfd/ospf_ism.c
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h
ospfd/ospf_lsdb.c
ospfd/ospf_nsm.c
ospfd/ospf_nsm.h
ospfd/ospf_opaque.c
ospfd/ospf_opaque.h
ospfd/ospf_packet.c
ospfd/ospf_packet.h
ospfd/ospf_te.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h
tests/aspath_test.c
tools/multiple-bgpd.sh
zebra/interface.c
zebra/irdp_interface.c
zebra/rt_netlink.c

index 9aac4c35fd557c9c2752a4e82a75c46707d924d4..6bbc680b95e9d80d831d7f531bffd95f5a73cdba 100755 (executable)
@@ -20,13 +20,15 @@ PREFIX=/usr/pkg
 case $1 in
 
     build)
+       # Omitted because it is now default:
+       #   --enable-opaque-lsa
        ./bootstrap.sh
        LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib" CPPFLAGS="-I/usr/pkg/include" \
        ./configure --prefix=${PREFIX} \
            --sysconfdir=/etc/zebra --localstatedir=/var/run/zebra \
            --enable-exampledir=${PREFIX}/share/examples/zebra \
            --enable-pkgsrcrcdir=${PREFIX}/etc/rc.d \
-           --enable-opaque-lsa --enable-vtysh
+           --enable-vtysh
        ${MAKE}
        ;;
 
index 87eb7ac7825d6bd0a855c4c237eb445ae4c03fff..666218fa8ce7ce2ea7cbfb4f5264073bbb5426e8 100644 (file)
@@ -140,13 +140,13 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
     baa->refcnt--;
 
   if (baa->refcnt && baa->attr)
-    bgp_attr_unintern (baa->attr);
+    bgp_attr_unintern (&baa->attr);
   else
     {
       if (baa->attr)
        {
          hash_release (hash, baa);
-         bgp_attr_unintern (baa->attr);
+         bgp_attr_unintern (&baa->attr);
        }
       baa_free (baa);
     }
@@ -319,7 +319,7 @@ bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
                    struct peer *peer, afi_t afi, safi_t safi)
 {
   if (adj->attr)
-    bgp_attr_unintern (adj->attr);
+    bgp_attr_unintern (&adj->attr);
 
   if (adj->adv)
     bgp_advertise_clean (peer, adj, afi, safi);
@@ -339,7 +339,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
        {
          if (adj->attr != attr)
            {
-             bgp_attr_unintern (adj->attr);
+             bgp_attr_unintern (&adj->attr);
              adj->attr = bgp_attr_intern (attr);
            }
          return;
@@ -355,7 +355,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
 void
 bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
 {
-  bgp_attr_unintern (bai->attr);
+  bgp_attr_unintern (&bai->attr);
   BGP_ADJ_IN_DEL (rn, bai);
   peer_unlock (bai->peer); /* adj_in peer reference */
   XFREE (MTYPE_BGP_ADJ_IN, bai);
index 5a73eeffae8650d503d36a3c3af227d9fdd7ba7c..776c7127e5786228ba49b6bc3b3f27192be68b8a 100644 (file)
@@ -91,13 +91,13 @@ static struct hash *ashash;
 /* Stream for SNMP. See aspath_snmp_pathseg */
 static struct stream *snmp_stream;
 \f
-static inline as_t *
+static as_t *
 assegment_data_new (int num)
 {
   return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
 }
 
-static inline void
+static void
 assegment_data_free (as_t *asdata)
 {
   XFREE (MTYPE_AS_SEG_DATA,asdata);
@@ -340,19 +340,21 @@ aspath_free (struct aspath *aspath)
 
 /* Unintern aspath from AS path bucket. */
 void
-aspath_unintern (struct aspath *aspath)
+aspath_unintern (struct aspath **aspath)
 {
   struct aspath *ret;
+  struct aspath *asp = *aspath;
+  
+  if (asp->refcnt)
+    asp->refcnt--;
 
-  if (aspath->refcnt)
-    aspath->refcnt--;
-
-  if (aspath->refcnt == 0)
+  if (asp->refcnt == 0)
     {
       /* This aspath must exist in aspath hash table. */
-      ret = hash_release (ashash, aspath);
+      ret = hash_release (ashash, asp);
       assert (ret != NULL);
-      aspath_free (aspath);
+      aspath_free (asp);
+      *aspath = NULL;
     }
 }
 
@@ -671,78 +673,78 @@ aspath_hash_alloc (void *arg)
   return aspath;
 }
 
-/* parse as-segment byte stream in struct assegment
- *
- * Returns NULL if the AS_PATH or AS4_PATH is not valid.
- */
-static struct assegment *
-assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
+/* parse as-segment byte stream in struct assegment */
+static int
+assegments_parse (struct stream *s, size_t length, 
+                  struct assegment **result, int use32bit)
 {
   struct assegment_header segh;
   struct assegment *seg, *prev = NULL, *head = NULL;
+  size_t bytes = 0;
   
-  assert (length > 0);  /* does not expect empty AS_PATH or AS4_PATH    */
+  /* empty aspath (ie iBGP or somesuch) */
+  if (length == 0)
+    return 0;
   
   if (BGP_DEBUG (as4, AS4_SEGMENT))
     zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu",
                (unsigned long) length);
-
-  /* double check that length does not exceed stream    */
-  if (STREAM_READABLE(s) < length)
-    return NULL;
+  /* basic checks */
+  if ((STREAM_READABLE(s) < length)
+      || (STREAM_READABLE(s) < AS_HEADER_SIZE) 
+      || (length % AS16_VALUE_SIZE ))
+    return -1;
   
-  /* deal with each segment in turn                             */
-  while (length > 0)
+  while (bytes < length)
     {
       int i;
       size_t seg_size;
       
-      /* softly softly, get the header first on its own */
-      if (length >= AS_HEADER_SIZE)
+      if ((length - bytes) <= AS_HEADER_SIZE)
         {
+          if (head)
+            assegment_free_all (head);
+          return -1;
+        }
+      
+      /* softly softly, get the header first on its own */
       segh.type = stream_getc (s);
       segh.length = stream_getc (s);
       
       seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
-                                      /* includes the header bytes */
 
       if (BGP_DEBUG (as4, AS4_SEGMENT))
        zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d",
                     segh.type, segh.length);
       
-          switch (segh.type)
-          {
-            case AS_SEQUENCE:
-            case AS_SET:
-              break ;
-
-            case AS_CONFED_SEQUENCE:
-            case AS_CONFED_SET:
-              if (!as4_path)
-                break ;
-              /* RFC4893 3: "invalid for the AS4_PATH attribute"            */
-              /* fall through */
-
-            default:    /* reject unknown or invalid AS_PATH segment types  */
-              seg_size = 0 ;
-          } ;
-        }
-      else
-        seg_size = 0 ;
-
-     /* Stop now if segment is not valid (discarding anything collected to date)
-      *
-      * RFC4271 4.3, Path Attributes, b) AS_PATH:
-      *
-      *   "path segment value field contains one or more AS numbers"
+      /* check it.. */
+      if ( ((bytes + seg_size) > length)
+          /* 1771bis 4.3b: seg length contains one or more */
+          || (segh.length == 0) 
+          /* Paranoia in case someone changes type of segment length.
+           * Shift both values by 0x10 to make the comparison operate
+           * on more, than 8 bits (otherwise it's a warning, bug #564).
            */
-      if ((seg_size == 0) || (seg_size > length) || (segh.length == 0))
+          || ((sizeof segh.length > 1) 
+              && (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX)))
         {
+          if (head)
             assegment_free_all (head);
-          return NULL;
+          return -1;
         }
       
-      length -= seg_size ;
+      switch (segh.type)
+        {
+          case AS_SEQUENCE:
+          case AS_SET:
+          case AS_CONFED_SEQUENCE:
+          case AS_CONFED_SET:
+            break;
+          default:
+            if (head)
+              assegment_free_all (head);
+            return -1;
+        }
       
       /* now its safe to trust lengths */
       seg = assegment_new (segh.type, segh.length);
@@ -755,52 +757,47 @@ assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
       for (i = 0; i < segh.length; i++)
        seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s);
 
+      bytes += seg_size;
+      
       if (BGP_DEBUG (as4, AS4_SEGMENT))
-       zlog_debug ("[AS4SEG] Parse aspath segment: length left: %lu",
-                   (unsigned long) length);
+       zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu",
+                   (unsigned long) bytes);
       
       prev = seg;
     }
  
-  return assegment_normalise (head);
+  *result = assegment_normalise (head);
+  return 0;
 }
 
-/* AS path parse function -- parses AS_PATH and AS4_PATH attributes
- *
- * Requires: s        -- stream, currently positioned before first segment
- *                       of AS_PATH or AS4_PATH (ie after attribute header)
- *           length   -- length of the value of the AS_PATH or AS4_PATH
- *           use32bit -- true <=> 4Byte ASN, otherwise 2Byte ASN
- *           as4_path -- true <=> AS4_PATH, otherwise AS_PATH
- *
- * Returns: if valid: address of struct aspath in the hash of known aspaths,
- *                    with reference count incremented.
- *              else: NULL
- *
- * NB: empty AS path (length == 0) is valid.  The returned struct aspath will
- *     have segments == NULL and str == zero length string (unique).
+/* AS path parse function.  pnt is a pointer to byte stream and length
+   is length of byte stream.  If there is same AS path in the the AS
+   path hash then return it else make new AS path structure. 
+   
+   On error NULL is returned.
  */
 struct aspath *
-aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
+aspath_parse (struct stream *s, size_t length, int use32bit)
 {
   struct aspath as;
   struct aspath *find;
 
-  /* Parse each segment and construct normalised list of struct assegment */
-  memset (&as, 0, sizeof (struct aspath));
-  if (length != 0)
-    {
-      as.segments = assegments_parse (s, length, use32bit, as4_path);
+  /* If length is odd it's malformed AS path. */
+  /* Nit-picking: if (use32bit == 0) it is malformed if odd,
+   * otherwise its malformed when length is larger than 2 and (length-2) 
+   * is not dividable by 4.
+   * But... this time we're lazy
+   */
+  if (length % AS16_VALUE_SIZE )
+    return NULL;
 
-      if (as.segments == NULL)
-        return NULL ;   /* Invalid AS_PATH or AS4_PATH  */
-    ;
+  memset (&as, 0, sizeof (struct aspath));
+  if (assegments_parse (s, length, &as.segments, use32bit) < 0)
+    return NULL;
   
   /* If already same aspath exist then return it. */
   find = hash_get (ashash, &as, aspath_hash_alloc);
   
-  assert(find) ;        /* valid aspath, so must find or create */
-  
   /* aspath_hash_alloc dupes segments too. that probably could be
    * optimised out.
    */
@@ -808,12 +805,14 @@ aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
   if (as.str)
     XFREE (MTYPE_AS_STR, as.str);
   
+  if (! find)
+    return NULL;
   find->refcnt++;
 
   return find;
 }
 
-static inline void
+static void
 assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
 {
   int i;
@@ -831,7 +830,7 @@ assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
       }
 }
 
-static inline size_t
+static size_t
 assegment_header_put (struct stream *s, u_char type, int length)
 {
   size_t lenp;
@@ -1631,7 +1630,7 @@ aspath_segment_add (struct aspath *as, int type)
 struct aspath *
 aspath_empty (void)
 {
-  return aspath_parse (NULL, 0, 1, 0); /* 32Bit ;-) not AS4_PATH */
+  return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
 }
 
 struct aspath *
index d63b914c18ff864045d0e9f44c0b608390e809cc..d55f9ce625d9100900651ffb13d544ec8c765c04 100644 (file)
@@ -65,7 +65,7 @@ struct aspath
 /* Prototypes. */
 extern void aspath_init (void);
 extern void aspath_finish (void);
-extern struct aspath *aspath_parse (struct stream *, size_t, int, int);
+extern struct aspath *aspath_parse (struct stream *, size_t, int);
 extern struct aspath *aspath_dup (struct aspath *);
 extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
 extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
@@ -80,7 +80,7 @@ extern struct aspath *aspath_empty_get (void);
 extern struct aspath *aspath_str2aspath (const char *);
 extern void aspath_free (struct aspath *);
 extern struct aspath *aspath_intern (struct aspath *);
-extern void aspath_unintern (struct aspath *);
+extern void aspath_unintern (struct aspath **);
 extern const char *aspath_print (struct aspath *);
 extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
 extern void aspath_print_all_vty (struct vty *);
index 2205e2679ea53203a0e33eddf1d11b4e57014e51..92c1a09f86225797af675e84c435f708b7fae2ea 100644 (file)
@@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "stream.h"
 #include "log.h"
 #include "hash.h"
+#include "jhash.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_attr.h"
@@ -127,18 +128,9 @@ cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
 static unsigned int
 cluster_hash_key_make (void *p)
 {
-  struct cluster_list * cluster = (struct cluster_list *) p;
-  unsigned int key = 0;
-  int length;
-  caddr_t pnt;
+  const struct cluster_list *cluster = p;
 
-  length = cluster->length;
-  pnt = (caddr_t) cluster->list;
-  
-  while (length)
-    key += pnt[--length];
-
-  return key;
+  return jhash(cluster->list, cluster->length, 0);
 }
 
 static int
@@ -194,14 +186,12 @@ cluster_intern (struct cluster_list *cluster)
 void
 cluster_unintern (struct cluster_list *cluster)
 {
-  struct cluster_list *ret;
-
   if (cluster->refcnt)
     cluster->refcnt--;
 
   if (cluster->refcnt == 0)
     {
-      ret = hash_release (cluster_hash, cluster);
+      hash_release (cluster_hash, cluster);
       cluster_free (cluster);
     }
 }
@@ -254,14 +244,12 @@ transit_intern (struct transit *transit)
 void
 transit_unintern (struct transit *transit)
 {
-  struct transit *ret;
-
   if (transit->refcnt)
     transit->refcnt--;
 
   if (transit->refcnt == 0)
     {
-      ret = hash_release (transit_hash, transit);
+      hash_release (transit_hash, transit);
       transit_free (transit);
     }
 }
@@ -269,18 +257,9 @@ transit_unintern (struct transit *transit)
 static unsigned int
 transit_hash_key_make (void *p)
 {
-  struct transit * transit = (struct transit *) p;
-  unsigned int key = 0;
-  int length;
-  caddr_t pnt;
-
-  length = transit->length;
-  pnt = (caddr_t) transit->val;
-  
-  while (length)
-    key += pnt[--length];
+  const struct transit * transit = p;
 
-  return key;
+  return jhash(transit->val, transit->length, 0);
 }
 
 static int
@@ -363,8 +342,14 @@ attr_unknown_count (void)
 unsigned int
 attrhash_key_make (void *p)
 {
-  struct attr * attr = (struct attr *) p;
-  unsigned int key = 0;
+  const struct attr * attr = (struct attr *) p;
+  uint32_t key = 0;
+#define MIX(val)       key = jhash_1word(val, key)
+
+  MIX(attr->origin);
+  MIX(attr->nexthop.s_addr);
+  MIX(attr->med);
+  MIX(attr->local_pref);
 
   key += attr->origin;
   key += attr->nexthop.s_addr;
@@ -373,36 +358,30 @@ attrhash_key_make (void *p)
   
   if (attr->extra)
     {
-      key += attr->extra->aggregator_as;
-      key += attr->extra->aggregator_addr.s_addr;
-      key += attr->extra->weight;
-      key += attr->extra->mp_nexthop_global_in.s_addr;
+      MIX(attr->extra->aggregator_as);
+      MIX(attr->extra->aggregator_addr.s_addr);
+      MIX(attr->extra->weight);
+      MIX(attr->extra->mp_nexthop_global_in.s_addr);
     }
   
   if (attr->aspath)
-    key += aspath_key_make (attr->aspath);
+    MIX(aspath_key_make (attr->aspath));
   if (attr->community)
-    key += community_hash_make (attr->community);
+    MIX(community_hash_make (attr->community));
   
   if (attr->extra)
     {
       if (attr->extra->ecommunity)
-        key += ecommunity_hash_make (attr->extra->ecommunity);
+        MIX(ecommunity_hash_make (attr->extra->ecommunity));
       if (attr->extra->cluster)
-        key += cluster_hash_key_make (attr->extra->cluster);
+        MIX(cluster_hash_key_make (attr->extra->cluster));
       if (attr->extra->transit)
-        key += transit_hash_key_make (attr->extra->transit);
+        MIX(transit_hash_key_make (attr->extra->transit));
 
 #ifdef HAVE_IPV6
-      {
-        int i;
-        
-        key += attr->extra->mp_nexthop_len;
-        for (i = 0; i < 16; i++)
-          key += attr->extra->mp_nexthop_global.s6_addr[i];
-        for (i = 0; i < 16; i++)
-          key += attr->extra->mp_nexthop_local.s6_addr[i];
-      }
+      MIX(attr->extra->mp_nexthop_len);
+      key = jhash(attr->extra->mp_nexthop_global.s6_addr, 16, key);
+      key = jhash(attr->extra->mp_nexthop_local.s6_addr, 16, key);
 #endif /* HAVE_IPV6 */
     }
 
@@ -528,6 +507,7 @@ bgp_attr_intern (struct attr *attr)
             attre->ecommunity = ecommunity_intern (attre->ecommunity);
           else
             attre->ecommunity->refcnt++;
+          
         }
       if (attre->cluster)
         {
@@ -544,10 +524,10 @@ bgp_attr_intern (struct attr *attr)
             attre->transit->refcnt++;
         }
     }
-
+  
   find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
   find->refcnt++;
-
+  
   return find;
 }
 
@@ -579,17 +559,16 @@ bgp_attr_default_intern (u_char origin)
 {
   struct attr attr;
   struct attr *new;
-  struct attr_extra *attre;
   
   memset (&attr, 0, sizeof (struct attr));
-  attre = bgp_attr_extra_get (&attr);
+  bgp_attr_extra_get (&attr);
   
   bgp_attr_default_set(&attr, origin);
 
   new = bgp_attr_intern (&attr);
   bgp_attr_extra_free (&attr);
   
-  aspath_unintern (new->aspath);
+  aspath_unintern (&new->aspath);
   return new;
 }
 
@@ -641,52 +620,68 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
   new = bgp_attr_intern (&attr);
   bgp_attr_extra_free (&attr);
   
-  aspath_unintern (new->aspath);
+  aspath_unintern (&new->aspath);
   return new;
 }
 
+/* Unintern just the sub-components of the attr, but not the attr */
+void
+bgp_attr_unintern_sub (struct attr *attr)
+{
+  /* aspath refcount shoud be decrement. */
+  if (attr->aspath)
+    aspath_unintern (&attr->aspath);
+  UNSET_FLAG(attr->flag, BGP_ATTR_AS_PATH);
+  
+  if (attr->community)
+    community_unintern (&attr->community);
+  UNSET_FLAG(attr->flag, BGP_ATTR_COMMUNITIES);
+  
+  if (attr->extra)
+    {
+      if (attr->extra->ecommunity)
+        ecommunity_unintern (&attr->extra->ecommunity);
+      UNSET_FLAG(attr->flag, BGP_ATTR_EXT_COMMUNITIES);
+      
+      if (attr->extra->cluster)
+        cluster_unintern (attr->extra->cluster);
+      UNSET_FLAG(attr->flag, BGP_ATTR_CLUSTER_LIST);
+      
+      if (attr->extra->transit)
+        transit_unintern (attr->extra->transit);
+    }
+}
+
 /* Free bgp attribute and aspath. */
 void
-bgp_attr_unintern (struct attr *attr)
+bgp_attr_unintern (struct attr **attr)
 {
   struct attr *ret;
-  struct aspath *aspath;
-  struct community *community;
-  struct ecommunity *ecommunity = NULL;
-  struct cluster_list *cluster = NULL;
-  struct transit *transit = NULL;
-
+  struct attr tmp;
+  
   /* Decrement attribute reference. */
-  attr->refcnt--;
-  aspath = attr->aspath;
-  community = attr->community;
-  if (attr->extra)
+  (*attr)->refcnt--;
+  
+  tmp = *(*attr);
+  
+  if ((*attr)->extra)
     {
-      ecommunity = attr->extra->ecommunity;
-      cluster = attr->extra->cluster;
-      transit = attr->extra->transit;
+      tmp.extra = bgp_attr_extra_new ();
+      memcpy (tmp.extra, (*attr)->extra, sizeof (struct attr_extra));
     }
-
+  
   /* If reference becomes zero then free attribute object. */
-  if (attr->refcnt == 0)
+  if ((*attr)->refcnt == 0)
     {    
-      ret = hash_release (attrhash, attr);
+      ret = hash_release (attrhash, *attr);
       assert (ret != NULL);
-      bgp_attr_extra_free (attr);
-      XFREE (MTYPE_ATTR, attr);
+      bgp_attr_extra_free (*attr);
+      XFREE (MTYPE_ATTR, *attr);
+      *attr = NULL;
     }
 
-  /* aspath refcount shoud be decrement. */
-  if (aspath)
-    aspath_unintern (aspath);
-  if (community)
-    community_unintern (community);
-  if (ecommunity)
-    ecommunity_unintern (ecommunity);
-  if (cluster)
-    cluster_unintern (cluster);
-  if (transit)
-    transit_unintern (transit);
+  bgp_attr_unintern_sub (&tmp);
+  bgp_attr_extra_free (&tmp);
 }
 
 void
@@ -699,8 +694,9 @@ bgp_attr_flush (struct attr *attr)
   if (attr->extra)
     {
       struct attr_extra *attre = attr->extra;
+
       if (attre->ecommunity && ! attre->ecommunity->refcnt)
-        ecommunity_free (attre->ecommunity);
+        ecommunity_free (&attre->ecommunity);
       if (attre->cluster && ! attre->cluster->refcnt)
         cluster_free (attre->cluster);
       if (attre->transit && ! attre->transit->refcnt)
@@ -708,6 +704,67 @@ bgp_attr_flush (struct attr *attr)
     }
 }
 
+/* Implement draft-scudder-idr-optional-transitive behaviour and
+ * avoid resetting sessions for malformed attributes which are
+ * are partial/optional and hence where the error likely was not
+ * introduced by the sending neighbour.
+ */
+static bgp_attr_parse_ret_t
+bgp_attr_malformed (struct peer *peer, u_char type, u_char flag,
+                    u_char subcode, u_char *startp, bgp_size_t length)
+{
+  /* Only relax error handling for eBGP peers */
+  if (peer_sort (peer) != BGP_PEER_EBGP)
+    {
+      bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
+                                 startp, length);
+      return BGP_ATTR_PARSE_ERROR;
+
+    }
+  
+  switch (type) {
+    /* where an optional attribute is inconsequential, e.g. it does not affect
+     * route selection, and can be safely ignored then any such attributes
+     * which are malformed should just be ignored and the route processed as
+     * normal.
+     */
+    case BGP_ATTR_AS4_AGGREGATOR:
+    case BGP_ATTR_AGGREGATOR:
+    case BGP_ATTR_ATOMIC_AGGREGATE:
+      return BGP_ATTR_PARSE_PROCEED;
+    
+    /* Core attributes, particularly ones which may influence route
+     * selection should always cause session resets
+     */
+    case BGP_ATTR_ORIGIN:
+    case BGP_ATTR_AS_PATH:
+    case BGP_ATTR_NEXT_HOP:
+    case BGP_ATTR_MULTI_EXIT_DISC:
+    case BGP_ATTR_LOCAL_PREF:
+    case BGP_ATTR_COMMUNITIES:
+    case BGP_ATTR_ORIGINATOR_ID:
+    case BGP_ATTR_CLUSTER_LIST:
+    case BGP_ATTR_MP_REACH_NLRI:
+    case BGP_ATTR_MP_UNREACH_NLRI:
+    case BGP_ATTR_EXT_COMMUNITIES:
+      bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode,
+                                 startp, length);
+      return BGP_ATTR_PARSE_ERROR;
+  }
+  
+  /* Partial optional attributes that are malformed should not cause
+   * the whole session to be reset. Instead treat it as a withdrawal
+   * of the routes, if possible.
+   */
+  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)
+      && CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+      && CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
+    return BGP_ATTR_PARSE_WITHDRAW;
+  
+  /* default to reset */
+  return BGP_ATTR_PARSE_ERROR;
+}
+
 /* Find out what is wrong with the path attribute flag bits and log the error.
    "Flag bits" here stand for Optional, Transitive and Partial, but not for
    Extended Length. Checking O/T/P bits at once implies, that the attribute
@@ -743,7 +800,7 @@ bgp_attr_flags_diagnose
 }
 
 /* Get origin attribute of the update message. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_origin (struct peer *peer, bgp_size_t length, 
                 struct attr *attr, u_char flag, u_char *startp)
 {
@@ -760,8 +817,7 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_ORIGIN, BGP_ATTR_FLAG_TRANS, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
   }
 
   /* If any recognized attribute has Attribute Length that conflicts
@@ -773,10 +829,9 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
     {
       zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
            length);
-      bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, 
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   /* Fetch origin attribute. */
@@ -791,12 +846,9 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
     {
       zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
              attr->origin);
-
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_UPDATE_ERR, 
-                                BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_ORIGIN, flag,
+                                 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
+                                 startp, total);
     }
 
   /* Set oring attribute flag. */
@@ -804,93 +856,72 @@ bgp_attr_origin (struct peer *peer, bgp_size_t length,
 
   return 0;
 }
-/* Parse AS path information.  This function is wrapper of aspath_parse.
- *
- * Parses AS_PATH or AS4_PATH.
- *
- * Returns: if valid: address of struct aspath in the hash of known aspaths,
- *                    with reference count incremented.
- *              else: NULL
- *
- * NB: empty AS path (length == 0) is valid.  The returned struct aspath will
- *     have segments == NULL and str == zero length string (unique).
- */
-static struct aspath *
+
+/* Parse AS path information.  This function is wrapper of
+   aspath_parse. */
+static int
 bgp_attr_aspath (struct peer *peer, bgp_size_t length, 
-                struct attr *attr, u_char flag, u_char *startp, int as4_path)
+                struct attr *attr, u_char flag, u_char *startp)
 {
-  u_char require ;
-  struct aspath *asp ;
   bgp_size_t total;
 
   total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
 
-  /* Check the attribute flags                                          */
-  if (!as4_path && CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
+  /* Flags check. */
+  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL))
     {
       zlog (peer->log, LOG_ERR,
            "AS_PATH attribute must not be flagged as \"partial\" (%u)", flag);
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
                                 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
                                 startp, total);
-      return NULL;
     }
 
-  require = as4_path ? BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
-                     :                          BGP_ATTR_FLAG_TRANS ;
-
-  if ((flag & (BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS)) != require)
+  if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
     {
-      const char* path_type ;
-
-      path_type = as4_path ? "AS4_PATH" : "AS_PATH" ;
-
-      if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
-      zlog (peer->log, LOG_ERR, 
-            "%s attribute flag isn't transitive %d", path_type, flag) ;
-
-      if ((flag & BGP_ATTR_FLAG_OPTIONAL) != (require & BGP_ATTR_FLAG_OPTIONAL))
-        zlog (peer->log, LOG_ERR,
-            "%s attribute flag must %sbe optional %d", path_type,
-            CHECK_FLAG (require, BGP_ATTR_FLAG_OPTIONAL) ? "" : "not ", flag);
-
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_UPDATE_ERR, 
+      zlog (peer->log, LOG_ERR,
+            "AS_PATH attribute must be flagged as \"transitive\" (%u)", flag);
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
                                 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
                                 startp, total);
+    }
+  
+  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
+    {
+      zlog (peer->log, LOG_ERR, 
+            "AS_PATH attribute must not be flagged as \"optional\" (%u)", flag);
+      
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                                 startp, total);
+    }
 
-      return NULL ;
-    } ;
-
-  /* Parse the AS_PATH/AS4_PATH body.
-   *
-   * For AS_PATH  peer with AS4 => 4Byte ASN otherwise 2Byte ASN
-   *     AS4_PATH 4Byte ASN
+  /*
+   * peer with AS4 => will get 4Byte ASnums
+   * otherwise, will get 16 Bit
    */
-  asp = aspath_parse (peer->ibuf, length,
-               as4_path || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV), as4_path) ;
+  attr->aspath = aspath_parse (peer->ibuf, length, 
+                               CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
 
-  if (asp != NULL)
+  /* In case of IBGP, length will be zero. */
+  if (! attr->aspath)
     {
-      attr->flag |= ATTR_FLAG_BIT (as4_path ? BGP_ATTR_AS4_PATH
-                                            : BGP_ATTR_AS_PATH) ;
+      zlog (peer->log, LOG_ERR,
+            "Malformed AS path from %s, length is %d",
+            peer->host, length);
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+                                 NULL, 0);
     }
-  else
-    {
-      zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
 
-      /* TODO: should BGP_NOTIFY_UPDATE_MAL_AS_PATH be sent for AS4_PATH ??  */
-      bgp_notify_send (peer, 
-                      BGP_NOTIFY_UPDATE_ERR, 
-                      BGP_NOTIFY_UPDATE_MAL_AS_PATH);
-    } ;
+  /* Set aspath attribute flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
 
-  return asp ;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
-static int bgp_attr_aspath_check( struct peer *peer, 
-               struct attr *attr)
+static bgp_attr_parse_ret_t
+bgp_attr_aspath_check (struct peer *peer, struct attr *attr, u_char flag)
 {
   /* These checks were part of bgp_attr_aspath, but with
    * as4 we should to check aspath things when
@@ -909,10 +940,9 @@ static int bgp_attr_aspath_check( struct peer *peer,
      (peer_sort (peer) == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
     {
       zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
-      bgp_notify_send (peer, 
-                      BGP_NOTIFY_UPDATE_ERR, 
-                      BGP_NOTIFY_UPDATE_MAL_AS_PATH);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+                                 NULL, 0);
     }
 
   /* First AS check for EBGP. */
@@ -923,10 +953,9 @@ static int bgp_attr_aspath_check( struct peer *peer,
        {
          zlog (peer->log, LOG_ERR,
                "%s incorrect first AS (must be %u)", peer->host, peer->as);
-         bgp_notify_send (peer,
-                          BGP_NOTIFY_UPDATE_ERR,
-                          BGP_NOTIFY_UPDATE_MAL_AS_PATH);
-         return -1;
+          return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+                                     BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+                                     NULL, 0);
        }
     }
 
@@ -936,16 +965,57 @@ static int bgp_attr_aspath_check( struct peer *peer,
     {
       aspath = aspath_dup (attr->aspath);
       aspath = aspath_add_seq (aspath, peer->change_local_as);
-      aspath_unintern (attr->aspath);
+      aspath_unintern (&attr->aspath);
       attr->aspath = aspath_intern (aspath);
     }
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
+}
+
+/* Parse AS4 path information.  This function is another wrapper of
+   aspath_parse. */
+static int
+bgp_attr_as4_path (struct peer *peer, bgp_size_t length,
+                struct attr *attr, u_char flag, u_char *startp,
+                struct aspath **as4_path)
+{
+  bgp_size_t total;
+
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* Flag check. */
+  if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+      || !CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+    {
+      zlog (peer->log, LOG_ERR, 
+           "As4-Path attribute flag isn't optional/transitive %d", flag);
+      return bgp_attr_malformed (peer, BGP_ATTR_AS4_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                                 startp, total);
+    }
+
+  *as4_path = aspath_parse (peer->ibuf, length, 1);
+
+  /* In case of IBGP, length will be zero. */
+  if (!*as4_path)
+    {
+      zlog (peer->log, LOG_ERR,
+            "Malformed AS4 path from %s, length is %d",
+            peer->host, length);
+      return bgp_attr_malformed (peer, BGP_ATTR_AS4_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+                                 NULL, 0);
+    }
 
+  /* Set aspath attribute flag. */
+  if (as4_path)
+    attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
+
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Nexthop attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_nexthop (struct peer *peer, bgp_size_t length, 
                  struct attr *attr, u_char flag, u_char *startp)
 {
@@ -958,8 +1028,7 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_NEXT_HOP, BGP_ATTR_FLAG_TRANS, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
   }
 
   /* Check nexthop attribute length. */
@@ -968,11 +1037,9 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
       zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
              length);
 
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_UPDATE_ERR, 
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
@@ -987,21 +1054,19 @@ bgp_attr_nexthop (struct peer *peer, bgp_size_t length,
       char buf[INET_ADDRSTRLEN];
       inet_ntop (AF_INET, &nexthop_h, buf, INET_ADDRSTRLEN);
       zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf);
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
-                                BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_NEXT_HOP, flag,
+                                 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
+                                 startp, total);
     }
 
   attr->nexthop.s_addr = nexthop_n;
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* MED atrribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_med (struct peer *peer, bgp_size_t length, 
              struct attr *attr, u_char flag, u_char *startp)
 {
@@ -1013,8 +1078,9 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_MULTI_EXIT_DISC, BGP_ATTR_FLAG_OPTIONAL, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_MULTI_EXIT_DISC, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
 
   /* Length check. */
@@ -1022,23 +1088,21 @@ bgp_attr_med (struct peer *peer, bgp_size_t length,
     {
       zlog (peer->log, LOG_ERR, 
            "MED attribute length isn't four [%d]", length);
-      
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_UPDATE_ERR, 
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+
+      return bgp_attr_malformed (peer, BGP_ATTR_MULTI_EXIT_DISC, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   attr->med = stream_getl (peer->ibuf);
 
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Local preference attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_local_pref (struct peer *peer, bgp_size_t length, 
                     struct attr *attr, u_char flag, u_char *startp)
 {
@@ -1049,18 +1113,17 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_LOCAL_PREF, BGP_ATTR_FLAG_TRANS, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_LOCAL_PREF, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
   /* Length check. */
   if (length != 4)
   {
     zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]", length);
-    bgp_notify_send_with_data (peer,
-                               BGP_NOTIFY_UPDATE_ERR,
+    return bgp_attr_malformed (peer, BGP_ATTR_LOCAL_PREF, flag,
                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
                                startp, total);
-    return -1;
   }
 
   /* If it is contained in an UPDATE message that is received from an
@@ -1069,7 +1132,7 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
   if (peer_sort (peer) == BGP_PEER_EBGP)
     {
       stream_forward_getp (peer->ibuf, length);
-      return 0;
+      return BGP_ATTR_PARSE_PROCEED;
     }
 
   attr->local_pref = stream_getl (peer->ibuf);
@@ -1077,7 +1140,7 @@ bgp_attr_local_pref (struct peer *peer, bgp_size_t length,
   /* Set atomic aggregate flag. */
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Atomic aggregate. */
@@ -1092,25 +1155,24 @@ bgp_attr_atomic (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_TRANS)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_ATOMIC_AGGREGATE, BGP_ATTR_FLAG_TRANS, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_ATOMIC_AGGREGATE, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
 
   /* Length check. */
   if (length != 0)
     {
       zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length);
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_ATOMIC_AGGREGATE, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   /* Set atomic aggregate flag. */
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Aggregator attribute */
@@ -1128,34 +1190,28 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
   {
     zlog (peer->log, LOG_ERR,
           "AGGREGATOR attribute must be flagged as \"optional\" (%u)", flag);
-    bgp_notify_send_with_data (peer,
-                               BGP_NOTIFY_UPDATE_ERR,
+    return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
                                BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
                                startp, total);
-    return -1;
   }
   if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
   {
     zlog (peer->log, LOG_ERR,
           "AGGREGATOR attribute must be flagged as \"transitive\" (%u)", flag);
-    bgp_notify_send_with_data (peer,
-                               BGP_NOTIFY_UPDATE_ERR,
+    return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
                                BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
                                startp, total);
-    return -1;
   }
   /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
-  if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
+  if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
     wantedlen = 8;
   
   if (length != wantedlen)
     {
       zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]", wantedlen, length);
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_AGGREGATOR, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
   
   if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
@@ -1167,36 +1223,35 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
   /* Set atomic aggregate flag. */
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* New Aggregator attribute */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_as4_aggregator (struct peer *peer, bgp_size_t length,
-                    struct attr *attr, as_t *as4_aggregator_as,
+                    struct attr *attr, u_char flag, 
+                    as_t *as4_aggregator_as,
                     struct in_addr *as4_aggregator_addr)
 {
   if (length != 8)
     {
       zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", length);
-
-      bgp_notify_send (peer,
-                      BGP_NOTIFY_UPDATE_ERR,
-                      BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_AS4_AGGREGATOR, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 NULL, 0);
     }
   *as4_aggregator_as = stream_getl (peer->ibuf);
   as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf);
 
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
  */
-static int
-bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
+static bgp_attr_parse_ret_t
+bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr, u_char flag,
                           struct aspath *as4_path, as_t as4_aggregator,
                           struct in_addr *as4_aggregator_addr)
 {
@@ -1204,7 +1259,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
   struct aspath *newpath;
   struct attr_extra *attre = attr->extra;
     
-  if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
+  if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV))
     {
       /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
        * if given.
@@ -1222,11 +1277,11 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
                         peer->host, "AS4 capable peer, yet it sent");
         }
       
-      return 0;
+      return BGP_ATTR_PARSE_PROCEED;
     }
   
-  if (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))
-      && !(attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH))))
+  if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH))
+      && !(attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))))
     {
       /* Hu? This is not supposed to happen at all!
        * got as4_path and no aspath,
@@ -1238,10 +1293,9 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
       zlog (peer->log, LOG_ERR, 
             "%s BGP not AS4 capable peer sent AS4_PATH but"
             " no AS_PATH, cant do anything here", peer->host);
-      bgp_notify_send (peer, 
-                       BGP_NOTIFY_UPDATE_ERR, 
-                       BGP_NOTIFY_UPDATE_MAL_ATTR);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_AS_PATH, flag,
+                                 BGP_NOTIFY_UPDATE_MAL_ATTR,
+                                 NULL, 0);
     }
 
   /* We have a asn16 peer.  First, look for AS4_AGGREGATOR
@@ -1249,7 +1303,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
    */
   if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
     {
-      if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
+      if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
         {
           assert (attre);
           
@@ -1265,7 +1319,7 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
            *        Aggregating node and the AS_PATH is to be
            *        constructed "as in all other cases"
            */
-          if ( attre->aggregator_as != BGP_AS_TRANS )
+          if (attre->aggregator_as != BGP_AS_TRANS)
             {
               /* ignore */
               if ( BGP_DEBUG(as4, AS4))
@@ -1300,24 +1354,27 @@ bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
     }
 
   /* need to reconcile NEW_AS_PATH and AS_PATH */
-  if ( !ignore_as4_path && (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))) )
+  if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH))))
     {
        newpath = aspath_reconcile_as4 (attr->aspath, as4_path);
-       aspath_unintern (attr->aspath);
+       aspath_unintern (&attr->aspath);
        attr->aspath = aspath_intern (newpath);
     }
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Community attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_community (struct peer *peer, bgp_size_t length, 
-                   struct attr *attr, u_char flag)
+                   struct attr *attr, u_char flag, u_char *startp)
 {
+  bgp_size_t total
+    = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+  
   if (length == 0)
     {
       attr->community = NULL;
-      return 0;
+      return BGP_ATTR_PARSE_PROCEED;
     }
   
   attr->community =
@@ -1327,15 +1384,17 @@ bgp_attr_community (struct peer *peer, bgp_size_t length,
   stream_forward_getp (peer->ibuf, length);
 
   if (!attr->community)
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_COMMUNITIES, flag,
+                               BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                               startp, total);
   
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Originator ID attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_originator_id (struct peer *peer, bgp_size_t length, 
                        struct attr *attr, u_char flag, u_char *startp)
 {
@@ -1346,19 +1405,18 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_ORIGINATOR_ID, BGP_ATTR_FLAG_OPTIONAL, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_ORIGINATOR_ID, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
   /* Length check. */
   if (length != 4)
     {
       zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
 
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_ORIGINATOR_ID, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   (bgp_attr_extra_get (attr))->originator_id.s_addr 
@@ -1366,11 +1424,11 @@ bgp_attr_originator_id (struct peer *peer, bgp_size_t length,
 
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Cluster list attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_cluster_list (struct peer *peer, bgp_size_t length, 
                       struct attr *attr, u_char flag, u_char *startp)
 {
@@ -1381,29 +1439,29 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_CLUSTER_LIST, BGP_ATTR_FLAG_OPTIONAL, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_CLUSTER_LIST, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
   /* Check length. */
   if (length % 4)
     {
       zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
 
-      bgp_notify_send_with_data (peer,
-                                BGP_NOTIFY_UPDATE_ERR,
-                                BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, BGP_ATTR_CLUSTER_LIST, flag,
+                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                 startp, total);
     }
 
   (bgp_attr_extra_get (attr))->cluster 
     = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length);
-
-  stream_forward_getp (peer->ibuf, length);;
+  
+  /* XXX: Fix cluster_parse to use stream API and then remove this */
+  stream_forward_getp (peer->ibuf, length);
 
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Multiprotocol reachability information parse. */
@@ -1425,8 +1483,9 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_MP_REACH_NLRI, BGP_ATTR_FLAG_OPTIONAL, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_MP_REACH_NLRI, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
   /* Set end of packet. */
   s = BGP_INPUT(peer);
@@ -1439,7 +1498,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
     {
       zlog_info ("%s: %s sent invalid length, %lu", 
                 __func__, peer->host, (unsigned long)length);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
   
   /* Load AFI, SAFI. */
@@ -1453,7 +1512,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
     {
       zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute", 
                 __func__, peer->host, attre->mp_nexthop_len);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
   
   /* Nexthop length check. */
@@ -1466,14 +1525,9 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
         memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4);
       break;
     case 12:
-      {
-       u_int32_t rd_high;
-       u_int32_t rd_low;
-
-       rd_high = stream_getl (s);
-       rd_low = stream_getl (s);
-       stream_get (&attre->mp_nexthop_global_in, s, 4);
-      }
+      stream_getl (s); /* RD high */
+      stream_getl (s); /* RD low */
+      stream_get (&attre->mp_nexthop_global_in, s, 4);
       break;
 #ifdef HAVE_IPV6
     case 16:
@@ -1501,14 +1555,14 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
     default:
       zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d", 
                 __func__, peer->host, attre->mp_nexthop_len);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
 
   if (!LEN_LEFT)
     {
       zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)",
                  __func__, peer->host);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
   
   {
@@ -1524,7 +1578,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
     {
       zlog_info ("%s: (%s) Failed to read NLRI",
                  __func__, peer->host);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
  
   if (safi != SAFI_MPLS_LABELED_VPN)
@@ -1534,7 +1588,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
         {
           zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
                      __func__, peer->host);
-         return -1;
+         return BGP_ATTR_PARSE_ERROR;
        }
     }
 
@@ -1545,7 +1599,7 @@ bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length,
 
   stream_forward_getp (s, nlri_len);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 #undef LEN_LEFT
 }
 
@@ -1567,15 +1621,16 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
   if ((flag & ~BGP_ATTR_FLAG_EXTLEN) != BGP_ATTR_FLAG_OPTIONAL)
   {
     bgp_attr_flags_diagnose (peer, BGP_ATTR_MP_UNREACH_NLRI, BGP_ATTR_FLAG_OPTIONAL, flag);
-    bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total);
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_MP_UNREACH_NLRI, flag,
+                               BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+                               startp, total);
   }
 
   s = peer->ibuf;
   
 #define BGP_MP_UNREACH_MIN_SIZE 3
   if ((length > STREAM_READABLE(s)) || (length <  BGP_MP_UNREACH_MIN_SIZE))
-    return -1;
+    return BGP_ATTR_PARSE_ERROR;
   
   afi = stream_getw (s);
   safi = stream_getc (s);
@@ -1586,7 +1641,7 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
     {
       ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
       if (ret < 0)
-       return -1;
+       return BGP_ATTR_PARSE_ERROR;
     }
 
   mp_withdraw->afi = afi;
@@ -1596,20 +1651,23 @@ bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length,
 
   stream_forward_getp (s, withdraw_len);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Extended Community attribute. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_ext_communities (struct peer *peer, bgp_size_t length, 
-                         struct attr *attr, u_char flag)
+                         struct attr *attr, u_char flag, u_char *startp)
 {
+  bgp_size_t total
+    = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+  
   if (length == 0)
     {
       if (attr->extra)
         attr->extra->ecommunity = NULL;
       /* Empty extcomm doesn't seem to be invalid per se */
-      return 0;
+      return BGP_ATTR_PARSE_PROCEED;
     }
 
   (bgp_attr_extra_get (attr))->ecommunity =
@@ -1618,15 +1676,17 @@ bgp_attr_ext_communities (struct peer *peer, bgp_size_t length,
   stream_forward_getp (peer->ibuf, length);
   
   if (!attr->extra->ecommunity)
-    return -1;
+    return bgp_attr_malformed (peer, BGP_ATTR_EXT_COMMUNITIES,
+                               flag, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                               startp, total);
   
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* BGP unknown attribute treatment. */
-static int
+static bgp_attr_parse_ret_t
 bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
                  u_char type, bgp_size_t length, u_char *startp)
 {
@@ -1652,20 +1712,17 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
      then the Error Subcode is set to Unrecognized Well-known
      Attribute.  The Data field contains the unrecognized attribute
      (type, length and value). */
-  if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
+  if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
     {
-      /* Adjust startp to do not include flag value. */
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_UPDATE_ERR, 
-                                BGP_NOTIFY_UPDATE_UNREC_ATTR,
-                                startp, total);
-      return -1;
+      return bgp_attr_malformed (peer, type, flag,
+                                 BGP_NOTIFY_UPDATE_UNREC_ATTR,
+                                 startp, total);
     }
 
   /* Unrecognized non-transitive optional attributes must be quietly
      ignored and not passed along to other BGP peers. */
   if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
-    return 0;
+    return BGP_ATTR_PARSE_PROCEED;
 
   /* If a path with recognized transitive optional attribute is
      accepted and passed along to other BGP peers and the Partial bit
@@ -1688,17 +1745,17 @@ bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
   memcpy (transit->val + transit->length, startp, total);
   transit->length += total;
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Read attribute of update packet.  This function is called from
    bgp_update() in bgpd.c.  */
-int
+bgp_attr_parse_ret_t
 bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
                struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
 {
   int ret;
-  u_char flag;
+  u_char flag = 0;
   u_char type = 0;
   bgp_size_t length;
   u_char *startp, *endp;
@@ -1715,7 +1772,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
 
   /* End pointer of BGP attribute. */
   endp = BGP_INPUT_PNT (peer) + size;
-
+  
   /* Get attributes to the end of attribute length. */
   while (BGP_INPUT_PNT (peer) < endp)
     {
@@ -1731,7 +1788,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          bgp_notify_send (peer, 
                           BGP_NOTIFY_UPDATE_ERR, 
                           BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-         return -1;
+         return BGP_ATTR_PARSE_ERROR;
        }
 
       /* Fetch attribute flag and type. */
@@ -1754,7 +1811,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          bgp_notify_send (peer, 
                           BGP_NOTIFY_UPDATE_ERR, 
                           BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-         return -1;
+         return BGP_ATTR_PARSE_ERROR;
        }
 
       /* Check extended attribue length bit. */
@@ -1776,7 +1833,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          bgp_notify_send (peer, 
                           BGP_NOTIFY_UPDATE_ERR, 
                           BGP_NOTIFY_UPDATE_MAL_ATTR);
-         return -1;
+         return BGP_ATTR_PARSE_ERROR;
        }
 
       /* Set type to bitmap to check duplicate attribute.  `type' is
@@ -1794,7 +1851,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          bgp_notify_send (peer, 
                           BGP_NOTIFY_UPDATE_ERR, 
                           BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-         return -1;
+         return BGP_ATTR_PARSE_ERROR;
        }
 
       /* OK check attribute and store it's value. */
@@ -1804,12 +1861,10 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          ret = bgp_attr_origin (peer, length, attr, flag, startp);
          break;
        case BGP_ATTR_AS_PATH:
-          attr->aspath = bgp_attr_aspath (peer, length, attr, flag, startp, 0);
-          ret = attr->aspath ? 0 : -1 ;
+         ret = bgp_attr_aspath (peer, length, attr, flag, startp);
          break;
        case BGP_ATTR_AS4_PATH:
-          as4_path = bgp_attr_aspath (peer, length, attr, flag, startp, 1);
-          ret = as4_path  ? 0 : -1 ;
+         ret = bgp_attr_as4_path (peer, length, attr, flag, startp, &as4_path);
          break;
        case BGP_ATTR_NEXT_HOP: 
          ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
@@ -1827,10 +1882,12 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          ret = bgp_attr_aggregator (peer, length, attr, flag, startp);
          break;
        case BGP_ATTR_AS4_AGGREGATOR:
-         ret = bgp_attr_as4_aggregator (peer, length, attr, &as4_aggregator, &as4_aggregator_addr);
+         ret = bgp_attr_as4_aggregator (peer, length, attr, flag,
+                                        &as4_aggregator, 
+                                        &as4_aggregator_addr);
          break;
        case BGP_ATTR_COMMUNITIES:
-         ret = bgp_attr_community (peer, length, attr, flag);
+         ret = bgp_attr_community (peer, length, attr, flag, startp);
          break;
        case BGP_ATTR_ORIGINATOR_ID:
          ret = bgp_attr_originator_id (peer, length, attr, flag, startp);
@@ -1845,26 +1902,39 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          ret = bgp_mp_unreach_parse (peer, length, flag, startp, mp_withdraw);
          break;
        case BGP_ATTR_EXT_COMMUNITIES:
-         ret = bgp_attr_ext_communities (peer, length, attr, flag);
+         ret = bgp_attr_ext_communities (peer, length, attr, flag, startp);
          break;
        default:
          ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
          break;
        }
-
-      /* If error occured immediately return to the caller. */
-      if (ret < 0)
+      
+      /* If hard error occured immediately return to the caller. */
+      if (ret == BGP_ATTR_PARSE_ERROR)
         {
           zlog (peer->log, LOG_WARNING,
                 "%s: Attribute %s, parse error", 
                 peer->host, 
                 LOOKUP (attr_str, type));
-           bgp_notify_send (peer, 
-                            BGP_NOTIFY_UPDATE_ERR,
-                            BGP_NOTIFY_UPDATE_MAL_ATTR);
-           return ret;
+          bgp_notify_send (peer, 
+                           BGP_NOTIFY_UPDATE_ERR,
+                           BGP_NOTIFY_UPDATE_MAL_ATTR);
+          if (as4_path)
+            aspath_unintern (&as4_path);
+          return ret;
         }
-
+      if (ret == BGP_ATTR_PARSE_WITHDRAW)
+        {
+          
+          zlog (peer->log, LOG_WARNING,
+                "%s: Attribute %s, parse error - treating as withdrawal",
+                peer->host,
+                LOOKUP (attr_str, type));
+          if (as4_path)
+            aspath_unintern (&as4_path);
+          return ret;
+        }
+      
       /* Check the fetched length. */
       if (BGP_INPUT_PNT (peer) != attr_endp)
        {
@@ -1874,7 +1944,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
          bgp_notify_send (peer, 
                           BGP_NOTIFY_UPDATE_ERR, 
                           BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-         return -1;
+          if (as4_path)
+            aspath_unintern (&as4_path);
+         return BGP_ATTR_PARSE_ERROR;
        }
     }
 
@@ -1887,7 +1959,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
       bgp_notify_send (peer, 
                       BGP_NOTIFY_UPDATE_ERR, 
                       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
-      return -1;
+      if (as4_path)
+        aspath_unintern (&as4_path);
+      return BGP_ATTR_PARSE_ERROR;
     }
 
   /* 
@@ -1901,19 +1975,22 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
    * all attributes first, including these 32bit ones, and now,
    * afterwards, we look what and if something is to be done for as4.
    */
-  if (bgp_attr_munge_as4_attrs (peer, attr, as4_path,
+  if (bgp_attr_munge_as4_attrs (peer, attr, flag, as4_path,
                                 as4_aggregator, &as4_aggregator_addr))
-    return -1;
+    {
+      if (as4_path)
+        aspath_unintern (&as4_path);
+      return BGP_ATTR_PARSE_ERROR;
+    }
 
   /* At this stage, we have done all fiddling with as4, and the
    * resulting info is in attr->aggregator resp. attr->aspath
    * so we can chuck as4_aggregator and as4_path alltogether in
    * order to save memory
    */
-  if ( as4_path )
+  if (as4_path)
     {
-      aspath_unintern( as4_path ); /* unintern - it is in the hash */
-      as4_path = NULL;
+      aspath_unintern (&as4_path); /* unintern - it is in the hash */
       /* The flag that we got this is still there, but that does not
        * do any trouble
        */
@@ -1928,10 +2005,10 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
    * Finally do the checks on the aspath we did not do yet
    * because we waited for a potentially synthesized aspath.
    */
-  if ( attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH)))
+  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
     {
-      ret = bgp_attr_aspath_check( peer, attr );
-      if ( ret < 0 )
+      ret = bgp_attr_aspath_check (peer, attr, flag);
+      if (ret != BGP_ATTR_PARSE_PROCEED)
        return ret;
     }
 
@@ -1939,7 +2016,7 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
   if (attr->extra && attr->extra->transit)
     attr->extra->transit = transit_intern (attr->extra->transit);
 
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 
 /* Well-known attribute check. */
@@ -1970,9 +2047,9 @@ bgp_attr_check (struct peer *peer, struct attr *attr)
                                 BGP_NOTIFY_UPDATE_ERR, 
                                 BGP_NOTIFY_UPDATE_MISS_ATTR,
                                 &type, 1);
-      return -1;
+      return BGP_ATTR_PARSE_ERROR;
     }
-  return 0;
+  return BGP_ATTR_PARSE_PROCEED;
 }
 \f
 int stream_put_prefix (struct stream *, struct prefix *);
index 4cb706784d107fa79c8d72d6f3085b8b9939235d..e6300740cf5f1b5fa0c0dae0ca704d43fb61d869 100644 (file)
@@ -132,17 +132,25 @@ struct transit
 
 #define ATTR_FLAG_BIT(X)  (1 << ((X) - 1))
 
+typedef enum {
+ BGP_ATTR_PARSE_PROCEED = 0,
+ BGP_ATTR_PARSE_ERROR = -1,
+ BGP_ATTR_PARSE_WITHDRAW = -2,
+} bgp_attr_parse_ret_t;
+
 /* Prototypes. */
 extern void bgp_attr_init (void);
 extern void bgp_attr_finish (void);
-extern int bgp_attr_parse (struct peer *, struct attr *, bgp_size_t,
-                   struct bgp_nlri *, struct bgp_nlri *);
+extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
+                                           bgp_size_t, struct bgp_nlri *,
+                                           struct bgp_nlri *);
 extern int bgp_attr_check (struct peer *, struct attr *);
 extern struct attr_extra *bgp_attr_extra_get (struct attr *);
 extern void bgp_attr_extra_free (struct attr *);
 extern void bgp_attr_dup (struct attr *, struct attr *);
 extern struct attr *bgp_attr_intern (struct attr *attr);
-extern void bgp_attr_unintern (struct attr *);
+extern void bgp_attr_unintern_sub (struct attr *);
+extern void bgp_attr_unintern (struct attr **);
 extern void bgp_attr_flush (struct attr *);
 extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
 extern struct attr *bgp_attr_default_intern (u_char);
index d6601674677ba843cd434dc50cde93bb090bc7a0..6c9976e3b8469eeab4e0aeb930910026e8b84ecd 100644 (file)
@@ -70,7 +70,7 @@ community_entry_free (struct community_entry *entry)
       if (entry->config)
         XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
       if (entry->u.ecom)
-        ecommunity_free (entry->u.ecom);
+        ecommunity_free (&entry->u.ecom);
       break;
     case COMMUNITY_LIST_EXPANDED:
     case EXTCOMMUNITY_LIST_EXPANDED:
@@ -806,7 +806,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
     entry = community_list_entry_lookup (list, str, direct);
 
   if (ecom)
-    ecommunity_free (ecom);
+    ecommunity_free (&ecom);
   if (regex)
     bgp_regex_free (regex);
 
index ae1d7a15579e541dea02c8546dc4d821fb5470e8..2ba45f6e4e8b65ffb26f989db6bdc8bc7e2fbc42 100644 (file)
@@ -321,21 +321,22 @@ community_intern (struct community *com)
 
 /* Free community attribute. */
 void
-community_unintern (struct community *com)
+community_unintern (struct community **com)
 {
   struct community *ret;
 
-  if (com->refcnt)
-    com->refcnt--;
+  if ((*com)->refcnt)
+    (*com)->refcnt--;
 
   /* Pull off from hash.  */
-  if (com->refcnt == 0)
+  if ((*com)->refcnt == 0)
     {
       /* Community value com must exist in hash. */
-      ret = (struct community *) hash_release (comhash, com);
+      ret = (struct community *) hash_release (comhash, *com);
       assert (ret != NULL);
 
-      community_free (com);
+      community_free (*com);
+      *com = NULL;
     }
 }
 
index bc1e56eff1e1592c45b935875efd94cc23800519..9e483770e9ea7c185c6672f95a60117f083c7af4 100644 (file)
@@ -57,7 +57,7 @@ extern void community_free (struct community *);
 extern struct community *community_uniq_sort (struct community *);
 extern struct community *community_parse (u_int32_t *, u_short);
 extern struct community *community_intern (struct community *);
-extern void community_unintern (struct community *);
+extern void community_unintern (struct community **);
 extern char *community_str (struct community *);
 extern unsigned int community_hash_make (struct community *);
 extern struct community *community_str2com (const char *);
index e7eb0a07f7a112adbf63a6cbabd161476df99946..440c15a4054c91fff1d52f1a7d892cc5712206a0 100644 (file)
@@ -42,13 +42,14 @@ ecommunity_new (void)
 
 /* Allocate ecommunities.  */
 void
-ecommunity_free (struct ecommunity *ecom)
+ecommunity_free (struct ecommunity **ecom)
 {
-  if (ecom->val)
-    XFREE (MTYPE_ECOMMUNITY_VAL, ecom->val);
-  if (ecom->str)
-    XFREE (MTYPE_ECOMMUNITY_STR, ecom->str);
-  XFREE (MTYPE_ECOMMUNITY, ecom);
+  if ((*ecom)->val)
+    XFREE (MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
+  if ((*ecom)->str)
+    XFREE (MTYPE_ECOMMUNITY_STR, (*ecom)->str);
+  XFREE (MTYPE_ECOMMUNITY, *ecom);
+  ecom = NULL;
 }
 
 /* Add a new Extended Communities value to Extended Communities
@@ -197,7 +198,7 @@ ecommunity_intern (struct ecommunity *ecom)
   find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
 
   if (find != ecom)
-    ecommunity_free (ecom);
+    ecommunity_free (&ecom);
 
   find->refcnt++;
 
@@ -209,18 +210,18 @@ ecommunity_intern (struct ecommunity *ecom)
 
 /* Unintern Extended Communities Attribute.  */
 void
-ecommunity_unintern (struct ecommunity *ecom)
+ecommunity_unintern (struct ecommunity **ecom)
 {
   struct ecommunity *ret;
 
-  if (ecom->refcnt)
-    ecom->refcnt--;
-
+  if ((*ecom)->refcnt)
+    (*ecom)->refcnt--;
+    
   /* Pull off from hash.  */
-  if (ecom->refcnt == 0)
+  if ((*ecom)->refcnt == 0)
     {
       /* Extended community must be in the hash.  */
-      ret = (struct ecommunity *) hash_release (ecomhash, ecom);
+      ret = (struct ecommunity *) hash_release (ecomhash, *ecom);
       assert (ret != NULL);
 
       ecommunity_free (ecom);
@@ -516,7 +517,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
          if (! keyword_included || keyword)
            {
              if (ecom)
-               ecommunity_free (ecom);
+               ecommunity_free (&ecom);
              return NULL;
            }
          keyword = 1;
@@ -536,7 +537,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
              if (! keyword)
                {
                  if (ecom)
-                   ecommunity_free (ecom);
+                   ecommunity_free (&ecom);
                  return NULL;
                }
              keyword = 0;
@@ -549,7 +550,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
        case ecommunity_token_unknown:
        default:
          if (ecom)
-           ecommunity_free (ecom);
+           ecommunity_free (&ecom);
          return NULL;
        }
     }
index 942fdc73305f546c51bc5ee528b89c929d8d3ba9..2f59dc4098a7f6f24f06b809f883287002e50577 100644 (file)
@@ -67,13 +67,13 @@ struct ecommunity_val
 
 extern void ecommunity_init (void);
 extern void ecommunity_finish (void);
-extern void ecommunity_free (struct ecommunity *);
+extern void ecommunity_free (struct ecommunity **);
 extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
 extern struct ecommunity *ecommunity_dup (struct ecommunity *);
 extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
 extern struct ecommunity *ecommunity_intern (struct ecommunity *);
 extern int ecommunity_cmp (const void *, const void *);
-extern void ecommunity_unintern (struct ecommunity *);
+extern void ecommunity_unintern (struct ecommunity **);
 extern unsigned int ecommunity_hash_make (void *);
 extern struct ecommunity *ecommunity_str2com (const char *, int, int);
 extern char *ecommunity_ecom2str (struct ecommunity *, int);
index f835fe771ed3f0b787b2ce464d736ecf816c0538..8dede587104f99e0dcb06c3597ccff7b530b5568 100644 (file)
@@ -247,7 +247,15 @@ bgp_exit (int status)
   if (retain_mode)
     if_add_hook (IF_DELETE_HOOK, NULL);
   for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
-    if_delete (ifp);
+    {
+      struct listnode *c_node, *c_nnode;
+      struct connected *c;
+
+      for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
+        bgp_connected_delete (c);
+
+      if_delete (ifp);
+    }
   list_free (iflist);
 
   /* reverse bgp_attr_init */
index b5c4c602b58a905fd5c4272407994bd38bb328e8..a7dca531327fb63acfc52b52d02e5d5b0d324bef 100644 (file)
@@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "command.h"
 #include "privs.h"
 #include "linklist.h"
+#include "network.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_fsm.h"
@@ -150,6 +151,7 @@ bgp_accept (struct thread *thread)
       zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
       return -1;
     }
+  set_nonblocking (bgp_sock);
 
   if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
@@ -172,8 +174,11 @@ bgp_accept (struct thread *thread)
     }
 
   /* In case of peer is EBGP, we should set TTL for this connection.  */
-  if (peer_sort (peer1) == BGP_PEER_EBGP)
+  if (peer_sort (peer1) == BGP_PEER_EBGP) {
     sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
+    if (peer1->gtsm_hops)
+      sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops);
+  }
 
   /* Make dummy peer until read Open packet. */
   if (BGP_DEBUG (events, EVENTS))
@@ -302,8 +307,11 @@ bgp_connect (struct peer *peer)
     return -1;
 
   /* If we can get socket for the peer, adjest TTL and make connection. */
-  if (peer_sort (peer) == BGP_PEER_EBGP)
+  if (peer_sort (peer) == BGP_PEER_EBGP) {
     sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+    if (peer->gtsm_hops)
+      sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
+  }
 
   sockopt_reuseaddr (peer->fd);
   sockopt_reuseport (peer->fd);
@@ -455,7 +463,10 @@ bgp_socket (unsigned short port, const char *address)
          zlog_err ("socket: %s", safe_strerror (errno));
          continue;
        }
-
+       
+      /* if we intend to implement ttl-security, this socket needs ttl=255 */
+      sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
+      
       ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
       if (ret == 0)
        ++count;
@@ -488,6 +499,9 @@ bgp_socket (unsigned short port, const char *address)
       return sock;
     }
 
+  /* if we intend to implement ttl-security, this socket needs ttl=255 */
+  sockopt_ttl (AF_INET, sock, MAXTTL);
+
   memset (&sin, 0, sizeof (struct sockaddr_in));
   sin.sin_family = AF_INET;
   sin.sin_port = htons (port);
index f8d1adecf1e8e64cb2d0e4b562d980bb648d2472..e9c78b3f0cb42e58f63323a237cea649e07d0008 100644 (file)
@@ -264,6 +264,8 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
 
                  if (bnc->metric != oldbnc->metric)
                    bnc->metricchanged = 1;
+
+                  bgp_unlock_node (oldrn);
                }
            }
        }
@@ -340,6 +342,8 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
 
                  if (bnc->metric != oldbnc->metric)
                    bnc->metricchanged = 1;
+
+                  bgp_unlock_node (oldrn);
                }
            }
        }
@@ -541,7 +545,7 @@ bgp_connected_add (struct connected *ifc)
        }
       else
        {
-         bc = XCALLOC (0, sizeof (struct bgp_connected_ref));
+         bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
          bc->refcnt = 1;
          rn->info = bc;
        }
@@ -566,7 +570,7 @@ bgp_connected_add (struct connected *ifc)
        }
       else
        {
-         bc = XCALLOC (0, sizeof (struct bgp_connected_ref));
+         bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
          bc->refcnt = 1;
          rn->info = bc;
        }
@@ -606,7 +610,7 @@ bgp_connected_delete (struct connected *ifc)
       bc->refcnt--;
       if (bc->refcnt == 0)
        {
-         XFREE (0, bc);
+         XFREE (MTYPE_BGP_CONN, bc);
          rn->info = NULL;
        }
       bgp_unlock_node (rn);
@@ -632,7 +636,7 @@ bgp_connected_delete (struct connected *ifc)
       bc->refcnt--;
       if (bc->refcnt == 0)
        {
-         XFREE (0, bc);
+         XFREE (MTYPE_BGP_CONN, bc);
          rn->info = NULL;
        }
       bgp_unlock_node (rn);
@@ -1101,11 +1105,15 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
   rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
   if (! rn1)
     return 0;
+  bgp_unlock_node (rn1);
   
   rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
   if (! rn2)
     return 0;
+  bgp_unlock_node (rn2);
 
+  /* This is safe, even with above unlocks, since we are just
+     comparing pointers to the objects, not the objects themselves. */
   if (rn1 == rn2)
     return 1;
 
@@ -1330,6 +1338,9 @@ bgp_scan_init (void)
 void
 bgp_scan_finish (void)
 {
+  /* Only the current one needs to be reset. */
+  bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
+
   bgp_table_unlock (cache1_table[AFI_IP]);
   cache1_table[AFI_IP] = NULL;
 
@@ -1340,6 +1351,9 @@ bgp_scan_finish (void)
   bgp_connected_table[AFI_IP] = NULL;
 
 #ifdef HAVE_IPV6
+  /* Only the current one needs to be reset. */
+  bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
+
   bgp_table_unlock (cache1_table[AFI_IP6]);
   cache1_table[AFI_IP6] = NULL;
 
index fc653e2176502e15f735c833d63df8a60d10b2b0..f5a74d1b7778bd0874246a13e91671dbaf24fba4 100644 (file)
@@ -206,7 +206,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
 
       /* Synchnorize attribute.  */
       if (adj->attr)
-       bgp_attr_unintern (adj->attr);
+       bgp_attr_unintern (&adj->attr);
       else
        peer->scount[afi][safi]++;
 
@@ -598,7 +598,6 @@ bgp_write (struct thread *thread)
   struct stream *s; 
   int num;
   unsigned int count = 0;
-  int write_errno;
 
   /* Yes first of all get peer pointer. */
   peer = THREAD_ARG (thread);
@@ -611,46 +610,37 @@ bgp_write (struct thread *thread)
       return 0;
     }
 
-    /* Nonblocking write until TCP output buffer is full.  */
-  while (1)
+  s = bgp_write_packet (peer);
+  if (!s)
+    return 0;  /* nothing to send */
+
+  sockopt_cork (peer->fd, 1);
+
+  /* Nonblocking write until TCP output buffer is full.  */
+  do
     {
       int writenum;
-      int val;
-
-      s = bgp_write_packet (peer);
-      if (! s)
-       return 0;
-      
-      /* XXX: FIXME, the socket should be NONBLOCK from the start
-       * status shouldnt need to be toggled on each write
-       */
-      val = fcntl (peer->fd, F_GETFL, 0);
-      fcntl (peer->fd, F_SETFL, val|O_NONBLOCK);
 
       /* Number of bytes to be sent.  */
       writenum = stream_get_endp (s) - stream_get_getp (s);
 
       /* Call write() system call.  */
       num = write (peer->fd, STREAM_PNT (s), writenum);
-      write_errno = errno;
-      fcntl (peer->fd, F_SETFL, val);
-      if (num <= 0)
+      if (num < 0)
        {
-         /* Partial write. */
-         if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)
-             break;
+         /* write failed either retry needed or error */
+         if (ERRNO_IO_RETRY(errno))
+               break;
 
-         BGP_EVENT_ADD (peer, TCP_fatal_error);
+          BGP_EVENT_ADD (peer, TCP_fatal_error);
          return 0;
        }
+
       if (num != writenum)
        {
+         /* Partial write */
          stream_forward_getp (s, num);
-
-         if (write_errno == EAGAIN)
-           break;
-
-         continue;
+         break;
        }
 
       /* Retrieve BGP packet type. */
@@ -691,13 +681,14 @@ bgp_write (struct thread *thread)
 
       /* OK we send packet so delete it. */
       bgp_packet_delete (peer);
-
-      if (++count >= BGP_WRITE_PACKET_MAX)
-       break;
     }
+  while (++count < BGP_WRITE_PACKET_MAX &&
+        (s = bgp_write_packet (peer)) != NULL);
   
   if (bgp_write_proceed (peer))
     BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+  else
+    sockopt_cork (peer->fd, 0);
   
   return 0;
 }
@@ -706,7 +697,7 @@ bgp_write (struct thread *thread)
 static int
 bgp_write_notify (struct peer *peer)
 {
-  int ret;
+  int ret, val;
   u_char type;
   struct stream *s; 
 
@@ -716,7 +707,10 @@ bgp_write_notify (struct peer *peer)
     return 0;
   assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
 
-  /* I'm not sure fd is writable. */
+  /* Put socket in blocking mode. */
+  val = fcntl (peer->fd, F_GETFL, 0);
+  fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK);
+
   ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
   if (ret <= 0)
     {
@@ -1602,26 +1596,47 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
                       BGP_NOTIFY_UPDATE_MAL_ATTR);
       return -1;
     }
+  
+  /* Certain attribute parsing errors should not be considered bad enough
+   * to reset the session for, most particularly any partial/optional
+   * attributes that have 'tunneled' over speakers that don't understand
+   * them. Instead we withdraw only the prefix concerned.
+   * 
+   * Complicates the flow a little though..
+   */
+  bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
+  /* This define morphs the update case into a withdraw when lower levels
+   * have signalled an error condition where this is best.
+   */
+#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
 
   /* Parse attribute when it exists. */
   if (attribute_len)
     {
-      ret = bgp_attr_parse (peer, &attr, attribute_len, 
+      attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len, 
                            &mp_update, &mp_withdraw);
-      if (ret < 0)
+      if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
        return -1;
     }
-
+  
   /* Logging the attribute. */
-  if (BGP_DEBUG (update, UPDATE_IN))
+  if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
+      || BGP_DEBUG (update, UPDATE_IN))
     {
       ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
+      int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+                 ? LOG_ERR : LOG_DEBUG;
+      
+      if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+        zlog (peer->log, LOG_ERR,
+              "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
+              peer->host);
 
       if (ret)
-       zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE w/ attr: %s",
+       zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
              peer->host, attrstr);
     }
-
+  
   /* Network Layer Reachability Information. */
   update_len = end - stream_pnt (s);
 
@@ -1630,7 +1645,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
       /* Check NLRI packet format and prefix length. */
       ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
       if (ret < 0)
-       return -1;
+        {
+          bgp_attr_unintern_sub (&attr);
+          if (attr.extra)
+            bgp_attr_extra_free (&attr);
+         return -1;
+       }
 
       /* Set NLRI portion to structure. */
       update.afi = AFI_IP;
@@ -1653,15 +1673,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
             update. */
          ret = bgp_attr_check (peer, &attr);
          if (ret < 0)
-           return -1;
+           {
+             bgp_attr_unintern_sub (&attr);
+              if (attr.extra)
+                bgp_attr_extra_free (&attr);
+             return -1;
+            }
 
-         bgp_nlri_parse (peer, &attr, &update);
+         bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
        }
 
       if (mp_update.length
          && mp_update.afi == AFI_IP 
          && mp_update.safi == SAFI_UNICAST)
-       bgp_nlri_parse (peer, &attr, &mp_update);
+       bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
 
       if (mp_withdraw.length
          && mp_withdraw.afi == AFI_IP 
@@ -1688,7 +1713,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
       if (mp_update.length
          && mp_update.afi == AFI_IP 
          && mp_update.safi == SAFI_MULTICAST)
-       bgp_nlri_parse (peer, &attr, &mp_update);
+       bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
 
       if (mp_withdraw.length
          && mp_withdraw.afi == AFI_IP 
@@ -1718,7 +1743,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
       if (mp_update.length 
          && mp_update.afi == AFI_IP6 
          && mp_update.safi == SAFI_UNICAST)
-       bgp_nlri_parse (peer, &attr, &mp_update);
+       bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
 
       if (mp_withdraw.length 
          && mp_withdraw.afi == AFI_IP6 
@@ -1747,7 +1772,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
       if (mp_update.length 
          && mp_update.afi == AFI_IP6 
          && mp_update.safi == SAFI_MULTICAST)
-       bgp_nlri_parse (peer, &attr, &mp_update);
+       bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
 
       if (mp_withdraw.length 
          && mp_withdraw.afi == AFI_IP6 
@@ -1775,7 +1800,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
       if (mp_update.length 
          && mp_update.afi == AFI_IP 
          && mp_update.safi == SAFI_MPLS_LABELED_VPN)
-       bgp_nlri_parse_vpnv4 (peer, &attr, &mp_update);
+       bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
 
       if (mp_withdraw.length 
          && mp_withdraw.afi == AFI_IP 
@@ -1797,21 +1822,10 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
 
   /* Everything is done.  We unintern temporary structures which
      interned in bgp_attr_parse(). */
-  if (attr.aspath)
-    aspath_unintern (attr.aspath);
-  if (attr.community)
-    community_unintern (attr.community);
+  bgp_attr_unintern_sub (&attr);
   if (attr.extra)
-    {
-      if (attr.extra->ecommunity)
-        ecommunity_unintern (attr.extra->ecommunity);
-      if (attr.extra->cluster)
-        cluster_unintern (attr.extra->cluster);
-      if (attr.extra->transit)
-        transit_unintern (attr.extra->transit);
-      bgp_attr_extra_free (&attr);
-    }
-
+    bgp_attr_extra_free (&attr);
+  
   /* If peering is stopped due to some reason, do not generate BGP
      event.  */
   if (peer->status != Established)
@@ -2028,7 +2042,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
                    * as possible without going beyond the bounds of the entry,
                    * to maximise debug information.
                    */
-                 int ok ;
+                 int ok;
                  memset (&orfp, 0, sizeof (struct orf_prefix));
                  common = *p_pnt++;
                  /* after ++: p_pnt <= p_end */
@@ -2042,9 +2056,9 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
                  ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
                  if (ok)
                    {
-                 memcpy (&seq, p_pnt, sizeof (u_int32_t));
-                 p_pnt += sizeof (u_int32_t);
-                 orfp.seq = ntohl (seq);
+                     memcpy (&seq, p_pnt, sizeof (u_int32_t));
+                      p_pnt += sizeof (u_int32_t);
+                      orfp.seq = ntohl (seq);
                    }
                  else
                    p_pnt = p_end ;
@@ -2082,16 +2096,17 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
                               inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, BUFSIZ),
                               orfp.p.prefixlen, orfp.ge, orfp.le,
                               ok ? "" : " MALFORMED");
-
+                  
                  if (ok)
-                 ret = prefix_bgp_orf_set (name, afi, &orfp,
-                                (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
-                                (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
+                   ret = prefix_bgp_orf_set (name, afi, &orfp,
+                                  (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
+                                  (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
 
                  if (!ok || (ret != CMD_SUCCESS))
                    {
                      if (BGP_DEBUG (normal, NORMAL))
-                       zlog_debug ("%s Received misformatted prefixlist ORF. Remove All pfxlist", peer->host);
+                       zlog_debug ("%s Received misformatted prefixlist ORF."
+                                   " Remove All pfxlist", peer->host);
                      prefix_bgp_orf_remove_all (name);
                      break;
                    }
@@ -2276,12 +2291,13 @@ bgp_read_packet (struct peer *peer)
     return 0;
 
   /* Read packet from fd. */
-  nbytes = stream_read_unblock (peer->ibuf, peer->fd, readsize);
+  nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
 
   /* If read byte is smaller than zero then error occured. */
   if (nbytes < 0) 
     {
-      if (errno == EAGAIN)
+      /* Transient error should retry */
+      if (nbytes == -2)
        return -1;
 
       plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
index 189929a0ddfba4452507d8cc6e133ddb9c410f8c..68d05484798221cd6c37283175439fc03f1d1681 100644 (file)
@@ -137,7 +137,7 @@ static void
 bgp_info_free (struct bgp_info *binfo)
 {
   if (binfo->attr)
-    bgp_attr_unintern (binfo->attr);
+    bgp_attr_unintern (&binfo->attr);
   
   bgp_info_extra_free (&binfo->extra);
 
@@ -1069,11 +1069,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
   struct bgp_filter *filter;
   struct bgp_info info;
   struct peer *from;
-  struct bgp *bgp;
 
   from = ri->peer;
   filter = &rsclient->filter[afi][safi];
-  bgp = rsclient->bgp;
 
   if (DISABLE_BGP_ANNOUNCE)
     return 0;
@@ -1568,14 +1566,13 @@ bgp_process_queue_init (void)
     }
   
   bm->process_main_queue->spec.workfunc = &bgp_process_main;
-  bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
   bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
-  bm->process_rsclient_queue->spec.del_item_data
-    =  bm->process_main_queue->spec.del_item_data;
-  bm->process_main_queue->spec.max_retries
-    = bm->process_main_queue->spec.max_retries = 0;
-  bm->process_rsclient_queue->spec.hold
-    = bm->process_main_queue->spec.hold = 50;
+  bm->process_main_queue->spec.max_retries = 0;
+  bm->process_main_queue->spec.hold = 50;
+  
+  memcpy (bm->process_rsclient_queue, bm->process_main_queue,
+          sizeof (struct work_queue *));
+  bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
 }
 
 void
@@ -1803,14 +1800,14 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
   /* Apply import policy. */
   if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
     {
-      bgp_attr_unintern (attr_new2);
+      bgp_attr_unintern (&attr_new2);
 
       reason = "import-policy;";
       goto filtered;
     }
 
   attr_new = bgp_attr_intern (&new_attr);
-  bgp_attr_unintern (attr_new2);
+  bgp_attr_unintern (&attr_new2);
 
   /* IPv4 unicast next hop check.  */
   if (afi == AFI_IP && safi == SAFI_UNICAST)
@@ -1819,7 +1816,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
       if (new_attr.nexthop.s_addr == 0
          || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
        {
-         bgp_attr_unintern (attr_new);
+         bgp_attr_unintern (&attr_new);
 
          reason = "martian next-hop;";
          goto filtered;
@@ -1849,7 +1846,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
                     p->prefixlen, rsclient->host);
 
           bgp_unlock_node (rn);
-          bgp_attr_unintern (attr_new);
+          bgp_attr_unintern (&attr_new);
 
           return;
         }
@@ -1869,7 +1866,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
       bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
 
       /* Update to new attribute.  */
-      bgp_attr_unintern (ri->attr);
+      bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
 
       /* Update MPLS tag.  */
@@ -2129,7 +2126,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
            }
 
          bgp_unlock_node (rn);
-         bgp_attr_unintern (attr_new);
+         bgp_attr_unintern (&attr_new);
          bgp_attr_extra_free (&new_attr);
          
          return 0;
@@ -2176,7 +2173,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
        }
        
       /* Update to new attribute.  */
-      bgp_attr_unintern (ri->attr);
+      bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
 
       /* Update MPLS tag.  */
@@ -2468,7 +2465,7 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
     }
   
   bgp_attr_extra_free (&attr);
-  aspath_unintern (aspath);
+  aspath_unintern (&aspath);
 }
 \f
 static void
@@ -3216,7 +3213,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
           bgp_attr_flush (&attr_tmp);
 
           /* Unintern original. */
-          aspath_unintern (attr.aspath);
+          aspath_unintern (&attr.aspath);
           bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
           bgp_attr_extra_free (&attr);
           
@@ -3227,7 +3224,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
   else
     attr_new = bgp_attr_intern (&attr);
   
-  new_attr = *attr_new;
+  bgp_attr_dup(&new_attr, attr_new);
   
   SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
 
@@ -3243,8 +3240,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
 
       bgp->peer_self->rmap_type = 0;
 
-      bgp_attr_unintern (attr_new);
-      aspath_unintern (attr.aspath);
+      bgp_attr_unintern (&attr_new);
+      aspath_unintern (&attr.aspath);
       bgp_attr_extra_free (&attr);
 
       bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
@@ -3254,8 +3251,9 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
 
   bgp->peer_self->rmap_type = 0;
 
-  bgp_attr_unintern (attr_new);
+  bgp_attr_unintern (&attr_new);
   attr_new = bgp_attr_intern (&new_attr);
+  bgp_attr_extra_free (&new_attr);
 
   for (ri = rn->info; ri; ri = ri->next)
     if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
@@ -3268,8 +3266,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
          !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
         {
           bgp_unlock_node (rn);
-          bgp_attr_unintern (attr_new);
-          aspath_unintern (attr.aspath);
+          bgp_attr_unintern (&attr_new);
+          aspath_unintern (&attr.aspath);
           bgp_attr_extra_free (&attr);
           return;
        }
@@ -3281,14 +3279,14 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
           /* Rewrite BGP route information. */
          if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
            bgp_info_restore(rn, ri);
-          bgp_attr_unintern (ri->attr);
+          bgp_attr_unintern (&ri->attr);
           ri->attr = attr_new;
           ri->uptime = bgp_clock ();
 
           /* Process change. */
           bgp_process (bgp, rn, afi, safi);
           bgp_unlock_node (rn);
-          aspath_unintern (attr.aspath);
+          aspath_unintern (&attr.aspath);
           bgp_attr_extra_free (&attr);
           return;
         }
@@ -3313,7 +3311,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
   bgp_process (bgp, rn, afi, safi);
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
   bgp_attr_extra_free (&attr);
 }
 
@@ -3363,7 +3361,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
          bgp_attr_flush (&attr_tmp);
 
          /* Unintern original. */
-         aspath_unintern (attr.aspath);
+         aspath_unintern (&attr.aspath);
          bgp_attr_extra_free (&attr);
          bgp_static_withdraw (bgp, p, afi, safi);
          return;
@@ -3384,8 +3382,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
          !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
        {
          bgp_unlock_node (rn);
-         bgp_attr_unintern (attr_new);
-         aspath_unintern (attr.aspath);
+         bgp_attr_unintern (&attr_new);
+         aspath_unintern (&attr.aspath);
          bgp_attr_extra_free (&attr);
          return;
        }
@@ -3399,7 +3397,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
            bgp_info_restore(rn, ri);
          else
            bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-         bgp_attr_unintern (ri->attr);
+         bgp_attr_unintern (&ri->attr);
          ri->attr = attr_new;
          ri->uptime = bgp_clock ();
 
@@ -3407,7 +3405,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
          bgp_aggregate_increment (bgp, p, ri, afi, safi);
          bgp_process (bgp, rn, afi, safi);
          bgp_unlock_node (rn);
-         aspath_unintern (attr.aspath);
+         aspath_unintern (&attr.aspath);
          bgp_attr_extra_free (&attr);
          return;
        }
@@ -3435,7 +3433,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
   bgp_process (bgp, rn, afi, safi);
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
   bgp_attr_extra_free (&attr);
 }
 
@@ -4806,9 +4804,8 @@ bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
 #define AGGREGATE_AS_SET       1
 
 static int
-bgp_aggregate_set (struct vty *vty, const char *prefix_str, 
-                   afi_t afi, safi_t safi,
-                  u_char summary_only, u_char as_set)
+bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
+                     afi_t afi, safi_t safi)
 {
   int ret;
   struct prefix p;
@@ -4829,34 +4826,33 @@ bgp_aggregate_set (struct vty *vty, const char *prefix_str,
   bgp = vty->index;
 
   /* Old configuration check. */
-  rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
-
-  if (rn->info)
+  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
+  if (! rn)
     {
-      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
-      bgp_unlock_node (rn);
+      vty_out (vty, "%% There is no aggregate-address configuration.%s",
+               VTY_NEWLINE);
       return CMD_WARNING;
     }
 
-  /* Make aggregate address structure. */
-  aggregate = bgp_aggregate_new ();
-  aggregate->summary_only = summary_only;
-  aggregate->as_set = as_set;
-  aggregate->safi = safi;
-  rn->info = aggregate;
+  aggregate = rn->info;
+  if (aggregate->safi & SAFI_UNICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (aggregate->safi & SAFI_MULTICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
 
-  /* Aggregate address insert into BGP routing table. */
-  if (safi & SAFI_UNICAST)
-    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
-  if (safi & SAFI_MULTICAST)
-    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+  /* Unlock aggregate address configuration. */
+  rn->info = NULL;
+  bgp_aggregate_free (aggregate);
+  bgp_unlock_node (rn);
+  bgp_unlock_node (rn);
 
   return CMD_SUCCESS;
 }
 
 static int
-bgp_aggregate_unset (struct vty *vty, const char *prefix_str, 
-                     afi_t afi, safi_t safi)
+bgp_aggregate_set (struct vty *vty, const char *prefix_str,
+                   afi_t afi, safi_t safi,
+                  u_char summary_only, u_char as_set)
 {
   int ret;
   struct prefix p;
@@ -4877,25 +4873,33 @@ bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
   bgp = vty->index;
 
   /* Old configuration check. */
-  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
-  if (! rn)
+  rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
+
+  if (rn->info)
     {
-      vty_out (vty, "%% There is no aggregate-address configuration.%s",
-              VTY_NEWLINE);
-      return CMD_WARNING;
+      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
+      /* try to remove the old entry */
+      ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
+      if (ret)
+        {
+          vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
+         bgp_unlock_node (rn);
+         return CMD_WARNING;
+        }
     }
 
-  aggregate = rn->info;
-  if (aggregate->safi & SAFI_UNICAST)
-    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
-  if (aggregate->safi & SAFI_MULTICAST)
-    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+  /* Make aggregate address structure. */
+  aggregate = bgp_aggregate_new ();
+  aggregate->summary_only = summary_only;
+  aggregate->as_set = as_set;
+  aggregate->safi = safi;
+  rn->info = aggregate;
 
-  /* Unlock aggregate address configuration. */
-  rn->info = NULL;
-  bgp_aggregate_free (aggregate);
-  bgp_unlock_node (rn);
-  bgp_unlock_node (rn);
+  /* Aggregate address insert into BGP routing table. */
+  if (safi & SAFI_UNICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (safi & SAFI_MULTICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
 
   return CMD_SUCCESS;
 }
@@ -5303,7 +5307,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
                  bgp_attr_extra_free (&attr_new);
                  
                  /* Unintern original. */
-                 aspath_unintern (attr.aspath);
+                 aspath_unintern (&attr.aspath);
                  bgp_attr_extra_free (&attr);
                  bgp_redistribute_delete (p, type);
                  return;
@@ -5326,8 +5330,8 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
              if (attrhash_cmp (bi->attr, new_attr) &&
                  !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
                {
-                 bgp_attr_unintern (new_attr);
-                 aspath_unintern (attr.aspath);
+                 bgp_attr_unintern (&new_attr);
+                 aspath_unintern (&attr.aspath);
                  bgp_attr_extra_free (&attr);
                  bgp_unlock_node (bn);
                  return;
@@ -5342,7 +5346,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
                    bgp_info_restore(bn, bi);
                  else
                    bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
-                 bgp_attr_unintern (bi->attr);
+                 bgp_attr_unintern (&bi->attr);
                  bi->attr = new_attr;
                  bi->uptime = bgp_clock ();
  
@@ -5350,7 +5354,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
                  bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
                  bgp_process (bgp, bn, afi, SAFI_UNICAST);
                  bgp_unlock_node (bn);
-                 aspath_unintern (attr.aspath);
+                 aspath_unintern (&attr.aspath);
                  bgp_attr_extra_free (&attr);
                  return;
                } 
@@ -5372,7 +5376,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
     }
 
   /* Unintern original. */
-  aspath_unintern (attr.aspath);
+  aspath_unintern (&attr.aspath);
   bgp_attr_extra_free (&attr);
 }
 
@@ -6381,7 +6385,10 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
               if ((rm = bgp_node_match (table, &match)) != NULL)
                 {
                   if (prefix_check && rm->p.prefixlen != match.prefixlen)
-                    continue;
+                    {
+                      bgp_unlock_node (rm);
+                      continue;
+                    }
 
                   for (ri = rm->info; ri; ri = ri->next)
                     {
@@ -6395,6 +6402,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                       display++;
                       route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
                     }
+
+                  bgp_unlock_node (rm);
                 }
             }
         }
@@ -6418,6 +6427,8 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                   route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
                 }
             }
+
+          bgp_unlock_node (rn);
         }
     }
 
@@ -6490,6 +6501,15 @@ DEFUN (show_ip_bgp_ipv4,
   return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
 }
 
+ALIAS (show_ip_bgp_ipv4,
+       show_bgp_ipv4_safi_cmd,
+       "show bgp ipv4 (unicast|multicast)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+
 DEFUN (show_ip_bgp_route,
        show_ip_bgp_route_cmd,
        "show ip bgp A.B.C.D",
@@ -6518,6 +6538,16 @@ DEFUN (show_ip_bgp_ipv4_route,
   return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
 }
 
+ALIAS (show_ip_bgp_ipv4_route,
+       show_bgp_ipv4_safi_route_cmd,
+       "show bgp ipv4 (unicast|multicast) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_ip_bgp_vpnv4_all_route,
        show_ip_bgp_vpnv4_all_route_cmd,
        "show ip bgp vpnv4 all A.B.C.D",
@@ -6582,6 +6612,16 @@ DEFUN (show_ip_bgp_ipv4_prefix,
   return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
 }
 
+ALIAS (show_ip_bgp_ipv4_prefix,
+       show_bgp_ipv4_safi_prefix_cmd,
+       "show bgp ipv4 (unicast|multicast) A.B.C.D/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+
 DEFUN (show_ip_bgp_vpnv4_all_prefix,
        show_ip_bgp_vpnv4_all_prefix_cmd,
        "show ip bgp vpnv4 all A.B.C.D/M",
@@ -6684,6 +6724,22 @@ ALIAS (show_bgp,
        BGP_STR
        "Address family\n")
 
+DEFUN (show_bgp_ipv6_safi,
+       show_bgp_ipv6_safi_cmd,
+       "show bgp ipv6 (unicast|multicast)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal,
+                     NULL);
+
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp,
        show_ipv6_bgp_cmd,
@@ -6714,6 +6770,22 @@ ALIAS (show_bgp_route,
        "Address family\n"
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_ipv6_safi_route,
+       show_bgp_ipv6_safi_route_cmd,
+       "show bgp ipv6 (unicast|multicast) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Network in the BGP routing table to display\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp_route,
        show_ipv6_bgp_route_cmd,
@@ -6744,6 +6816,22 @@ ALIAS (show_bgp_prefix,
        "Address family\n"
        "IPv6 prefix <network>/<length>\n")
 
+DEFUN (show_bgp_ipv6_safi_prefix,
+       show_bgp_ipv6_safi_prefix_cmd,
+       "show bgp ipv6 (unicast|multicast) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp_prefix,
        show_ipv6_bgp_prefix_cmd,
@@ -7448,15 +7536,36 @@ DEFUN (show_ipv6_mbgp_community_all,
 #endif /* HAVE_IPV6 */
 \f
 static int
-bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
-                    afi_t afi, safi_t safi)
+bgp_show_community (struct vty *vty, const char *view_name, int argc,
+                   const char **argv, int exact, afi_t afi, safi_t safi)
 {
   struct community *com;
   struct buffer *b;
+  struct bgp *bgp;
   int i;
   char *str;
   int first = 0;
 
+  /* BGP structure lookup */
+  if (view_name)
+    {
+      bgp = bgp_lookup_by_name (view_name);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
   b = buffer_new (1024);
   for (i = 0; i < argc; i++)
     {
@@ -7484,7 +7593,7 @@ bgp_show_community (struct vty *vty, int argc, const char **argv, int exact,
       return CMD_WARNING;
     }
 
-  return bgp_show (vty, NULL, afi, safi,
+  return bgp_show (vty, bgp, afi, safi,
                    (exact ? bgp_show_type_community_exact :
                            bgp_show_type_community), com);
 }
@@ -7501,7 +7610,7 @@ DEFUN (show_ip_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_community,
@@ -7580,9 +7689,9 @@ DEFUN (show_ip_bgp_ipv4_community,
        "Do not export to next AS (well-known community)\n")
 {
   if (strncmp (argv[0], "m", 1) == 0)
-    return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
+    return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
  
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_ipv4_community,
@@ -7654,28 +7763,101 @@ ALIAS (show_ip_bgp_ipv4_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 
-DEFUN (show_ip_bgp_community_exact,
-       show_ip_bgp_community_exact_cmd,
-       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+DEFUN (show_bgp_view_afi_safi_community_all,
+       show_bgp_view_afi_safi_community_all_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes containing communities\n")
+{
+  int afi;
+  int safi;
+  struct bgp *bgp;
+
+  /* BGP structure lookup. */
+  bgp = bgp_lookup_by_name (argv[0]);
+  if (bgp == NULL)
+    {
+      vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+#endif
+  return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL);
+}
+
+DEFUN (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+#endif
        SHOW_STR
-       IP_STR
        BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
        "Display routes matching the communities\n"
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
        "Do not advertise to any peer (well-known community)\n"
-       "Do not export to next AS (well-known community)\n"
-       "Exact match of the communities")
+       "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+  int afi;
+  int safi;
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi);
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi);
+#endif
 }
 
-ALIAS (show_ip_bgp_community_exact,
-       show_ip_bgp_community2_exact_cmd,
-       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community2_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
        SHOW_STR
-       IP_STR
        BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
        "Display routes matching the communities\n"
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
@@ -7684,15 +7866,25 @@ ALIAS (show_ip_bgp_community_exact,
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
        "Do not advertise to any peer (well-known community)\n"
-       "Do not export to next AS (well-known community)\n"
-       "Exact match of the communities")
+       "Do not export to next AS (well-known community)\n")
 
-ALIAS (show_ip_bgp_community_exact,
-       show_ip_bgp_community3_exact_cmd,
-       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community3_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
        SHOW_STR
-       IP_STR
        BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
        "Display routes matching the communities\n"
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
@@ -7705,15 +7897,25 @@ ALIAS (show_ip_bgp_community_exact,
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
        "Do not advertise to any peer (well-known community)\n"
-       "Do not export to next AS (well-known community)\n"
-       "Exact match of the communities")
+       "Do not export to next AS (well-known community)\n")
 
-ALIAS (show_ip_bgp_community_exact,
-       show_ip_bgp_community4_exact_cmd,
-       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+ALIAS (show_bgp_view_afi_safi_community,
+       show_bgp_view_afi_safi_community4_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+#endif
        SHOW_STR
-       IP_STR
        BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
        "Display routes matching the communities\n"
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
@@ -7730,12 +7932,90 @@ ALIAS (show_ip_bgp_community_exact,
        "community number\n"
        "Do not send outside local AS (well-known community)\n"
        "Do not advertise to any peer (well-known community)\n"
-       "Do not export to next AS (well-known community)\n"
-       "Exact match of the communities")
+       "Do not export to next AS (well-known community)\n")
 
-DEFUN (show_ip_bgp_ipv4_community_exact,
-       show_ip_bgp_ipv4_community_exact_cmd,
-       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+DEFUN (show_ip_bgp_community_exact,
+       show_ip_bgp_community_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+}
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community2_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community3_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community4_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+DEFUN (show_ip_bgp_ipv4_community_exact,
+       show_ip_bgp_ipv4_community_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) exact-match",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -7750,9 +8030,9 @@ DEFUN (show_ip_bgp_ipv4_community_exact,
        "Exact match of the communities")
 {
   if (strncmp (argv[0], "m", 1) == 0)
-    return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
+    return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
  
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
 }
 
 ALIAS (show_ip_bgp_ipv4_community_exact,
@@ -7839,7 +8119,7 @@ DEFUN (show_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
 }
 
 ALIAS (show_bgp_community,
@@ -7984,7 +8264,7 @@ DEFUN (show_ipv6_bgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
 }
 
 /* old command */
@@ -8062,7 +8342,7 @@ DEFUN (show_bgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
 }
 
 ALIAS (show_bgp_community_exact,
@@ -8215,7 +8495,7 @@ DEFUN (show_ipv6_bgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
 }
 
 /* old command */
@@ -8297,7 +8577,7 @@ DEFUN (show_ipv6_mbgp_community,
        "Do not advertise to any peer (well-known community)\n"
        "Do not export to next AS (well-known community)\n")
 {
-  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
 }
 
 /* old command */
@@ -8377,7 +8657,7 @@ DEFUN (show_ipv6_mbgp_community_exact,
        "Do not export to next AS (well-known community)\n"
        "Exact match of the communities")
 {
-  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
+  return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
 }
 
 /* old command */
@@ -9777,6 +10057,56 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
   return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1);
 }
 
+DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes,
+       show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd,
+#ifdef HAVE_IPV6
+       "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#else
+       "show bgp view WORD ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)",
+#endif
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+#ifdef HAVE_IPV6
+       "Address family\n"
+#endif
+       "Address family modifier\n"
+       "Address family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the advertised routes to neighbor\n"
+       "Display the received routes from neighbor\n")
+{
+  int afi;
+  int safi;
+  int in;
+  struct peer *peer;
+
+#ifdef HAVE_IPV6
+    peer = peer_lookup_in_view (vty, argv[0], argv[3]);
+#else
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+#endif
+
+  if (! peer)
+    return CMD_WARNING;
+
+#ifdef HAVE_IPV6
+  afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
+  safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0;
+#else
+  afi = AFI_IP;
+  safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  in = (strncmp (argv[3], "r", 1) == 0) ? 1 : 0;
+#endif
+
+  return peer_adj_routes (vty, peer, afi, safi, in);
+}
+
 DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
        show_ip_bgp_neighbor_received_prefix_filter_cmd,
        "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
@@ -10184,6 +10514,65 @@ ALIAS (show_ip_bgp_view_rsclient,
        "Information about Route Server Client\n"
        NEIGHBOR_ADDR_STR)
 
+DEFUN (show_bgp_view_ipv4_safi_rsclient,
+       show_bgp_view_ipv4_safi_rsclient_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+{
+  struct bgp_table *table;
+  struct peer *peer;
+  safi_t safi;
+
+  if (argc == 3) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  table = peer->rib[AFI_IP][safi];
+
+  return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient,
+       show_bgp_ipv4_safi_rsclient_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+
 DEFUN (show_ip_bgp_view_rsclient_route,
        show_ip_bgp_view_rsclient_route_cmd,
        "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
@@ -10257,6 +10646,87 @@ ALIAS (show_ip_bgp_view_rsclient_route,
        NEIGHBOR_ADDR_STR
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_view_ipv4_safi_rsclient_route,
+       show_bgp_view_ipv4_safi_rsclient_route_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient_route,
+       show_bgp_ipv4_safi_rsclient_route_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_ip_bgp_view_rsclient_prefix,
        show_ip_bgp_view_rsclient_prefix_cmd,
        "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
@@ -10330,6 +10800,86 @@ ALIAS (show_ip_bgp_view_rsclient_prefix,
        NEIGHBOR_ADDR_STR
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
 
+DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix,
+       show_bgp_view_ipv4_safi_rsclient_prefix_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+{
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+    return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP, safi, NULL, 1);
+}
+
+ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix,
+       show_bgp_ipv4_safi_rsclient_prefix_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
 
 #ifdef HAVE_IPV6
 DEFUN (show_bgp_view_neighbor_routes,
@@ -10596,6 +11146,65 @@ ALIAS (show_bgp_view_rsclient,
        "Information about Route Server Client\n"
        NEIGHBOR_ADDR_STR)
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient,
+       show_bgp_view_ipv6_safi_rsclient_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+{
+  struct bgp_table *table;
+  struct peer *peer;
+  safi_t safi;
+
+  if (argc == 3) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  table = peer->rib[AFI_IP6][safi];
+
+  return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient,
+       show_bgp_ipv6_safi_rsclient_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR)
+
 DEFUN (show_bgp_view_rsclient_route,
        show_bgp_view_rsclient_route_cmd,
        "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
@@ -10667,6 +11276,87 @@ ALIAS (show_bgp_view_rsclient_route,
        NEIGHBOR_ADDR_STR
        "Network in the BGP routing table to display\n")
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient_route,
+       show_bgp_view_ipv6_safi_rsclient_route_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+    {
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP6, safi, NULL, 0);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_route,
+       show_bgp_ipv6_safi_rsclient_route_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "Network in the BGP routing table to display\n")
+
 DEFUN (show_bgp_view_rsclient_prefix,
        show_bgp_view_rsclient_prefix_cmd,
        "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
@@ -10738,6 +11428,87 @@ ALIAS (show_bgp_view_rsclient_prefix,
        NEIGHBOR_ADDR_STR
        "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
 
+DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix,
+       show_bgp_view_ipv6_safi_rsclient_prefix_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  safi_t safi;
+
+  /* BGP structure lookup. */
+  if (argc == 4)
+    {
+      bgp = bgp_lookup_by_name (argv[0]);
+      if (bgp == NULL)
+       {
+         vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+       {
+         vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  if (argc == 4) {
+    peer = peer_lookup_in_view (vty, argv[0], argv[2]);
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  } else {
+    peer = peer_lookup_in_view (vty, NULL, argv[1]);
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+  }
+
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! peer->afc[AFI_IP6][safi])
+    {
+      vty_out (vty, "%% Activate the neighbor for the address family first%s",
+            VTY_NEWLINE);
+      return CMD_WARNING;
+}
+
+  if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi],
+              PEER_FLAG_RSERVER_CLIENT))
+{
+      vty_out (vty, "%% Neighbor is not a Route-Server client%s",
+            VTY_NEWLINE);
+    return CMD_WARNING;
+    }
+
+  return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi],
+                                  (argc == 4) ? argv[3] : argv[2],
+                                  AFI_IP6, safi, NULL, 1);
+}
+
+ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix,
+       show_bgp_ipv6_safi_rsclient_prefix_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Client\n"
+       NEIGHBOR_ADDR_STR
+       "IP prefix <network>/<length>, e.g., 3ffe::/16\n")
+
 #endif /* HAVE_IPV6 */
 \f
 struct bgp_table *bgp_distance_table;
@@ -11166,41 +11937,49 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name,
 
          if ((table = rn->info) != NULL)
            if ((rm = bgp_node_match (table, &match)) != NULL)
-             if (! prefix_check || rm->p.prefixlen == match.prefixlen)
-               {
-                 ri = rm->info;
-                 while (ri)
-                   {
-                     if (ri->extra && ri->extra->damp_info)
-                       {
-                         ri_temp = ri->next;
-                         bgp_damp_info_free (ri->extra->damp_info, 1);
-                         ri = ri_temp;
-                       }
-                     else
-                       ri = ri->next;
-                   }
-               }
+              {
+                if (! prefix_check || rm->p.prefixlen == match.prefixlen)
+                  {
+                    ri = rm->info;
+                    while (ri)
+                      {
+                        if (ri->extra && ri->extra->damp_info)
+                          {
+                            ri_temp = ri->next;
+                            bgp_damp_info_free (ri->extra->damp_info, 1);
+                            ri = ri_temp;
+                          }
+                        else
+                          ri = ri->next;
+                      }
+                  }
+
+                bgp_unlock_node (rm);
+              }
         }
     }
   else
     {
       if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
-       if (! prefix_check || rn->p.prefixlen == match.prefixlen)
-         {
-           ri = rn->info;
-           while (ri)
-             {
-               if (ri->extra && ri->extra->damp_info)
-                 {
-                   ri_temp = ri->next;
-                   bgp_damp_info_free (ri->extra->damp_info, 1);
-                   ri = ri_temp;
-                 }
-               else
-                 ri = ri->next;
-             }
-         }
+        {
+          if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+            {
+              ri = rn->info;
+              while (ri)
+                {
+                  if (ri->extra && ri->extra->damp_info)
+                    {
+                      ri_temp = ri->next;
+                      bgp_damp_info_free (ri->extra->damp_info, 1);
+                      ri = ri_temp;
+                    }
+                  else
+                    ri = ri->next;
+                }
+            }
+
+          bgp_unlock_node (rn);
+        }
     }
 
   return CMD_SUCCESS;
@@ -11555,12 +12334,15 @@ bgp_route_init (void)
 
   install_element (VIEW_NODE, &show_ip_bgp_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_cmd);
@@ -11586,6 +12368,11 @@ bgp_route_init (void)
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_community4_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -11604,6 +12391,7 @@ bgp_route_init (void)
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
@@ -11621,20 +12409,28 @@ bgp_route_init (void)
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
   
   /* Restricted node: VIEW_NODE - (set of dangerous commands) */
   install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd);
@@ -11647,6 +12443,11 @@ bgp_route_init (void)
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community4_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_community_exact_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_community2_exact_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -11656,18 +12457,25 @@ bgp_route_init (void)
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
 
   install_element (ENABLE_NODE, &show_ip_bgp_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_cmd);
@@ -11693,6 +12501,11 @@ bgp_route_init (void)
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_all_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community2_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community3_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community4_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd);
@@ -11711,6 +12524,7 @@ bgp_route_init (void)
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
@@ -11728,13 +12542,19 @@ bgp_route_init (void)
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd);
 
  /* BGP dampening clear commands */
   install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
@@ -11771,10 +12591,13 @@ bgp_route_init (void)
 
   install_element (VIEW_NODE, &show_bgp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_cmd);
   install_element (VIEW_NODE, &show_bgp_route_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_cmd);
   install_element (VIEW_NODE, &show_bgp_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_regexp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd);
   install_element (VIEW_NODE, &show_bgp_prefix_list_cmd);
@@ -11820,8 +12643,11 @@ bgp_route_init (void)
   install_element (VIEW_NODE, &show_bgp_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
   install_element (VIEW_NODE, &show_bgp_view_cmd);
   install_element (VIEW_NODE, &show_bgp_view_ipv6_cmd);
   install_element (VIEW_NODE, &show_bgp_view_route_cmd);
@@ -11841,16 +12667,21 @@ bgp_route_init (void)
   install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd);
   install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); 
   install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
   install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
   install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
   
   /* Restricted:
    * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev) 
    */
   install_element (RESTRICTED_NODE, &show_bgp_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_community_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_community2_cmd);
@@ -11868,7 +12699,9 @@ bgp_route_init (void)
   install_element (RESTRICTED_NODE, &show_bgp_community4_exact_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_exact_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_prefix_cmd);
@@ -11876,14 +12709,19 @@ bgp_route_init (void)
   install_element (RESTRICTED_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_prefix_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
 
   install_element (ENABLE_NODE, &show_bgp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_cmd);
   install_element (ENABLE_NODE, &show_bgp_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_regexp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd);
   install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd);
@@ -11929,8 +12767,11 @@ bgp_route_init (void)
   install_element (ENABLE_NODE, &show_bgp_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_ipv6_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_route_cmd);
@@ -11950,8 +12791,11 @@ bgp_route_init (void)
   install_element (ENABLE_NODE, &show_bgp_view_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd);
   install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd);
   
   /* Statistics */
   install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
index 42c3e053e59fee3402791d9d65831b21bdb0f49d..abb85fd219bdbed1de58c657212d0cba44db9647 100644 (file)
@@ -1470,6 +1470,13 @@ route_set_community_delete (void *rule, struct prefix *prefix,
          new = community_uniq_sort (merge);
          community_free (merge);
 
+         /* HACK: if the old community is not intern'd,
+          * we should free it here, or all reference to it may be lost.
+          * Really need to cleanup attribute caching sometime.
+          */
+         if (old->refcnt == 0)
+           community_free (old);
+
          if (new->size == 0)
            {
              binfo->attr->community = NULL;
@@ -1552,10 +1559,10 @@ route_set_ecommunity_rt (void *rule, struct prefix *prefix,
       else
        new_ecom = ecommunity_dup (ecom);
 
-      bgp_info->attr->extra->ecommunity = new_ecom;
+      bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
 
       if (old_ecom)
-       ecommunity_free (old_ecom);
+       ecommunity_unintern (&old_ecom);
 
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
     }
@@ -1571,7 +1578,7 @@ route_set_ecommunity_rt_compile (const char *arg)
   ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
   if (! ecom)
     return NULL;
-  return ecom;
+  return ecommunity_intern (ecom);
 }
 
 /* Free function for set community. */
@@ -1579,7 +1586,7 @@ static void
 route_set_ecommunity_rt_free (void *rule)
 {
   struct ecommunity *ecom = rule;
-  ecommunity_free (ecom);
+  ecommunity_unintern (&ecom);
 }
 
 /* Set community rule structure. */
@@ -1598,7 +1605,7 @@ static route_map_result_t
 route_set_ecommunity_soo (void *rule, struct prefix *prefix, 
                         route_map_object_t type, void *object)
 {
-  struct ecommunity *ecom;
+  struct ecommunity *ecom, *old_ecom, *new_ecom;
   struct bgp_info *bgp_info;
 
   if (type == RMAP_BGP)
@@ -1609,8 +1616,19 @@ route_set_ecommunity_soo (void *rule, struct prefix *prefix,
       if (! ecom)
        return RMAP_OKAY;
     
+      old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
+      
+      if (old_ecom)
+       new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
+      else
+       new_ecom = ecommunity_dup (ecom);
+
+      bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
+
+      if (old_ecom)
+       ecommunity_unintern (&old_ecom);
+
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
-      (bgp_attr_extra_get (bgp_info->attr))->ecommunity = ecommunity_dup (ecom);
     }
   return RMAP_OKAY;
 }
@@ -1625,7 +1643,7 @@ route_set_ecommunity_soo_compile (const char *arg)
   if (! ecom)
     return NULL;
   
-  return ecom;
+  return ecommunity_intern (ecom);
 }
 
 /* Free function for set community. */
@@ -1633,7 +1651,7 @@ static void
 route_set_ecommunity_soo_free (void *rule)
 {
   struct ecommunity *ecom = rule;
-  ecommunity_free (ecom);
+  ecommunity_unintern (&ecom);
 }
 
 /* Set community rule structure. */
index 91cab60671937c07465a5ef0e54b95a291c158b1..a249c23d9dc6161717d7552db5acb81a41c2a95a 100644 (file)
@@ -350,7 +350,6 @@ bgp_node_get (struct bgp_table *const table, struct prefix *p)
       if (new->p.prefixlen != p->prefixlen)
        {
          match = new;
-         bgp_lock_node (match);
          new = bgp_node_set (table, p);
          set_link (match, new);
          table->count++;
index 9cb30182af17564cf86e1ff46f05b17abc3c9699..f65bb157119ce27c28e2bd258b140ae6bebc164d 100644 (file)
@@ -213,6 +213,12 @@ bgp_vty_return (struct vty *vty, int ret)
     case BGP_ERR_TCPSIG_FAILED:
       str = "Error while applying TCP-Sig to session(s)";
       break;
+    case BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK:
+      str = "ebgp-multihop and ttl-security cannot be configured together";
+      break;
+    case BGP_ERR_NO_IBGP_WITH_TTLHACK:
+      str = "ttl-security only allowed for EBGP peers";
+      break;
     }
   if (str)
     {
@@ -2636,9 +2642,7 @@ peer_ebgp_multihop_set_vty (struct vty *vty, const char *ip_str,
   else
     VTY_GET_INTEGER_RANGE ("TTL", ttl, ttl_str, 1, 255);
 
-  peer_ebgp_multihop_set (peer, ttl);
-
-  return CMD_SUCCESS;
+  return bgp_vty_return (vty,  peer_ebgp_multihop_set (peer, ttl));
 }
 
 static int
@@ -2650,9 +2654,7 @@ peer_ebgp_multihop_unset_vty (struct vty *vty, const char *ip_str)
   if (! peer)
     return CMD_WARNING;
 
-  peer_ebgp_multihop_unset (peer);
-
-  return CMD_SUCCESS;
+  return bgp_vty_return (vty, peer_ebgp_multihop_unset (peer));
 }
 
 /* neighbor ebgp-multihop. */
@@ -3954,6 +3956,42 @@ DEFUN (no_neighbor_allowas_in,
   return bgp_vty_return (vty, ret);
 }
 \f
+DEFUN (neighbor_ttl_security,
+       neighbor_ttl_security_cmd,
+       NEIGHBOR_CMD2 "ttl-security hops <1-254>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify the maximum number of hops to the BGP peer\n")
+{
+  struct peer *peer;
+  int gtsm_hops;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+    
+  VTY_GET_INTEGER_RANGE ("", gtsm_hops, argv[1], 1, 254);
+
+  return bgp_vty_return (vty, peer_ttl_security_hops_set (peer, gtsm_hops));
+}
+
+DEFUN (no_neighbor_ttl_security,
+       no_neighbor_ttl_security_cmd,
+       NO_NEIGHBOR_CMD2 "ttl-security hops <1-254>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify the maximum number of hops to the BGP peer\n")
+{
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  return bgp_vty_return (vty, peer_ttl_security_hops_unset (peer));
+}
+\f
 /* Address family configuration.  */
 DEFUN (address_family_ipv4,
        address_family_ipv4_cmd,
@@ -6856,6 +6894,16 @@ DEFUN (show_ip_bgp_ipv4_summary,
   return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
 }
 
+ALIAS (show_ip_bgp_ipv4_summary,
+       show_bgp_ipv4_safi_summary_cmd,
+       "show bgp ipv4 (unicast|multicast) summary",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+
 DEFUN (show_ip_bgp_instance_ipv4_summary,
        show_ip_bgp_instance_ipv4_summary_cmd,
        "show ip bgp view WORD ipv4 (unicast|multicast) summary",
@@ -6875,6 +6923,18 @@ DEFUN (show_ip_bgp_instance_ipv4_summary,
     return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
 }
 
+ALIAS (show_ip_bgp_instance_ipv4_summary,
+       show_bgp_instance_ipv4_safi_summary_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+
 DEFUN (show_ip_bgp_vpnv4_all_summary,
        show_ip_bgp_vpnv4_all_summary_cmd,
        "show ip bgp vpnv4 all summary",
@@ -6953,6 +7013,40 @@ ALIAS (show_bgp_instance_summary,
        "Address family\n"
        "Summary of BGP neighbor status\n")
 
+DEFUN (show_bgp_ipv6_safi_summary,
+       show_bgp_ipv6_safi_summary_cmd,
+       "show bgp ipv6 (unicast|multicast) summary",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_MULTICAST);
+
+  return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_instance_ipv6_safi_summary,
+       show_bgp_instance_ipv6_safi_summary_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_MULTICAST);
+
+  return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
 /* old command */
 DEFUN (show_ipv6_bgp_summary, 
        show_ipv6_bgp_summary_cmd,
@@ -7544,10 +7638,16 @@ bgp_show_peer (struct vty *vty, struct peer *p)
                 p->host, VTY_NEWLINE);
     }
 
-  /* EBGP Multihop */
-  if (peer_sort (p) != BGP_PEER_IBGP && p->ttl > 1)
-    vty_out (vty, "  External BGP neighbor may be up to %d hops away.%s",
-            p->ttl, VTY_NEWLINE);
+  /* EBGP Multihop and GTSM */
+  if (peer_sort (p) != BGP_PEER_IBGP)
+    {
+      if (p->gtsm_hops > 0)
+       vty_out (vty, "  External BGP neighbor may be up to %d hops away.%s",
+                p->gtsm_hops, VTY_NEWLINE);
+      else if (p->ttl > 1)
+       vty_out (vty, "  External BGP neighbor may be up to %d hops away.%s",
+                p->ttl, VTY_NEWLINE);
+    }
 
   /* Local address. */
   if (p->su_local)
@@ -8154,6 +8254,41 @@ DEFUN (show_ip_bgp_instance_ipv4_rsclient_summary,
   return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
 }
 
+DEFUN (show_bgp_instance_ipv4_safi_rsclient_summary,
+       show_bgp_instance_ipv4_safi_rsclient_summary_cmd,
+       "show bgp view WORD ipv4 (unicast|multicast) rsclient summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Clients\n"
+       "Summary of all Route Server Clients\n")
+{
+  safi_t safi;
+
+  if (argc == 2) {
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+    return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, safi);
+  } else {
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+    return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, safi);
+  }
+}
+
+ALIAS (show_bgp_instance_ipv4_safi_rsclient_summary,
+       show_bgp_ipv4_safi_rsclient_summary_cmd,
+       "show bgp ipv4 (unicast|multicast) rsclient summary",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Clients\n"
+       "Summary of all Route Server Clients\n")
+
 #ifdef HAVE_IPV6
 DEFUN (show_bgp_rsclient_summary,
        show_bgp_rsclient_summary_cmd,
@@ -8198,6 +8333,42 @@ ALIAS (show_bgp_instance_rsclient_summary,
        "Address family\n"
        "Information about Route Server Clients\n"
        "Summary of all Route Server Clients\n")
+
+DEFUN (show_bgp_instance_ipv6_safi_rsclient_summary,
+       show_bgp_instance_ipv6_safi_rsclient_summary_cmd,
+       "show bgp view WORD ipv6 (unicast|multicast) rsclient summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Clients\n"
+       "Summary of all Route Server Clients\n")
+{
+  safi_t safi;
+
+  if (argc == 2) {
+    safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+    return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP6, safi);
+  } else {
+    safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
+    return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP6, safi);
+  }
+}
+
+ALIAS (show_bgp_instance_ipv6_safi_rsclient_summary,
+       show_bgp_ipv6_safi_rsclient_summary_cmd,
+       "show bgp ipv6 (unicast|multicast) rsclient summary",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Information about Route Server Clients\n"
+       "Summary of all Route Server Clients\n")
+
 #endif /* HAVE IPV6 */
 \f
 /* Redistribute VTY commands.  */
@@ -9627,38 +9798,50 @@ bgp_vty_init (void)
   install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_instance_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
 #ifdef HAVE_IPV6
   install_element (VIEW_NODE, &show_bgp_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_instance_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_instance_ipv6_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
 #endif /* HAVE_IPV6 */
   install_element (RESTRICTED_NODE, &show_ip_bgp_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_instance_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
 #ifdef HAVE_IPV6
   install_element (RESTRICTED_NODE, &show_bgp_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_instance_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
 #endif /* HAVE_IPV6 */
   install_element (ENABLE_NODE, &show_ip_bgp_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_instance_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
 #ifdef HAVE_IPV6
   install_element (ENABLE_NODE, &show_bgp_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_instance_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_instance_ipv6_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_summary_cmd);
 #endif /* HAVE_IPV6 */
 
   /* "show ip bgp neighbors" commands. */
@@ -9722,28 +9905,40 @@ bgp_vty_init (void)
   install_element (VIEW_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd);
 
 #ifdef HAVE_IPV6
   install_element (VIEW_NODE, &show_bgp_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_instance_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_instance_rsclient_summary_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+  install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_ipv6_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_instance_rsclient_summary_cmd);
   install_element (ENABLE_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd);
 #endif /* HAVE_IPV6 */
 
   /* "show ip bgp paths" commands. */
@@ -9784,6 +9979,10 @@ bgp_vty_init (void)
   install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_metric_rmap_cmd);
 #endif /* HAVE_IPV6 */
 
+  /* ttl_security commands */
+  install_element (BGP_NODE, &neighbor_ttl_security_cmd);
+  install_element (BGP_NODE, &no_neighbor_ttl_security_cmd);
+
   /* "show bgp memory" commands. */
   install_element (VIEW_NODE, &show_bgp_memory_cmd);
   install_element (RESTRICTED_NODE, &show_bgp_memory_cmd);
index d7af349aacc804c3b01367ee3d29e247c67f6451..76c519cbe0c3c302e0d650a4299fc97551a510df 100644 (file)
@@ -232,12 +232,10 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
 {
   struct stream *s;
   struct zapi_ipv4 api;
-  unsigned long ifindex;
   struct in_addr nexthop;
   struct prefix_ipv4 p;
 
   s = zclient->ibuf;
-  ifindex = 0;
   nexthop.s_addr = 0;
 
   /* Type, flags, message. */
@@ -260,7 +258,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
     {
       api.ifindex_num = stream_getc (s);
-      ifindex = stream_getl (s);
+      stream_getl (s); /* ifindex, unused */
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
@@ -310,12 +308,10 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
 {
   struct stream *s;
   struct zapi_ipv6 api;
-  unsigned long ifindex;
   struct in6_addr nexthop;
   struct prefix_ipv6 p;
 
   s = zclient->ibuf;
-  ifindex = 0;
   memset (&nexthop, 0, sizeof (struct in6_addr));
 
   /* Type, flags, message. */
@@ -338,7 +334,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
     {
       api.ifindex_num = stream_getc (s);
-      ifindex = stream_getl (s);
+      stream_getl (s); /* ifindex, unused */
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
index 0d462db93cc2fded34e6a7a8c15e3118fc1cf66d..5dc014be9bcb37faa084d9f4e07005e7bca5b312 100644 (file)
@@ -695,7 +695,7 @@ peer_sort (struct peer *peer)
     }
 }
 
-static inline void
+static void
 peer_free (struct peer *peer)
 {
   assert (peer->status == Deleted);
@@ -1379,6 +1379,7 @@ peer_group_get (struct bgp *bgp, const char *name)
   group->conf->group = group;
   group->conf->as = 0; 
   group->conf->ttl = 1;
+  group->conf->gtsm_hops = 0;
   group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
   UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
   UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
@@ -1416,6 +1417,9 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
   /* TTL */
   peer->ttl = conf->ttl;
 
+  /* GTSM hops */
+  peer->gtsm_hops = conf->gtsm_hops;
+
   /* Weight */
   peer->weight = conf->weight;
 
@@ -2664,10 +2668,36 @@ peer_ebgp_multihop_set (struct peer *peer, int ttl)
 {
   struct peer_group *group;
   struct listnode *node, *nnode;
+  struct peer *peer1;
 
   if (peer_sort (peer) == BGP_PEER_IBGP)
     return 0;
 
+  /* see comment in peer_ttl_security_hops_set() */
+  if (ttl != MAXTTL)
+    {
+      if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+        {
+          group = peer->group;
+          if (group->conf->gtsm_hops != 0)
+            return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
+          for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
+            {
+              if (peer_sort (peer1) == BGP_PEER_IBGP)
+                continue;
+
+              if (peer1->gtsm_hops != 0)
+                return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+            }
+        }
+      else
+        {
+          if (peer->gtsm_hops != 0)
+            return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+        }
+    }
+
   peer->ttl = ttl;
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
@@ -2701,6 +2731,9 @@ peer_ebgp_multihop_unset (struct peer *peer)
   if (peer_sort (peer) == BGP_PEER_IBGP)
     return 0;
 
+  if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
+      return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
   if (peer_group_active (peer))
     peer->ttl = peer->group->conf->ttl;
   else
@@ -4332,6 +4365,137 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
   return 0;
 }
 \f
+/* Set # of hops between us and BGP peer. */
+int
+peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
+{
+  struct peer_group *group;
+  struct listnode *node, *nnode;
+  struct peer *peer1;
+  int ret;
+
+  zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    return BGP_ERR_NO_IBGP_WITH_TTLHACK;
+
+  /* We cannot configure ttl-security hops when ebgp-multihop is already
+     set.  For non peer-groups, the check is simple.  For peer-groups, it's
+     slightly messy, because we need to check both the peer-group structure
+     and all peer-group members for any trace of ebgp-multihop configuration
+     before actually applying the ttl-security rules.  Cisco really made a
+     mess of this configuration parameter, and OpenBGPD got it right.
+  */
+  
+  if (peer->gtsm_hops == 0) {
+    if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+      {
+        group = peer->group;
+        if (group->conf->ttl != 1)
+          return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+
+        for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
+          {
+            if (peer_sort (peer1) == BGP_PEER_IBGP)
+              continue;
+
+            if (peer1->ttl != 1)
+              return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+          }
+      }
+    else
+      {
+        if (peer->ttl != 1)
+          return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
+      }
+    /* specify MAXTTL on outgoing packets */
+    ret = peer_ebgp_multihop_set (peer, MAXTTL);
+    if (ret != 0)
+      return ret;
+  }
+  
+  peer->gtsm_hops = gtsm_hops;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+       sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
+    }
+  else
+    {
+      group = peer->group;
+      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+       {
+         if (peer_sort (peer) == BGP_PEER_IBGP)
+           continue;
+
+         peer->gtsm_hops = group->conf->gtsm_hops;
+
+         /* Change setting of existing peer
+          *   established then change value (may break connectivity)
+          *   not established yet (teardown session and restart)
+          *   no session then do nothing (will get handled by next connection)
+          */
+         if (peer->status == Established)
+           {
+             if (peer->fd >= 0 && peer->gtsm_hops != 0)
+               sockopt_minttl (peer->su.sa.sa_family, peer->fd,
+                               MAXTTL + 1 - peer->gtsm_hops);
+           }
+         else if (peer->status < Established)
+           {
+             if (BGP_DEBUG (events, EVENTS))
+               zlog_debug ("%s Min-ttl changed", peer->host);
+             BGP_EVENT_ADD (peer, BGP_Stop);
+           }
+       }
+    }
+
+  return 0;
+}
+
+int
+peer_ttl_security_hops_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *node, *nnode;
+  struct peer *opeer;
+
+  zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+      return 0;
+
+  /* if a peer-group member, then reset to peer-group default rather than 0 */
+  if (peer_group_active (peer))
+    peer->gtsm_hops = peer->group->conf->gtsm_hops;
+  else
+    peer->gtsm_hops = 0;
+
+  opeer = peer;
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+       sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+    }
+  else
+    {
+      group = peer->group;
+      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+       {
+         if (peer_sort (peer) == BGP_PEER_IBGP)
+           continue;
+
+         peer->gtsm_hops = 0;
+         
+         if (peer->fd >= 0)
+           sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
+       }
+    }
+
+  return peer_ebgp_multihop_unset (opeer);
+}
+\f
 int
 peer_clear (struct peer *peer)
 {
@@ -4557,12 +4721,10 @@ static void
 bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
                       struct peer *peer, afi_t afi, safi_t safi)
 {
-  struct bgp_filter *filter;
   struct peer *g_peer = NULL;
   char buf[SU_ADDRSTRLEN];
   char *addr;
 
-  filter = &peer->filter[afi][safi];
   addr = peer->host;
   if (peer_group_active (peer))
     g_peer = peer->group->conf;
@@ -4636,12 +4798,19 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
          vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
 
       /* EBGP multihop.  */
-      if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
+      if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1 &&
+                   !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
         if (! peer_group_active (peer) ||
            g_peer->ttl != peer->ttl)
          vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
                   VTY_NEWLINE);
 
+     /* ttl-security hops */
+      if (peer_sort (peer) != BGP_PEER_IBGP && peer->gtsm_hops != 0)
+        if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
+          vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
+                   peer->gtsm_hops, VTY_NEWLINE);
+
       /* disable-connected-check.  */
       if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
        if (! peer_group_active (peer) ||
index 91773e3c107925705bc3534fa4cb8575cc77cca6..892e7decc632ac81fab61181ebbcd4f28247040d 100644 (file)
@@ -303,6 +303,7 @@ struct peer
   /* Peer information */
   int fd;                      /* File descriptor */
   int ttl;                     /* TTL of TCP connection to the peer. */
+  int gtsm_hops;               /* minimum hopcount to peer */
   char *desc;                  /* Description of the peer. */
   unsigned short port;          /* Destination port for peer */
   char *host;                  /* Printable address of the peer. */
@@ -801,7 +802,9 @@ enum bgp_clear_type
 #define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP  -27
 #define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS    -28
 #define BGP_ERR_TCPSIG_FAILED                  -29
-#define BGP_ERR_MAX                             -30
+#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK  -30
+#define BGP_ERR_NO_IBGP_WITH_TTLHACK           -31
+#define BGP_ERR_MAX                            -32
 
 extern struct bgp_master *bm;
 
@@ -954,4 +957,7 @@ extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
 extern int peer_clear (struct peer *);
 extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type);
 
+extern int peer_ttl_security_hops_set (struct peer *, int);
+extern int peer_ttl_security_hops_unset (struct peer *);
+
 #endif /* _QUAGGA_BGPD_H */
index 676c5dcc8b31a1b4d7c8502bae82ff9c8c04e591..4e5b5359bb2b9d42cef7fb4bc4ccd670d52e170f 100755 (executable)
@@ -7,7 +7,7 @@
 ##
 AC_PREREQ(2.53)
 
-AC_INIT(Quagga, 0.99.17.6, [https://bugzilla.quagga.net])
+AC_INIT(Quagga, 0.99.20, [https://bugzilla.quagga.net])
 AC_CONFIG_SRCDIR(lib/zebra.h)
 AC_CONFIG_MACRO_DIR([m4])
 
@@ -218,15 +218,14 @@ AC_ARG_WITH(libpam,
 AC_ARG_ENABLE(tcp-zebra,
 [  --enable-tcp-zebra      enable TCP/IP socket connection between zebra and protocol daemon])
 AC_ARG_ENABLE(opaque-lsa,
-[  --enable-opaque-lsa     enable OSPF Opaque-LSA with OSPFAPI support (RFC2370)])
+  AC_HELP_STRING([--disable-opaque-lsa],[do not build OSPF Opaque-LSA with OSPFAPI support (RFC2370)]))
 AC_ARG_ENABLE(ospfapi,
-[  --disable-ospfapi       do not build OSPFAPI to access the OSPF LSA Database, 
-                          (this is the default if --enable-opaque-lsa is not set)])
+[  --disable-ospfapi       do not build OSPFAPI to access the OSPF LSA Database])
 AC_ARG_ENABLE(ospfclient,
 [  --disable-ospfclient    do not build OSPFAPI client for OSPFAPI, 
                           (this is the default if --disable-ospfapi is set)])
 AC_ARG_ENABLE(ospf-te,
-[  --enable-ospf-te        enable Traffic Engineering Extension to OSPF])
+  AC_HELP_STRING([--disable-ospf-te],[disable Traffic Engineering Extension to OSPF]))
 AC_ARG_ENABLE(multipath,
 [  --enable-multipath=ARG  enable multipath function, ARG must be digit])
 AC_ARG_ENABLE(user,
@@ -291,11 +290,11 @@ if test "${enable_tcp_zebra}" = "yes"; then
   AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication)
 fi
 
-if test "${enable_opaque_lsa}" = "yes"; then
+if test "${enable_opaque_lsa}" != "no"; then
   AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
 fi
 
-if test "${enable_ospf_te}" = "yes"; then
+if test "${enable_ospf_te}" != "no"; then
   AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
   AC_DEFINE(HAVE_OSPF_TE,,OSPF TE)
 fi
@@ -1243,7 +1242,7 @@ else
 fi
 
 OSPFCLIENT=""
-if test "${enable_opaque_lsa}" = "yes"; then
+if test "${enable_opaque_lsa}" != "no"; then
   if test "${enable_ospfapi}" != "no";then
     AC_DEFINE(SUPPORT_OSPF_API,,OSPFAPI)
 
index ebb50b40d45acf8b4e5da7a29313fa80cfa2d116..4f6d184da81fa3b1e33f648b85ac7494b5443551 100644 (file)
@@ -3648,6 +3648,8 @@ cmd_init (int terminal)
       install_element (VIEW_NODE, &show_thread_cpu_cmd);
       install_element (ENABLE_NODE, &show_thread_cpu_cmd);
       install_element (RESTRICTED_NODE, &show_thread_cpu_cmd);
+      
+      install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
       install_element (VIEW_NODE, &show_work_queues_cmd);
       install_element (ENABLE_NODE, &show_work_queues_cmd);
     }
index 7f84b80ed86911c9ffef4800d06d8ab5750a2ac9..04889030f7e47881e200f2dc4008ee2f4dbca663 100644 (file)
@@ -114,16 +114,11 @@ distribute_get (const char *ifname)
 }
 
 static unsigned int
-distribute_hash_make (struct distribute *dist)
+distribute_hash_make (void *arg)
 {
-  unsigned int i, key;
+  const struct distribute *dist = arg;
 
-  key = 0;
-  if (dist->ifname)
-    for (i = 0; i < strlen (dist->ifname); i++)
-      key += dist->ifname[i];
-
-  return key;
+  return dist->ifname ? string_hash_make (dist->ifname) : 0;
 }
 
 /* If two distribute-list have same value then return 1 else return
@@ -304,7 +299,6 @@ DEFUN (distribute_list_all,
        "Filter outgoing routing updates\n")
 {
   enum distribute_type type;
-  struct distribute *dist;
 
   /* Check of distribute list type. */
   if (strncmp (argv[1], "i", 1) == 0)
@@ -319,7 +313,7 @@ DEFUN (distribute_list_all,
     }
 
   /* Get interface name corresponding distribute list. */
-  dist = distribute_list_set (NULL, type, argv[0]);
+  distribute_list_set (NULL, type, argv[0]);
 
   return CMD_SUCCESS;
 }
@@ -384,7 +378,6 @@ DEFUN (distribute_list,
        "Interface name\n")
 {
   enum distribute_type type;
-  struct distribute *dist;
 
   /* Check of distribute list type. */
   if (strncmp (argv[1], "i", 1) == 0)
@@ -398,7 +391,7 @@ DEFUN (distribute_list,
     }
 
   /* Get interface name corresponding distribute list. */
-  dist = distribute_list_set (argv[2], type, argv[0]);
+  distribute_list_set (argv[2], type, argv[0]);
 
   return CMD_SUCCESS;
 }       
@@ -463,7 +456,6 @@ DEFUN (distribute_list_prefix_all,
        "Filter outgoing routing updates\n")
 {
   enum distribute_type type;
-  struct distribute *dist;
 
   /* Check of distribute list type. */
   if (strncmp (argv[1], "i", 1) == 0)
@@ -478,7 +470,7 @@ DEFUN (distribute_list_prefix_all,
     }
 
   /* Get interface name corresponding distribute list. */
-  dist = distribute_list_prefix_set (NULL, type, argv[0]);
+  distribute_list_prefix_set (NULL, type, argv[0]);
 
   return CMD_SUCCESS;
 }       
@@ -546,7 +538,6 @@ DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,
        "Interface name\n")
 {
   enum distribute_type type;
-  struct distribute *dist;
 
   /* Check of distribute list type. */
   if (strncmp (argv[1], "i", 1) == 0)
@@ -561,7 +552,7 @@ DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,
     }
 
   /* Get interface name corresponding distribute list. */
-  dist = distribute_list_prefix_set (argv[2], type, argv[0]);
+  distribute_list_prefix_set (argv[2], type, argv[0]);
 
   return CMD_SUCCESS;
 }       
@@ -763,7 +754,7 @@ distribute_list_reset ()
 void
 distribute_list_init (int node)
 {
-  disthash = hash_create ((unsigned int (*) (void *)) distribute_hash_make,
+  disthash = hash_create (distribute_hash_make,
                           (int (*) (const void *, const void *)) distribute_cmp);
 
   if(node==RIP_NODE) {
index 672327ec5b990726e13212cfe4184efc3d054918..6db79ea77a6ba7c9d1b27702c9d755e69c766830 100644 (file)
@@ -101,6 +101,17 @@ hash_lookup (struct hash *hash, void *data)
   return hash_get (hash, data, NULL);
 }
 
+/* Simple Bernstein hash which is simple and fast for common case */
+unsigned int string_hash_make (const char *str)
+{
+  unsigned int hash = 0;
+
+  while (*str)
+    hash = (hash * 33) ^ (unsigned int) *str++;
+
+  return hash;
+}
+
 /* This function release registered value from specified hash.  When
    release is successfully finished, return the data pointer in the
    hash backet.  */
index f4b1c23eb5c0e63d9af687c0ea3f28b43e921a3a..4cb772e5797ee6ff209da2ccc73476dee03a7572 100644 (file)
@@ -70,4 +70,6 @@ extern void hash_iterate (struct hash *,
 extern void hash_clean (struct hash *, void (*) (void *));
 extern void hash_free (struct hash *);
 
+extern unsigned int string_hash_make (const char *);
+
 #endif /* _ZEBRA_HASH_H */
index 31c60e3fe85f813066af459d4dc7785318043b32..1e99ffbca561a96d72f9d189f00e49e7618e05ad 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -426,16 +426,20 @@ if_flag_dump (unsigned long flag)
 static void
 if_dump (const struct interface *ifp)
 {
-  zlog_info ("Interface %s index %d metric %d mtu %d "
+  struct listnode *node;
+  struct connected *c;
+
+  for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
+    zlog_info ("Interface %s index %d metric %d mtu %d "
 #ifdef HAVE_IPV6
-             "mtu6 %d "
+               "mtu6 %d "
 #endif /* HAVE_IPV6 */
-             "%s",
-            ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, 
+               "%s",
+               ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, 
 #ifdef HAVE_IPV6
-            ifp->mtu6,
+               ifp->mtu6,
 #endif /* HAVE_IPV6 */
-            if_flag_dump (ifp->flags));
+               if_flag_dump (ifp->flags));
 }
 
 /* Interface printing for all interface. */
index ddc62fd51b2ccc32d99fa7adfc7c3e98f3cface7..7d049b87207d3e05e48370e6c0d3f3da045fcfc7 100644 (file)
@@ -109,14 +109,9 @@ if_rmap_get (const char *ifname)
 static unsigned int
 if_rmap_hash_make (void *data)
 {
-  struct if_rmap *if_rmap = data;
-  unsigned int i, key;
+  const struct if_rmap *if_rmap = data;
 
-  key = 0;
-  for (i = 0; i < strlen (if_rmap->ifname); i++)
-    key += if_rmap->ifname[i];
-
-  return key;
+  return string_hash_make (if_rmap->ifname);
 }
 
 static int
@@ -212,7 +207,6 @@ DEFUN (if_rmap,
        "Route map interface name\n")
 {
   enum if_rmap_type type;
-  struct if_rmap *if_rmap;
 
   if (strncmp (argv[1], "i", 1) == 0)
     type = IF_RMAP_IN;
@@ -224,7 +218,7 @@ DEFUN (if_rmap,
       return CMD_WARNING;
     }
 
-  if_rmap = if_rmap_set (argv[2], type, argv[0]);
+  if_rmap_set (argv[2], type, argv[0]);
 
   return CMD_SUCCESS;
 }      
index 4bac31dbb45ba87ef22268d9336f639fee25779c..4090fd901f2a27b0b6f87cd5253623ffe21a582e 100644 (file)
@@ -111,6 +111,9 @@ zrealloc (int type, void *ptr, size_t size)
   memory = realloc (ptr, size);
   if (memory == NULL)
     zerror ("realloc", type, size);
+  if (ptr == NULL)
+    alloc_inc (type);
+
   return memory;
 }
 
@@ -123,8 +126,11 @@ zrealloc (int type, void *ptr, size_t size)
 void
 zfree (int type, void *ptr)
 {
-  alloc_dec (type);
-  free (ptr);
+  if (ptr != NULL)
+    {
+      alloc_dec (type);
+      free (ptr);
+    }
 }
 
 /*
index d0ce8c5ead6a16e87cbb108acdbb0b32e1987528..d2bc1c62e21905f5cda14a3f305aaea7a6ef45fd 100644 (file)
@@ -106,6 +106,7 @@ struct memory_list memory_list_bgp[] =
   { MTYPE_BGP_NODE,            "BGP node"                      },
   { MTYPE_BGP_ROUTE,           "BGP route"                     },
   { MTYPE_BGP_ROUTE_EXTRA,     "BGP ancillary route info"      },
+  { MTYPE_BGP_CONN,            "BGP connected"                 },
   { MTYPE_BGP_STATIC,          "BGP static"                    },
   { MTYPE_BGP_ADVERTISE_ATTR,  "BGP adv attr"                  },
   { MTYPE_BGP_ADVERTISE,       "BGP adv"                       },
index ceda08de253fb05d6aaa95d5171ef7a5ba367138..5e8cff04b0c11973c2fc5c6887713c7a97835e94 100644 (file)
@@ -2317,6 +2317,21 @@ static const char map64kto17_nbo[0xffff + 1] =
 
 #define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff)
 
+unsigned int
+prefix_bit (const u_char *prefix, const u_char prefixlen)
+{
+  unsigned int offset = prefixlen / 8;
+  unsigned int shift  = 7 - (prefixlen % 8);
+  
+  return (prefix[offset] >> shift) & 1;
+}
+
+unsigned int
+prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
+{
+  return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
+}
+\f
 /* Address Famiy Identifier to Address Family converter. */
 int
 afi2family (afi_t afi)
index dab4202ea817a6780f65151f8d3826d87828edbf..7f0d36070b181f32de527c12b8134c375c16fa62 100644 (file)
@@ -128,26 +128,14 @@ struct prefix_rd
 /* Prefix's family member. */
 #define PREFIX_FAMILY(p)  ((p)->family)
 
-/* Check bit of the prefix. */
-static inline unsigned int
-prefix_bit (const u_char *prefix, const u_char prefixlen)
-{
-  unsigned int offset = prefixlen / 8;
-  unsigned int shift  = 7 - (prefixlen % 8);
-
-  return (prefix[offset] >> shift) & 1;
-}
-
-static inline unsigned int
-prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
-{
-  return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
-}
-
 /* Prototypes. */
 extern int afi2family (afi_t);
 extern afi_t family2afi (int);
 
+/* Check bit of the prefix. */
+extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen);
+extern unsigned int prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen);
+
 extern struct prefix *prefix_new (void);
 extern void prefix_free (struct prefix *);
 extern const char *prefix_family_str (const struct prefix *);
index 10224a053fa69dea1c92461b361b0d44b1d5f84b..59770529313d523a68951a881ab51437204fd1b4 100644 (file)
@@ -526,6 +526,46 @@ sockopt_ttl (int family, int sock, int ttl)
   return 0;
 }
 
+int
+sockopt_cork (int sock, int onoff)
+{
+#ifdef TCP_CORK
+  return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
+#else
+  return 0;
+#endif
+}
+
+int
+sockopt_minttl (int family, int sock, int minttl)
+{
+#ifdef IP_MINTTL
+  if (family == AF_INET)
+    {
+      int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
+      if (ret < 0)
+         zlog (NULL, LOG_WARNING,
+               "can't set sockopt IP_MINTTL to %d on socket %d: %s",
+               minttl, sock, safe_strerror (errno));
+      return ret;
+    }
+#endif /* IP_MINTTL */
+#ifdef IPV6_MINHOPCNT
+  if (family == AF_INET6)
+    {
+      int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
+      if (ret < 0)
+         zlog (NULL, LOG_WARNING,
+               "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
+               minttl, sock, safe_strerror (errno));
+      return ret;
+    }
+#endif
+
+  errno = EOPNOTSUPP;
+  return -1;
+}
+
 int
 sockopt_v6only (int family, int sock)
 {
index db145cf271af61bbd6d5ff1574fbc94b19b2a410..4531f620ab92d1b619e22c376eacd62469270335 100644 (file)
@@ -103,6 +103,8 @@ extern int sockopt_v6only (int family, int sock);
 extern int sockunion_bind (int sock, union sockunion *, 
                            unsigned short, union sockunion *);
 extern int sockopt_ttl (int family, int sock, int ttl);
+extern int sockopt_minttl (int family, int sock, int minttl);
+extern int sockopt_cork (int sock, int onoff);
 extern int sockunion_socket (union sockunion *su);
 extern const char *inet_sutop (union sockunion *su, char *str);
 extern enum connect_result sockunion_connect (int fd, union sockunion *su, 
index 04df3af5793ccc8094af4d64f5b9e3497767c4c4..e40e67072251edbd497071c6a046beda63e6dca8 100644 (file)
@@ -209,6 +209,10 @@ route_node_match (const struct route_table *table, const struct prefix *p)
     {
       if (node->info)
        matched = node;
+      
+      if (node->p.prefixlen == p->prefixlen)
+        break;
+      
       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
     }
 
@@ -260,8 +264,8 @@ route_node_lookup (struct route_table *table, struct prefix *p)
   while (node && node->p.prefixlen <= p->prefixlen && 
         prefix_match (&node->p, p))
     {
-      if (node->p.prefixlen == p->prefixlen && node->info)
-       return route_lock_node (node);
+      if (node->p.prefixlen == p->prefixlen)
+        return node->info ? route_lock_node (node) : NULL;
 
       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
     }
@@ -283,10 +287,8 @@ route_node_get (struct route_table *table, struct prefix *p)
         prefix_match (&node->p, p))
     {
       if (node->p.prefixlen == p->prefixlen)
-       {
-         route_lock_node (node);
-         return node;
-       }
+        return route_lock_node (node);
+      
       match = node;
       node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
     }
index e89af541c61f7ddaaa1709d4bb5e444f775785d0..6d3c3cb38602c8a51562282e9dda80315a1e8a16 100644 (file)
@@ -248,7 +248,7 @@ cpu_record_hash_free (void *a)
   XFREE (MTYPE_THREAD_STATS, hist);
 }
 
-static inline void 
+static void 
 vty_out_cpu_thread_history(struct vty* vty,
                           struct cpu_thread_history *a)
 {
@@ -303,7 +303,7 @@ cpu_record_print(struct vty *vty, thread_type filter)
   void *args[3] = {&tmp, vty, &filter};
 
   memset(&tmp, 0, sizeof tmp);
-  tmp.funcname = "TOTAL";
+  tmp.funcname = (char *)"TOTAL";
   tmp.types = filter;
 
 #ifdef HAVE_RUSAGE
@@ -382,6 +382,89 @@ DEFUN(show_thread_cpu,
   cpu_record_print(vty, filter);
   return CMD_SUCCESS;
 }
+
+static void
+cpu_record_hash_clear (struct hash_backet *bucket, 
+                     void *args)
+{
+  thread_type *filter = args;
+  struct cpu_thread_history *a = bucket->data;
+  
+  a = bucket->data;
+  if ( !(a->types & *filter) )
+       return;
+  
+  hash_release (cpu_record, bucket->data);
+}
+
+static void
+cpu_record_clear (thread_type filter)
+{
+  thread_type *tmp = &filter;
+  hash_iterate (cpu_record,
+               (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
+               tmp);
+}
+
+DEFUN(clear_thread_cpu,
+      clear_thread_cpu_cmd,
+      "clear thread cpu [FILTER]",
+      "Clear stored data\n"
+      "Thread information\n"
+      "Thread CPU usage\n"
+      "Display filter (rwtexb)\n")
+{
+  int i = 0;
+  thread_type filter = (thread_type) -1U;
+
+  if (argc > 0)
+    {
+      filter = 0;
+      while (argv[0][i] != '\0')
+       {
+         switch ( argv[0][i] )
+           {
+           case 'r':
+           case 'R':
+             filter |= (1 << THREAD_READ);
+             break;
+           case 'w':
+           case 'W':
+             filter |= (1 << THREAD_WRITE);
+             break;
+           case 't':
+           case 'T':
+             filter |= (1 << THREAD_TIMER);
+             break;
+           case 'e':
+           case 'E':
+             filter |= (1 << THREAD_EVENT);
+             break;
+           case 'x':
+           case 'X':
+             filter |= (1 << THREAD_EXECUTE);
+             break;
+           case 'b':
+           case 'B':
+             filter |= (1 << THREAD_BACKGROUND);
+             break;
+           default:
+             break;
+           }
+         ++i;
+       }
+      if (filter == 0)
+       {
+         vty_out(vty, "Invalid filter \"%s\" specified,"
+                  " must contain at least one of 'RWTEXB'%s",
+                 argv[0], VTY_NEWLINE);
+         return CMD_WARNING;
+       }
+    }
+
+  cpu_record_clear (filter);
+  return CMD_SUCCESS;
+}
 \f
 /* List allocation and head/tail print out. */
 static void
@@ -525,7 +608,7 @@ thread_master_free (struct thread_master *m)
 }
 
 /* Thread list is empty or not.  */
-static inline int
+static int
 thread_empty (struct thread_list *list)
 {
   return  list->head ? 0 : 1;
@@ -903,6 +986,24 @@ thread_timer_process (struct thread_list *list, struct timeval *timenow)
   return ready;
 }
 
+/* process a list en masse, e.g. for event thread lists */
+static unsigned int
+thread_process (struct thread_list *list)
+{
+  struct thread *thread;
+  unsigned int ready = 0;
+  
+  for (thread = list->head; thread; thread = thread->next)
+    {
+      thread_list_delete (list, thread);
+      thread->type = THREAD_READY;
+      thread_list_add (&thread->master->ready, thread);
+      ready++;
+    }
+  return ready;
+}
+
+
 /* Fetch next ready thread. */
 struct thread *
 thread_fetch (struct thread_master *m, struct thread *fetch)
@@ -911,41 +1012,48 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
   fd_set readfd;
   fd_set writefd;
   fd_set exceptfd;
-  struct timeval timer_val;
+  struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 };
   struct timeval timer_val_bg;
-  struct timeval *timer_wait;
+  struct timeval *timer_wait = &timer_val;
   struct timeval *timer_wait_bg;
 
   while (1)
     {
       int num = 0;
       
-      /* Signals are highest priority */
+      /* Signals pre-empt everything */
       quagga_sigevent_process ();
        
-      /* Normal event are the next highest priority.  */
-      if ((thread = thread_trim_head (&m->event)) != NULL)
-        return thread_run (m, thread, fetch);
-      
-      /* If there are any ready threads from previous scheduler runs,
-       * process top of them.  
+      /* Drain the ready queue of already scheduled jobs, before scheduling
+       * more.
        */
       if ((thread = thread_trim_head (&m->ready)) != NULL)
         return thread_run (m, thread, fetch);
       
+      /* To be fair to all kinds of threads, and avoid starvation, we
+       * need to be careful to consider all thread types for scheduling
+       * in each quanta. I.e. we should not return early from here on.
+       */
+       
+      /* Normal event are the next highest priority.  */
+      thread_process (&m->event);
+      
       /* Structure copy.  */
       readfd = m->readfd;
       writefd = m->writefd;
       exceptfd = m->exceptfd;
       
       /* Calculate select wait timer if nothing else to do */
-      quagga_get_relative (NULL);
-      timer_wait = thread_timer_wait (&m->timer, &timer_val);
-      timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
-      
-      if (timer_wait_bg &&
-         (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
-       timer_wait = timer_wait_bg;
+      if (m->ready.count == 0)
+        {
+          quagga_get_relative (NULL);
+          timer_wait = thread_timer_wait (&m->timer, &timer_val);
+          timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
+          
+          if (timer_wait_bg &&
+              (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
+            timer_wait = timer_wait_bg;
+        }
       
       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
       
index b52bc541d6fcb53860121cc9647cc9ea592d7c72..978aa6b0ad4972908f1bdda89b758a5706fd1371 100644 (file)
@@ -82,7 +82,7 @@ struct thread
 struct cpu_thread_history 
 {
   int (*func)(struct thread *);
-  const char *funcname;
+  char *funcname;
   unsigned int total_calls;
   struct time_stats
   {
@@ -197,6 +197,7 @@ extern int thread_should_yield (struct thread *);
 /* Internal libzebra exports */
 extern void thread_getrusage (RUSAGE_T *);
 extern struct cmd_element show_thread_cpu_cmd;
+extern struct cmd_element clear_thread_cpu_cmd;
 
 /* replacements for the system gettimeofday(), clock_gettime() and
  * time() functions, providing support for non-decrementing clock on
index d9eb921e26a80fd94774702d68ecbbdb02e07732..83bd6785fc51bb7b5bcbdade4c809897bb603fc4 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -1685,7 +1685,6 @@ static int
 vty_accept (struct thread *thread)
 {
   int vty_sock;
-  struct vty *vty;
   union sockunion su;
   int ret;
   unsigned int on;
@@ -1770,7 +1769,7 @@ vty_accept (struct thread *thread)
   if (bufp)
     XFREE (MTYPE_TMP, bufp);
 
-  vty = vty_create (vty_sock, &su);
+  vty_create (vty_sock, &su);
 
   return 0;
 }
index 7c811edd14592922b565cba492a342c3adb5c43f..61643bf814003a1a08c8101a4d59b51e41052504 100644 (file)
@@ -103,7 +103,7 @@ work_queue_free (struct work_queue *wq)
   return;
 }
 
-static inline int
+static int
 work_queue_schedule (struct work_queue *wq, unsigned int delay)
 {
   /* if appropriate, schedule work queue thread */
@@ -341,7 +341,7 @@ work_queue_run (struct thread *thread)
 
 stats:
 
-#define WQ_HYSTERIS_FACTOR 2
+#define WQ_HYSTERESIS_FACTOR 4
 
   /* we yielded, check whether granularity should be reduced */
   if (yielded && (cycles < wq->cycles.granularity))
@@ -349,17 +349,18 @@ stats:
       wq->cycles.granularity = ((cycles > 0) ? cycles 
                                              : WORK_QUEUE_MIN_GRANULARITY);
     }
-  
-  if (cycles >= (wq->cycles.granularity))
+  /* otherwise, should granularity increase? */
+  else if (cycles >= (wq->cycles.granularity))
     {
       if (cycles > wq->cycles.best)
         wq->cycles.best = cycles;
       
-      /* along with yielded check, provides hysteris for granularity */
-      if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR * 2))
-        wq->cycles.granularity *= WQ_HYSTERIS_FACTOR; /* quick ramp-up */
-      else if (cycles > (wq->cycles.granularity * WQ_HYSTERIS_FACTOR))
-        wq->cycles.granularity += WQ_HYSTERIS_FACTOR;
+      /* along with yielded check, provides hysteresis for granularity */
+      if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR
+                                           * WQ_HYSTERESIS_FACTOR))
+        wq->cycles.granularity *= WQ_HYSTERESIS_FACTOR; /* quick ramp-up */
+      else if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR))
+        wq->cycles.granularity += WQ_HYSTERESIS_FACTOR;
     }
 #undef WQ_HYSTERIS_FACTOR
   
index 37ee2420ff76bfeedd2340977e98771c32fe756b..12d113e7760832c497dc4c77b2354801ea04853a 100644 (file)
@@ -837,7 +837,6 @@ zebra_interface_address_read (int type, struct stream *s)
 static int
 zclient_read (struct thread *thread)
 {
-  int ret;
   size_t already;
   uint16_t length, command;
   uint8_t marker, version;
@@ -932,47 +931,47 @@ zclient_read (struct thread *thread)
     {
     case ZEBRA_ROUTER_ID_UPDATE:
       if (zclient->router_id_update)
-       ret = (*zclient->router_id_update) (command, zclient, length);
+       (*zclient->router_id_update) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_ADD:
       if (zclient->interface_add)
-       ret = (*zclient->interface_add) (command, zclient, length);
+       (*zclient->interface_add) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_DELETE:
       if (zclient->interface_delete)
-       ret = (*zclient->interface_delete) (command, zclient, length);
+       (*zclient->interface_delete) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_ADDRESS_ADD:
       if (zclient->interface_address_add)
-       ret = (*zclient->interface_address_add) (command, zclient, length);
+       (*zclient->interface_address_add) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_ADDRESS_DELETE:
       if (zclient->interface_address_delete)
-       ret = (*zclient->interface_address_delete) (command, zclient, length);
+       (*zclient->interface_address_delete) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_UP:
       if (zclient->interface_up)
-       ret = (*zclient->interface_up) (command, zclient, length);
+       (*zclient->interface_up) (command, zclient, length);
       break;
     case ZEBRA_INTERFACE_DOWN:
       if (zclient->interface_down)
-       ret = (*zclient->interface_down) (command, zclient, length);
+       (*zclient->interface_down) (command, zclient, length);
       break;
     case ZEBRA_IPV4_ROUTE_ADD:
       if (zclient->ipv4_route_add)
-       ret = (*zclient->ipv4_route_add) (command, zclient, length);
+       (*zclient->ipv4_route_add) (command, zclient, length);
       break;
     case ZEBRA_IPV4_ROUTE_DELETE:
       if (zclient->ipv4_route_delete)
-       ret = (*zclient->ipv4_route_delete) (command, zclient, length);
+       (*zclient->ipv4_route_delete) (command, zclient, length);
       break;
     case ZEBRA_IPV6_ROUTE_ADD:
       if (zclient->ipv6_route_add)
-       ret = (*zclient->ipv6_route_add) (command, zclient, length);
+       (*zclient->ipv6_route_add) (command, zclient, length);
       break;
     case ZEBRA_IPV6_ROUTE_DELETE:
       if (zclient->ipv6_route_delete)
-       ret = (*zclient->ipv6_route_delete) (command, zclient, length);
+       (*zclient->ipv6_route_delete) (command, zclient, length);
       break;
     default:
       break;
index 65fcb597a56a3269b6e24916fed597c23122d095..d40bd97f3023c523a1ca13f4f8c6122b5220272e 100644 (file)
@@ -131,7 +131,7 @@ Report bugs to zebra@zebra.org\n", progname);
   exit (status);
 }
 
-static void
+static void __attribute__ ((noreturn))
 ospf6_exit (int status)
 {
   extern struct ospf6 *ospf6;
index 0a8ac3e4fde74792dcd8a5a876159eb3e7323d92..881771a7f4d921464798a92d9dc811e820cb9a3f 100644 (file)
@@ -132,6 +132,9 @@ ospf6_zebra_if_state_update (int command, struct zclient *zclient,
   struct interface *ifp;
 
   ifp = zebra_interface_state_read (zclient->ibuf);
+  if (ifp == NULL)
+    return 0;
+  
   if (IS_OSPF6_DEBUG_ZEBRA (RECV))
     zlog_debug ("Zebra Interface state change: "
                 "%s index %d flags %llx metric %d mtu %d",
index d06a34adaa4eaeeaa7be12738a77e022c0ace49a..b7cc20dd87bceb2aa807291f0a8ce0e2be5b76b7 100644 (file)
@@ -565,8 +565,7 @@ ospf_check_abr_status (struct ospf *ospf)
       if (IS_DEBUG_OSPF_EVENT)
        zlog_debug ("ospf_check_abr_status(): new router flags: %x",new_flags);
       ospf->flags = new_flags;
-      OSPF_TIMER_ON (ospf->t_router_lsa_update,
-                    ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+      ospf_router_lsa_update (ospf);
     }
 }
 
@@ -751,7 +750,7 @@ ospf_abr_announce_network_to_area (struct prefix_ipv4 *p, u_int32_t cost,
             zlog_debug ("ospf_abr_announce_network_to_area(): "
                        "refreshing summary");
           set_metric (old, cost);
-          lsa = ospf_summary_lsa_refresh (area->ospf, old);
+          lsa = ospf_lsa_refresh (area->ospf, old);
           
           if (!lsa)
             {
@@ -1139,7 +1138,7 @@ ospf_abr_announce_rtr_to_area (struct prefix_ipv4 *p, u_int32_t cost,
       if (old) 
        { 
          set_metric (old, cost);
-         lsa = ospf_summary_asbr_lsa_refresh (area->ospf, old);
+         lsa = ospf_lsa_refresh (area->ospf, old);
        }
       else
        lsa = ospf_summary_asbr_lsa_originate (p, cost, area);
index 773831910740bb4ce17100fed8ea0e6fb9ef31be..fc3b51ddfd330aae9a08109eaf501ab9c13223eb 100644 (file)
@@ -219,7 +219,7 @@ msg_print (struct msg *msg)
 #else /* ORIGINAL_CODING */
   /* API message common header part. */
   zlog_debug
-    ("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%lu)",
+    ("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%zd)",
      ospf_api_typename (msg->hdr.msgtype), msg->hdr.msgtype, 
      ntohs (msg->hdr.msglen), (unsigned long) ntohl (msg->hdr.msgseq),
      STREAM_DATA (msg->s), STREAM_SIZE (msg->s));
index 15fd2e5fc0c25dcf577f1f7ffd85d43cdd1f5491..2a9003b72b8b854521a83c097bcb0ba30529a654 100644 (file)
@@ -1831,7 +1831,7 @@ ospf_apiserver_lsa11_originator (void *arg)
 
 /* Periodically refresh opaque LSAs so that they do not expire in
    other routers. */
-void
+struct ospf_lsa *
 ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
 {
   struct ospf_apiserver *apiserv;
@@ -1904,7 +1904,7 @@ ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa)
     }
 
 out:
-  return;
+  return new;
 }
 
 
index 9a8ae254e88b02371b8c0c424bda000afcb46601..b60f56b4fc9e7b7a60d4b4647f62b06ffbf16bef 100644 (file)
@@ -180,7 +180,7 @@ extern void ospf_apiserver_config_write_router (struct vty *vty);
 extern void ospf_apiserver_config_write_if (struct vty *vty, struct interface *ifp);
 extern void ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa);
 extern int ospf_ospf_apiserver_lsa_originator (void *arg);
-extern void ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa);
+extern struct ospf_lsa *ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa);
 extern void ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
                                      u_char lsa_type, u_char opaque_type);
 
index 9d2aedb206727d5781bb5fa9b6f515269c7fb5a6..a23b4f2be1d4455705080670dbd9ff76a14f742f 100644 (file)
@@ -264,8 +264,7 @@ ospf_asbr_status_update (struct ospf *ospf, u_char status)
 
   /* Transition from/to status ASBR, schedule timer. */
   ospf_spf_calculate_schedule (ospf);
-  OSPF_TIMER_ON (ospf->t_router_lsa_update,
-                ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+  ospf_router_lsa_update (ospf);
 }
 
 void
index 7b7a798abb926209c7d1802623f8b9fbd68bf383..6a72e31dc41773696b14ebbc13ec1e080685cdba 100644 (file)
@@ -450,7 +450,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
 
   /* if there is a Intra/Inter area route to the N
      do not install external route */
-  if (NULL != (rn = route_node_lookup (ospf->new_table,
+  if ((rn = route_node_lookup (ospf->new_table,
                              (struct prefix *) &p)))
     {
       route_unlock_node(rn);
@@ -462,7 +462,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa)
     }
   /* Find a route to the same dest */
   /* If there is no route, create new one. */
-  if (NULL != (rn = route_node_lookup (ospf->new_external_route,
+  if ((rn = route_node_lookup (ospf->new_external_route,
                               (struct prefix *) &p)))
       route_unlock_node(rn);
 
@@ -717,7 +717,6 @@ ospf_ase_register_external_lsa (struct ospf_lsa *lsa, struct ospf *top)
 
   /* We assume that if LSA is deleted from DB
      is is also deleted from this RT */
-
   listnode_add (lst, ospf_lsa_lock (lsa)); /* external_lsas lst */
 }
 
@@ -798,7 +797,8 @@ ospf_ase_incremental_update (struct ospf *ospf, struct ospf_lsa *lsa)
     }
 
   rn = route_node_lookup (ospf->external_lsas, (struct prefix *) &p);
-  assert (rn && rn->info);
+  assert (rn); 
+  assert (rn->info);
   lsas = rn->info;
   route_unlock_node (rn);
 
index f72087b5d23b654d1882e0b0bf4f46c1d0cc143c..2ebae89ac39c91c8ee865b6a8ba8d22ef804e47a 100644 (file)
@@ -135,7 +135,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf,
       /* Originate a new instance and schedule flooding */
       if (area->router_lsa_self)
        area->router_lsa_self->data->ls_seqnum = new->data->ls_seqnum;
-      ospf_router_lsa_timer_add (area);
+      ospf_router_lsa_update_area (area);
       return;
     case OSPF_NETWORK_LSA:
 #ifdef HAVE_OPAQUE_LSA
@@ -171,7 +171,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf,
             if (oi->network_lsa_self)
              oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum;
             /* Schedule network-LSA origination. */
-            ospf_network_lsa_timer_add (oi);
+            ospf_network_lsa_update (oi);
             return;
           }
       break;
@@ -992,3 +992,33 @@ ospf_lsa_flush_as (struct ospf *ospf, struct ospf_lsa *lsa)
   ospf_flood_through_as (ospf, NULL, lsa);
   ospf_lsa_maxage (ospf, lsa);
 }
+
+void
+ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa)
+{
+  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
+  
+  switch (lsa->data->type)
+    {
+      case OSPF_ROUTER_LSA:
+      case OSPF_NETWORK_LSA:
+      case OSPF_SUMMARY_LSA:
+      case OSPF_ASBR_SUMMARY_LSA:
+      case OSPF_AS_NSSA_LSA:
+#ifdef HAVE_OPAQUE_LSA
+      case OSPF_OPAQUE_LINK_LSA:
+      case OSPF_OPAQUE_AREA_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+        ospf_lsa_flush_area (lsa, lsa->area);
+        break;
+      case OSPF_AS_EXTERNAL_LSA:
+#ifdef HAVE_OPAQUE_LSA
+      case OSPF_OPAQUE_AS_LSA:
+#endif /* HAVE_OPAQUE_LSA */
+        ospf_lsa_flush_as (ospf, lsa);
+        break;
+      default:
+        zlog_info ("%s: Unknown LSA type %u", __func__, lsa->data->type);
+        break;
+    }
+}
index 5382e8fe240bdeae0c6bff1529f745931786017b..1ab11b88b147000ebbfb326712f1fd309a983fa4 100644 (file)
@@ -66,6 +66,7 @@ extern void ospf_flood_lsa_area (struct ospf_lsa *, struct ospf_area *);
 extern void ospf_flood_lsa_as (struct ospf_lsa *);
 extern void ospf_lsa_flush_area (struct ospf_lsa *, struct ospf_area *);
 extern void ospf_lsa_flush_as (struct ospf *, struct ospf_lsa *);
+extern void ospf_lsa_flush (struct ospf *, struct ospf_lsa *);
 extern struct external_info *ospf_external_info_check (struct ospf_lsa *);
 
 extern void ospf_lsdb_init (struct ospf_lsdb *);
index afe3acf133e817636c9e40769fcec32421995924..dc0787d562753aa23df6e1e1ea1d325eaf17a880 100644 (file)
@@ -97,7 +97,7 @@ ospf_if_recalculate_output_cost (struct interface *ifp)
       if (oi->output_cost != newcost)
        {
          oi->output_cost = newcost;
-         ospf_router_lsa_timer_add (oi->area);
+         ospf_router_lsa_update_area (oi->area);
        }
     }
 }
@@ -219,9 +219,6 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p)
   ospf_add_to_if (ifp, oi);
   listnode_add (ospf->oiflist, oi);
   
-  /* Clear self-originated network-LSA. */
-  oi->network_lsa_self = NULL;
-
   /* Initialize neighbor list. */
   oi->nbrs = route_table_init ();
 
@@ -301,10 +298,6 @@ ospf_if_cleanup (struct ospf_interface *oi)
   ospf_nbr_delete (oi->nbr_self);
   oi->nbr_self = ospf_nbr_new (oi);
   ospf_nbr_add_self (oi);
-  
-  ospf_lsa_unlock (&oi->network_lsa_self);
-  oi->network_lsa_self = NULL;
-  OSPF_TIMER_OFF (oi->t_network_lsa_self);
 }
 
 void
@@ -335,6 +328,8 @@ ospf_if_free (struct ospf_interface *oi)
   listnode_delete (oi->ospf->oiflist, oi);
   listnode_delete (oi->area->oiflist, oi);
 
+  thread_cancel_event (master, oi);
+
   memset (oi, 0, sizeof (*oi));
   XFREE (MTYPE_OSPF_IF, oi);
 }
@@ -534,6 +529,8 @@ ospf_new_if_params (void)
 
   oip->auth_crypt = list_new ();
   
+  oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
+
   return oip;
 }
 
@@ -572,7 +569,8 @@ ospf_free_if_params (struct interface *ifp, struct in_addr addr)
       !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
       !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
       !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
-      listcount (oip->auth_crypt) == 0)
+      listcount (oip->auth_crypt) == 0 &&
+      ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER)
     {
       ospf_del_if_params (oip);
       rn->info = NULL;
@@ -1121,8 +1119,8 @@ ospf_vl_up_check (struct ospf_area *area, struct in_addr rid,
              if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
                zlog_debug ("ospf_vl_up_check: VL cost change,"
                           " scheduling router lsa refresh");
-             if(ospf->backbone)
-               ospf_router_lsa_timer_add (ospf->backbone);
+             if (ospf->backbone)
+               ospf_router_lsa_update_area (ospf->backbone);
              else if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
                zlog_debug ("ospf_vl_up_check: VL cost change, no backbone!");
            }
index ab0b758078f52715cac2b3db9e0bd59d93003946..6db887738bd9429c48e5ffed448882724e725f64 100644 (file)
@@ -73,6 +73,9 @@ struct ospf_if_params
   
   DECLARE_IF_PARAM (struct list *, auth_crypt);    /* List of Auth cryptographic data. */
   DECLARE_IF_PARAM (int, auth_type);               /* OSPF authentication type */
+  
+  /* Other, non-configuration state */
+  u_int32_t network_lsa_seqnum;                /* Network LSA seqnum */
 };
 
 enum
@@ -167,6 +170,7 @@ struct ospf_interface
 
   /* Configured varables. */
   struct ospf_if_params *params;
+  
   u_int32_t crypt_seqnum;              /* Cryptographic Sequence Number */ 
   u_int32_t output_cost;               /* Acutual Interface Output Cost */
 
@@ -206,8 +210,6 @@ struct ospf_interface
   struct thread *t_ls_ack;              /* timer */
   struct thread *t_ls_ack_direct;       /* event */
   struct thread *t_ls_upd_event;        /* event */
-  struct thread *t_network_lsa_self;    /* self-originated network-LSA
-                                           reflesh thread. timer */
 #ifdef HAVE_OPAQUE_LSA
   struct thread *t_opaque_lsa_self;     /* Type-9 Opaque-LSAs */
 #endif /* HAVE_OPAQUE_LSA */
index 3172587a91ffcf888f4683c441cc5d4c9197df63..db53882d0194259d288062720b5f6000d535f86f 100644 (file)
@@ -578,20 +578,17 @@ ism_change_state (struct ospf_interface *oi, int state)
     oi->area->act_ints++;
 
   /* schedule router-LSA originate. */
-  ospf_router_lsa_timer_add (oi->area);
+  ospf_router_lsa_update_area (oi->area);
 
   /* Originate network-LSA. */
   if (old_state != ISM_DR && state == ISM_DR)
-    ospf_network_lsa_timer_add (oi);
+    ospf_network_lsa_update (oi);
   else if (old_state == ISM_DR && state != ISM_DR)
     {
       /* Free self originated network LSA. */
       lsa = oi->network_lsa_self;
       if (lsa)
-       {
-         ospf_lsa_flush_area (lsa, oi->area);
-         OSPF_TIMER_OFF (oi->t_network_lsa_self);
-       }
+        ospf_lsa_flush_area (lsa, oi->area);
 
       ospf_lsa_unlock (&oi->network_lsa_self);
       oi->network_lsa_self = NULL;
index 2f50676e2b1ac63d9fdf8383541aaaf487a26d05..d5959eb11b80c2a1d963281be1835a8d8be24684 100644 (file)
@@ -372,7 +372,7 @@ lsa_header_set (struct stream *s, u_char options,
 
   lsah = (struct lsa_header *) STREAM_DATA (s);
 
-  lsah->ls_age = htons (0);
+  lsah->ls_age = htons (OSPF_LSA_INITIAL_AGE);
   lsah->options = options;
   lsah->type = type;
   lsah->id = id;
@@ -741,12 +741,12 @@ ospf_stub_router_timer (struct thread *t)
   
   UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
   
-  ospf_router_lsa_timer_add (area);
+  ospf_router_lsa_update_area (area);
   
   return 0;
 }
 
-inline static void
+static void
 ospf_stub_router_check (struct ospf_area *area)
 {
   /* area must either be administratively configured to be stub
@@ -885,6 +885,9 @@ ospf_router_lsa_refresh (struct ospf_lsa *lsa)
   /* Delete LSA from neighbor retransmit-list. */
   ospf_ls_retransmit_delete_nbr_area (area, lsa);
 
+  /* Unregister LSA from refresh-list */
+  ospf_refresher_unregister_lsa (area->ospf, lsa);
+  
   /* Create new router-LSA instance. */
   if ( (new = ospf_router_lsa_new (area)) == NULL)
     {
@@ -910,20 +913,15 @@ ospf_router_lsa_refresh (struct ospf_lsa *lsa)
   return NULL;
 }
 
-static int
-ospf_router_lsa_timer (struct thread *t)
+int
+ospf_router_lsa_update_area (struct ospf_area *area)
 {
-  struct ospf_area *area;
-
   if (IS_DEBUG_OSPF_EVENT)
-    zlog_debug ("Timer[router-LSA]: (router-LSA Refresh expire)");
-
-  area = THREAD_ARG (t);
-  area->t_router_lsa_self = NULL;
+    zlog_debug ("[router-LSA]: (router-LSA area update)");
 
   /* Now refresh router-LSA. */
   if (area->router_lsa_self)
-    ospf_router_lsa_refresh (area->router_lsa_self);
+    ospf_lsa_refresh (area->ospf, area->router_lsa_self);
   /* Newly originate router-LSA. */
   else
     ospf_router_lsa_originate (area);
@@ -931,50 +929,15 @@ ospf_router_lsa_timer (struct thread *t)
   return 0;
 }
 
-void
-ospf_router_lsa_timer_add (struct ospf_area *area)
-{
-  /* Keep area's self-originated router-LSA. */
-  struct ospf_lsa *lsa = area->router_lsa_self;
-
-  /* Cancel previously scheduled router-LSA timer. */
-  if (area->t_router_lsa_self)
-    if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
-      zlog_debug ("LSA[Type1]: Cancel previous router-LSA timer");
-
-  OSPF_TIMER_OFF (area->t_router_lsa_self);
-
-  /* If router-LSA is originated previously, check the interval time. */
-  if (lsa)
-    {
-      int delay;
-      if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
-        {
-         OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
-                             ospf_router_lsa_timer, delay);
-         return;
-        }
-    }
-
-  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
-    zlog_debug ("LSA[Type1]: Scheduling router-LSA origination right away");
-
-  /* Immediately refresh router-LSA. */
-  OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);
-}
-
 int
-ospf_router_lsa_update_timer (struct thread *thread)
+ospf_router_lsa_update (struct ospf *ospf)
 {
-  struct ospf *ospf = THREAD_ARG (thread);
   struct listnode *node, *nnode;
   struct ospf_area *area;
 
   if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
     zlog_debug ("Timer[router-LSA Update]: (timer expire)");
 
-  ospf->t_router_lsa_update = NULL;
-
   for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
     {
       struct ospf_lsa *lsa = area->router_lsa_self;
@@ -999,19 +962,20 @@ ospf_router_lsa_update_timer (struct thread *thread)
          if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
            zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
                      lsa->data->type, inet_ntoa (lsa->data->id), area_str);
+          ospf_refresher_unregister_lsa (ospf, lsa);
          ospf_lsa_flush_area (lsa, area);
          ospf_lsa_unlock (&area->router_lsa_self);
          area->router_lsa_self = NULL;
 
          /* Refresh router-LSA, (not install) and flood through area. */
-         ospf_router_lsa_timer_add (area);
+         ospf_router_lsa_update_area (area);
        }
       else
        {
          rl = (struct router_lsa *) lsa->data;
          /* Refresh router-LSA, (not install) and flood through area. */
          if (rl->flags != ospf->flags)
-           ospf_router_lsa_timer_add (area);
+           ospf_router_lsa_update_area (area);
        }
     }
 
@@ -1048,6 +1012,7 @@ ospf_network_lsa_new (struct ospf_interface *oi)
   struct stream *s;
   struct ospf_lsa *new;
   struct lsa_header *lsah;
+  struct ospf_if_params *oip;
   int length;
 
   /* If there are no neighbours on this network (the net is stub),
@@ -1086,20 +1051,42 @@ ospf_network_lsa_new (struct ospf_interface *oi)
   new->data = ospf_lsa_data_new (length);
   memcpy (new->data, lsah, length);
   stream_free (s);
-
+  
+  /* Remember prior network LSA sequence numbers, even if we stop
+   * originating one for this oi, to try avoid re-originating LSAs with a
+   * prior sequence number, and thus speed up adjency forming & convergence.
+   */
+  if ((oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4)))
+    {
+      new->data->ls_seqnum = oip->network_lsa_seqnum;
+      new->data->ls_seqnum = lsa_seqnum_increment (new);
+    }
+  else
+    {
+      oip = ospf_get_if_params (oi->ifp, oi->address->u.prefix4);
+      ospf_if_update_params (oi->ifp, oi->address->u.prefix4);
+    }
+  oip->network_lsa_seqnum = new->data->ls_seqnum;
+  
   return new;
 }
 
 /* Originate network-LSA. */
-static struct ospf_lsa *
-ospf_network_lsa_originate (struct ospf_interface *oi)
+void
+ospf_network_lsa_update (struct ospf_interface *oi)
 {
   struct ospf_lsa *new;
-
+  
+  if (oi->network_lsa_self != NULL)
+    {
+      ospf_lsa_refresh (oi->ospf, oi->network_lsa_self);
+      return;
+    }
+  
   /* Create new network-LSA instance. */
   new = ospf_network_lsa_new (oi);
   if (new == NULL)
-    return NULL;
+    return;
 
   /* Install LSA to LSDB. */
   new = ospf_lsa_install (oi->ospf, oi, new);
@@ -1117,28 +1104,51 @@ ospf_network_lsa_originate (struct ospf_interface *oi)
       ospf_lsa_header_dump (new->data);
     }
 
-  return new;
+  return;
 }
 
-int
-ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
+static struct ospf_lsa *
+ospf_network_lsa_refresh (struct ospf_lsa *lsa)
 {
   struct ospf_area *area = lsa->area;
-  struct ospf_lsa *new;
-
+  struct ospf_lsa *new, *new2;
+  struct ospf_if_params *oip;
+  struct ospf_interface *oi;
+  
   assert (lsa->data);
-
+  
+  /* Retrieve the oi for the network LSA */
+  oi = ospf_if_lookup_by_local_addr (area->ospf, NULL, lsa->data->id);
+  if (oi == NULL)
+    {
+      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
+        {
+          zlog_debug ("LSA[Type%d:%s]: network-LSA refresh: "
+                      "no oi found, ick, ignoring.",
+                     lsa->data->type, inet_ntoa (lsa->data->id));
+          ospf_lsa_header_dump (lsa->data);
+        }
+      return NULL;
+    }
   /* Delete LSA from neighbor retransmit-list. */
   ospf_ls_retransmit_delete_nbr_area (area, lsa);
 
+  /* Unregister LSA from refresh-list */
+  ospf_refresher_unregister_lsa (area->ospf, lsa);
+  
   /* Create new network-LSA instance. */
   new = ospf_network_lsa_new (oi);
   if (new == NULL)
-    return -1;
-  new->data->ls_seqnum = lsa_seqnum_increment (lsa);
-
-  ospf_lsa_install (area->ospf, oi, new);
+    return NULL;
+  
+  oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4);
+  assert (oip != NULL);
+  oip->network_lsa_seqnum = new->data->ls_seqnum = lsa_seqnum_increment (lsa);
 
+  new2 = ospf_lsa_install (area->ospf, oi, new);
+  
+  assert (new2 == new);
+  
   /* Flood LSA through aera. */
   ospf_flood_through_area (area, NULL, new);
 
@@ -1149,60 +1159,8 @@ ospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
       ospf_lsa_header_dump (new->data);
     }
 
-  return 0;
-}
-
-static int
-ospf_network_lsa_refresh_timer (struct thread *t)
-{
-  struct ospf_interface *oi;
-
-  oi = THREAD_ARG (t);
-  oi->t_network_lsa_self = NULL;
-
-  if (oi->network_lsa_self)
-    /* Now refresh network-LSA. */
-    ospf_network_lsa_refresh (oi->network_lsa_self, oi);
-  else
-    /* Newly create network-LSA. */
-    ospf_network_lsa_originate (oi);
-
-  return 0;
-}
-
-void
-ospf_network_lsa_timer_add (struct ospf_interface *oi)
-{
-  /* Keep interface's self-originated network-LSA. */
-  struct ospf_lsa *lsa = oi->network_lsa_self;
-
-  /* Cancel previously schedules network-LSA timer. */
-  if (oi->t_network_lsa_self)
-    if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
-      zlog_debug ("LSA[Type2]: Cancel previous network-LSA timer");
-  OSPF_TIMER_OFF (oi->t_network_lsa_self);
-
-  /* If network-LSA is originated previously, check the interval time. */
-  if (lsa)
-    {
-      int delay;
-      if ((delay = ospf_lsa_refresh_delay (lsa)) > 0)
-        {
-          oi->t_network_lsa_self =
-            thread_add_timer (master, ospf_network_lsa_refresh_timer,
-                             oi, delay);
-          return;
-        }
-    }
-
-  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
-    zlog_debug ("Scheduling network-LSA origination right away");
-
-  /* Immediately refresh network-LSA. */
-  oi->t_network_lsa_self =
-    thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);
+  return new;
 }
-
 \f
 static void
 stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
@@ -1326,7 +1284,7 @@ ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
   return new;
 }
 
-struct ospf_lsa*
+static struct ospf_lsa*
 ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
 {
   struct ospf_lsa *new;
@@ -1473,7 +1431,7 @@ ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
   return new;
 }
 
-struct ospf_lsa*
+static struct ospf_lsa*
 ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
 {
   struct ospf_lsa *new;
@@ -2299,6 +2257,7 @@ ospf_external_lsa_refresh_default (struct ospf *ospf)
        {
          if (IS_DEBUG_OSPF_EVENT)
            zlog_debug ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
+          ospf_refresher_unregister_lsa (ospf, lsa);
          ospf_lsa_flush_as (ospf, lsa);
        }
     }
@@ -2327,7 +2286,7 @@ ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force)
 }
 
 /* Refresh AS-external-LSA. */
-void
+struct ospf_lsa *
 ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
                           struct external_info *ei, int force)
 {
@@ -2343,7 +2302,7 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
                    lsa->data->type, inet_ntoa (lsa->data->id));
       ospf_external_lsa_flush (ospf, ei->type, &ei->p,
                               ei->ifindex /*, ei->nexthop */);
-      return;
+      return NULL;
     }
 
   if (!changed && !force)
@@ -2351,7 +2310,7 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
       if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
         zlog_debug ("LSA[Type%d:%s]: Not refreshed, not changed/forced",
                    lsa->data->type, inet_ntoa (lsa->data->id));
-      return;
+      return NULL;
     }
 
   /* Delete LSA from neighbor retransmit-list. */
@@ -2367,7 +2326,7 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
       if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
        zlog_debug ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
                   inet_ntoa (lsa->data->id));
-      return;
+      return NULL;
     }
   
   new->data->ls_seqnum = lsa_seqnum_increment (lsa);
@@ -2396,7 +2355,7 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
       ospf_lsa_header_dump (new->data);
     }
 
-  return;
+  return new;
 }
 
 \f
@@ -2404,8 +2363,8 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
 
 /* Install router-LSA to an area. */
 static struct ospf_lsa *
-ospf_router_lsa_install (struct ospf *ospf,
-                        struct ospf_lsa *new, int rt_recalc)
+ospf_router_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
+                         int rt_recalc)
 {
   struct ospf_area *area = new->area;
 
@@ -2424,15 +2383,11 @@ ospf_router_lsa_install (struct ospf *ospf,
       if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
        return new; /* ignore stale LSA */
 
-      /* Set router-LSA refresh timer. */
-      OSPF_TIMER_OFF (area->t_router_lsa_self);
-      OSPF_AREA_TIMER_ON (area->t_router_lsa_self,
-                          ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME);
-
       /* Set self-originated router-LSA. */
       ospf_lsa_unlock (&area->router_lsa_self);
       area->router_lsa_self = ospf_lsa_lock (new);
 
+      ospf_refresher_register_lsa (ospf, new);
     }
   if (rt_recalc)
     ospf_spf_calculate_schedule (ospf);
@@ -2465,15 +2420,9 @@ ospf_network_lsa_install (struct ospf *ospf,
       if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
        return new; /* ignore stale LSA */
 
-      /* Set LSRefresh timer. */
-      OSPF_TIMER_OFF (oi->t_network_lsa_self);
-
-      OSPF_INTERFACE_TIMER_ON (oi->t_network_lsa_self,
-                              ospf_network_lsa_refresh_timer,
-                              OSPF_LS_REFRESH_TIME);
-
       ospf_lsa_unlock (&oi->network_lsa_self);
       oi->network_lsa_self = ospf_lsa_lock (new);
+      ospf_refresher_register_lsa (ospf, new);
     }
   if (rt_recalc)
     ospf_spf_calculate_schedule (ospf);
@@ -2721,7 +2670,8 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
           if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
             {
              zlog_debug ("ospf_lsa_install() Premature Aging "
-                        "lsa 0x%lx", (u_long)lsa);
+                        "lsa 0x%p, seqnum 0x%x",
+                        lsa, ntohl(lsa->data->ls_seqnum));
              ospf_lsa_header_dump (lsa->data);
             }
         }
@@ -2826,7 +2776,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
                    new->data->type, 
                    inet_ntoa (new->data->id), 
                    lsa);
-      ospf_lsa_maxage (ospf, lsa);
+      ospf_lsa_flush (ospf, lsa);
     }
 
   return new;
@@ -2858,35 +2808,6 @@ ospf_check_nbr_status (struct ospf *ospf)
 }
 
 \f
-#ifdef ORIGINAL_CODING
-/* This function flood the maxaged LSA to DR. */
-void
-ospf_maxage_flood (struct ospf_lsa *lsa)
-{
-  switch (lsa->data->type)
-    {
-    case OSPF_ROUTER_LSA:
-    case OSPF_NETWORK_LSA:
-    case OSPF_SUMMARY_LSA:
-    case OSPF_ASBR_SUMMARY_LSA:
-    case OSPF_AS_NSSA_LSA:
-#ifdef HAVE_OPAQUE_LSA
-    case OSPF_OPAQUE_LINK_LSA:
-    case OSPF_OPAQUE_AREA_LSA:
-#endif /* HAVE_OPAQUE_LSA */
-      ospf_flood_through_area (lsa->area, NULL, lsa);
-      break;
-    case OSPF_AS_EXTERNAL_LSA:
-#ifdef HAVE_OPAQUE_LSA
-    case OSPF_OPAQUE_AS_LSA:
-#endif /* HAVE_OPAQUE_LSA */
-      ospf_flood_through_as (NULL, lsa);
-      break;
-    default:
-      break;
-    }
-}
-#endif /* ORIGINAL_CODING */
 
 static int
 ospf_maxage_lsa_remover (struct thread *thread)
@@ -2911,7 +2832,11 @@ ospf_maxage_lsa_remover (struct thread *thread)
             reschedule = 1;
             continue;
           }
-
+        
+        /* TODO: maybe convert this function to a work-queue */
+        if (thread_should_yield (thread))
+          OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0);
+          
         /* Remove LSA from the LSDB */
         if (IS_LSA_SELF (lsa))
           if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
@@ -2922,19 +2847,11 @@ ospf_maxage_lsa_remover (struct thread *thread)
           zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list",
                      lsa->data->type, inet_ntoa (lsa->data->id));
 
-       /* Flood max age LSA. */
-#ifdef ORIGINAL_CODING
-       ospf_maxage_flood (lsa);
-#else /* ORIGINAL_CODING */
-        ospf_flood_through (ospf, NULL, lsa);
-#endif /* ORIGINAL_CODING */
-
-       if (lsa->flags & OSPF_LSA_PREMATURE_AGE)  
+       if (CHECK_FLAG (lsa->flags, OSPF_LSA_PREMATURE_AGE))
           {
             if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
-              zlog_debug ("originating new router lsa for lsa 0x%lx \n", 
-                         (u_long)lsa);
-            ospf_router_lsa_originate(lsa->area);
+              zlog_debug ("originating new lsa for lsa 0x%p\n", lsa);
+            ospf_lsa_refresh (ospf, lsa);
           }
 
        /* Remove from lsdb. */
@@ -2953,7 +2870,8 @@ ospf_maxage_lsa_remover (struct thread *thread)
         neighbor Link state retransmission lists and b) none of the router's
         neighbors are in states Exchange or Loading. */
   if (reschedule)
-    OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
+    OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover,
+                   ospf->maxage_delay);
 
   return 0;
 }
@@ -2971,6 +2889,11 @@ ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
     }
 }
 
+/* Add LSA onto the MaxAge list, and schedule for removal.
+ * This does *not* lead to the LSA being flooded, that must be taken
+ * care of elsewhere, see, e.g., ospf_lsa_flush* (which are callers of this
+ * function).
+ */
 void
 ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
 {
@@ -2990,7 +2913,8 @@ ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
   if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
     zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
 
-  OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2);
+  OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover,
+                 ospf->maxage_delay);
 }
 
 static int
@@ -3035,6 +2959,10 @@ ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa)
        ospf_lsa_maxage (ospf, lsa);
       }
 
+  if (IS_LSA_MAXAGE (lsa) && !ospf_lsa_is_self_originated (ospf, lsa))
+    if (LS_AGE (lsa) > OSPF_LSA_MAXAGE + 30)
+      printf ("Eek! Shouldn't happen!\n");
+
   return 0;
 }
 
@@ -3353,6 +3281,7 @@ ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
   switch (lsa->data->type)
     {
 #ifdef HAVE_OPAQUE_LSA
+    /* Opaque wants to be notified of flushes */
     case OSPF_OPAQUE_LINK_LSA:
     case OSPF_OPAQUE_AREA_LSA:
     case OSPF_OPAQUE_AS_LSA:
@@ -3360,7 +3289,8 @@ ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
       break;
 #endif /* HAVE_OPAQUE_LSA */
     default:
-      ospf_lsa_maxage (ospf, lsa);
+      ospf_refresher_unregister_lsa (ospf, lsa);
+      ospf_lsa_flush (ospf, lsa);
       break;
     }
 
@@ -3383,12 +3313,13 @@ ospf_flush_self_originated_lsas_now (struct ospf *ospf)
       if ((lsa = area->router_lsa_self) != NULL)
         {
           if (IS_DEBUG_OSPF_EVENT)
-            zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
-
+            zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH",
+                        lsa->data->type, inet_ntoa (lsa->data->id));
+          
+          ospf_refresher_unregister_lsa (ospf, lsa);
           ospf_lsa_flush_area (lsa, area);
           ospf_lsa_unlock (&area->router_lsa_self);
           area->router_lsa_self = NULL;
-          OSPF_TIMER_OFF (area->t_router_lsa_self);
         }
 
       for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
@@ -3398,12 +3329,13 @@ ospf_flush_self_originated_lsas_now (struct ospf *ospf)
                &&   oi->full_nbrs > 0)
             {
               if (IS_DEBUG_OSPF_EVENT)
-                zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
-
+                zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH",
+                            lsa->data->type, inet_ntoa (lsa->data->id));
+              
+              ospf_refresher_unregister_lsa (ospf, oi->network_lsa_self);
               ospf_lsa_flush_area (oi->network_lsa_self, area);
               ospf_lsa_unlock (&oi->network_lsa_self);
               oi->network_lsa_self = NULL;
-              OSPF_TIMER_OFF (oi->t_network_lsa_self);
             }
 
           if (oi->type != OSPF_IFTYPE_VIRTUALLINK
@@ -3603,23 +3535,29 @@ ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
 
 \f
 /* LSA Refreshment functions. */
-static void
+struct ospf_lsa *
 ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
 {
   struct external_info *ei;
+  struct ospf_lsa *new = NULL;
+  assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
   assert (IS_LSA_SELF (lsa));
+  assert (lsa->lock > 0);
 
   switch (lsa->data->type)
     {
       /* Router and Network LSAs are processed differently. */
     case OSPF_ROUTER_LSA:
+      new = ospf_router_lsa_refresh (lsa);
+      break;
     case OSPF_NETWORK_LSA: 
+      new = ospf_network_lsa_refresh (lsa);
       break;
     case OSPF_SUMMARY_LSA:
-      ospf_summary_lsa_refresh (ospf, lsa);
+      new = ospf_summary_lsa_refresh (ospf, lsa);
       break;
     case OSPF_ASBR_SUMMARY_LSA:
-      ospf_summary_asbr_lsa_refresh (ospf, lsa);
+      new = ospf_summary_asbr_lsa_refresh (ospf, lsa);
       break;
     case OSPF_AS_EXTERNAL_LSA:
       /* Translated from NSSA Type-5s are refreshed when 
@@ -3629,7 +3567,7 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
         break;
       ei = ospf_external_info_check (lsa);
       if (ei)
-        ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
+        new = ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
       else
         ospf_lsa_flush_as (ospf, lsa);
       break;
@@ -3637,12 +3575,13 @@ ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
     case OSPF_OPAQUE_LINK_LSA:
     case OSPF_OPAQUE_AREA_LSA:
     case OSPF_OPAQUE_AS_LSA:
-      ospf_opaque_lsa_refresh (lsa);
+      new = ospf_opaque_lsa_refresh (lsa);
       break;
 #endif /* HAVE_OPAQUE_LSA */
     default:
       break;
     }
+  return new;
 }
 
 void
@@ -3650,6 +3589,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
 {
   u_int16_t index, current_index;
   
+  assert (lsa->lock > 0);
   assert (IS_LSA_SELF (lsa));
 
   if (lsa->refresh_list < 0)
@@ -3668,11 +3608,11 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
       if (delay < 0)
        delay = 0;
 
-      current_index = ospf->lsa_refresh_queue.index +
-       (quagga_time (NULL) - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
+      current_index = ospf->lsa_refresh_queue.index + (quagga_time (NULL)
+                - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
       
       index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
-       % (OSPF_LSA_REFRESHER_SLOTS);
+             % (OSPF_LSA_REFRESHER_SLOTS);
 
       if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
        zlog_debug ("LSA[Refresh]: lsa %s with age %d added to index %d",
@@ -3684,7 +3624,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
       lsa->refresh_list = index;
       if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
         zlog_debug ("LSA[Refresh:%s]: ospf_refresher_register_lsa(): "
-                   "setting refresh_list on lsa %p (index %u)", 
+                   "setting refresh_list on lsa %p (slod %d)", 
                    inet_ntoa (lsa->data->id), lsa, index);
     }
 }
@@ -3692,6 +3632,7 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
 void
 ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
 {
+  assert (lsa->lock > 0);
   assert (IS_LSA_SELF (lsa));
   if (lsa->refresh_list >= 0)
     {
@@ -3728,8 +3669,9 @@ ospf_lsa_refresh_walker (struct thread *t)
      modulus. */
   ospf->lsa_refresh_queue.index =
    ((unsigned long)(ospf->lsa_refresh_queue.index +
-                   (quagga_time (NULL) - ospf->lsa_refresher_started) /
-                   OSPF_LSA_REFRESHER_GRANULARITY)) % OSPF_LSA_REFRESHER_SLOTS;
+                   (quagga_time (NULL) - ospf->lsa_refresher_started)
+                   / OSPF_LSA_REFRESHER_GRANULARITY))
+                   % OSPF_LSA_REFRESHER_SLOTS;
 
   if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
     zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
@@ -3744,6 +3686,8 @@ ospf_lsa_refresh_walker (struct thread *t)
 
       refresh_list = ospf->lsa_refresh_queue.qs [i];
       
+      assert (i >= 0);
+
       ospf->lsa_refresh_queue.qs [i] = NULL;
 
       if (refresh_list)
@@ -3755,8 +3699,8 @@ ospf_lsa_refresh_walker (struct thread *t)
                           "refresh lsa %p (slot %d)", 
                           inet_ntoa (lsa->data->id), lsa, i);
              
+             assert (lsa->lock > 0);
              list_delete_node (refresh_list, node);
-             ospf_lsa_unlock (&lsa); /* lsa_refresh_queue */
              lsa->refresh_list = -1;
              listnode_add (lsa_to_refresh, lsa);
            }
@@ -3769,7 +3713,11 @@ ospf_lsa_refresh_walker (struct thread *t)
   ospf->lsa_refresher_started = quagga_time (NULL);
 
   for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa))
-    ospf_lsa_refresh (ospf, lsa);
+    {
+      ospf_lsa_refresh (ospf, lsa);
+      assert (lsa->lock > 0);
+      ospf_lsa_unlock (&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/
+    }
   
   list_delete (lsa_to_refresh);
   
index 6b2ba2289cad6c2ace3e1f38cce7b61727197cd1..f364840f6b5476e07012ea5cc37e4e78724e22c7 100644 (file)
@@ -115,11 +115,9 @@ struct ospf_lsa
 
   /* Refreshement List or Queue */
   int refresh_list;
-
-#ifdef HAVE_OPAQUE_LSA
-  /* For Type-9 Opaque-LSAs, reference to ospf-interface is required. */
+  
+  /* For Type-9 Opaque-LSAs */
   struct ospf_interface *oi;
-#endif /* HAVE_OPAQUE_LSA */
 };
 
 /* OSPF LSA Link Type. */
@@ -255,19 +253,16 @@ extern struct lsa_header *ospf_lsa_data_dup (struct lsa_header *);
 extern void ospf_lsa_data_free (struct lsa_header *);
 
 /* Prototype for various LSAs */
-extern int ospf_router_lsa_update_timer (struct thread *);
-extern void ospf_router_lsa_timer_add (struct ospf_area *);
+extern int ospf_router_lsa_update (struct ospf *);
+extern int ospf_router_lsa_update_area (struct ospf_area *);
 
-extern int ospf_network_lsa_refresh (struct ospf_lsa *, struct ospf_interface *);
-extern void ospf_network_lsa_timer_add (struct ospf_interface *);
+extern void ospf_network_lsa_update (struct ospf_interface *);
 
 extern struct ospf_lsa *ospf_summary_lsa_originate (struct prefix_ipv4 *, u_int32_t,
                                             struct ospf_area *);
 extern struct ospf_lsa *ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *,
                                                  u_int32_t,
                                                  struct ospf_area *);
-extern struct ospf_lsa *ospf_summary_lsa_refresh (struct ospf *, struct ospf_lsa *);
-extern struct ospf_lsa *ospf_summary_asbr_lsa_refresh (struct ospf *, struct ospf_lsa *);
 
 extern struct ospf_lsa *ospf_lsa_install (struct ospf *,
                                   struct ospf_interface *, struct ospf_lsa *);
@@ -302,12 +297,15 @@ extern void ospf_lsa_maxage (struct ospf *, struct ospf_lsa *);
 extern u_int32_t get_metric (u_char *);
 
 extern int ospf_lsa_maxage_walker (struct thread *);
-
+extern struct ospf_lsa *ospf_lsa_refresh (struct ospf *, struct ospf_lsa *);
 extern void ospf_external_lsa_refresh_default (struct ospf *);
 
 extern void ospf_external_lsa_refresh_type (struct ospf *, u_char, int);
-extern void ospf_external_lsa_refresh (struct ospf *, struct ospf_lsa *,
-                               struct external_info *, int);
+extern struct ospf_lsa *ospf_external_lsa_refresh (struct ospf *,
+                                                   struct ospf_lsa *,
+                                                   struct external_info *,
+                                                   int);
 extern struct in_addr ospf_lsa_unique_id (struct ospf *, struct ospf_lsdb *, u_char,
                                   struct prefix_ipv4 *);
 extern void ospf_schedule_lsa_flood_area (struct ospf_area *, struct ospf_lsa *);
index c906f05283b6ddcac750dcee31b8c26170762ff4..ea9a35284439c44ce294129d3c340c1dd9dac63e 100644 (file)
@@ -120,7 +120,10 @@ ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
   
   /* nothing to do? */
   if (rn->info && rn->info == lsa)
-    return;
+    {
+      route_unlock_node (rn);
+      return;
+    }
   
   /* purge old entry? */
   if (rn->info)
@@ -162,12 +165,13 @@ ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
       return;
     }
   
+  assert (lsa->data->type < OSPF_MAX_LSA);
   table = lsdb->type[lsa->data->type].db;
   lsdb_prefix_set (&lp, lsa);
-  rn = route_node_lookup (table, (struct prefix *) &lp);
-  if (rn && (rn->info == lsa))
+  if ((rn = route_node_lookup (table, (struct prefix *) &lp)))
     {
-      ospf_lsdb_delete_entry (lsdb, rn);
+      if (rn->info == lsa)
+        ospf_lsdb_delete_entry (lsdb, rn);
       route_unlock_node (rn); /* route_node_lookup */
     }
 }
@@ -274,7 +278,8 @@ ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type,
       rn = route_top (table);
   else
     {
-      rn = route_node_get (table, (struct prefix *) &lp);
+      if ((rn = route_node_lookup (table, (struct prefix *) &lp)) == NULL)
+        return NULL;
       rn = route_next (rn);
     }
 
index 15fff349acf54eb4c3b2d89c0e743420cd3a1a7b..cbc31716b324777c8b94e3af9d3602189a499578 100644 (file)
@@ -162,7 +162,7 @@ nsm_should_adj (struct ospf_neighbor *nbr)
 \f
 /* OSPF NSM functions. */
 static int
-nsm_hello_received (struct ospf_neighbor *nbr)
+nsm_packet_received (struct ospf_neighbor *nbr)
 {
   /* Start or Restart Inactivity Timer. */
   OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
@@ -216,7 +216,7 @@ ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
     {
     case OSPF_OPAQUE_LINK_LSA:
       /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */
-      if (lsa->oi != nbr->oi)
+      if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi)
           return 0;
       break;
     case OSPF_OPAQUE_AREA_LSA:
@@ -408,7 +408,7 @@ struct {
   {
     /* DependUpon: dummy state. */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { NULL,                    NSM_DependUpon }, /* HelloReceived     */
+    { NULL,                    NSM_DependUpon }, /* PacketReceived    */
     { NULL,                    NSM_DependUpon }, /* Start             */
     { NULL,                    NSM_DependUpon }, /* 2-WayReceived     */
     { NULL,                    NSM_DependUpon }, /* NegotiationDone   */
@@ -425,7 +425,7 @@ struct {
   {
     /* Deleted: dummy state. */
     { NULL,                    NSM_Deleted    }, /* NoEvent           */
-    { NULL,                    NSM_Deleted    }, /* HelloReceived     */
+    { NULL,                    NSM_Deleted    }, /* PacketReceived    */
     { NULL,                    NSM_Deleted    }, /* Start             */
     { NULL,                    NSM_Deleted    }, /* 2-WayReceived     */
     { NULL,                    NSM_Deleted    }, /* NegotiationDone   */
@@ -442,7 +442,7 @@ struct {
   {
     /* Down: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Init       }, /* PacketReceived    */
     { nsm_start,               NSM_Attempt    }, /* Start             */
     { NULL,                    NSM_Down       }, /* 2-WayReceived     */
     { NULL,                    NSM_Down       }, /* NegotiationDone   */
@@ -459,7 +459,7 @@ struct {
   {
     /* Attempt: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Init       }, /* PacketReceived    */
     { NULL,                    NSM_Attempt    }, /* Start             */
     { NULL,                    NSM_Attempt    }, /* 2-WayReceived     */
     { NULL,                    NSM_Attempt    }, /* NegotiationDone   */
@@ -476,7 +476,7 @@ struct {
   {
     /* Init: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Init       }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Init      }, /* PacketReceived    */
     { NULL,                    NSM_Init       }, /* Start             */
     { nsm_twoway_received,     NSM_DependUpon }, /* 2-WayReceived     */
     { NULL,                    NSM_Init       }, /* NegotiationDone   */
@@ -493,7 +493,7 @@ struct {
   {
     /* 2-Way: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_TwoWay     }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_TwoWay     }, /* HelloReceived     */
     { NULL,                    NSM_TwoWay     }, /* Start             */
     { NULL,                    NSM_TwoWay     }, /* 2-WayReceived     */
     { NULL,                    NSM_TwoWay     }, /* NegotiationDone   */
@@ -510,7 +510,7 @@ struct {
   {
     /* ExStart: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_ExStart    }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_ExStart    }, /* PacaketReceived   */
     { NULL,                    NSM_ExStart    }, /* Start             */
     { NULL,                    NSM_ExStart    }, /* 2-WayReceived     */
     { nsm_negotiation_done,    NSM_Exchange   }, /* NegotiationDone   */
@@ -527,7 +527,7 @@ struct {
   {
     /* Exchange: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Exchange   }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Exchange   }, /* PacketReceived    */
     { NULL,                    NSM_Exchange   }, /* Start             */
     { NULL,                    NSM_Exchange   }, /* 2-WayReceived     */
     { NULL,                    NSM_Exchange   }, /* NegotiationDone   */
@@ -544,7 +544,7 @@ struct {
   {
     /* Loading: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Loading    }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Loading    }, /* PacketReceived    */
     { NULL,                    NSM_Loading    }, /* Start             */
     { NULL,                    NSM_Loading    }, /* 2-WayReceived     */
     { NULL,                    NSM_Loading    }, /* NegotiationDone   */
@@ -560,7 +560,7 @@ struct {
   },
   { /* Full: */
     { NULL,                    NSM_DependUpon }, /* NoEvent           */
-    { nsm_hello_received,      NSM_Full       }, /* HelloReceived     */
+    { nsm_packet_received,     NSM_Full       }, /* PacketReceived    */
     { NULL,                    NSM_Full       }, /* Start             */
     { NULL,                    NSM_Full       }, /* 2-WayReceived     */
     { NULL,                    NSM_Full       }, /* NegotiationDone   */
@@ -579,7 +579,7 @@ struct {
 static const char *ospf_nsm_event_str[] =
 {
   "NoEvent",
-  "HelloReceived",
+  "PacketReceived",
   "Start",
   "2-WayReceived",
   "NegotiationDone",
@@ -711,7 +711,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state)
                 LOOKUP(ospf_nsm_state_msg, old_state),
                 LOOKUP(ospf_nsm_state_msg, state));
 
-      ospf_router_lsa_timer_add (oi->area);
+      ospf_router_lsa_update_area (oi->area);
 
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
        {
@@ -719,7 +719,7 @@ nsm_change_state (struct ospf_neighbor *nbr, int state)
            ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id);
          
          if (vl_area)
-           ospf_router_lsa_timer_add (vl_area);
+           ospf_router_lsa_update_area (vl_area);
        }
 
       /* Originate network-LSA. */
@@ -730,10 +730,9 @@ nsm_change_state (struct ospf_neighbor *nbr, int state)
              ospf_lsa_flush_area (oi->network_lsa_self, oi->area);
              ospf_lsa_unlock (&oi->network_lsa_self);
              oi->network_lsa_self = NULL;
-             OSPF_TIMER_OFF (oi->t_network_lsa_self);
            }
          else
-           ospf_network_lsa_timer_add (oi);
+           ospf_network_lsa_update (oi);
        }
     }
 
index 1121dae6108a856084fe72d0cc58a6dfc2fc2264..4f2ae808393f530e50d306cb281661867f823ea6 100644 (file)
@@ -39,7 +39,7 @@
 
 /* OSPF Neighbor State Machine Event. */
 #define NSM_NoEvent            0
-#define NSM_HelloReceived      1
+#define NSM_PacketReceived     1 /* HelloReceived in the protocol */
 #define NSM_Start              2
 #define NSM_TwoWayReceived     3
 #define NSM_NegotiationDone    4
index 0b6ac4cb7b8f88d782791f420c5a98cb3c48c8a5..aa126e1922e1485d5ab7649af9c667ae27a4f7b0 100644 (file)
@@ -251,7 +251,7 @@ struct ospf_opaque_functab
   void (* config_write_debug )(struct vty *vty);
   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa);
   int  (* lsa_originator)(void *arg);
-  void (* lsa_refresher )(struct ospf_lsa *lsa);
+  struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa);
   int (* new_lsa_hook)(struct ospf_lsa *lsa);
   int (* del_lsa_hook)(struct ospf_lsa *lsa);
 };
@@ -354,7 +354,7 @@ ospf_register_opaque_functab (
   void (* config_write_debug )(struct vty *vty),
   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
   int  (* lsa_originator)(void *arg),
-  void (* lsa_refresher )(struct ospf_lsa *lsa),
+  struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
   int (* new_lsa_hook)(struct ospf_lsa *lsa),
   int (* del_lsa_hook)(struct ospf_lsa *lsa))
 {
@@ -1608,12 +1608,13 @@ out:
   return new;
 }
 
-void
+struct ospf_lsa *
 ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
 {
   struct ospf *ospf;
   struct ospf_opaque_functab *functab;
-
+  struct ospf_lsa *new = NULL;
+  
   ospf = ospf_lookup ();
 
   if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL
@@ -1630,12 +1631,12 @@ ospf_opaque_lsa_refresh (struct ospf_lsa *lsa)
         zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id));
 
       lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
-      ospf_lsa_maxage (ospf, lsa);
+      ospf_lsa_flush (ospf, lsa);
     }
   else
-    (* functab->lsa_refresher)(lsa);
+    new = (* functab->lsa_refresher)(lsa);
 
-  return;
+  return new;
 }
 
 /*------------------------------------------------------------------------*
@@ -2108,7 +2109,7 @@ ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0)
     zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)));
 
   /* This lsa will be flushed and removed eventually. */
-  ospf_lsa_maxage (lsa0->area->ospf, lsa);
+  ospf_lsa_flush (lsa0->area->ospf, lsa);
 
 out:
   return;
index f49fe4606405692bbe1f42c423f78f10fe65495d..22730645667a7506cc372c7472c89497ec2badd5 100644 (file)
@@ -120,7 +120,7 @@ ospf_register_opaque_functab (
   void (* config_write_debug )(struct vty *vty),
   void (* show_opaque_info   )(struct vty *vty, struct ospf_lsa *lsa),
   int  (* lsa_originator)(void *arg),
-  void (* lsa_refresher )(struct ospf_lsa *lsa),
+  struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa),
   int (* new_lsa_hook)(struct ospf_lsa *lsa),
   int (* del_lsa_hook)(struct ospf_lsa *lsa)
 );
@@ -143,7 +143,7 @@ extern void ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi,
                                                int *init_delay);
 extern struct ospf_lsa *ospf_opaque_lsa_install (struct ospf_lsa *,
                                                 int rt_recalc);
-extern void ospf_opaque_lsa_refresh (struct ospf_lsa *lsa);
+extern struct ospf_lsa *ospf_opaque_lsa_refresh (struct ospf_lsa *lsa);
 
 extern void ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent,
                                                  u_char lsa_type,
index 994d36297f13b35ba1ddae632a71554e2274323e..b714c27de0f73e33bd95d79967d76eea2218fffb 100644 (file)
@@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
   fifo->count++;
 }
 
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+  op->next = fifo->head;
+  
+  if (fifo->tail == NULL)
+    fifo->tail = op;
+  
+  fifo->head = op;
+  
+  fifo->count++;
+}
+
 /* Delete first packet from fifo. */
 struct ospf_packet *
 ospf_fifo_pop (struct ospf_fifo *fifo)
@@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
   /* ospf_fifo_debug (oi->obuf); */
 }
 
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+  if (!oi->obuf)
+    {
+      zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+              "destination %s) called with NULL obuf, ignoring "
+              "(please report this bug)!\n",
+              IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+              ospf_packet_type_str[stream_getc_from(op->s, 1)],
+              inet_ntoa (op->dst));
+      return;
+    }
+
+  /* Add packet to head of queue. */
+  ospf_fifo_push_head (oi->obuf, op);
+
+  /* Debug of packet fifo*/
+  /* ospf_fifo_debug (oi->obuf); */
+}
+
 void
 ospf_packet_delete (struct ospf_interface *oi)
 {
@@ -231,7 +266,7 @@ ospf_packet_dup (struct ospf_packet *op)
 }
 
 /* XXX inline */
-static inline unsigned int
+static unsigned int
 ospf_packet_authspace (struct ospf_interface *oi)
 {
   int auth = 0;
@@ -653,6 +688,13 @@ ospf_write (struct thread *thread)
   iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
   iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
 
+#if defined(__DragonFly__)
+  /*
+   * DragonFly's raw socket expects ip_len/ip_off in network byte order.
+   */
+  iph.ip_len = htons(iph.ip_len);
+#endif
+
 #ifdef WANT_OSPF_WRITE_FRAGMENT
   /* XXX-MT: not thread-safe at all..
    * XXX: this presumes this is only programme sending OSPF packets 
@@ -881,7 +923,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   old_state = nbr->state;
 
   /* Add event to thread. */
-  OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
 
   /*  RFC2328  Section 9.5.1
       If the router is not eligible to become Designated Router,
@@ -901,7 +943,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   if (oi->type == OSPF_IFTYPE_NBMA &&
       (old_state == NSM_Down || old_state == NSM_Attempt))
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
       nbr->priority = hello->priority;
       nbr->d_router = hello->d_router;
       nbr->bd_router = hello->bd_router;
@@ -911,12 +953,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
   if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
                              size - OSPF_HELLO_MIN_SIZE))
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
       nbr->options |= hello->options;
     }
   else
     {
-      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
       /* Set neighbor information. */
       nbr->priority = hello->priority;
       nbr->d_router = hello->d_router;
@@ -1191,6 +1233,9 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
     }
 #endif /* HAVE_OPAQUE_LSA */
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Process DD packet by neighbor status. */
   switch (nbr->state)
     {
@@ -1412,6 +1457,9 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Neighbor State should be Exchange or later. */
   if (nbr->state != NSM_Exchange &&
       nbr->state != NSM_Loading &&
@@ -1649,6 +1697,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   /* Check neighbor state. */
   if (nbr->state < NSM_Exchange)
     {
@@ -1951,7 +2002,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
              quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
              
              if (tv_cmp (tv_sub (now, current->tv_orig), 
-                         int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
+                         int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
                /* Trap NSSA type later.*/
                ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
              DISCARD_LSA (lsa, 8);
@@ -1982,6 +2033,9 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
       return;
     }
 
+  /* Add event to thread. */
+  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
   if (nbr->state < NSM_Exchange)
     {
       zlog_warn ("Link State Acknowledgment: "
@@ -2085,6 +2139,15 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
   ip_len = ip_len + (iph->ip_hl << 2);
 #endif
   
+#if defined(__DragonFly__)
+  /*
+   * in DragonFly's raw socket, ip_len/ip_off are read 
+   * in network byte order.
+   * As OpenBSD < 200311 adjust ip_len to strip IP header size!
+   */
+  ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
+#endif
+
   ifindex = getsockopt_ifindex (AF_INET, &msgh);
   
   *ifp = if_lookup_by_index (ifindex);
@@ -2150,7 +2213,7 @@ ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
   return NULL;
 }
 
-static inline int
+static int
 ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
 {
   /* Check match the Area ID of the receiving interface. */
@@ -2978,8 +3041,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
   return length;
 }
 
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
 {
   struct ospf_packet *op;
   u_int16_t length = OSPF_HEADER_SIZE;
@@ -2998,10 +3061,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
   /* Set packet length. */
   op->length = length;
 
-  op->dst.s_addr = addr->s_addr;
+  op->dst.s_addr = addr;
 
-  /* Add packet to the interface output queue. */
-  ospf_packet_add (oi, op);
+  /* Add packet to the top of the interface output queue, so that they
+   * can't get delayed by things like long queues of LS Update packets
+   */
+  ospf_packet_add_top (oi, op);
 
   /* Hook thread to write packet. */
   OSPF_ISM_WRITE_ON (oi->ospf);
@@ -3032,7 +3097,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
       && oi->state != ISM_DR && oi->state != ISM_Backup)
     return;
 
-  ospf_hello_send_sub (oi, &nbr_nbma->addr);
+  ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
 }
 
 int
@@ -3071,7 +3136,7 @@ ospf_hello_reply_timer (struct thread *thread)
     zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
          IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
 
-  ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+  ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
 
   return 0;
 }
@@ -3080,27 +3145,10 @@ ospf_hello_reply_timer (struct thread *thread)
 void
 ospf_hello_send (struct ospf_interface *oi)
 {
-  struct ospf_packet *op;
-  u_int16_t length = OSPF_HEADER_SIZE;
-
   /* If this is passive interface, do not send OSPF Hello. */
   if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
     return;
 
-  op = ospf_packet_new (oi->ifp->mtu);
-
-  /* Prepare OSPF common header. */
-  ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
-  /* Prepare OSPF Hello body. */
-  length += ospf_make_hello (oi, op->s);
-
-  /* Fill OSPF header. */
-  ospf_fill_header (oi, op->s, length);
-
-  /* Set packet length. */
-  op->length = length;
-
   if (oi->type == OSPF_IFTYPE_NBMA)
     {
       struct ospf_neighbor *nbr;
@@ -3130,34 +3178,16 @@ ospf_hello_send (struct ospf_interface *oi)
                if (nbr->priority == 0 && oi->state == ISM_DROther)
                  continue;
                /* if oi->state == Waiting, send hello to all neighbors */
-               {
-                 struct ospf_packet *op_dup;
-
-                 op_dup = ospf_packet_dup(op);
-                 op_dup->dst = nbr->address.u.prefix4;
-
-                 /* Add packet to the interface output queue. */
-                 ospf_packet_add (oi, op_dup);
-
-                 OSPF_ISM_WRITE_ON (oi->ospf);
-               }
-
+               ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
              }
-      ospf_packet_free (op);
     }
   else
     {
       /* Decide destination address. */
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-       op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
-      else 
-       op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
-      /* Add packet to the interface output queue. */
-      ospf_packet_add (oi, op);
-
-      /* Hook thread to write packet. */
-      OSPF_ISM_WRITE_ON (oi->ospf);
+        ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+      else
+        ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
     }
 }
 
index 7b3d686612049fd924dfbb5e4e3f247950f5d6c8..9a472081a6718c165140749ec620b380d4b39ee0 100644 (file)
@@ -162,6 +162,5 @@ extern int ospf_ls_upd_timer (struct thread *);
 extern int ospf_ls_ack_timer (struct thread *);
 extern int ospf_poll_timer (struct thread *);
 extern int ospf_hello_reply_timer (struct thread *);
-extern void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *);
 
 #endif /* _ZEBRA_OSPF_PACKET_H */
index c5ec0ad8d06566f0a27e0627785797a6a60464c8..24e81052f75a96bba01947ae20fd5757d9a8779c 100644 (file)
@@ -133,7 +133,7 @@ static void ospf_mpls_te_config_write_router (struct vty *vty);
 static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);
 static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);
 static int ospf_mpls_te_lsa_originate (void *arg);
-static void ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
+static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);
 static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);
 
 static void del_mpls_te_link (void *val);
@@ -1009,7 +1009,7 @@ out:
   return rc;
 }
 
-static void
+static struct ospf_lsa *
 ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
 {
   struct mpls_te_link *lp;
@@ -1070,7 +1070,7 @@ ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa)
     }
 
 out:
-  return;
+  return new;
 }
 
 static void
index f68adb2d1dc49b6cc03fafe8af4f4f5fa348621d..97c8e8d62e0d2a148193fef52b76f96afa07ef31 100644 (file)
@@ -2913,7 +2913,13 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
                       inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
            }
        }
-
+      
+      /* Next network-LSA sequence number we'll use, if we're elected DR */
+      if (oi->params && ntohl (oi->params->network_lsa_seqnum)
+                          != OSPF_INITIAL_SEQUENCE_NUMBER)
+        vty_out (vty, "  Saved Network-LSA sequence number 0x%x%s",
+                 ntohl (oi->params->network_lsa_seqnum), VTY_NEWLINE);
+      
       vty_out (vty, "  Multicast group memberships:");
       if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)
           || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
@@ -7012,7 +7018,7 @@ DEFUN (ospf_max_metric_router_lsa_admin,
       SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
       
       if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
-          ospf_router_lsa_timer_add (area);
+          ospf_router_lsa_update_area (area);
     }
   return CMD_SUCCESS;
 }
@@ -7038,7 +7044,7 @@ DEFUN (no_ospf_max_metric_router_lsa_admin,
           && !area->t_stub_router)
         {
           UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
-          ospf_router_lsa_timer_add (area);
+          ospf_router_lsa_update_area (area);
         }
     }
   return CMD_SUCCESS;
@@ -7091,7 +7097,7 @@ DEFUN (no_ospf_max_metric_router_lsa_startup,
       if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
         {
           UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
-          ospf_router_lsa_timer_add (area);
+          ospf_router_lsa_update_area (area);
         }
     }
   return CMD_SUCCESS;
index c250fe9e731e9acc747733ee09f5000fdd6feadc..e8405136765303f7159a5ea58c49de5c21cb1bbc 100644 (file)
@@ -131,8 +131,8 @@ ospf_router_id_update (struct ospf *ospf)
          ospf->external_origin = 0;
        }
 
-      OSPF_TIMER_ON (ospf->t_router_lsa_update,
-                    ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
+      /* update router-lsa's for each area */
+      ospf_router_lsa_update (ospf);
       
       /* update ospf_interface's */
       for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
@@ -199,6 +199,7 @@ ospf_new (void)
   new->spf_hold_multiplier = 1;
 
   /* MaxAge init. */
+  new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
   new->maxage_lsa = list_new ();
   new->t_maxage_walker =
     thread_add_timer (master, ospf_lsa_maxage_walker,
@@ -337,7 +338,7 @@ ospf_deferred_shutdown_check (struct ospf *ospf)
           SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED);
           
           if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
-              ospf_router_lsa_timer_add (area);
+            ospf_router_lsa_update_area (area);
         }
       timeout = ospf->stub_router_shutdown_time;
     }
@@ -473,7 +474,6 @@ ospf_finish_final (struct ospf *ospf)
 
   /* Cancel all timers. */
   OSPF_TIMER_OFF (ospf->t_external_lsa);
-  OSPF_TIMER_OFF (ospf->t_router_lsa_update);
   OSPF_TIMER_OFF (ospf->t_spf_calc);
   OSPF_TIMER_OFF (ospf->t_ase_calc);
   OSPF_TIMER_OFF (ospf->t_maxage);
@@ -631,7 +631,6 @@ ospf_area_free (struct ospf_area *area)
     free (IMPORT_NAME (area));
 
   /* Cancel timer. */
-  OSPF_TIMER_OFF (area->t_router_lsa_self);
   OSPF_TIMER_OFF (area->t_stub_router);
 #ifdef HAVE_OPAQUE_LSA
   OSPF_TIMER_OFF (area->t_opaque_lsa_self);
@@ -1041,7 +1040,7 @@ ospf_area_type_set (struct ospf_area *area, int type)
       break;
     }
 
-  ospf_router_lsa_timer_add (area);
+  ospf_router_lsa_update_area (area);
   ospf_schedule_abr_task (area->ospf);
 }
 
@@ -1052,7 +1051,7 @@ ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode)
     return 0;
 
   area->shortcut_configured = mode;
-  ospf_router_lsa_timer_add (area);
+  ospf_router_lsa_update_area (area);
   ospf_schedule_abr_task (ospf);
 
   ospf_area_check_free (ospf, area->area_id);
@@ -1064,7 +1063,7 @@ int
 ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area)
 {
   area->shortcut_configured = OSPF_SHORTCUT_DEFAULT;
-  ospf_router_lsa_timer_add (area);
+  ospf_router_lsa_update_area (area);
   ospf_area_check_free (ospf, area->area_id);
   ospf_schedule_abr_task (ospf);
 
index 6eeaaf99c78759404c071ce7ae214269c1e163f8..7a56d163fa529d21f4ba486c146730d3401d4572 100644 (file)
@@ -58,6 +58,7 @@
 #endif
 #define OSPF_MIN_LS_INTERVAL                     5
 #define OSPF_MIN_LS_ARRIVAL                      1
+#define OSPF_LSA_INITIAL_AGE                     0     /* useful for debug */
 #define OSPF_LSA_MAXAGE                       3600
 #define OSPF_CHECK_AGE                         300
 #define OSPF_LSA_MAXAGE_DIFF                   900
@@ -66,7 +67,6 @@
 #define OSPF_INITIAL_SEQUENCE_NUMBER    0x80000001
 #define OSPF_MAX_SEQUENCE_NUMBER        0x7fffffff
 
-#define OSPF_LSA_MAXAGE_CHECK_INTERVAL          30
 #define OSPF_NSSA_TRANS_STABLE_DEFAULT         40
 
 #define OSPF_ALLSPFROUTERS              0xe0000005      /* 224.0.0.5 */
@@ -247,7 +247,6 @@ struct ospf
   int redistribute;                     /* Num of redistributed protocols. */
 
   /* Threads. */
-  struct thread *t_router_lsa_update;   /* router-LSA update timer. */
   struct thread *t_abr_task;            /* ABR task timer. */
   struct thread *t_asbr_check;          /* ASBR check timer. */
   struct thread *t_distribute_update;   /* Distirbute list update timer. */
@@ -257,8 +256,13 @@ struct ospf
 #ifdef HAVE_OPAQUE_LSA
   struct thread *t_opaque_lsa_self;    /* Type-11 Opaque-LSAs origin event. */
 #endif /* HAVE_OPAQUE_LSA */
+
+#define OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT   60
+  unsigned int maxage_delay;           /* Delay on Maxage remover timer, sec */
   struct thread *t_maxage;              /* MaxAge LSA remover timer. */
+#define OSPF_LSA_MAXAGE_CHECK_INTERVAL         30
   struct thread *t_maxage_walker;       /* MaxAge LSA checking timer. */
+
   struct thread *t_deferred_shutdown;  /* deferred/stub-router shutdown timer*/
 
   struct thread *t_write;
@@ -429,7 +433,6 @@ struct ospf_area
   struct vertex *spf;
 
   /* Threads. */
-  struct thread *t_router_lsa_self;/* Self-originated router-LSA timer. */
   struct thread *t_stub_router;    /* Stub-router timer */
 #ifdef HAVE_OPAQUE_LSA
   struct thread *t_opaque_lsa_self;    /* Type-10 Opaque-LSAs origin. */
index 9e51e8dd88c24f0fcc4b36946de55d4cb23d06a2..4a2ce9aa07b3bedb6cfe8002b8a7540d3f9e4bbf 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_attr.h"
 
 #define VT100_RESET "\x1b[0m"
 #define VT100_RED "\x1b[31m"
@@ -407,7 +408,7 @@ static struct test_segment {
     "#ASNs = 0, data = seq(8466 3 52737 4096 3456)",
     { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 },
     12,
-    { "", "",
+    { NULL, NULL,
       0, 0, 0, 0, 0, 0 },
   },
   { /* 26  */ 
@@ -417,10 +418,190 @@ static struct test_segment {
       0x2,0x2, 0x10,0x00, 0x0d,0x80 },
     14
     ,
-    { "", "",
+    { NULL, NULL,
       0, 0, 0, 0, 0, 0 },
   },
-  { NULL, NULL, {0}, 0, { NULL, 0, 0 } }
+  { /* 27  */ 
+    "invalid segment type",
+    "type=8(4096 3456)",
+    { 0x8,0x2, 0x10,0x00, 0x0d,0x80 },
+    14
+    ,
+    { NULL, NULL,
+      0, 0, 0, 0, 0, 0 },
+  },  { NULL, NULL, {0}, 0, { NULL, 0, 0 } }
+};
+
+/* */
+static struct aspath_tests {
+  const char *desc;
+  const struct test_segment *segment;
+  const char *shouldbe;  /* String it should evaluate to */
+  const enum as4 { AS4_DATA, AS2_DATA }
+          as4;         /* whether data should be as4 or not (ie as2) */
+  const int result;    /* expected result for bgp_attr_parse */
+  const int cap;       /* capabilities to set for peer */
+  const char attrheader [1024];
+  size_t len;
+} aspath_tests [] =
+{
+  /* 0 */
+  {
+    "basic test",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, 0,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 1 */
+  {
+    "length too short",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      8,
+    },
+    3,
+  },
+  /* 2 */
+  {
+    "length too long",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      12,
+    },
+    3,
+  },
+  /* 3 */
+  {
+    "incorrect flag",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 4 */
+  {
+    "as4_path, with as2 format data",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS2_DATA, -1,
+    0,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 5 */
+  {
+    "as4, with incorrect attr length",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      10,
+    },
+    3,
+  },
+  /* 6 */
+  {
+    "basic 4-byte as-path",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, 0,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      18,
+    },
+    3,
+  },
+  /* 7 */
+  {
+    "4b AS_PATH: too short",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      16,
+    },
+    3,
+  },
+  /* 8 */
+  {
+    "4b AS_PATH: too long",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      20,
+    },
+    3,
+  },
+  /* 9 */
+  {
+    "4b AS_PATH: too long2",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS,
+      BGP_ATTR_AS_PATH, 
+      22,
+    },
+    3,
+  },
+  /* 10 */
+  {
+    "4b AS_PATH: bad flags",
+    &test_segments[0],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS_PATH, 
+      18,
+    },
+    3,
+  },
+  /* 11 */
+  {
+    "4b AS_PATH: confed",
+    &test_segments[6],
+    "8466 3 52737 4096",
+    AS4_DATA, -1,
+    PEER_CAP_AS4_ADV,
+    { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL,
+      BGP_ATTR_AS4_PATH, 
+      14,
+    },
+    3,
+  },
+  { NULL, NULL, NULL, 0, 0, 0, { 0 }, 0 },
 };
 
 /* prepending tests */
@@ -430,21 +611,25 @@ static struct tests {
   struct test_spec sp;
 } prepend_tests[] = 
 {
+  /* 0 */
   { &test_segments[0], &test_segments[1],
     { "8466 3 52737 4096 8722 4",
       "8466 3 52737 4096 8722 4",
       6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 },
   },
+  /* 1 */
   { &test_segments[1], &test_segments[3],
     { "8722 4 8482 51457 {5204}",
       "8722 4 8482 51457 {5204}",
       5, 0, NOT_ALL_PRIVATE, 5204, 1, 8722 }
   },
+  /* 2 */
   { &test_segments[3], &test_segments[4],
     { "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}",
       "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}",
       7, 0, NOT_ALL_PRIVATE, 5204, 1, 8482 },
   },
+  /* 3 */
   { &test_segments[4], &test_segments[5],
     { "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665"
       " {2457,4369,61697} 1842 41590 51793",
@@ -452,11 +637,13 @@ static struct tests {
       " {2457,4369,61697} 1842 41590 51793",
       11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467 }
   },
+  /* 4 */
   { &test_segments[5], &test_segments[6],
-    { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793 (123 456 789)",
-      "6435 59408 21665 {2457,4369,61697} 1842 41590 51793 (123 456 789)",
-      7, 3, NOT_ALL_PRIVATE, 123, 1, 6435 },
+    { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793",
+      "6435 59408 21665 {2457,4369,61697} 1842 41590 51793",
+      7, 0, NOT_ALL_PRIVATE, 1842, 1, 6435 },
   },
+  /* 5 */
   { &test_segments[6], &test_segments[7],
     { "(123 456 789) (123 456 789) (111 222)",
       "",
@@ -649,7 +836,7 @@ make_aspath (const u_char *data, size_t len, int use32bit)
       s = stream_new (len);
       stream_put (s, data, len);
     }
-  as = aspath_parse (s, len, use32bit, 0);
+  as = aspath_parse (s, len, use32bit);
   
   if (s)
     stream_free (s);
@@ -682,6 +869,12 @@ validate (struct aspath *as, const struct test_spec *sp)
   static struct stream *s;
   struct aspath *asinout, *asconfeddel, *asstr, *as4;
   
+  if (as == NULL && sp->shouldbe == NULL)
+    {
+      printf ("Correctly failed to parse\n");
+      return fails;
+    }
+  
   out = aspath_snmp_pathseg (as, &bytes);
   asinout = make_aspath (out, bytes, 0);
   
@@ -826,7 +1019,7 @@ parse_test (struct test_segment *t)
   printf ("%s: %s\n", t->name, t->desc);
 
   asp = make_aspath (t->asdata, t->len, 0);
-
+  
   printf ("aspath: %s\nvalidating...:\n", aspath_print (asp));
 
   if (!validate (asp, &t->sp))
@@ -835,7 +1028,9 @@ parse_test (struct test_segment *t)
     printf (FAILED "\n");
   
   printf ("\n");
-  aspath_unintern (asp);
+  
+  if (asp)
+    aspath_unintern (asp);
 }
 
 /* prepend testing */
@@ -891,7 +1086,8 @@ empty_prepend_test (struct test_segment *t)
     printf (FAILED "!\n");
   
   printf ("\n");
-  aspath_unintern (asp1);
+  if (asp1)
+    aspath_unintern (asp1);
   aspath_free (asp2);
 }
 
@@ -993,30 +1189,106 @@ cmp_test ()
       aspath_unintern (asp2);
     }
 }
-     
+
+static int
+handle_attr_test (struct aspath_tests *t)
+{
+  struct bgp bgp = { 0 }; 
+  struct peer peer = { 0 };
+  struct attr attr = { 0 };  
+  int ret;
+  int initfail = failed;
+  struct aspath *asp;
+  size_t datalen;
+  
+  asp = make_aspath (t->segment->asdata, t->segment->len, 0);
+    
+  peer.ibuf = stream_new (BGP_MAX_PACKET_SIZE);
+  peer.obuf = stream_fifo_new ();
+  peer.bgp = &bgp;
+  peer.host = (char *)"none";
+  peer.fd = -1;
+  peer.cap = t->cap;
+  
+  stream_write (peer.ibuf, t->attrheader, t->len);
+  datalen = aspath_put (peer.ibuf, asp, t->as4 == AS4_DATA);
+  
+  ret = bgp_attr_parse (&peer, &attr, t->len + datalen, NULL, NULL);
+  
+  if (ret != t->result)
+    {
+      printf ("bgp_attr_parse returned %d, expected %d\n", ret, t->result);
+      printf ("datalen %d\n", datalen);
+      failed++;
+    }
+  if (ret != 0)
+    goto out;
+  
+  if (attr.aspath == NULL)
+    {
+      printf ("aspath is NULL!\n");
+      failed++;
+    }
+  if (attr.aspath && strcmp (attr.aspath->str, t->shouldbe))
+    {
+      printf ("attr str and 'shouldbe' mismatched!\n"
+              "attr str:  %s\n"
+              "shouldbe:  %s\n",
+              attr.aspath->str, t->shouldbe);
+      failed++;
+    }
+
+out:
+  if (attr.aspath)
+    aspath_unintern (attr.aspath);
+  if (asp)
+    aspath_unintern (asp);
+  return failed - initfail;
+}
+
+static void
+attr_test (struct aspath_tests *t)
+{
+    printf ("%s\n", t->desc);
+    printf ("%s\n\n", handle_attr_test (t) ? FAILED : OK);  
+}
+
 int
 main (void)
 {
   int i = 0;
-  aspath_init();
+  bgp_master_init ();
+  master = bm->master;
+  bgp_attr_init ();
+  
   while (test_segments[i].name)
     {
+      printf ("test %u\n", i);
       parse_test (&test_segments[i]);
       empty_prepend_test (&test_segments[i++]);
     }
   
   i = 0;
   while (prepend_tests[i].test1)
-    prepend_test (&prepend_tests[i++]);
+    {
+      printf ("prepend test %u\n", i);
+      prepend_test (&prepend_tests[i++]);
+    }
   
   i = 0;
   while (aggregate_tests[i].test1)
-    aggregate_test (&aggregate_tests[i++]);
+    {
+      printf ("aggregate test %u\n", i);
+      aggregate_test (&aggregate_tests[i++]);
+    }
   
   i = 0;
   
   while (reconcile_tests[i].test1)
-    as4_reconcile_test (&reconcile_tests[i++]);
+    {
+      printf ("reconcile test %u\n", i);
+      as4_reconcile_test (&reconcile_tests[i++]);
+    }
   
   i = 0;
   
@@ -1026,6 +1298,14 @@ main (void)
   
   empty_get_test();
   
+  i = 0;
+  
+  while (aspath_tests[i].desc)
+    {
+      printf ("aspath_attr test %d\n", i);
+      attr_test (&aspath_tests[i++]);
+    }
+  
   printf ("failures: %d\n", failed);
   printf ("aspath count: %ld\n", aspath_count());
   
index 028ad696e52a1189e064150b2a798b09dd8622eb..d6a38ed4511f69b26f17773a9575db9549a1f0c5 100644 (file)
@@ -25,13 +25,14 @@ for H in `seq 1 ${NUM}` ; do
                NEXTAS=$((${ASBASE} + $NEXT))
                PREVADDR="${PREFIX}${PREV}"
                PREVAS=$((${ASBASE} + $PREV))
+               ASN=$((64560+${H}))
                
                # Edit config to suit.
                cat > "$CONF" <<- EOF
                        password whatever
                        service advanced-vty
                        !
-                       router bgp $((64560+${H}))
+                       router bgp ${ASN}
                         bgp router-id ${ADDR}
                         network 10.${H}.1.0/24 pathlimit 1
                         network 10.${H}.2.0/24 pathlimit 2
@@ -40,6 +41,7 @@ for H in `seq 1 ${NUM}` ; do
                         neighbor default update-source ${ADDR}
                         neighbor default capability orf prefix-list both
                         neighbor default soft-reconfiguration inbound
+                        neighbor default route-map test out
                         neighbor ${NEXTADDR} remote-as ${NEXTAS}
                         neighbor ${NEXTADDR} peer-group default
                         neighbor ${PREVADDR} remote-as ${PREVAS}
@@ -53,10 +55,15 @@ for H in `seq 1 ${NUM}` ; do
                         neighbor default activate
                         neighbor default capability orf prefix-list both
                         neighbor default default-originate
+                        neighbor default route-map test out
                         neighbor ${NEXTADDR} peer-group default
                         neighbor ${PREVADDR} peer-group default
                         exit-address-family
                        !
+                       route-map test permit 10
+                        set extcommunity rt ${ASN}:1
+                        set extcommunity soo ${ASN}:2
+                        set community ${ASN}:1
                        line vty
                        !
                        end
index 03e7ff71386695f20702ac297c6031fc0ac0542b..933d6425459d9bc50dc52673ceb66c530fa5d0c5 100644 (file)
@@ -216,7 +216,7 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)
  * interface will affect only the primary interface/address on Solaris.
  ************************End Solaris flags hacks ***********************
  */
-static inline void
+static void
 if_flags_mangle (struct interface *ifp, uint64_t *newflags)
 {
 #ifdef SUNOS_5
index 8742b62b8cc8572a9a1af508ea55037af9636449..6403830b9af8c008a87e6cb57d7a83d39abc3c63 100644 (file)
@@ -99,14 +99,11 @@ if_group (struct interface *ifp,
          u_int32_t group, 
          int add_leave)
 {
-  struct zebra_if *zi;
   struct ip_mreq m;
   struct prefix *p;
   int ret;
   char b1[INET_ADDRSTRLEN];
 
-  zi = ifp->info;
-
   memset (&m, 0, sizeof (m));
   m.imr_multiaddr.s_addr = htonl (group);
   p = irdp_get_prefix(ifp);
index eb9eae3aab0ac5b1a70cf8ae62b4855f9693b87b..a09e459c3819b79ac8f9ed49ea2e929a45f7462a 100644 (file)
@@ -1827,11 +1827,7 @@ extern struct thread_master *master;
 static int
 kernel_read (struct thread *thread)
 {
-  int ret;
-  int sock;
-
-  sock = THREAD_FD (thread);
-  ret = netlink_parse_info (netlink_information_fetch, &netlink);
+  netlink_parse_info (netlink_information_fetch, &netlink);
   thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
 
   return 0;