summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xREADME.NetBSD4
-rw-r--r--bgpd/bgp_advertise.c10
-rw-r--r--bgpd/bgp_aspath.c167
-rw-r--r--bgpd/bgp_aspath.h4
-rw-r--r--bgpd/bgp_attr.c763
-rw-r--r--bgpd/bgp_attr.h14
-rw-r--r--bgpd/bgp_clist.c4
-rw-r--r--bgpd/bgp_community.c13
-rw-r--r--bgpd/bgp_community.h2
-rw-r--r--bgpd/bgp_ecommunity.c33
-rw-r--r--bgpd/bgp_ecommunity.h4
-rw-r--r--bgpd/bgp_main.c10
-rw-r--r--bgpd/bgp_network.c20
-rw-r--r--bgpd/bgp_nexthop.c22
-rw-r--r--bgpd/bgp_packet.c158
-rw-r--r--bgpd/bgp_route.c1088
-rw-r--r--bgpd/bgp_routemap.c34
-rw-r--r--bgpd/bgp_table.c1
-rw-r--r--bgpd/bgp_vty.c219
-rw-r--r--bgpd/bgp_zebra.c8
-rw-r--r--bgpd/bgpd.c177
-rw-r--r--bgpd/bgpd.h8
-rwxr-xr-xconfigure.ac15
-rw-r--r--lib/command.c2
-rw-r--r--lib/distribute.c25
-rw-r--r--lib/hash.c11
-rw-r--r--lib/hash.h2
-rw-r--r--lib/if.c16
-rw-r--r--lib/if_rmap.c12
-rw-r--r--lib/memory.c10
-rw-r--r--lib/memtypes.c1
-rw-r--r--lib/prefix.c15
-rw-r--r--lib/prefix.h20
-rw-r--r--lib/sockunion.c40
-rw-r--r--lib/sockunion.h2
-rw-r--r--lib/table.c14
-rw-r--r--lib/thread.c146
-rw-r--r--lib/thread.h3
-rw-r--r--lib/vty.c3
-rw-r--r--lib/workqueue.c19
-rw-r--r--lib/zclient.c23
-rw-r--r--ospf6d/ospf6_main.c2
-rw-r--r--ospf6d/ospf6_zebra.c3
-rw-r--r--ospfd/ospf_abr.c7
-rw-r--r--ospfd/ospf_api.c2
-rw-r--r--ospfd/ospf_apiserver.c4
-rw-r--r--ospfd/ospf_apiserver.h2
-rw-r--r--ospfd/ospf_asbr.c3
-rw-r--r--ospfd/ospf_ase.c8
-rw-r--r--ospfd/ospf_flood.c34
-rw-r--r--ospfd/ospf_flood.h1
-rw-r--r--ospfd/ospf_interface.c20
-rw-r--r--ospfd/ospf_interface.h6
-rw-r--r--ospfd/ospf_ism.c9
-rw-r--r--ospfd/ospf_lsa.c356
-rw-r--r--ospfd/ospf_lsa.h24
-rw-r--r--ospfd/ospf_lsdb.c15
-rw-r--r--ospfd/ospf_nsm.c33
-rw-r--r--ospfd/ospf_nsm.h2
-rw-r--r--ospfd/ospf_opaque.c17
-rw-r--r--ospfd/ospf_opaque.h4
-rw-r--r--ospfd/ospf_packet.c136
-rw-r--r--ospfd/ospf_packet.h1
-rw-r--r--ospfd/ospf_te.c6
-rw-r--r--ospfd/ospf_vty.c14
-rw-r--r--ospfd/ospfd.c15
-rw-r--r--ospfd/ospfd.h9
-rw-r--r--tests/aspath_test.c310
-rw-r--r--tools/multiple-bgpd.sh9
-rw-r--r--zebra/interface.c2
-rw-r--r--zebra/irdp_interface.c3
-rw-r--r--zebra/rt_netlink.c6
72 files changed, 3019 insertions, 1186 deletions
diff --git a/README.NetBSD b/README.NetBSD
index 9aac4c35..6bbc680b 100755
--- a/README.NetBSD
+++ b/README.NetBSD
@@ -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}
;;
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 87eb7ac7..666218fa 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -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);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 5a73eeff..776c7127 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -91,13 +91,13 @@ static struct hash *ashash;
/* Stream for SNMP. See aspath_snmp_pathseg */
static struct stream *snmp_stream;
-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 *
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index d63b914c..d55f9ce6 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -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 *);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 2205e267..92c1a09f 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -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;
}
int stream_put_prefix (struct stream *, struct prefix *);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 4cb70678..e6300740 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -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);
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index d6601674..6c9976e3 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -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);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index ae1d7a15..2ba45f6e 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -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;
}
}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index bc1e56ef..9e483770 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -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 *);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index e7eb0a07..440c15a4 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -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;
}
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 942fdc73..2f59dc40 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -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);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index f835fe77..8dede587 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -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 */
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index b5c4c602..a7dca531 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -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);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index f8d1adec..e9c78b3f 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -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;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index fc653e21..f5a74d1b 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -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",
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 189929a0..68d05484 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -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);
}
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 */
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,6 +7763,177 @@ 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_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
+ 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")
+{
+ 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_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
+ 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"
+ "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")
+
+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
+ 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"
+ "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")
+
+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
+ 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"
+ "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")
+
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",
@@ -7667,7 +7947,7 @@ DEFUN (show_ip_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_IP, SAFI_UNICAST);
+ return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
}
ALIAS (show_ip_bgp_community_exact,
@@ -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 */
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);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 42c3e053..abb85fd2 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -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. */
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 91cab606..a249c23d 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -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++;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 9cb30182..f65bb157 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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);
}
+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));
+}
+
/* 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 */
/* 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);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d7af349a..76c519cb 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 0d462db9..5dc014be 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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;
}
+/* 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);
+}
+
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) ||
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 91773e3c..892e7dec 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -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 */
diff --git a/configure.ac b/configure.ac
index 676c5dcc..4e5b5359 100755
--- a/configure.ac
+++ b/configure.ac
@@ -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)
diff --git a/lib/command.c b/lib/command.c
index ebb50b40..4f6d184d 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -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);
}
diff --git a/lib/distribute.c b/lib/distribute.c
index 7f84b80e..04889030 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -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) {
diff --git a/lib/hash.c b/lib/hash.c
index 672327ec..6db79ea7 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -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. */
diff --git a/lib/hash.h b/lib/hash.h
index f4b1c23e..4cb772e5 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -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 */
diff --git a/lib/if.c b/lib/if.c
index 31c60e3f..1e99ffbc 100644
--- 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. */
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index ddc62fd5..7d049b87 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -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;
}
diff --git a/lib/memory.c b/lib/memory.c
index 4bac31db..4090fd90 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -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);
+ }
}
/*
diff --git a/lib/memtypes.c b/lib/memtypes.c
index d0ce8c5e..d2bc1c62 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -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" },
diff --git a/lib/prefix.c b/lib/prefix.c
index ceda08de..5e8cff04 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -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);
+}
+
/* Address Famiy Identifier to Address Family converter. */
int
afi2family (afi_t afi)
diff --git a/lib/prefix.h b/lib/prefix.h
index dab4202e..7f0d3607 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -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 *);
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 10224a05..59770529 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -527,6 +527,46 @@ sockopt_ttl (int family, int sock, int ttl)
}
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)
{
int ret, on = 1;
diff --git a/lib/sockunion.h b/lib/sockunion.h
index db145cf2..4531f620 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -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,
diff --git a/lib/table.c b/lib/table.c
index 04df3af5..e40e6707 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -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)];
}
diff --git a/lib/thread.c b/lib/thread.c
index e89af541..6d3c3cb3 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -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;
+}
/* 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);
diff --git a/lib/thread.h b/lib/thread.h
index b52bc541..978aa6b0 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -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
diff --git a/lib/vty.c b/lib/vty.c
index d9eb921e..83bd6785 100644
--- 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;
}
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 7c811edd..61643bf8 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -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
diff --git a/lib/zclient.c b/lib/zclient.c
index 37ee2420..12d113e7 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -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;
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 65fcb597..d40bd97f 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -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;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 0a8ac3e4..881771a7 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -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",
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index d06a34ad..b7cc20dd 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -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);
diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c
index 77383191..fc3b51dd 100644
--- a/ospfd/ospf_api.c
+++ b/ospfd/ospf_api.c
@@ -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));
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index 15fd2e5f..2a9003b7 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -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;
}
diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h
index 9a8ae254..b60f56b4 100644
--- a/ospfd/ospf_apiserver.h
+++ b/ospfd/ospf_apiserver.h
@@ -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);
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 9d2aedb2..a23b4f2b 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -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
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index 7b7a798a..6a72e31d 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -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);
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index f72087b5..2ebae89a 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -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;
+ }
+}
diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h
index 5382e8fe..1ab11b88 100644
--- a/ospfd/ospf_flood.h
+++ b/ospfd/ospf_flood.h
@@ -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 *);
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index afe3acf1..dc0787d5 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -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!");
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index ab0b7580..6db88773 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -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 */
diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c
index 3172587a..db53882d 100644
--- a/ospfd/ospf_ism.c
+++ b/ospfd/ospf_ism.c
@@ -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;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 2f50676e..d5959eb1 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -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;
}
-
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;
}
@@ -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)
}
-#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)
/* 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);
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 6b2ba228..f364840f 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -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 *);
diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c
index c906f052..ea9a3528 100644
--- a/ospfd/ospf_lsdb.c
+++ b/ospfd/ospf_lsdb.c
@@ -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);
}
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 15fff349..cbc31716 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -162,7 +162,7 @@ nsm_should_adj (struct ospf_neighbor *nbr)
/* 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);
}
}
diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h
index 1121dae6..4f2ae808 100644
--- a/ospfd/ospf_nsm.h
+++ b/ospfd/ospf_nsm.h
@@ -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
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index 0b6ac4cb..aa126e19 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -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;
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index f49fe460..22730645 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -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,
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 994d3629..b714c27d 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -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));
}
}
diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h
index 7b3d6866..9a472081 100644
--- a/ospfd/ospf_packet.h
+++ b/ospfd/ospf_packet.h
@@ -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 */
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index c5ec0ad8..24e81052 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -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
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index f68adb2d..97c8e8d6 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -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;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index c250fe9e..e8405136 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -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);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 6eeaaf99..7a56d163 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -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. */
diff --git a/tests/aspath_test.c b/tests/aspath_test.c
index 9e51e8dd..4a2ce9aa 100644
--- a/tests/aspath_test.c
+++ b/tests/aspath_test.c
@@ -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());
diff --git a/tools/multiple-bgpd.sh b/tools/multiple-bgpd.sh
index 028ad696..d6a38ed4 100644
--- a/tools/multiple-bgpd.sh
+++ b/tools/multiple-bgpd.sh
@@ -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
diff --git a/zebra/interface.c b/zebra/interface.c
index 03e7ff71..933d6425 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -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
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 8742b62b..6403830b 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -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);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index eb9eae3a..a09e459c 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -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;