mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 12:49:18 +00:00
[bgpd] Merge AS4 support
2007-10-14 Paul Jakma <paul.jakma@sun.com> * NEWS: Note that MRT dumps are now version 2 * (general) Merge in Juergen Kammer's AS4 patch. 2007-09-27 Paul Jakma <paul.jakma@sun.com> * bgp_aspath.c: (assegment_normalise) remove duplicates from from sets. (aspath_reconcile_as4) disregard a broken part of the RFC around error handling in path reconciliation. * aspath_test.c: Test dupe-weeding from sets. Test that reconciliation merges AS_PATH and AS4_PATH where former is shorter than latter. 2007-09-26 Paul Jakma <paul.jakma@sun.com> * aspath_test.c: Test AS4_PATH reconcilation where length of AS_PATH and AS4_PATH is same. 2007-09-25 Paul Jakma <paul.jakma@sun.com> * bgp_open.c: (peek_for_as4_capability) Fix to work. * bgp_packet.c: (bgp_open_receive) Fix sanity check of as4. * tests/bgp_capability_test.c: (general) Extend tests to validate peek_for_as4_capability. Add test of full OPEN Option block, with multiple capabilities, both as a series of Option, and a single option. Add some crap to beginning of stream, to prevent code depending on getp == 0. 2007-09-18 Paul Jakma <paul.jakma@sun.com> * bgp_open.c: (bgp_capability_as4) debug printf inline with others. (peek_for_as4_capability) There's no need to signal failure, as failure is better dealt with through full capability parser - just return the AS4, simpler. * bgp_packet.c: (bgp_open_receive) Update to match peek_for_as4_capability change. Allow use of BGP_AS_TRANS by 2b speakers. Use NOTIFY_OPEN_ERR rather than CEASE for OPEN parsing errors. (bgp_capability_msg_parse) missing argument to debug print (bgp_capability_receive) missing return values. * tests/bgp_capability_test.c: (parse_test) update for changes to peek_for_as4_capability 2007-07-25 Paul Jakma <paul.jakma@sun.com> * Remove 2-byte size macros, just make existing macros take argument to indicate which size to use. Adjust all users - typically they want '1'. * bgp_aspath.c: (aspath_has_as4) New, return 1 if there are any as4's in a path. (aspath_put) Return the number of bytes actually written, to fix the bug Juergen noted: Splitting of segments will change the number of bytes written from that already written to the AS_PATH header. (aspath_snmp_pathseg) Pass 2-byte flag to aspath_put. SNMP is still defined as 2b. (aspath_aggregate) fix latent bug. (aspath_reconcile_as4) AS_PATH+NEW_AS_PATH reconciliation function. (aspath_key_make) Hash the AS_PATH string, rather than just taking the addition of assegment ASes as the hash value, hopefully sligthly more collision resistant. (bgp_attr_munge_as4_attrs) Collide the NEW_ attributes together with the OLD 2-byte forms, code Juergen had in bgp_attr_parse but re-organised a bit. (bgp_attr_parse) Bunch of code from Juergen moves to previous function. (bgp_packet_attribute) Compact significantly by just /always/ using extended-length attr header. Fix bug Juergen noted, by using aspath_put's (new) returned size value for the attr header rather than the (guesstimate) of aspath_size() - the two could differ when aspath_put had to split large segments, unlikely this bug was ever hit in the 'wild'. (bgp_dump_routes_attr) Always use extended-len and use aspath_put return for header length. Output 4b ASN for AS_PATH and AGGREGATOR. * bgp_ecommunity.c: (ecommunity_{hash_make,cmp}) fix hash callback declarations to match prototypes. (ecommunity_gettoken) Updated for ECOMMUNITY_ENCODE_AS4, complete rewrite of Juergen's changes (no asdot support) * bgp_open.c: (bgp_capability_as4) New, does what it says on the tin. (peek_for_as4_capability) Rewritten to use streams and bgp_capability_as4. * bgp_packet.c: (bgp_open_send) minor edit checked (in the abstract at least) with Juergen. Changes are to be more accepting, e.g, allow AS_TRANS on a 2-byte session. * (general) Update all commands to use CMD_AS_RANGE. * bgp_vty.c: (bgp_clear) Fix return vals to use CMD_.. Remove stuff replicated by VTY_GET_LONG (bgp_clear_vty) Return bgp_clear directly to vty. * tests/aspath_test.c: Exercise 32bit parsing. Test reconcile function. * tests/ecommunity_test.c: New, test AS4 ecommunity changes, positive test only at this time, error cases not tested yet. 2007-07-25 Juergen Kammer <j.kammer@eurodata.de> * (general) AS4 support. * bgpd.h: as_t changes to 4-bytes. * bgp_aspath.h: Add BGP_AS4_MAX and BGP_AS_TRANS defines. * bgp_aspath.c: AS_VALUE_SIZE becomes 4-byte, AS16_VALUE_SIZE added for 2-byte. Add AS16 versions of length calc macros. (aspath_count_numas) New, count number of ASes. (aspath_has_as4) New, return 1 if there are any as4's in a path. (assegments_parse) Interpret assegment as 4 or 2 byte, according to how the caller instructs us, with a new argument. (aspath_parse) Add use32bit argument to pass to assegments_parse. Adjust all its callers to pass 1, unless otherwise noted. (assegment_data_put) Adjust to be able to write 2 or 4 byte AS, according to new use32bit argument. (aspath_put) Adjust to write 2 or 4. (aspath_gettoken) Use a long for passed in asno. * bgp_attr.c: (attr_str) Add BGP_ATTR_AS4_PATH and BGP_ATTR_AS4_AGGREGATOR. (bgp_attr_aspath) Call aspath_parse with right 2/4 arg, as determined by received-capability flag. (bgp_attr_aspath_check) New, code previously in attr_aspath but moved to new func so it can be run after NEW_AS_PATH reconciliation. (bgp_attr_as4_path) New, handle NEW_AS_PATH. (bgp_attr_aggregator) Adjust to cope with 2/4 byte ASes. (bgp_attr_as4_aggregator) New, read NEW_AGGREGATOR. (bgp_attr_parse) Add handoffs to previous parsers for the two new AS4 NEW_ attributes. Various checks added for NEW/OLD reconciliation. (bgp_packet_attribute) Support 2/4 for AS_PATH and AGGREGATOR, detect when NEW_ attrs need to be sent. * bgp_debug.{c,h}: Add 'debug bgp as4'. * bgp_dump.c: MRTv2 support, unconditionally enabled, which supports AS4. Based on patches from Erik (RIPE?). * bgp_ecommunity.c: (ecommunity_ecom2str) ECOMMUNITY_ENCODE_AS4 support. * bgp_open.c: (peek_for_as4_capability) New, peek for AS4 capability prior to full capability parsing, so we know which ASN to use for struct peer lookup. (bgp_open_capability) Always send AS4 capability. * bgp_packet.c: (bgp_open_send) AS4 handling for AS field (bgp_open_receive) Peek for AS4 capability first, and figure out which AS to believe. * bgp_vty.c: (bgp_show_peer) Print AS4 cap * tests/aspath_test.c: Support asn32 changes, call aspath_parse with 16 bit. * vtysh/extract.pl: AS4 compatibility for router bgp ASNUMBER * vtysh/extract.pl.in: AS4 compatibility for router bgp ASNUMBER * vtysh/vtysh.c: AS4 compatibility for router bgp ASNUMBER
This commit is contained in:
parent
7593fddfa1
commit
0b2aa3a0a8
@ -1,3 +1,7 @@
|
|||||||
|
2007-10-14 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* NEWS: Note that MRT dumps are now version 2
|
||||||
|
|
||||||
2007-09-07 Paul Jakma <paul.jakma@sun.com>
|
2007-09-07 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
* configure.ac: Bump version to 0.99.9
|
* configure.ac: Bump version to 0.99.9
|
||||||
|
6
NEWS
6
NEWS
@ -1,5 +1,11 @@
|
|||||||
* Changes in Quagga 0.99.2
|
* Changes in Quagga 0.99.2
|
||||||
|
|
||||||
|
- [bgpd] 4-byte AS support added
|
||||||
|
- [bgpd] MRT format changes to version 2. Those relying on
|
||||||
|
bgpd MRT table dumps may need to update their tools.
|
||||||
|
|
||||||
|
* Changes in Quagga 0.99.2
|
||||||
|
|
||||||
- [bgpd] Work queues added to bgpd to split up update processing,
|
- [bgpd] Work queues added to bgpd to split up update processing,
|
||||||
particularly beneficial when a peer session goes down. AS_PATH
|
particularly beneficial when a peer session goes down. AS_PATH
|
||||||
parsing rewritten to be clearer, more robust and ready for 4-byte.
|
parsing rewritten to be clearer, more robust and ready for 4-byte.
|
||||||
|
128
bgpd/ChangeLog
128
bgpd/ChangeLog
@ -1,3 +1,131 @@
|
|||||||
|
2007-09-27 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* bgp_aspath.c: (assegment_normalise) remove duplicates from
|
||||||
|
from sets.
|
||||||
|
(aspath_reconcile_as4) disregard a broken part of the RFC around
|
||||||
|
error handling in path reconciliation.
|
||||||
|
|
||||||
|
2007-09-25 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* bgp_open.c: (peek_for_as4_capability) Fix to work.
|
||||||
|
* bgp_packet.c: (bgp_open_receive) Fix sanity check of as4.
|
||||||
|
|
||||||
|
2007-09-18 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* bgp_open.c: (bgp_capability_as4) debug printf inline with others.
|
||||||
|
(peek_for_as4_capability) There's no need to signal failure, as
|
||||||
|
failure is better dealt with through full capability parser -
|
||||||
|
just return the AS4, simpler.
|
||||||
|
* bgp_packet.c: (bgp_open_receive) Update to match
|
||||||
|
peek_for_as4_capability change.
|
||||||
|
Allow use of BGP_AS_TRANS by 2b speakers.
|
||||||
|
Use NOTIFY_OPEN_ERR rather than CEASE for OPEN parsing errors.
|
||||||
|
(bgp_capability_msg_parse) missing argument to debug print
|
||||||
|
(bgp_capability_receive) missing return values.
|
||||||
|
|
||||||
|
|
||||||
|
2007-07-25 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* Remove 2-byte size macros, just make existing macros take
|
||||||
|
argument to indicate which size to use.
|
||||||
|
Adjust all users - typically they want '1'.
|
||||||
|
* bgp_aspath.c: (aspath_has_as4) New, return 1 if there are any
|
||||||
|
as4's in a path.
|
||||||
|
(aspath_put) Return the number of bytes actually written, to
|
||||||
|
fix the bug Juergen noted: Splitting of segments will change
|
||||||
|
the number of bytes written from that already written to the
|
||||||
|
AS_PATH header.
|
||||||
|
(aspath_snmp_pathseg) Pass 2-byte flag to aspath_put. SNMP
|
||||||
|
is still defined as 2b.
|
||||||
|
(aspath_aggregate) fix latent bug.
|
||||||
|
(aspath_reconcile_as4) AS_PATH+NEW_AS_PATH reconciliation
|
||||||
|
function.
|
||||||
|
(aspath_key_make) Hash the AS_PATH string, rather than
|
||||||
|
just taking the addition of assegment ASes as the hash value,
|
||||||
|
hopefully sligthly more collision resistant.
|
||||||
|
(bgp_attr_munge_as4_attrs) Collide the NEW_ attributes
|
||||||
|
together with the OLD 2-byte forms, code Juergen
|
||||||
|
had in bgp_attr_parse but re-organised a bit.
|
||||||
|
(bgp_attr_parse) Bunch of code from Juergen moves
|
||||||
|
to previous function.
|
||||||
|
(bgp_packet_attribute) Compact significantly by
|
||||||
|
just /always/ using extended-length attr header.
|
||||||
|
Fix bug Juergen noted, by using aspath_put's
|
||||||
|
(new) returned size value for the attr header rather
|
||||||
|
than the (guesstimate) of aspath_size() - the two could
|
||||||
|
differ when aspath_put had to split large segments, unlikely
|
||||||
|
this bug was ever hit in the 'wild'.
|
||||||
|
(bgp_dump_routes_attr) Always use extended-len and
|
||||||
|
use aspath_put return for header length. Output 4b ASN
|
||||||
|
for AS_PATH and AGGREGATOR.
|
||||||
|
* bgp_ecommunity.c: (ecommunity_{hash_make,cmp}) fix
|
||||||
|
hash callback declarations to match prototypes.
|
||||||
|
(ecommunity_gettoken) Updated for ECOMMUNITY_ENCODE_AS4,
|
||||||
|
complete rewrite of Juergen's changes (no asdot support)
|
||||||
|
* bgp_open.c: (bgp_capability_as4) New, does what it says
|
||||||
|
on the tin.
|
||||||
|
(peek_for_as4_capability) Rewritten to use streams and
|
||||||
|
bgp_capability_as4.
|
||||||
|
* bgp_packet.c: (bgp_open_send) minor edit
|
||||||
|
checked (in the abstract at least) with Juergen.
|
||||||
|
Changes are to be more accepting, e.g, allow AS_TRANS on
|
||||||
|
a 2-byte session.
|
||||||
|
* (general) Update all commands to use CMD_AS_RANGE.
|
||||||
|
* bgp_vty.c: (bgp_clear) Fix return vals to use CMD_..
|
||||||
|
Remove stuff replicated by VTY_GET_LONG
|
||||||
|
(bgp_clear_vty) Return bgp_clear directly to vty.
|
||||||
|
|
||||||
|
|
||||||
|
2007-07-25 Juergen Kammer <j.kammer@eurodata.de>
|
||||||
|
|
||||||
|
* (general) AS4 support.
|
||||||
|
* bgpd.h: as_t changes to 4-bytes.
|
||||||
|
* bgp_aspath.h: Add BGP_AS4_MAX and BGP_AS_TRANS defines.
|
||||||
|
* bgp_aspath.c: AS_VALUE_SIZE becomes 4-byte, AS16_VALUE_SIZE
|
||||||
|
added for 2-byte.
|
||||||
|
Add AS16 versions of length calc macros.
|
||||||
|
(aspath_count_numas) New, count number of ASes.
|
||||||
|
(aspath_has_as4) New, return 1 if there are any as4's in a
|
||||||
|
path.
|
||||||
|
(assegments_parse) Interpret assegment as 4 or 2 byte,
|
||||||
|
according to how the caller instructs us, with a new
|
||||||
|
argument.
|
||||||
|
(aspath_parse) Add use32bit argument to pass to
|
||||||
|
assegments_parse. Adjust all its callers to pass 1, unless
|
||||||
|
otherwise noted.
|
||||||
|
(assegment_data_put) Adjust to be able to write 2 or 4 byte
|
||||||
|
AS, according to new use32bit argument.
|
||||||
|
(aspath_put) Adjust to write 2 or 4.
|
||||||
|
(aspath_gettoken) Use a long for passed in asno.
|
||||||
|
* bgp_attr.c: (attr_str) Add BGP_ATTR_AS4_PATH and
|
||||||
|
BGP_ATTR_AS4_AGGREGATOR.
|
||||||
|
(bgp_attr_aspath) Call aspath_parse with right 2/4 arg, as
|
||||||
|
determined by received-capability flag.
|
||||||
|
(bgp_attr_aspath_check) New, code previously in attr_aspath
|
||||||
|
but moved to new func so it can be run after NEW_AS_PATH
|
||||||
|
reconciliation.
|
||||||
|
(bgp_attr_as4_path) New, handle NEW_AS_PATH.
|
||||||
|
(bgp_attr_aggregator) Adjust to cope with 2/4 byte ASes.
|
||||||
|
(bgp_attr_as4_aggregator) New, read NEW_AGGREGATOR.
|
||||||
|
(bgp_attr_parse) Add handoffs to previous parsers for the two
|
||||||
|
new AS4 NEW_ attributes.
|
||||||
|
Various checks added for NEW/OLD reconciliation.
|
||||||
|
(bgp_packet_attribute) Support 2/4 for AS_PATH and
|
||||||
|
AGGREGATOR, detect when NEW_ attrs need to be sent.
|
||||||
|
* bgp_debug.{c,h}: Add 'debug bgp as4'.
|
||||||
|
* bgp_dump.c: MRTv2 support, unconditionally enabled, which
|
||||||
|
supports AS4. Based on patches from Erik (RIPE?).
|
||||||
|
* bgp_ecommunity.c: (ecommunity_ecom2str) ECOMMUNITY_ENCODE_AS4
|
||||||
|
support.
|
||||||
|
* bgp_open.c: (peek_for_as4_capability) New, peek for AS4
|
||||||
|
capability prior to full capability parsing, so we know which
|
||||||
|
ASN to use for struct peer lookup.
|
||||||
|
(bgp_open_capability) Always send AS4 capability.
|
||||||
|
* bgp_packet.c: (bgp_open_send) AS4 handling for AS field
|
||||||
|
(bgp_open_receive) Peek for AS4 capability first, and figure
|
||||||
|
out which AS to believe.
|
||||||
|
* bgp_vty.c: (bgp_show_peer) Print AS4 cap
|
||||||
|
|
||||||
2007-09-17 Paul Jakma <paul.jakma@sun.com>
|
2007-09-17 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
* bgp_open.c: (bgp_capability_mp) We were setting
|
* bgp_open.c: (bgp_capability_mp) We were setting
|
||||||
|
@ -28,15 +28,20 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
#include "jhash.h"
|
||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_aspath.h"
|
#include "bgpd/bgp_aspath.h"
|
||||||
|
#include "bgpd/bgp_debug.h"
|
||||||
|
#include "bgpd/bgp_attr.h"
|
||||||
|
|
||||||
/* Attr. Flags and Attr. Type Code. */
|
/* Attr. Flags and Attr. Type Code. */
|
||||||
#define AS_HEADER_SIZE 2
|
#define AS_HEADER_SIZE 2
|
||||||
|
|
||||||
/* Two octet is used for AS value. */
|
/* Now FOUR octets are used for AS value. */
|
||||||
#define AS_VALUE_SIZE sizeof (as_t)
|
#define AS_VALUE_SIZE sizeof (as_t)
|
||||||
|
/* This is the old one */
|
||||||
|
#define AS16_VALUE_SIZE sizeof (as16_t)
|
||||||
|
|
||||||
/* Maximum protocol segment length value */
|
/* Maximum protocol segment length value */
|
||||||
#define AS_SEGMENT_MAX 255
|
#define AS_SEGMENT_MAX 255
|
||||||
@ -46,16 +51,20 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
* sizes and lengths. At present (200508) they sort of match, however
|
* sizes and lengths. At present (200508) they sort of match, however
|
||||||
* the ONLY functions which should now about the on-wire syntax are
|
* the ONLY functions which should now about the on-wire syntax are
|
||||||
* aspath_put, assegment_put and assegment_parse.
|
* aspath_put, assegment_put and assegment_parse.
|
||||||
|
*
|
||||||
|
* aspath_put returns bytes written, the only definitive record of
|
||||||
|
* size of wire-format attribute..
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Calculated size in bytes of ASN segment data to hold N ASN's */
|
/* Calculated size in bytes of ASN segment data to hold N ASN's */
|
||||||
#define ASSEGMENT_DATA_SIZE(N) ((N) * AS_VALUE_SIZE)
|
#define ASSEGMENT_DATA_SIZE(N,S) \
|
||||||
|
((N) * ( (S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE) )
|
||||||
|
|
||||||
/* Calculated size of segment struct to hold N ASN's */
|
/* Calculated size of segment struct to hold N ASN's */
|
||||||
#define ASSEGMENT_SIZE(N) (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N))
|
#define ASSEGMENT_SIZE(N,S) (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N,S))
|
||||||
|
|
||||||
/* AS segment octet length. */
|
/* AS segment octet length. */
|
||||||
#define ASSEGMENT_LEN(X) ASSEGMENT_SIZE((X)->length)
|
#define ASSEGMENT_LEN(X,S) ASSEGMENT_SIZE((X)->length,S)
|
||||||
|
|
||||||
/* AS_SEQUENCE segments can be packed together */
|
/* AS_SEQUENCE segments can be packed together */
|
||||||
/* Can the types of X and Y be considered for packing? */
|
/* Can the types of X and Y be considered for packing? */
|
||||||
@ -85,7 +94,7 @@ static struct stream *snmp_stream;
|
|||||||
static inline as_t *
|
static inline as_t *
|
||||||
assegment_data_new (int num)
|
assegment_data_new (int num)
|
||||||
{
|
{
|
||||||
return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num)));
|
return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -150,7 +159,7 @@ assegment_dup (struct assegment *seg)
|
|||||||
struct assegment *new;
|
struct assegment *new;
|
||||||
|
|
||||||
new = assegment_new (seg->type, seg->length);
|
new = assegment_new (seg->type, seg->length);
|
||||||
memcpy (new->as, seg->as, ASSEGMENT_DATA_SIZE (new->length) );
|
memcpy (new->as, seg->as, ASSEGMENT_DATA_SIZE (new->length, 1) );
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
@ -197,7 +206,7 @@ assegment_prepend_asns (struct assegment *seg, as_t asnum, int num)
|
|||||||
for (i = 0; i < num; i++)
|
for (i = 0; i < num; i++)
|
||||||
newas[i] = asnum;
|
newas[i] = asnum;
|
||||||
|
|
||||||
memcpy (newas + num, seg->as, ASSEGMENT_DATA_SIZE (seg->length));
|
memcpy (newas + num, seg->as, ASSEGMENT_DATA_SIZE (seg->length, 1));
|
||||||
XFREE (MTYPE_AS_SEG_DATA, seg->as);
|
XFREE (MTYPE_AS_SEG_DATA, seg->as);
|
||||||
seg->as = newas;
|
seg->as = newas;
|
||||||
seg->length += num;
|
seg->length += num;
|
||||||
@ -215,12 +224,12 @@ assegment_append_asns (struct assegment *seg, as_t *asnos, int num)
|
|||||||
as_t *newas;
|
as_t *newas;
|
||||||
|
|
||||||
newas = XREALLOC (MTYPE_AS_SEG_DATA, seg->as,
|
newas = XREALLOC (MTYPE_AS_SEG_DATA, seg->as,
|
||||||
ASSEGMENT_DATA_SIZE (seg->length + num));
|
ASSEGMENT_DATA_SIZE (seg->length + num, 1));
|
||||||
|
|
||||||
if (newas)
|
if (newas)
|
||||||
{
|
{
|
||||||
seg->as = newas;
|
seg->as = newas;
|
||||||
memcpy (seg->as + seg->length, asnos, ASSEGMENT_DATA_SIZE(num));
|
memcpy (seg->as + seg->length, asnos, ASSEGMENT_DATA_SIZE(num, 1));
|
||||||
seg->length += num;
|
seg->length += num;
|
||||||
return seg;
|
return seg;
|
||||||
}
|
}
|
||||||
@ -263,8 +272,27 @@ assegment_normalise (struct assegment *head)
|
|||||||
* and because it helps other lesser implementations ;)
|
* and because it helps other lesser implementations ;)
|
||||||
*/
|
*/
|
||||||
if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
|
if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
|
||||||
|
{
|
||||||
|
int tail = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
qsort (seg->as, seg->length, sizeof(as_t), int_cmp);
|
qsort (seg->as, seg->length, sizeof(as_t), int_cmp);
|
||||||
|
|
||||||
|
/* weed out dupes */
|
||||||
|
for (i=1; i < seg->length; i++)
|
||||||
|
{
|
||||||
|
if (seg->as[tail] == seg->as[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tail++;
|
||||||
|
if (tail < i)
|
||||||
|
seg->as[tail] = seg->as[i];
|
||||||
|
}
|
||||||
|
/* seg->length can be 0.. */
|
||||||
|
if (seg->length)
|
||||||
|
seg->length = tail + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* read ahead from the current, pinned segment while the segments
|
/* read ahead from the current, pinned segment while the segments
|
||||||
* are packable/mergeable. Append all following packable segments
|
* are packable/mergeable. Append all following packable segments
|
||||||
* to the segment we have pinned and remove these appended
|
* to the segment we have pinned and remove these appended
|
||||||
@ -420,6 +448,12 @@ aspath_count_hops (struct aspath *aspath)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Estimate size aspath /might/ take if encoded into an
|
||||||
|
* ASPATH attribute.
|
||||||
|
*
|
||||||
|
* This is a quick estimate, not definitive! aspath_put()
|
||||||
|
* may return a different number!!
|
||||||
|
*/
|
||||||
unsigned int
|
unsigned int
|
||||||
aspath_size (struct aspath *aspath)
|
aspath_size (struct aspath *aspath)
|
||||||
{
|
{
|
||||||
@ -428,7 +462,7 @@ aspath_size (struct aspath *aspath)
|
|||||||
|
|
||||||
while (seg)
|
while (seg)
|
||||||
{
|
{
|
||||||
size += ASSEGMENT_SIZE(seg->length);
|
size += ASSEGMENT_SIZE(seg->length, 1);
|
||||||
seg = seg->next;
|
seg = seg->next;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
@ -454,6 +488,39 @@ aspath_highest (struct aspath *aspath)
|
|||||||
return highest;
|
return highest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if there are any 4-byte ASes in the path */
|
||||||
|
unsigned int
|
||||||
|
aspath_has_as4 (struct aspath *aspath)
|
||||||
|
{
|
||||||
|
struct assegment *seg = aspath->segments;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
while (seg)
|
||||||
|
{
|
||||||
|
for (i = 0; i < seg->length; i++)
|
||||||
|
if (seg->as[i] > BGP_AS_MAX)
|
||||||
|
return 1;
|
||||||
|
seg = seg->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return number of as numbers in in path */
|
||||||
|
unsigned int
|
||||||
|
aspath_count_numas (struct aspath *aspath)
|
||||||
|
{
|
||||||
|
struct assegment *seg = aspath->segments;
|
||||||
|
unsigned int num;
|
||||||
|
|
||||||
|
num=0;
|
||||||
|
while (seg)
|
||||||
|
{
|
||||||
|
num += seg->length;
|
||||||
|
seg = seg->next;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert aspath structure to string expression. */
|
/* Convert aspath structure to string expression. */
|
||||||
static char *
|
static char *
|
||||||
aspath_make_str_count (struct aspath *as)
|
aspath_make_str_count (struct aspath *as)
|
||||||
@ -478,6 +545,9 @@ aspath_make_str_count (struct aspath *as)
|
|||||||
* 2 chars for segment delimiters, and the final '\0'.
|
* 2 chars for segment delimiters, and the final '\0'.
|
||||||
* Hopefully this is large enough to avoid hitting the realloc
|
* Hopefully this is large enough to avoid hitting the realloc
|
||||||
* code below for most common sequences.
|
* code below for most common sequences.
|
||||||
|
*
|
||||||
|
* With 32bit ASNs, this range will increase, but only worth changing
|
||||||
|
* once there are significant numbers of ASN >= 100000
|
||||||
*/
|
*/
|
||||||
#define ASN_STR_LEN (5 + 1)
|
#define ASN_STR_LEN (5 + 1)
|
||||||
str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1,
|
str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1,
|
||||||
@ -510,6 +580,9 @@ aspath_make_str_count (struct aspath *as)
|
|||||||
* have been wrong. need 5 chars for ASN, a seperator each and
|
* have been wrong. need 5 chars for ASN, a seperator each and
|
||||||
* potentially two segment delimiters, plus a space between each
|
* potentially two segment delimiters, plus a space between each
|
||||||
* segment and trailing zero.
|
* segment and trailing zero.
|
||||||
|
*
|
||||||
|
* This may need to revised if/when significant numbers of
|
||||||
|
* ASNs >= 100000 are assigned and in-use on the internet...
|
||||||
*/
|
*/
|
||||||
#define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1)
|
#define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1)
|
||||||
if ( (len + SEGMENT_STR_LEN(seg)) > str_size)
|
if ( (len + SEGMENT_STR_LEN(seg)) > str_size)
|
||||||
@ -605,7 +678,7 @@ aspath_hash_alloc (void *arg)
|
|||||||
{
|
{
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
/* New aspath strucutre is needed. */
|
/* New aspath structure is needed. */
|
||||||
aspath = aspath_dup (arg);
|
aspath = aspath_dup (arg);
|
||||||
|
|
||||||
/* Malformed AS path value. */
|
/* Malformed AS path value. */
|
||||||
@ -620,7 +693,7 @@ aspath_hash_alloc (void *arg)
|
|||||||
|
|
||||||
/* parse as-segment byte stream in struct assegment */
|
/* parse as-segment byte stream in struct assegment */
|
||||||
static struct assegment *
|
static struct assegment *
|
||||||
assegments_parse (struct stream *s, size_t length)
|
assegments_parse (struct stream *s, size_t length, int use32bit)
|
||||||
{
|
{
|
||||||
struct assegment_header segh;
|
struct assegment_header segh;
|
||||||
struct assegment *seg, *prev = NULL, *head = NULL;
|
struct assegment *seg, *prev = NULL, *head = NULL;
|
||||||
@ -630,27 +703,37 @@ assegments_parse (struct stream *s, size_t length)
|
|||||||
if (length == 0)
|
if (length == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
|
zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu",
|
||||||
|
(unsigned long) length);
|
||||||
/* basic checks */
|
/* basic checks */
|
||||||
if ( (STREAM_READABLE(s) < length)
|
if ( (STREAM_READABLE(s) < length)
|
||||||
|| (STREAM_READABLE(s) < AS_HEADER_SIZE)
|
|| (STREAM_READABLE(s) < AS_HEADER_SIZE)
|
||||||
|| (length % AS_VALUE_SIZE))
|
|| (length % AS16_VALUE_SIZE ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while ( (STREAM_READABLE(s) > AS_HEADER_SIZE)
|
while ( (STREAM_READABLE(s) > AS_HEADER_SIZE)
|
||||||
&& (bytes < length))
|
&& (bytes < length))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int seg_size;
|
||||||
|
|
||||||
/* softly softly, get the header first on its own */
|
/* softly softly, get the header first on its own */
|
||||||
segh.type = stream_getc (s);
|
segh.type = stream_getc (s);
|
||||||
segh.length = stream_getc (s);
|
segh.length = stream_getc (s);
|
||||||
|
|
||||||
|
seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
|
zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d",
|
||||||
|
segh.type, segh.length);
|
||||||
|
|
||||||
/* check it.. */
|
/* check it.. */
|
||||||
if ( ((bytes + ASSEGMENT_SIZE(segh.length)) > length)
|
if ( ((bytes + seg_size) > length)
|
||||||
/* 1771bis 4.3b: seg length contains one or more */
|
/* 1771bis 4.3b: seg length contains one or more */
|
||||||
|| (segh.length == 0)
|
|| (segh.length == 0)
|
||||||
/* Paranoia in case someone changes type of segment length */
|
/* Paranoia in case someone changes type of segment length */
|
||||||
|| ((sizeof segh.length > 1) && segh.length > AS_SEGMENT_MAX))
|
|| ((sizeof segh.length > 1) && (segh.length > AS_SEGMENT_MAX)) )
|
||||||
{
|
{
|
||||||
if (head)
|
if (head)
|
||||||
assegment_free_all (head);
|
assegment_free_all (head);
|
||||||
@ -666,9 +749,13 @@ assegments_parse (struct stream *s, size_t length)
|
|||||||
head = prev = seg;
|
head = prev = seg;
|
||||||
|
|
||||||
for (i = 0; i < segh.length; i++)
|
for (i = 0; i < segh.length; i++)
|
||||||
seg->as[i] = stream_getw (s);
|
seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s);
|
||||||
|
|
||||||
bytes += ASSEGMENT_SIZE(segh.length);
|
bytes += seg_size;
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
|
zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu",
|
||||||
|
(unsigned long) bytes);
|
||||||
|
|
||||||
prev = seg;
|
prev = seg;
|
||||||
}
|
}
|
||||||
@ -680,16 +767,22 @@ assegments_parse (struct stream *s, size_t length)
|
|||||||
is length of byte stream. If there is same AS path in the the AS
|
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. */
|
path hash then return it else make new AS path structure. */
|
||||||
struct aspath *
|
struct aspath *
|
||||||
aspath_parse (struct stream *s, size_t length)
|
aspath_parse (struct stream *s, size_t length, int use32bit)
|
||||||
{
|
{
|
||||||
struct aspath as;
|
struct aspath as;
|
||||||
struct aspath *find;
|
struct aspath *find;
|
||||||
|
|
||||||
/* If length is odd it's malformed AS path. */
|
/* If length is odd it's malformed AS path. */
|
||||||
if (length % AS_VALUE_SIZE)
|
/* 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;
|
return NULL;
|
||||||
|
|
||||||
as.segments = assegments_parse (s, length);
|
memset (&as, 0, sizeof (struct aspath));
|
||||||
|
as.segments = assegments_parse (s, length, use32bit);
|
||||||
|
|
||||||
/* If already same aspath exist then return it. */
|
/* If already same aspath exist then return it. */
|
||||||
find = hash_get (ashash, &as, aspath_hash_alloc);
|
find = hash_get (ashash, &as, aspath_hash_alloc);
|
||||||
@ -698,6 +791,8 @@ aspath_parse (struct stream *s, size_t length)
|
|||||||
* optimised out.
|
* optimised out.
|
||||||
*/
|
*/
|
||||||
assegment_free_all (as.segments);
|
assegment_free_all (as.segments);
|
||||||
|
if (as.str)
|
||||||
|
XFREE (MTYPE_AS_STR, as.str);
|
||||||
|
|
||||||
if (! find)
|
if (! find)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -707,13 +802,21 @@ aspath_parse (struct stream *s, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
assegment_data_put (struct stream *s, as_t *as, int num)
|
assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
assert (num <= AS_SEGMENT_MAX);
|
assert (num <= AS_SEGMENT_MAX);
|
||||||
|
|
||||||
for (i = 0; i < num; i++)
|
for (i = 0; i < num; i++)
|
||||||
|
if ( use32bit )
|
||||||
|
stream_putl (s, as[i]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( as[i] <= BGP_AS_MAX )
|
||||||
stream_putw(s, as[i]);
|
stream_putw(s, as[i]);
|
||||||
|
else
|
||||||
|
stream_putw(s, BGP_AS_TRANS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
@ -728,38 +831,51 @@ assegment_header_put (struct stream *s, u_char type, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write aspath data to stream */
|
/* write aspath data to stream */
|
||||||
void
|
size_t
|
||||||
aspath_put (struct stream *s, struct aspath *as)
|
aspath_put (struct stream *s, struct aspath *as, int use32bit )
|
||||||
{
|
{
|
||||||
struct assegment *seg = as->segments;
|
struct assegment *seg = as->segments;
|
||||||
|
size_t bytes = 0;
|
||||||
|
|
||||||
if (!seg || seg->length == 0)
|
if (!seg || seg->length == 0)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (seg)
|
if (seg)
|
||||||
{
|
{
|
||||||
while (seg && (ASSEGMENT_LEN (seg) <= STREAM_WRITEABLE(s)))
|
/*
|
||||||
|
* Hey, what do we do when we have > STREAM_WRITABLE(s) here?
|
||||||
|
* At the moment, we would write out a partial aspath, and our peer
|
||||||
|
* will complain and drop the session :-/
|
||||||
|
*
|
||||||
|
* The general assumption here is that many things tested will
|
||||||
|
* never happen. And, in real live, up to now, they have not.
|
||||||
|
*/
|
||||||
|
while (seg && (ASSEGMENT_LEN(seg, use32bit) <= STREAM_WRITEABLE(s)))
|
||||||
{
|
{
|
||||||
|
struct assegment *next = seg->next;
|
||||||
int written = 0;
|
int written = 0;
|
||||||
|
int asns_packed = 0;
|
||||||
size_t lenp;
|
size_t lenp;
|
||||||
|
|
||||||
/* Overlength segments have to be split up */
|
/* Overlength segments have to be split up */
|
||||||
while ( (seg->length - written) > AS_SEGMENT_MAX)
|
while ( (seg->length - written) > AS_SEGMENT_MAX)
|
||||||
{
|
{
|
||||||
assegment_header_put (s, seg->type, AS_SEGMENT_MAX);
|
assegment_header_put (s, seg->type, AS_SEGMENT_MAX);
|
||||||
assegment_data_put (s, seg->as, AS_SEGMENT_MAX);
|
assegment_data_put (s, seg->as, AS_SEGMENT_MAX, use32bit);
|
||||||
written += AS_SEGMENT_MAX;
|
written += AS_SEGMENT_MAX;
|
||||||
|
bytes += ASSEGMENT_SIZE (written, use32bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the final segment, probably is also the first */
|
/* write the final segment, probably is also the first */
|
||||||
lenp = assegment_header_put (s, seg->type, seg->length - written);
|
lenp = assegment_header_put (s, seg->type, seg->length - written);
|
||||||
assegment_data_put (s, (seg->as + written), seg->length - written);
|
assegment_data_put (s, (seg->as + written), seg->length - written,
|
||||||
|
use32bit);
|
||||||
|
|
||||||
/* Sequence-type segments can be 'packed' together
|
/* Sequence-type segments can be 'packed' together
|
||||||
* Case of a segment which was overlength and split up
|
* Case of a segment which was overlength and split up
|
||||||
* will be missed here, but that doesn't matter.
|
* will be missed here, but that doesn't matter.
|
||||||
*/
|
*/
|
||||||
if (seg->next && ASSEGMENTS_PACKABLE (seg, seg->next))
|
while (next && ASSEGMENTS_PACKABLE (seg, next))
|
||||||
{
|
{
|
||||||
/* NB: We should never normally get here given we
|
/* NB: We should never normally get here given we
|
||||||
* normalise aspath data when parse them. However, better
|
* normalise aspath data when parse them. However, better
|
||||||
@ -771,17 +887,21 @@ aspath_put (struct stream *s, struct aspath *as)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Next segment's data can fit in this one */
|
/* Next segment's data can fit in this one */
|
||||||
assegment_data_put (s, seg->next->as, seg->next->length);
|
assegment_data_put (s, next->as, next->length, use32bit);
|
||||||
|
|
||||||
/* update the length of the segment header */
|
/* update the length of the segment header */
|
||||||
stream_putc_at (s, lenp,
|
stream_putc_at (s, lenp, seg->length - written + next->length);
|
||||||
seg->length - written + seg->next->length);
|
asns_packed += next->length;
|
||||||
seg = seg->next->next; /* skip to past next */
|
|
||||||
|
next = next->next;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
seg = seg->next;
|
bytes += ASSEGMENT_SIZE (seg->length - written + asns_packed,
|
||||||
|
use32bit);
|
||||||
|
seg = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is for SNMP BGP4PATHATTRASPATHSEGMENT
|
/* This is for SNMP BGP4PATHATTRASPATHSEGMENT
|
||||||
@ -803,7 +923,7 @@ aspath_snmp_pathseg (struct aspath *as, size_t *varlen)
|
|||||||
*varlen = 0;
|
*varlen = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
aspath_put (snmp_stream, as);
|
aspath_put (snmp_stream, as, 0); /* use 16 bit for now here */
|
||||||
|
|
||||||
*varlen = stream_get_endp (snmp_stream);
|
*varlen = stream_get_endp (snmp_stream);
|
||||||
return stream_pnt(snmp_stream);
|
return stream_pnt(snmp_stream);
|
||||||
@ -861,8 +981,9 @@ aspath_aggregate (struct aspath *as1, struct aspath *as2)
|
|||||||
int from;
|
int from;
|
||||||
struct assegment *seg1 = as1->segments;
|
struct assegment *seg1 = as1->segments;
|
||||||
struct assegment *seg2 = as2->segments;
|
struct assegment *seg2 = as2->segments;
|
||||||
struct aspath *aspath;
|
struct aspath *aspath = NULL;
|
||||||
struct assegment *asset;
|
struct assegment *asset;
|
||||||
|
struct assegment *prevseg = NULL;
|
||||||
|
|
||||||
match = 0;
|
match = 0;
|
||||||
minlen = 0;
|
minlen = 0;
|
||||||
@ -885,11 +1006,19 @@ aspath_aggregate (struct aspath *as1, struct aspath *as2)
|
|||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
|
struct assegment *seg = assegment_new (seg1->type, 0);
|
||||||
|
|
||||||
|
seg = assegment_append_asns (seg, seg1->as, match);
|
||||||
|
|
||||||
if (! aspath)
|
if (! aspath)
|
||||||
|
{
|
||||||
aspath = aspath_new ();
|
aspath = aspath_new ();
|
||||||
aspath->segments = assegment_new (seg1->type, 0);
|
aspath->segments = seg;
|
||||||
aspath->segments = assegment_append_asns (aspath->segments,
|
}
|
||||||
seg1->as, match);
|
else
|
||||||
|
prevseg->next = seg;
|
||||||
|
|
||||||
|
prevseg = seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match != minlen || match != seg1->length
|
if (match != minlen || match != seg1->length
|
||||||
@ -1174,6 +1303,108 @@ aspath_cmp_left (struct aspath *aspath1, struct aspath *aspath2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Truncate an aspath after a number of hops, and put the hops remaining
|
||||||
|
* at the front of another aspath. Needed for AS4 compat.
|
||||||
|
*
|
||||||
|
* Returned aspath is a /new/ aspath, which should either by free'd or
|
||||||
|
* interned by the caller, as desired.
|
||||||
|
*/
|
||||||
|
struct aspath *
|
||||||
|
aspath_reconcile_as4 ( struct aspath *aspath, struct aspath *as4path)
|
||||||
|
{
|
||||||
|
struct assegment *seg, *newseg, *prevseg = NULL;
|
||||||
|
struct aspath *newpath = NULL, *mergedpath;
|
||||||
|
int hops, cpasns = 0;
|
||||||
|
|
||||||
|
if (!aspath)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
seg = aspath->segments;
|
||||||
|
|
||||||
|
/* CONFEDs should get reconciled too.. */
|
||||||
|
hops = (aspath_count_hops (aspath) + aspath_count_confeds (aspath))
|
||||||
|
- aspath_count_hops (as4path);
|
||||||
|
|
||||||
|
if (hops < 0)
|
||||||
|
{
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_warn ("[AS4] Fewer hops in AS_PATH than NEW_AS_PATH");
|
||||||
|
/* Something's gone wrong. The RFC says we should now ignore AS4_PATH,
|
||||||
|
* which is daft behaviour - it contains vital loop-detection
|
||||||
|
* information which must have been removed from AS_PATH.
|
||||||
|
*/
|
||||||
|
hops = aspath_count_hops (aspath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hops)
|
||||||
|
return aspath_dup (as4path);
|
||||||
|
|
||||||
|
if ( BGP_DEBUG(as4, AS4))
|
||||||
|
zlog_debug("[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now",
|
||||||
|
aspath->str, as4path->str);
|
||||||
|
|
||||||
|
while (seg && hops > 0)
|
||||||
|
{
|
||||||
|
switch (seg->type)
|
||||||
|
{
|
||||||
|
case AS_SET:
|
||||||
|
case AS_CONFED_SET:
|
||||||
|
hops--;
|
||||||
|
cpasns = seg->length;
|
||||||
|
break;
|
||||||
|
case AS_CONFED_SEQUENCE:
|
||||||
|
/* Should never split a confed-sequence, if hop-count
|
||||||
|
* suggests we must then something's gone wrong somewhere.
|
||||||
|
*
|
||||||
|
* Most important goal is to preserve AS_PATHs prime function
|
||||||
|
* as loop-detector, so we fudge the numbers so that the entire
|
||||||
|
* confed-sequence is merged in.
|
||||||
|
*/
|
||||||
|
if (hops < seg->length)
|
||||||
|
{
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_debug ("[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls"
|
||||||
|
" across 2/4 ASN boundary somewhere, broken..");
|
||||||
|
hops = seg->length;
|
||||||
|
}
|
||||||
|
case AS_SEQUENCE:
|
||||||
|
cpasns = MIN(seg->length, hops);
|
||||||
|
hops -= seg->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (cpasns <= seg->length);
|
||||||
|
|
||||||
|
newseg = assegment_new (seg->type, 0);
|
||||||
|
newseg = assegment_append_asns (newseg, seg->as, cpasns);
|
||||||
|
|
||||||
|
if (!newpath)
|
||||||
|
{
|
||||||
|
newpath = aspath_new ();
|
||||||
|
newpath->segments = newseg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prevseg->next = newseg;
|
||||||
|
|
||||||
|
prevseg = newseg;
|
||||||
|
seg = seg->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We may be able to join some segments here, and we must
|
||||||
|
* do this because... we want normalised aspaths in out hash
|
||||||
|
* and we do not want to stumble in aspath_put.
|
||||||
|
*/
|
||||||
|
mergedpath = aspath_merge (newpath, aspath_dup(as4path));
|
||||||
|
aspath_free (newpath);
|
||||||
|
mergedpath->segments = assegment_normalise (mergedpath->segments);
|
||||||
|
aspath_str_update (mergedpath);
|
||||||
|
|
||||||
|
if ( BGP_DEBUG(as4, AS4))
|
||||||
|
zlog_debug ("[AS4] result of synthesizing is %s",
|
||||||
|
mergedpath->str);
|
||||||
|
|
||||||
|
return mergedpath;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare leftmost AS value for MED check. If as1's leftmost AS and
|
/* Compare leftmost AS value for MED check. If as1's leftmost AS and
|
||||||
as2's leftmost AS is same return 1. (confederation as-path
|
as2's leftmost AS is same return 1. (confederation as-path
|
||||||
only). */
|
only). */
|
||||||
@ -1273,7 +1504,7 @@ aspath_segment_add (struct aspath *as, int type)
|
|||||||
struct aspath *
|
struct aspath *
|
||||||
aspath_empty (void)
|
aspath_empty (void)
|
||||||
{
|
{
|
||||||
return aspath_parse (NULL, 0);
|
return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aspath *
|
struct aspath *
|
||||||
@ -1316,7 +1547,7 @@ enum as_token
|
|||||||
|
|
||||||
/* Return next token and point for string parse. */
|
/* Return next token and point for string parse. */
|
||||||
static const char *
|
static const char *
|
||||||
aspath_gettoken (const char *buf, enum as_token *token, u_short *asno)
|
aspath_gettoken (const char *buf, enum as_token *token, u_long *asno)
|
||||||
{
|
{
|
||||||
const char *p = buf;
|
const char *p = buf;
|
||||||
|
|
||||||
@ -1364,6 +1595,7 @@ aspath_gettoken (const char *buf, enum as_token *token, u_short *asno)
|
|||||||
*token = as_token_asval;
|
*token = as_token_asval;
|
||||||
asval = (*p - '0');
|
asval = (*p - '0');
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
while (isdigit ((int) *p))
|
while (isdigit ((int) *p))
|
||||||
{
|
{
|
||||||
asval *= 10;
|
asval *= 10;
|
||||||
@ -1384,7 +1616,7 @@ aspath_str2aspath (const char *str)
|
|||||||
{
|
{
|
||||||
enum as_token token = as_token_unknown;
|
enum as_token token = as_token_unknown;
|
||||||
u_short as_type;
|
u_short as_type;
|
||||||
u_short asno = 0;
|
u_long asno = 0;
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
int needtype;
|
int needtype;
|
||||||
|
|
||||||
@ -1451,24 +1683,11 @@ aspath_key_make (void *p)
|
|||||||
{
|
{
|
||||||
struct aspath * aspath = (struct aspath *) p;
|
struct aspath * aspath = (struct aspath *) p;
|
||||||
unsigned int key = 0;
|
unsigned int key = 0;
|
||||||
unsigned int i;
|
|
||||||
struct assegment *seg = aspath->segments;
|
|
||||||
struct assegment *prev = NULL;
|
|
||||||
|
|
||||||
while (seg)
|
if (!aspath->str)
|
||||||
{
|
aspath_str_update (aspath);
|
||||||
/* segment types should be part of the hash
|
|
||||||
* otherwise seq(1) and set(1) will hash to same value
|
|
||||||
*/
|
|
||||||
if (!(prev && seg->type == AS_SEQUENCE && seg->type == prev->type))
|
|
||||||
key += seg->type;
|
|
||||||
|
|
||||||
for (i = 0; i < seg->length; i++)
|
key = jhash (aspath->str, strlen(aspath->str), 2334325);
|
||||||
key += seg->as[i];
|
|
||||||
|
|
||||||
prev = seg;
|
|
||||||
seg = seg->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#define BGP_PRIVATE_AS_MIN 64512U
|
#define BGP_PRIVATE_AS_MIN 64512U
|
||||||
#define BGP_PRIVATE_AS_MAX 65535U
|
#define BGP_PRIVATE_AS_MAX 65535U
|
||||||
|
|
||||||
|
/* we leave BGP_AS_MAX as the 16bit AS MAX number. */
|
||||||
#define BGP_AS_MAX 65535U
|
#define BGP_AS_MAX 65535U
|
||||||
|
#define BGP_AS4_MAX 4294967295U
|
||||||
|
/* Transition 16Bit AS as defined by IANA */
|
||||||
|
#define BGP_AS_TRANS 23456U
|
||||||
|
|
||||||
/* AS_PATH segment data in abstracted form, no limit is placed on length */
|
/* AS_PATH segment data in abstracted form, no limit is placed on length */
|
||||||
struct assegment
|
struct assegment
|
||||||
@ -61,7 +65,7 @@ struct aspath
|
|||||||
/* Prototypes. */
|
/* Prototypes. */
|
||||||
extern void aspath_init (void);
|
extern void aspath_init (void);
|
||||||
extern void aspath_finish (void);
|
extern void aspath_finish (void);
|
||||||
extern struct aspath *aspath_parse (struct stream *, size_t);
|
extern struct aspath *aspath_parse (struct stream *, size_t, int);
|
||||||
extern struct aspath *aspath_dup (struct aspath *);
|
extern struct aspath *aspath_dup (struct aspath *);
|
||||||
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
|
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
|
||||||
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
|
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
|
||||||
@ -88,7 +92,11 @@ extern unsigned int aspath_count_hops (struct aspath *);
|
|||||||
extern unsigned int aspath_count_confeds (struct aspath *);
|
extern unsigned int aspath_count_confeds (struct aspath *);
|
||||||
extern unsigned int aspath_size (struct aspath *);
|
extern unsigned int aspath_size (struct aspath *);
|
||||||
extern as_t aspath_highest (struct aspath *);
|
extern as_t aspath_highest (struct aspath *);
|
||||||
extern void aspath_put (struct stream *, struct aspath *);
|
extern size_t aspath_put (struct stream *, struct aspath *, int);
|
||||||
|
|
||||||
|
extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *);
|
||||||
|
extern unsigned int aspath_has_as4 (struct aspath *);
|
||||||
|
extern unsigned int aspath_count_numas (struct aspath *);
|
||||||
|
|
||||||
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
|
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
|
||||||
extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
|
extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
|
||||||
|
393
bgpd/bgp_attr.c
393
bgpd/bgp_attr.c
@ -56,8 +56,10 @@ static struct message attr_str [] =
|
|||||||
{ BGP_ATTR_RCID_PATH, "RCID_PATH" },
|
{ BGP_ATTR_RCID_PATH, "RCID_PATH" },
|
||||||
{ BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
|
{ BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" },
|
||||||
{ BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
|
{ BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
|
||||||
{ BGP_ATTR_EXT_COMMUNITIES, "BGP_ATTR_EXT_COMMUNITIES" },
|
{ BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" },
|
||||||
{ BGP_ATTR_AS_PATHLIMIT, "BGP_ATTR_AS_PATHLIMIT" },
|
{ BGP_ATTR_AS4_PATH, "AS4_PATH" },
|
||||||
|
{ BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" },
|
||||||
|
{ BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
|
int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]);
|
||||||
@ -794,8 +796,6 @@ static int
|
|||||||
bgp_attr_aspath (struct peer *peer, bgp_size_t length,
|
bgp_attr_aspath (struct peer *peer, bgp_size_t length,
|
||||||
struct attr *attr, u_char flag, u_char *startp)
|
struct attr *attr, u_char flag, u_char *startp)
|
||||||
{
|
{
|
||||||
struct bgp *bgp;
|
|
||||||
struct aspath *aspath;
|
|
||||||
bgp_size_t total;
|
bgp_size_t total;
|
||||||
|
|
||||||
total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
|
total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
|
||||||
@ -813,8 +813,14 @@ bgp_attr_aspath (struct peer *peer, bgp_size_t length,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* peer with AS4 => will get 4Byte ASnums
|
||||||
|
* otherwise, will get 16 Bit
|
||||||
|
*/
|
||||||
|
attr->aspath = aspath_parse (peer->ibuf, length,
|
||||||
|
CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV));
|
||||||
|
|
||||||
/* In case of IBGP, length will be zero. */
|
/* In case of IBGP, length will be zero. */
|
||||||
attr->aspath = aspath_parse (peer->ibuf, length);
|
|
||||||
if (! attr->aspath)
|
if (! attr->aspath)
|
||||||
{
|
{
|
||||||
zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
|
zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
|
||||||
@ -824,6 +830,28 @@ bgp_attr_aspath (struct peer *peer, bgp_size_t length,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward pointer. */
|
||||||
|
/* stream_forward_getp (peer->ibuf, length);*/
|
||||||
|
|
||||||
|
/* Set aspath attribute flag. */
|
||||||
|
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bgp_attr_aspath_check( struct peer *peer,
|
||||||
|
struct attr *attr)
|
||||||
|
{
|
||||||
|
/* These checks were part of bgp_attr_aspath, but with
|
||||||
|
* as4 we should to check aspath things when
|
||||||
|
* aspath synthesizing with as4_path has already taken place.
|
||||||
|
* Otherwise we check ASPATH and use the synthesized thing, and that is
|
||||||
|
* not right.
|
||||||
|
* So do the checks later, i.e. here
|
||||||
|
*/
|
||||||
|
struct bgp *bgp = peer->bgp;
|
||||||
|
struct aspath *aspath;
|
||||||
|
|
||||||
bgp = peer->bgp;
|
bgp = peer->bgp;
|
||||||
|
|
||||||
/* First AS check for EBGP. */
|
/* First AS check for EBGP. */
|
||||||
@ -851,11 +879,20 @@ bgp_attr_aspath (struct peer *peer, bgp_size_t length,
|
|||||||
attr->aspath = aspath_intern (aspath);
|
attr->aspath = aspath_intern (aspath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward pointer. */
|
return 0;
|
||||||
/* stream_forward_getp (peer->ibuf, length);*/
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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, struct aspath **as4_path)
|
||||||
|
{
|
||||||
|
*as4_path = aspath_parse (peer->ibuf, length, 1);
|
||||||
|
|
||||||
/* Set aspath attribute flag. */
|
/* Set aspath attribute flag. */
|
||||||
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
|
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -981,17 +1018,26 @@ static int
|
|||||||
bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
|
bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
|
||||||
struct attr *attr, u_char flag)
|
struct attr *attr, u_char flag)
|
||||||
{
|
{
|
||||||
|
int wantedlen = 6;
|
||||||
struct attr_extra *attre = bgp_attr_extra_get (attr);
|
struct attr_extra *attre = bgp_attr_extra_get (attr);
|
||||||
|
|
||||||
if (length != 6)
|
/* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
|
||||||
|
if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
|
||||||
|
wantedlen = 8;
|
||||||
|
|
||||||
|
if (length != wantedlen)
|
||||||
{
|
{
|
||||||
zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length);
|
zlog (peer->log, LOG_ERR, "Aggregator length is not %d [%d]", wantedlen, length);
|
||||||
|
|
||||||
bgp_notify_send (peer,
|
bgp_notify_send (peer,
|
||||||
BGP_NOTIFY_UPDATE_ERR,
|
BGP_NOTIFY_UPDATE_ERR,
|
||||||
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
|
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) )
|
||||||
|
attre->aggregator_as = stream_getl (peer->ibuf);
|
||||||
|
else
|
||||||
attre->aggregator_as = stream_getw (peer->ibuf);
|
attre->aggregator_as = stream_getw (peer->ibuf);
|
||||||
attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
|
attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
|
||||||
|
|
||||||
@ -1001,6 +1047,145 @@ bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* New Aggregator attribute */
|
||||||
|
static int
|
||||||
|
bgp_attr_as4_aggregator (struct peer *peer, bgp_size_t length,
|
||||||
|
struct attr *attr, 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;
|
||||||
|
}
|
||||||
|
*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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
bgp_attr_munge_as4_attrs (struct peer *peer, struct attr *attr,
|
||||||
|
struct aspath *as4_path, as_t as4_aggregator,
|
||||||
|
struct in_addr *as4_aggregator_addr)
|
||||||
|
{
|
||||||
|
int ignore_as4_path = 0;
|
||||||
|
struct aspath *newpath;
|
||||||
|
struct attr_extra *attre = attr->extra;
|
||||||
|
|
||||||
|
if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
|
||||||
|
{
|
||||||
|
/* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
|
||||||
|
* if given.
|
||||||
|
* It is worth a warning though, because the peer really
|
||||||
|
* should not send them
|
||||||
|
*/
|
||||||
|
if (BGP_DEBUG(as4, AS4))
|
||||||
|
{
|
||||||
|
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
|
||||||
|
zlog_debug ("[AS4] %s %s AS4_PATH",
|
||||||
|
peer->host, "AS4 capable peer, yet it sent");
|
||||||
|
|
||||||
|
if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
|
||||||
|
zlog_debug ("[AS4] %s %s AS4_AGGREGATOR",
|
||||||
|
peer->host, "AS4 capable peer, yet it sent");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
* This should already
|
||||||
|
* have been handled by 'well known attributes missing'
|
||||||
|
* But... yeah, paranoia
|
||||||
|
* Take this as a "malformed attribute"
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have a asn16 peer. First, look for AS4_AGGREGATOR
|
||||||
|
* because that may override AS4_PATH
|
||||||
|
*/
|
||||||
|
if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
|
||||||
|
{
|
||||||
|
assert (attre);
|
||||||
|
|
||||||
|
if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
|
||||||
|
{
|
||||||
|
/* received both.
|
||||||
|
* if the as_number in aggregator is not AS_TRANS,
|
||||||
|
* then AS4_AGGREGATOR and AS4_PATH shall be ignored
|
||||||
|
* and the Aggregator shall be taken as
|
||||||
|
* info on the aggregating node, and the AS_PATH
|
||||||
|
* shall be taken as the AS_PATH
|
||||||
|
* otherwise
|
||||||
|
* the Aggregator shall be ignored and the
|
||||||
|
* AS4_AGGREGATOR shall be taken as the
|
||||||
|
* Aggregating node and the AS_PATH is to be
|
||||||
|
* constructed "as in all other cases"
|
||||||
|
*/
|
||||||
|
if ( attre->aggregator_as != BGP_AS_TRANS )
|
||||||
|
{
|
||||||
|
/* ignore */
|
||||||
|
if ( BGP_DEBUG(as4, AS4))
|
||||||
|
zlog_debug ("[AS4] %s BGP not AS4 capable peer"
|
||||||
|
" send AGGREGATOR != AS_TRANS and"
|
||||||
|
" AS4_AGGREGATOR, so ignore"
|
||||||
|
" AS4_AGGREGATOR and AS4_PATH", peer->host);
|
||||||
|
ignore_as4_path = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* "New_aggregator shall be taken as aggregator" */
|
||||||
|
attre->aggregator_as = as4_aggregator;
|
||||||
|
attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We received a AS4_AGGREGATOR but no AGGREGATOR.
|
||||||
|
* That is bogus - but reading the conditions
|
||||||
|
* we have to handle AS4_AGGREGATOR as if it were
|
||||||
|
* AGGREGATOR in that case
|
||||||
|
*/
|
||||||
|
if ( BGP_DEBUG(as4, AS4))
|
||||||
|
zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
|
||||||
|
" AS4_AGGREGATOR but no AGGREGATOR, will take"
|
||||||
|
" it as if AGGREGATOR with AS_TRANS had been there", peer->host);
|
||||||
|
attre->aggregator_as = as4_aggregator;
|
||||||
|
/* sweep it under the carpet and simulate a "good" AGGREGATOR */
|
||||||
|
attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* need to reconcile NEW_AS_PATH and AS_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);
|
||||||
|
attr->aspath = aspath_intern (newpath);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Community attribute. */
|
/* Community attribute. */
|
||||||
static int
|
static int
|
||||||
bgp_attr_community (struct peer *peer, bgp_size_t length,
|
bgp_attr_community (struct peer *peer, bgp_size_t length,
|
||||||
@ -1318,11 +1503,16 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u_char flag;
|
u_char flag;
|
||||||
u_char type;
|
u_char type = 0;
|
||||||
bgp_size_t length;
|
bgp_size_t length;
|
||||||
u_char *startp, *endp;
|
u_char *startp, *endp;
|
||||||
u_char *attr_endp;
|
u_char *attr_endp;
|
||||||
u_char seen[BGP_ATTR_BITMAP_SIZE];
|
u_char seen[BGP_ATTR_BITMAP_SIZE];
|
||||||
|
/* we need the as4_path only until we have synthesized the as_path with it */
|
||||||
|
/* same goes for as4_aggregator */
|
||||||
|
struct aspath *as4_path = NULL;
|
||||||
|
as_t as4_aggregator = 0;
|
||||||
|
struct in_addr as4_aggregator_addr = { 0 };
|
||||||
|
|
||||||
/* Initialize bitmap. */
|
/* Initialize bitmap. */
|
||||||
memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
|
memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
|
||||||
@ -1339,7 +1529,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
|
|||||||
/* XXX warning: long int format, int arg (arg 5) */
|
/* XXX warning: long int format, int arg (arg 5) */
|
||||||
zlog (peer->log, LOG_WARNING,
|
zlog (peer->log, LOG_WARNING,
|
||||||
"%s error BGP attribute length %lu is smaller than min len",
|
"%s error BGP attribute length %lu is smaller than min len",
|
||||||
peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));
|
peer->host,
|
||||||
|
(unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
|
||||||
|
|
||||||
bgp_notify_send (peer,
|
bgp_notify_send (peer,
|
||||||
BGP_NOTIFY_UPDATE_ERR,
|
BGP_NOTIFY_UPDATE_ERR,
|
||||||
@ -1401,6 +1592,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
|
|||||||
case BGP_ATTR_AS_PATH:
|
case BGP_ATTR_AS_PATH:
|
||||||
ret = bgp_attr_aspath (peer, length, attr, flag, startp);
|
ret = bgp_attr_aspath (peer, length, attr, flag, startp);
|
||||||
break;
|
break;
|
||||||
|
case BGP_ATTR_AS4_PATH:
|
||||||
|
ret = bgp_attr_as4_path (peer, length, attr, &as4_path );
|
||||||
|
break;
|
||||||
case BGP_ATTR_NEXT_HOP:
|
case BGP_ATTR_NEXT_HOP:
|
||||||
ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
|
ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
|
||||||
break;
|
break;
|
||||||
@ -1416,6 +1610,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
|
|||||||
case BGP_ATTR_AGGREGATOR:
|
case BGP_ATTR_AGGREGATOR:
|
||||||
ret = bgp_attr_aggregator (peer, length, attr, flag);
|
ret = bgp_attr_aggregator (peer, length, attr, flag);
|
||||||
break;
|
break;
|
||||||
|
case BGP_ATTR_AS4_AGGREGATOR:
|
||||||
|
ret = bgp_attr_as4_aggregator (peer, length, attr, &as4_aggregator, &as4_aggregator_addr);
|
||||||
|
break;
|
||||||
case BGP_ATTR_COMMUNITIES:
|
case BGP_ATTR_COMMUNITIES:
|
||||||
ret = bgp_attr_community (peer, length, attr, flag);
|
ret = bgp_attr_community (peer, length, attr, flag);
|
||||||
break;
|
break;
|
||||||
@ -1480,6 +1677,51 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this place we can see whether we got AS4_PATH and/or
|
||||||
|
* AS4_AGGREGATOR from a 16Bit peer and act accordingly.
|
||||||
|
* We can not do this before we've read all attributes because
|
||||||
|
* the as4 handling does not say whether AS4_PATH has to be sent
|
||||||
|
* after AS_PATH or not - and when AS4_AGGREGATOR will be send
|
||||||
|
* in relationship to AGGREGATOR.
|
||||||
|
* So, to be defensive, we are not relying on any order and read
|
||||||
|
* 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,
|
||||||
|
as4_aggregator, &as4_aggregator_addr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
|
{
|
||||||
|
aspath_unintern( as4_path ); /* unintern - it is in the hash */
|
||||||
|
as4_path = NULL;
|
||||||
|
/* The flag that we got this is still there, but that does not
|
||||||
|
* do any trouble
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The "rest" of the code does nothing with as4_aggregator.
|
||||||
|
* there is no memory attached specifically which is not part
|
||||||
|
* of the attr.
|
||||||
|
* so ignoring just means do nothing.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* 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)))
|
||||||
|
{
|
||||||
|
ret = bgp_attr_aspath_check( peer, attr );
|
||||||
|
if ( ret < 0 )
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally intern unknown attribute. */
|
/* Finally intern unknown attribute. */
|
||||||
if (attr->extra && attr->extra->transit)
|
if (attr->extra && attr->extra->transit)
|
||||||
attr->extra->transit = transit_intern (attr->extra->transit);
|
attr->extra->transit = transit_intern (attr->extra->transit);
|
||||||
@ -1530,8 +1772,11 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
|
|||||||
struct prefix_rd *prd, u_char *tag)
|
struct prefix_rd *prd, u_char *tag)
|
||||||
{
|
{
|
||||||
size_t cp;
|
size_t cp;
|
||||||
unsigned int aspath_data_size;
|
size_t aspath_sizep;
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
int send_as4_path = 0;
|
||||||
|
int send_as4_aggregator = 0;
|
||||||
|
int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
|
||||||
|
|
||||||
if (! bgp)
|
if (! bgp)
|
||||||
bgp = bgp_get_default ();
|
bgp = bgp_get_default ();
|
||||||
@ -1578,24 +1823,26 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
|
|||||||
else
|
else
|
||||||
aspath = attr->aspath;
|
aspath = attr->aspath;
|
||||||
|
|
||||||
/* AS path attribute extended length bit check. */
|
/* If peer is not AS4 capable, then:
|
||||||
aspath_data_size = aspath_size (aspath);
|
* - send the created AS_PATH out as AS4_PATH (optional, transitive),
|
||||||
if (aspath_data_size > 255)
|
* but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
|
||||||
{
|
* types are in it (i.e. exclude them if they are there)
|
||||||
|
* AND do this only if there is at least one asnum > 65535 in the path!
|
||||||
|
* - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change
|
||||||
|
* all ASnums > 65535 to BGP_AS_TRANS
|
||||||
|
*/
|
||||||
|
|
||||||
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
|
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
|
||||||
stream_putc (s, BGP_ATTR_AS_PATH);
|
stream_putc (s, BGP_ATTR_AS_PATH);
|
||||||
stream_putw (s, aspath_data_size);
|
aspath_sizep = stream_get_endp (s);
|
||||||
}
|
stream_putw (s, 0);
|
||||||
else
|
stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit));
|
||||||
{
|
|
||||||
stream_putc (s, BGP_ATTR_FLAG_TRANS);
|
|
||||||
stream_putc (s, BGP_ATTR_AS_PATH);
|
|
||||||
stream_putc (s, aspath_data_size);
|
|
||||||
}
|
|
||||||
aspath_put (s, aspath);
|
|
||||||
|
|
||||||
if (aspath != attr->aspath)
|
/* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
|
||||||
aspath_free (aspath);
|
* in the path
|
||||||
|
*/
|
||||||
|
if (!use32bit && aspath_has_as4 (aspath))
|
||||||
|
send_as4_path = 1; /* we'll do this later, at the correct place */
|
||||||
|
|
||||||
/* Nexthop attribute. */
|
/* Nexthop attribute. */
|
||||||
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
|
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
|
||||||
@ -1645,10 +1892,36 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
|
|||||||
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
|
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
|
||||||
{
|
{
|
||||||
assert (attr->extra);
|
assert (attr->extra);
|
||||||
|
|
||||||
|
/* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
|
||||||
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
|
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
|
||||||
stream_putc (s, BGP_ATTR_AGGREGATOR);
|
stream_putc (s, BGP_ATTR_AGGREGATOR);
|
||||||
|
|
||||||
|
if (use32bit)
|
||||||
|
{
|
||||||
|
/* AS4 capable peer */
|
||||||
|
stream_putc (s, 8);
|
||||||
|
stream_putl (s, attr->extra->aggregator_as);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 2-byte AS peer */
|
||||||
stream_putc (s, 6);
|
stream_putc (s, 6);
|
||||||
stream_putw (s, attr->extra->aggregator_as);
|
|
||||||
|
/* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */
|
||||||
|
if ( attr->extra->aggregator_as > 65535 )
|
||||||
|
{
|
||||||
|
stream_putw (s, BGP_AS_TRANS);
|
||||||
|
|
||||||
|
/* we have to send AS4_AGGREGATOR, too.
|
||||||
|
* we'll do that later in order to send attributes in ascending
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
send_as4_aggregator = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stream_putw (s, (u_int16_t) attr->extra->aggregator_as);
|
||||||
|
}
|
||||||
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
|
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,6 +2147,47 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( send_as4_path )
|
||||||
|
{
|
||||||
|
/* If the peer is NOT As4 capable, AND */
|
||||||
|
/* there are ASnums > 65535 in path THEN
|
||||||
|
* give out AS4_PATH */
|
||||||
|
|
||||||
|
/* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
|
||||||
|
* path segments!
|
||||||
|
* Hm, I wonder... confederation things *should* only be at
|
||||||
|
* the beginning of an aspath, right? Then we should use
|
||||||
|
* aspath_delete_confed_seq for this, because it is already
|
||||||
|
* there! (JK)
|
||||||
|
* Folks, talk to me: what is reasonable here!?
|
||||||
|
*/
|
||||||
|
aspath = aspath_delete_confed_seq (aspath);
|
||||||
|
|
||||||
|
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
|
||||||
|
stream_putc (s, BGP_ATTR_AS4_PATH);
|
||||||
|
aspath_sizep = stream_get_endp (s);
|
||||||
|
stream_putw (s, 0);
|
||||||
|
stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aspath != attr->aspath)
|
||||||
|
aspath_free (aspath);
|
||||||
|
|
||||||
|
if ( send_as4_aggregator )
|
||||||
|
{
|
||||||
|
assert (attr->extra);
|
||||||
|
|
||||||
|
/* send AS4_AGGREGATOR, at this place */
|
||||||
|
/* this section of code moved here in order to ensure the correct
|
||||||
|
* *ascending* order of attributes
|
||||||
|
*/
|
||||||
|
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
|
||||||
|
stream_putc (s, BGP_ATTR_AS4_AGGREGATOR);
|
||||||
|
stream_putc (s, 8);
|
||||||
|
stream_putl (s, attr->extra->aggregator_as);
|
||||||
|
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
|
||||||
|
}
|
||||||
|
|
||||||
/* AS-Pathlimit */
|
/* AS-Pathlimit */
|
||||||
if (attr->pathlimit.ttl)
|
if (attr->pathlimit.ttl)
|
||||||
{
|
{
|
||||||
@ -1967,7 +2281,7 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
|
|||||||
{
|
{
|
||||||
unsigned long cp;
|
unsigned long cp;
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
unsigned int aspathlen;
|
size_t aspath_lenp;
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
/* Remember current pointer. */
|
/* Remember current pointer. */
|
||||||
@ -1984,19 +2298,12 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
|
|||||||
|
|
||||||
aspath = attr->aspath;
|
aspath = attr->aspath;
|
||||||
|
|
||||||
if ( (aspathlen = aspath_size (aspath)) > 255 )
|
|
||||||
{
|
|
||||||
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
|
stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
|
||||||
stream_putc (s, BGP_ATTR_AS_PATH);
|
stream_putc (s, BGP_ATTR_AS_PATH);
|
||||||
stream_putw (s, aspathlen);
|
aspath_lenp = stream_get_endp (s);
|
||||||
}
|
stream_putw (s, 0);
|
||||||
else
|
|
||||||
{
|
stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1));
|
||||||
stream_putc (s, BGP_ATTR_FLAG_TRANS);
|
|
||||||
stream_putc (s, BGP_ATTR_AS_PATH);
|
|
||||||
stream_putc (s, aspathlen);
|
|
||||||
}
|
|
||||||
aspath_put (s, aspath);
|
|
||||||
|
|
||||||
/* Nexthop attribute. */
|
/* Nexthop attribute. */
|
||||||
/* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
|
/* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
|
||||||
@ -2044,8 +2351,8 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
|
|||||||
assert (attr->extra);
|
assert (attr->extra);
|
||||||
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
|
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
|
||||||
stream_putc (s, BGP_ATTR_AGGREGATOR);
|
stream_putc (s, BGP_ATTR_AGGREGATOR);
|
||||||
stream_putc (s, 6);
|
stream_putc (s, 8);
|
||||||
stream_putw (s, attr->extra->aggregator_as);
|
stream_putl (s, attr->extra->aggregator_as);
|
||||||
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
|
stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
bgpd/bgp_debug.c
118
bgpd/bgp_debug.c
@ -36,6 +36,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#include "bgpd/bgp_debug.h"
|
#include "bgpd/bgp_debug.h"
|
||||||
#include "bgpd/bgp_community.h"
|
#include "bgpd/bgp_community.h"
|
||||||
|
|
||||||
|
unsigned long conf_bgp_debug_as4;
|
||||||
unsigned long conf_bgp_debug_fsm;
|
unsigned long conf_bgp_debug_fsm;
|
||||||
unsigned long conf_bgp_debug_events;
|
unsigned long conf_bgp_debug_events;
|
||||||
unsigned long conf_bgp_debug_packet;
|
unsigned long conf_bgp_debug_packet;
|
||||||
@ -45,6 +46,7 @@ unsigned long conf_bgp_debug_update;
|
|||||||
unsigned long conf_bgp_debug_normal;
|
unsigned long conf_bgp_debug_normal;
|
||||||
unsigned long conf_bgp_debug_zebra;
|
unsigned long conf_bgp_debug_zebra;
|
||||||
|
|
||||||
|
unsigned long term_bgp_debug_as4;
|
||||||
unsigned long term_bgp_debug_fsm;
|
unsigned long term_bgp_debug_fsm;
|
||||||
unsigned long term_bgp_debug_events;
|
unsigned long term_bgp_debug_events;
|
||||||
unsigned long term_bgp_debug_packet;
|
unsigned long term_bgp_debug_packet;
|
||||||
@ -297,6 +299,92 @@ debug (unsigned int option)
|
|||||||
return bgp_debug_option & option;
|
return bgp_debug_option & option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (debug_bgp_as4,
|
||||||
|
debug_bgp_as4_cmd,
|
||||||
|
"debug bgp as4",
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 actions\n")
|
||||||
|
{
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON (as4, AS4);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TERM_DEBUG_ON (as4, AS4);
|
||||||
|
vty_out (vty, "BGP as4 debugging is on%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_debug_bgp_as4,
|
||||||
|
no_debug_bgp_as4_cmd,
|
||||||
|
"no debug bgp as4",
|
||||||
|
NO_STR
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 actions\n")
|
||||||
|
{
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF (as4, AS4);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TERM_DEBUG_OFF (as4, AS4);
|
||||||
|
vty_out (vty, "BGP as4 debugging is off%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS (no_debug_bgp_as4,
|
||||||
|
undebug_bgp_as4_cmd,
|
||||||
|
"undebug bgp as4",
|
||||||
|
UNDEBUG_STR
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 actions\n")
|
||||||
|
|
||||||
|
DEFUN (debug_bgp_as4_segment,
|
||||||
|
debug_bgp_as4_segment_cmd,
|
||||||
|
"debug bgp as4 segment",
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 aspath segment handling\n")
|
||||||
|
{
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON (as4, AS4_SEGMENT);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TERM_DEBUG_ON (as4, AS4_SEGMENT);
|
||||||
|
vty_out (vty, "BGP as4 segment debugging is on%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_debug_bgp_as4_segment,
|
||||||
|
no_debug_bgp_as4_segment_cmd,
|
||||||
|
"no debug bgp as4 segment",
|
||||||
|
NO_STR
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 aspath segment handling\n")
|
||||||
|
{
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF (as4, AS4_SEGMENT);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TERM_DEBUG_OFF (as4, AS4_SEGMENT);
|
||||||
|
vty_out (vty, "BGP as4 segment debugging is off%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS (no_debug_bgp_as4_segment,
|
||||||
|
undebug_bgp_as4_segment_cmd,
|
||||||
|
"undebug bgp as4 segment",
|
||||||
|
UNDEBUG_STR
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP AS4 aspath segment handling\n")
|
||||||
|
|
||||||
DEFUN (debug_bgp_fsm,
|
DEFUN (debug_bgp_fsm,
|
||||||
debug_bgp_fsm_cmd,
|
debug_bgp_fsm_cmd,
|
||||||
"debug bgp fsm",
|
"debug bgp fsm",
|
||||||
@ -651,6 +739,8 @@ DEFUN (no_debug_bgp_all,
|
|||||||
TERM_DEBUG_OFF (keepalive, KEEPALIVE);
|
TERM_DEBUG_OFF (keepalive, KEEPALIVE);
|
||||||
TERM_DEBUG_OFF (update, UPDATE_IN);
|
TERM_DEBUG_OFF (update, UPDATE_IN);
|
||||||
TERM_DEBUG_OFF (update, UPDATE_OUT);
|
TERM_DEBUG_OFF (update, UPDATE_OUT);
|
||||||
|
TERM_DEBUG_OFF (as4, AS4);
|
||||||
|
TERM_DEBUG_OFF (as4, AS4_SEGMENT);
|
||||||
TERM_DEBUG_OFF (fsm, FSM);
|
TERM_DEBUG_OFF (fsm, FSM);
|
||||||
TERM_DEBUG_OFF (filter, FILTER);
|
TERM_DEBUG_OFF (filter, FILTER);
|
||||||
TERM_DEBUG_OFF (zebra, ZEBRA);
|
TERM_DEBUG_OFF (zebra, ZEBRA);
|
||||||
@ -693,6 +783,10 @@ DEFUN (show_debugging_bgp,
|
|||||||
vty_out (vty, " BGP filter debugging is on%s", VTY_NEWLINE);
|
vty_out (vty, " BGP filter debugging is on%s", VTY_NEWLINE);
|
||||||
if (BGP_DEBUG (zebra, ZEBRA))
|
if (BGP_DEBUG (zebra, ZEBRA))
|
||||||
vty_out (vty, " BGP zebra debugging is on%s", VTY_NEWLINE);
|
vty_out (vty, " BGP zebra debugging is on%s", VTY_NEWLINE);
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
vty_out (vty, " BGP as4 debugging is on%s", VTY_NEWLINE);
|
||||||
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
|
vty_out (vty, " BGP as4 aspath segment debugging is on%s", VTY_NEWLINE);
|
||||||
vty_out (vty, "%s", VTY_NEWLINE);
|
vty_out (vty, "%s", VTY_NEWLINE);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -708,6 +802,18 @@ bgp_config_write_debug (struct vty *vty)
|
|||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CONF_BGP_DEBUG (as4, AS4))
|
||||||
|
{
|
||||||
|
vty_out (vty, "debug bgp as4%s", VTY_NEWLINE);
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONF_BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
|
{
|
||||||
|
vty_out (vty, "debug bgp as4 segment%s", VTY_NEWLINE);
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
|
||||||
if (CONF_BGP_DEBUG (events, EVENTS))
|
if (CONF_BGP_DEBUG (events, EVENTS))
|
||||||
{
|
{
|
||||||
vty_out (vty, "debug bgp events%s", VTY_NEWLINE);
|
vty_out (vty, "debug bgp events%s", VTY_NEWLINE);
|
||||||
@ -771,6 +877,11 @@ bgp_debug_init (void)
|
|||||||
|
|
||||||
install_element (ENABLE_NODE, &show_debugging_bgp_cmd);
|
install_element (ENABLE_NODE, &show_debugging_bgp_cmd);
|
||||||
|
|
||||||
|
install_element (ENABLE_NODE, &debug_bgp_as4_cmd);
|
||||||
|
install_element (CONFIG_NODE, &debug_bgp_as4_cmd);
|
||||||
|
install_element (ENABLE_NODE, &debug_bgp_as4_segment_cmd);
|
||||||
|
install_element (CONFIG_NODE, &debug_bgp_as4_segment_cmd);
|
||||||
|
|
||||||
install_element (ENABLE_NODE, &debug_bgp_fsm_cmd);
|
install_element (ENABLE_NODE, &debug_bgp_fsm_cmd);
|
||||||
install_element (CONFIG_NODE, &debug_bgp_fsm_cmd);
|
install_element (CONFIG_NODE, &debug_bgp_fsm_cmd);
|
||||||
install_element (ENABLE_NODE, &debug_bgp_events_cmd);
|
install_element (ENABLE_NODE, &debug_bgp_events_cmd);
|
||||||
@ -788,6 +899,13 @@ bgp_debug_init (void)
|
|||||||
install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
|
install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
|
||||||
install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
|
install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
|
||||||
|
|
||||||
|
install_element (ENABLE_NODE, &no_debug_bgp_as4_cmd);
|
||||||
|
install_element (ENABLE_NODE, &undebug_bgp_as4_cmd);
|
||||||
|
install_element (CONFIG_NODE, &no_debug_bgp_as4_cmd);
|
||||||
|
install_element (ENABLE_NODE, &no_debug_bgp_as4_segment_cmd);
|
||||||
|
install_element (ENABLE_NODE, &undebug_bgp_as4_segment_cmd);
|
||||||
|
install_element (CONFIG_NODE, &no_debug_bgp_as4_segment_cmd);
|
||||||
|
|
||||||
install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
|
install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
|
||||||
install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
|
install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
|
||||||
install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd);
|
install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd);
|
||||||
|
@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#ifndef _QUAGGA_BGP_DEBUG_H
|
#ifndef _QUAGGA_BGP_DEBUG_H
|
||||||
#define _QUAGGA_BGP_DEBUG_H
|
#define _QUAGGA_BGP_DEBUG_H
|
||||||
|
|
||||||
|
#include "bgp_attr.h"
|
||||||
|
|
||||||
/* sort of packet direction */
|
/* sort of packet direction */
|
||||||
#define DUMP_ON 1
|
#define DUMP_ON 1
|
||||||
#define DUMP_SEND 2
|
#define DUMP_SEND 2
|
||||||
@ -56,6 +58,7 @@ extern void bgp_packet_dump (struct stream *);
|
|||||||
|
|
||||||
extern int debug (unsigned int option);
|
extern int debug (unsigned int option);
|
||||||
|
|
||||||
|
extern unsigned long conf_bgp_debug_as4;
|
||||||
extern unsigned long conf_bgp_debug_fsm;
|
extern unsigned long conf_bgp_debug_fsm;
|
||||||
extern unsigned long conf_bgp_debug_events;
|
extern unsigned long conf_bgp_debug_events;
|
||||||
extern unsigned long conf_bgp_debug_packet;
|
extern unsigned long conf_bgp_debug_packet;
|
||||||
@ -65,6 +68,7 @@ extern unsigned long conf_bgp_debug_update;
|
|||||||
extern unsigned long conf_bgp_debug_normal;
|
extern unsigned long conf_bgp_debug_normal;
|
||||||
extern unsigned long conf_bgp_debug_zebra;
|
extern unsigned long conf_bgp_debug_zebra;
|
||||||
|
|
||||||
|
extern unsigned long term_bgp_debug_as4;
|
||||||
extern unsigned long term_bgp_debug_fsm;
|
extern unsigned long term_bgp_debug_fsm;
|
||||||
extern unsigned long term_bgp_debug_events;
|
extern unsigned long term_bgp_debug_events;
|
||||||
extern unsigned long term_bgp_debug_packet;
|
extern unsigned long term_bgp_debug_packet;
|
||||||
@ -74,6 +78,9 @@ extern unsigned long term_bgp_debug_update;
|
|||||||
extern unsigned long term_bgp_debug_normal;
|
extern unsigned long term_bgp_debug_normal;
|
||||||
extern unsigned long term_bgp_debug_zebra;
|
extern unsigned long term_bgp_debug_zebra;
|
||||||
|
|
||||||
|
#define BGP_DEBUG_AS4 0x01
|
||||||
|
#define BGP_DEBUG_AS4_SEGMENT 0x02
|
||||||
|
|
||||||
#define BGP_DEBUG_FSM 0x01
|
#define BGP_DEBUG_FSM 0x01
|
||||||
#define BGP_DEBUG_EVENTS 0x01
|
#define BGP_DEBUG_EVENTS 0x01
|
||||||
#define BGP_DEBUG_PACKET 0x01
|
#define BGP_DEBUG_PACKET 0x01
|
||||||
|
259
bgpd/bgp_dump.c
259
bgpd/bgp_dump.c
@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "linklist.h"
|
||||||
#include "bgpd/bgp_table.h"
|
#include "bgpd/bgp_table.h"
|
||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
@ -53,7 +54,8 @@ enum MRT_MSG_TYPES {
|
|||||||
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
|
MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
|
||||||
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
|
MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
|
||||||
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
|
MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
|
||||||
MSG_TABLE_DUMP /* routing table dump */
|
MSG_TABLE_DUMP, /* routing table dump */
|
||||||
|
MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int bgp_dump_interval_func (struct thread *);
|
static int bgp_dump_interval_func (struct thread *);
|
||||||
@ -191,137 +193,189 @@ bgp_dump_set_size (struct stream *s, int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
|
bgp_dump_routes_index_table(struct bgp *bgp)
|
||||||
int type, unsigned int seq)
|
|
||||||
{
|
{
|
||||||
struct stream *obuf;
|
|
||||||
struct attr *attr;
|
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
int plen;
|
struct listnode *node;
|
||||||
int safi = 0;
|
uint16_t peerno = 0;
|
||||||
|
struct stream *obuf;
|
||||||
|
|
||||||
/* Make dump stream. */
|
|
||||||
obuf = bgp_dump_obuf;
|
obuf = bgp_dump_obuf;
|
||||||
stream_reset (obuf);
|
stream_reset (obuf);
|
||||||
|
|
||||||
attr = info->attr;
|
/* MRT header */
|
||||||
peer = info->peer;
|
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE);
|
||||||
|
|
||||||
/* We support MRT's old format. */
|
/* Collector BGP ID */
|
||||||
if (type == MSG_TABLE_DUMP)
|
stream_put_in_addr (obuf, &bgp->router_id);
|
||||||
|
|
||||||
|
/* View name */
|
||||||
|
if(bgp->name)
|
||||||
{
|
{
|
||||||
bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
|
stream_putw (obuf, strlen(bgp->name));
|
||||||
stream_putw (obuf, 0); /* View # */
|
stream_put(obuf, bgp->name, strlen(bgp->name));
|
||||||
stream_putw (obuf, seq); /* Sequence number. */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
|
stream_putw(obuf, 0);
|
||||||
|
|
||||||
stream_putl (obuf, info->uptime); /* Time Last Change */
|
|
||||||
stream_putw (obuf, afi); /* Address Family */
|
|
||||||
stream_putc (obuf, safi); /* SAFI */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (afi == AFI_IP)
|
/* Peer count */
|
||||||
|
stream_putw (obuf, listcount(bgp->peer));
|
||||||
|
|
||||||
|
/* Walk down all peers */
|
||||||
|
for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
|
||||||
{
|
{
|
||||||
if (type == MSG_TABLE_DUMP)
|
|
||||||
|
/* Peer's type */
|
||||||
|
if (sockunion_family(&peer->su) == AF_INET)
|
||||||
{
|
{
|
||||||
/* Prefix */
|
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
|
||||||
stream_put_in_addr (obuf, &p->u.prefix4);
|
|
||||||
stream_putc (obuf, p->prefixlen);
|
|
||||||
|
|
||||||
/* Status */
|
|
||||||
stream_putc (obuf, 1);
|
|
||||||
|
|
||||||
/* Originated */
|
|
||||||
stream_putl (obuf, info->uptime);
|
|
||||||
|
|
||||||
/* Peer's IP address */
|
|
||||||
stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
|
|
||||||
|
|
||||||
/* Peer's AS number. */
|
|
||||||
stream_putw (obuf, peer->as);
|
|
||||||
|
|
||||||
/* Dump attribute. */
|
|
||||||
bgp_dump_routes_attr (obuf, attr, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Next-Hop-Len */
|
|
||||||
stream_putc (obuf, IPV4_MAX_BYTELEN);
|
|
||||||
stream_put_in_addr (obuf, &attr->nexthop);
|
|
||||||
stream_putc (obuf, p->prefixlen);
|
|
||||||
plen = PSIZE (p->prefixlen);
|
|
||||||
stream_put (obuf, &p->u.prefix4, plen);
|
|
||||||
bgp_dump_routes_attr (obuf, attr, p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (afi == AFI_IP6)
|
else if (sockunion_family(&peer->su) == AF_INET6)
|
||||||
{
|
{
|
||||||
if (type == MSG_TABLE_DUMP)
|
stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
|
||||||
{
|
|
||||||
/* Prefix */
|
|
||||||
stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
|
|
||||||
stream_putc (obuf, p->prefixlen);
|
|
||||||
|
|
||||||
/* Status */
|
|
||||||
stream_putc (obuf, 1);
|
|
||||||
|
|
||||||
/* Originated */
|
|
||||||
stream_putl (obuf, info->uptime);
|
|
||||||
|
|
||||||
/* Peer's IP address */
|
|
||||||
stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
|
|
||||||
IPV6_MAX_BYTELEN);
|
|
||||||
|
|
||||||
/* Peer's AS number. */
|
|
||||||
stream_putw (obuf, peer->as);
|
|
||||||
|
|
||||||
/* Dump attribute. */
|
|
||||||
bgp_dump_routes_attr (obuf, attr, p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
/* Set length. */
|
/* Peer's BGP ID */
|
||||||
bgp_dump_set_size (obuf, type);
|
stream_put_in_addr (obuf, &peer->remote_id);
|
||||||
|
|
||||||
|
/* Peer's IP address */
|
||||||
|
if (sockunion_family(&peer->su) == AF_INET)
|
||||||
|
{
|
||||||
|
stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (sockunion_family(&peer->su) == AF_INET6)
|
||||||
|
{
|
||||||
|
stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
|
||||||
|
IPV6_MAX_BYTELEN);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
|
/* Peer's AS number. */
|
||||||
|
/* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
|
||||||
|
stream_putl (obuf, peer->as);
|
||||||
|
|
||||||
|
/* Store the peer number for this peer */
|
||||||
|
peer->table_dump_index = peerno;
|
||||||
|
peerno++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
|
||||||
|
|
||||||
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
|
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
|
||||||
fflush (bgp_dump_routes.fp);
|
fflush (bgp_dump_routes.fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Runs under child process. */
|
/* Runs under child process. */
|
||||||
static void
|
static unsigned int
|
||||||
bgp_dump_routes_func (int afi)
|
bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
|
||||||
{
|
{
|
||||||
struct stream *obuf;
|
struct stream *obuf;
|
||||||
struct bgp_node *rn;
|
|
||||||
struct bgp_info *info;
|
struct bgp_info *info;
|
||||||
|
struct bgp_node *rn;
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
struct bgp_table *table;
|
struct bgp_table *table;
|
||||||
unsigned int seq = 0;
|
|
||||||
|
|
||||||
obuf = bgp_dump_obuf;
|
|
||||||
|
|
||||||
bgp = bgp_get_default ();
|
bgp = bgp_get_default ();
|
||||||
if (!bgp)
|
if (!bgp)
|
||||||
return;
|
return seq;
|
||||||
|
|
||||||
if (bgp_dump_routes.fp == NULL)
|
if (bgp_dump_routes.fp == NULL)
|
||||||
return;
|
return seq;
|
||||||
|
|
||||||
|
/* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
|
||||||
|
so this should only be done on the first call to bgp_dump_routes_func.
|
||||||
|
( this function will be called once for ipv4 and once for ipv6 ) */
|
||||||
|
if(first_run)
|
||||||
|
bgp_dump_routes_index_table(bgp);
|
||||||
|
|
||||||
|
obuf = bgp_dump_obuf;
|
||||||
|
stream_reset(obuf);
|
||||||
|
|
||||||
/* Walk down each BGP route. */
|
/* Walk down each BGP route. */
|
||||||
table = bgp->rib[afi][SAFI_UNICAST];
|
table = bgp->rib[afi][SAFI_UNICAST];
|
||||||
|
|
||||||
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
|
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
|
||||||
|
{
|
||||||
|
if(!rn->info)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
stream_reset(obuf);
|
||||||
|
|
||||||
|
/* MRT header */
|
||||||
|
if (afi == AFI_IP)
|
||||||
|
{
|
||||||
|
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (afi == AFI_IP6)
|
||||||
|
{
|
||||||
|
bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
|
/* Sequence number */
|
||||||
|
stream_putl(obuf, seq);
|
||||||
|
|
||||||
|
/* Prefix length */
|
||||||
|
stream_putc (obuf, rn->p.prefixlen);
|
||||||
|
|
||||||
|
/* Prefix */
|
||||||
|
if (afi == AFI_IP)
|
||||||
|
{
|
||||||
|
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
|
||||||
|
stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (afi == AFI_IP6)
|
||||||
|
{
|
||||||
|
/* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
|
||||||
|
stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
|
/* Save where we are now, so we can overwride the entry count later */
|
||||||
|
int sizep = stream_get_endp(obuf);
|
||||||
|
|
||||||
|
/* Entry count */
|
||||||
|
uint16_t entry_count = 0;
|
||||||
|
|
||||||
|
/* Entry count, note that this is overwritten later */
|
||||||
|
stream_putw(obuf, 0);
|
||||||
|
|
||||||
for (info = rn->info; info; info = info->next)
|
for (info = rn->info; info; info = info->next)
|
||||||
bgp_dump_routes_entry (&rn->p, info, afi, MSG_TABLE_DUMP, seq++);
|
{
|
||||||
|
entry_count++;
|
||||||
|
|
||||||
|
/* Peer index */
|
||||||
|
stream_putw(obuf, info->peer->table_dump_index);
|
||||||
|
|
||||||
|
/* Originated */
|
||||||
|
stream_putl (obuf, info->uptime);
|
||||||
|
|
||||||
|
/* Dump attribute. */
|
||||||
|
/* Skip prefix & AFI/SAFI for MP_NLRI */
|
||||||
|
bgp_dump_routes_attr (obuf, info->attr, &rn->p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overwrite the entry count, now that we know the right number */
|
||||||
|
stream_putw_at (obuf, sizep, entry_count);
|
||||||
|
|
||||||
|
seq++;
|
||||||
|
|
||||||
|
bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
|
||||||
|
fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush (bgp_dump_routes.fp);
|
||||||
|
|
||||||
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -337,9 +391,9 @@ bgp_dump_interval_func (struct thread *t)
|
|||||||
/* In case of bgp_dump_routes, we need special route dump function. */
|
/* In case of bgp_dump_routes, we need special route dump function. */
|
||||||
if (bgp_dump->type == BGP_DUMP_ROUTES)
|
if (bgp_dump->type == BGP_DUMP_ROUTES)
|
||||||
{
|
{
|
||||||
bgp_dump_routes_func (AFI_IP);
|
unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
bgp_dump_routes_func (AFI_IP6);
|
bgp_dump_routes_func (AFI_IP6, 0, seq);
|
||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
/* Close the file now. For a RIB dump there's no point in leaving
|
/* Close the file now. For a RIB dump there's no point in leaving
|
||||||
* it open until the next scheduled dump starts. */
|
* it open until the next scheduled dump starts. */
|
||||||
@ -356,13 +410,21 @@ bgp_dump_interval_func (struct thread *t)
|
|||||||
|
|
||||||
/* Dump common information. */
|
/* Dump common information. */
|
||||||
static void
|
static void
|
||||||
bgp_dump_common (struct stream *obuf, struct peer *peer)
|
bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
|
||||||
{
|
{
|
||||||
char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||||
|
|
||||||
/* Source AS number and Destination AS number. */
|
/* Source AS number and Destination AS number. */
|
||||||
|
if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
|
||||||
|
{
|
||||||
|
stream_putl (obuf, peer->as);
|
||||||
|
stream_putl (obuf, peer->local_as);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
stream_putw (obuf, peer->as);
|
stream_putw (obuf, peer->as);
|
||||||
stream_putw (obuf, peer->local_as);
|
stream_putw (obuf, peer->local_as);
|
||||||
|
}
|
||||||
|
|
||||||
if (peer->su.sa.sa_family == AF_INET)
|
if (peer->su.sa.sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
@ -408,8 +470,8 @@ bgp_dump_state (struct peer *peer, int status_old, int status_new)
|
|||||||
obuf = bgp_dump_obuf;
|
obuf = bgp_dump_obuf;
|
||||||
stream_reset (obuf);
|
stream_reset (obuf);
|
||||||
|
|
||||||
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE);
|
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4);
|
||||||
bgp_dump_common (obuf, peer);
|
bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
|
||||||
|
|
||||||
stream_putw (obuf, status_old);
|
stream_putw (obuf, status_old);
|
||||||
stream_putw (obuf, status_new);
|
stream_putw (obuf, status_new);
|
||||||
@ -437,8 +499,15 @@ bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
|
|||||||
stream_reset (obuf);
|
stream_reset (obuf);
|
||||||
|
|
||||||
/* Dump header and common part. */
|
/* Dump header and common part. */
|
||||||
|
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
|
||||||
|
{
|
||||||
|
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
|
bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
|
||||||
bgp_dump_common (obuf, peer);
|
}
|
||||||
|
bgp_dump_common (obuf, peer, 0);
|
||||||
|
|
||||||
/* Packet contents. */
|
/* Packet contents. */
|
||||||
stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
|
stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
|
||||||
|
@ -29,10 +29,24 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#define BGP4MP_MESSAGE 1
|
#define BGP4MP_MESSAGE 1
|
||||||
#define BGP4MP_ENTRY 2
|
#define BGP4MP_ENTRY 2
|
||||||
#define BGP4MP_SNAPSHOT 3
|
#define BGP4MP_SNAPSHOT 3
|
||||||
|
#define BGP4MP_MESSAGE_AS4 4
|
||||||
|
#define BGP4MP_STATE_CHANGE_AS4 5
|
||||||
|
|
||||||
#define BGP_DUMP_HEADER_SIZE 12
|
#define BGP_DUMP_HEADER_SIZE 12
|
||||||
#define BGP_DUMP_MSG_HEADER 40
|
#define BGP_DUMP_MSG_HEADER 40
|
||||||
|
|
||||||
|
#define TABLE_DUMP_V2_PEER_INDEX_TABLE 1
|
||||||
|
#define TABLE_DUMP_V2_RIB_IPV4_UNICAST 2
|
||||||
|
#define TABLE_DUMP_V2_RIB_IPV4_MULTICAST 3
|
||||||
|
#define TABLE_DUMP_V2_RIB_IPV6_UNICAST 4
|
||||||
|
#define TABLE_DUMP_V2_RIB_IPV6_MULTICAST 5
|
||||||
|
#define TABLE_DUMP_V2_RIB_GENERIC 6
|
||||||
|
|
||||||
|
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_IP 0
|
||||||
|
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6 1
|
||||||
|
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS2 0
|
||||||
|
#define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2
|
||||||
|
|
||||||
extern void bgp_dump_init (void);
|
extern void bgp_dump_init (void);
|
||||||
extern void bgp_dump_state (struct peer *, int, int);
|
extern void bgp_dump_state (struct peer *, int, int);
|
||||||
extern void bgp_dump_packet (struct peer *, int, struct stream *);
|
extern void bgp_dump_packet (struct peer *, int, struct stream *);
|
||||||
|
@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_ecommunity.h"
|
#include "bgpd/bgp_ecommunity.h"
|
||||||
|
#include "bgpd/bgp_aspath.h"
|
||||||
|
|
||||||
/* Hash of community attribute. */
|
/* Hash of community attribute. */
|
||||||
struct hash *ecomhash;
|
struct hash *ecomhash;
|
||||||
@ -228,8 +229,9 @@ ecommunity_unintern (struct ecommunity *ecom)
|
|||||||
|
|
||||||
/* Utinity function to make hash key. */
|
/* Utinity function to make hash key. */
|
||||||
unsigned int
|
unsigned int
|
||||||
ecommunity_hash_make (struct ecommunity *ecom)
|
ecommunity_hash_make (void *arg)
|
||||||
{
|
{
|
||||||
|
const struct ecommunity *ecom = arg;
|
||||||
int c;
|
int c;
|
||||||
unsigned int key;
|
unsigned int key;
|
||||||
u_int8_t *pnt;
|
u_int8_t *pnt;
|
||||||
@ -245,9 +247,11 @@ ecommunity_hash_make (struct ecommunity *ecom)
|
|||||||
|
|
||||||
/* Compare two Extended Communities Attribute structure. */
|
/* Compare two Extended Communities Attribute structure. */
|
||||||
int
|
int
|
||||||
ecommunity_cmp (const struct ecommunity *ecom1,
|
ecommunity_cmp (void *arg1, void *arg2)
|
||||||
const struct ecommunity *ecom2)
|
|
||||||
{
|
{
|
||||||
|
const struct ecommunity *ecom1 = arg1;
|
||||||
|
const struct ecommunity *ecom2 = arg2;
|
||||||
|
|
||||||
if (ecom1->size == ecom2->size
|
if (ecom1->size == ecom2->size
|
||||||
&& memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0)
|
&& memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
@ -256,7 +260,7 @@ ecommunity_cmp (const struct ecommunity *ecom1,
|
|||||||
|
|
||||||
/* Initialize Extended Comminities related hash. */
|
/* Initialize Extended Comminities related hash. */
|
||||||
void
|
void
|
||||||
ecommunity_init ()
|
ecommunity_init (void)
|
||||||
{
|
{
|
||||||
ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp);
|
ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp);
|
||||||
}
|
}
|
||||||
@ -279,11 +283,12 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
|
|||||||
int dot = 0;
|
int dot = 0;
|
||||||
int digit = 0;
|
int digit = 0;
|
||||||
int separator = 0;
|
int separator = 0;
|
||||||
u_int32_t val_low = 0;
|
|
||||||
u_int32_t val_high = 0;
|
|
||||||
const char *p = str;
|
const char *p = str;
|
||||||
|
char *endptr;
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
char ipstr[INET_ADDRSTRLEN + 1];
|
as_t as = 0;
|
||||||
|
u_int32_t val = 0;
|
||||||
|
char buf[INET_ADDRSTRLEN + 1];
|
||||||
|
|
||||||
/* Skip white space. */
|
/* Skip white space. */
|
||||||
while (isspace ((int) *p))
|
while (isspace ((int) *p))
|
||||||
@ -346,6 +351,19 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* What a mess, there are several possibilities:
|
||||||
|
*
|
||||||
|
* a) A.B.C.D:MN
|
||||||
|
* b) EF:OPQR
|
||||||
|
* c) GHJK:MN
|
||||||
|
*
|
||||||
|
* A.B.C.D: Four Byte IP
|
||||||
|
* EF: Two byte ASN
|
||||||
|
* GHJK: Four-byte ASN
|
||||||
|
* MN: Two byte value
|
||||||
|
* OPQR: Four byte value
|
||||||
|
*
|
||||||
|
*/
|
||||||
while (isdigit ((int) *p) || *p == ':' || *p == '.')
|
while (isdigit ((int) *p) || *p == ':' || *p == '.')
|
||||||
{
|
{
|
||||||
if (*p == ':')
|
if (*p == ':')
|
||||||
@ -356,22 +374,27 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
|
|||||||
separator = 1;
|
separator = 1;
|
||||||
digit = 0;
|
digit = 0;
|
||||||
|
|
||||||
if (dot)
|
|
||||||
{
|
|
||||||
if ((p - str) > INET_ADDRSTRLEN)
|
if ((p - str) > INET_ADDRSTRLEN)
|
||||||
goto error;
|
goto error;
|
||||||
|
memset (buf, 0, INET_ADDRSTRLEN + 1);
|
||||||
|
memcpy (buf, str, p - str);
|
||||||
|
|
||||||
memset (ipstr, 0, INET_ADDRSTRLEN + 1);
|
if (dot)
|
||||||
memcpy (ipstr, str, p - str);
|
{
|
||||||
|
/* Parsing A.B.C.D in:
|
||||||
ret = inet_aton (ipstr, &ip);
|
* A.B.C.D:MN
|
||||||
|
*/
|
||||||
|
ret = inet_aton (buf, &ip);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
val_high = val_low;
|
{
|
||||||
|
/* ASN */
|
||||||
val_low = 0;
|
as = strtoul (buf, &endptr, 10);
|
||||||
|
if (*endptr != '\0' || as == BGP_AS4_MAX)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (*p == '.')
|
else if (*p == '.')
|
||||||
{
|
{
|
||||||
@ -384,8 +407,13 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
digit = 1;
|
digit = 1;
|
||||||
val_low *= 10;
|
|
||||||
val_low += (*p - '0');
|
/* We're past the IP/ASN part */
|
||||||
|
if (separator)
|
||||||
|
{
|
||||||
|
val *= 10;
|
||||||
|
val += (*p - '0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@ -397,22 +425,40 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval,
|
|||||||
/* Encode result into routing distinguisher. */
|
/* Encode result into routing distinguisher. */
|
||||||
if (dot)
|
if (dot)
|
||||||
{
|
{
|
||||||
|
if (val > UINT16_MAX)
|
||||||
|
goto error;
|
||||||
|
|
||||||
eval->val[0] = ECOMMUNITY_ENCODE_IP;
|
eval->val[0] = ECOMMUNITY_ENCODE_IP;
|
||||||
eval->val[1] = 0;
|
eval->val[1] = 0;
|
||||||
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
|
memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
|
||||||
eval->val[6] = (val_low >> 8) & 0xff;
|
eval->val[6] = (val >> 8) & 0xff;
|
||||||
eval->val[7] = val_low & 0xff;
|
eval->val[7] = val & 0xff;
|
||||||
|
}
|
||||||
|
else if (as > BGP_AS_MAX)
|
||||||
|
{
|
||||||
|
if (val > UINT16_MAX)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
eval->val[0] = ECOMMUNITY_ENCODE_AS4;
|
||||||
|
eval->val[1] = 0;
|
||||||
|
eval->val[2] = (as >>24) & 0xff;
|
||||||
|
eval->val[3] = (as >>16) & 0xff;
|
||||||
|
eval->val[4] = (as >>8) & 0xff;
|
||||||
|
eval->val[5] = as & 0xff;
|
||||||
|
eval->val[6] = (val >> 8) & 0xff;
|
||||||
|
eval->val[7] = val & 0xff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
||||||
eval->val[1] = 0;
|
eval->val[1] = 0;
|
||||||
eval->val[2] = (val_high >>8) & 0xff;
|
|
||||||
eval->val[3] = val_high & 0xff;
|
eval->val[2] = (as >>8) & 0xff;
|
||||||
eval->val[4] = (val_low >>24) & 0xff;
|
eval->val[3] = as & 0xff;
|
||||||
eval->val[5] = (val_low >>16) & 0xff;
|
eval->val[4] = (val >>24) & 0xff;
|
||||||
eval->val[6] = (val_low >>8) & 0xff;
|
eval->val[5] = (val >>16) & 0xff;
|
||||||
eval->val[7] = val_low & 0xff;
|
eval->val[6] = (val >>8) & 0xff;
|
||||||
|
eval->val[7] = val & 0xff;
|
||||||
}
|
}
|
||||||
*token = ecommunity_token_val;
|
*token = ecommunity_token_val;
|
||||||
return p;
|
return p;
|
||||||
@ -533,7 +579,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
|
|||||||
u_int8_t *pnt;
|
u_int8_t *pnt;
|
||||||
int encode = 0;
|
int encode = 0;
|
||||||
int type = 0;
|
int type = 0;
|
||||||
#define ECOMMUNITY_STR_DEFAULT_LEN 26
|
#define ECOMMUNITY_STR_DEFAULT_LEN 27
|
||||||
int str_size;
|
int str_size;
|
||||||
int str_pnt;
|
int str_pnt;
|
||||||
char *str_buf;
|
char *str_buf;
|
||||||
@ -576,7 +622,8 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
|
|||||||
|
|
||||||
/* High-order octet of type. */
|
/* High-order octet of type. */
|
||||||
encode = *pnt++;
|
encode = *pnt++;
|
||||||
if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP)
|
if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP
|
||||||
|
&& encode != ECOMMUNITY_ENCODE_AS4)
|
||||||
{
|
{
|
||||||
len = sprintf (str_buf + str_pnt, "?");
|
len = sprintf (str_buf + str_pnt, "?");
|
||||||
str_pnt += len;
|
str_pnt += len;
|
||||||
@ -618,6 +665,21 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Put string into buffer. */
|
/* Put string into buffer. */
|
||||||
|
if (encode == ECOMMUNITY_ENCODE_AS4)
|
||||||
|
{
|
||||||
|
eas.as = (*pnt++ << 24);
|
||||||
|
eas.as |= (*pnt++ << 16);
|
||||||
|
eas.as |= (*pnt++ << 8);
|
||||||
|
eas.as |= (*pnt++);
|
||||||
|
|
||||||
|
eas.val = (*pnt++ << 8);
|
||||||
|
eas.val |= (*pnt++);
|
||||||
|
|
||||||
|
len = sprintf( str_buf + str_pnt, "%s%d:%d", prefix,
|
||||||
|
eas.as, eas.val );
|
||||||
|
str_pnt += len;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
if (encode == ECOMMUNITY_ENCODE_AS)
|
if (encode == ECOMMUNITY_ENCODE_AS)
|
||||||
{
|
{
|
||||||
eas.as = (*pnt++ << 8);
|
eas.as = (*pnt++ << 8);
|
||||||
|
@ -24,6 +24,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
/* High-order octet of the Extended Communities type field. */
|
/* High-order octet of the Extended Communities type field. */
|
||||||
#define ECOMMUNITY_ENCODE_AS 0x00
|
#define ECOMMUNITY_ENCODE_AS 0x00
|
||||||
#define ECOMMUNITY_ENCODE_IP 0x01
|
#define ECOMMUNITY_ENCODE_IP 0x01
|
||||||
|
#define ECOMMUNITY_ENCODE_AS4 0x02
|
||||||
|
|
||||||
/* Low-order octet of the Extended Communityes type field. */
|
/* Low-order octet of the Extended Communityes type field. */
|
||||||
#define ECOMMUNITY_ROUTE_TARGET 0x02
|
#define ECOMMUNITY_ROUTE_TARGET 0x02
|
||||||
@ -71,9 +72,9 @@ extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
|
|||||||
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
|
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
|
||||||
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
|
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
|
||||||
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
|
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
|
||||||
extern int ecommunity_cmp (const struct ecommunity *, const struct ecommunity *);
|
extern int ecommunity_cmp (void *, void *);
|
||||||
extern void ecommunity_unintern (struct ecommunity *);
|
extern void ecommunity_unintern (struct ecommunity *);
|
||||||
extern unsigned int ecommunity_hash_make (struct ecommunity *);
|
extern unsigned int ecommunity_hash_make (void *);
|
||||||
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
|
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
|
||||||
extern char *ecommunity_ecom2str (struct ecommunity *, int);
|
extern char *ecommunity_ecom2str (struct ecommunity *, int);
|
||||||
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *);
|
extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *);
|
||||||
|
116
bgpd/bgp_open.c
116
bgpd/bgp_open.c
@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#include "bgpd/bgp_fsm.h"
|
#include "bgpd/bgp_fsm.h"
|
||||||
#include "bgpd/bgp_packet.h"
|
#include "bgpd/bgp_packet.h"
|
||||||
#include "bgpd/bgp_open.h"
|
#include "bgpd/bgp_open.h"
|
||||||
|
#include "bgpd/bgp_aspath.h"
|
||||||
#include "bgpd/bgp_vty.h"
|
#include "bgpd/bgp_vty.h"
|
||||||
|
|
||||||
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
|
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
|
||||||
@ -427,6 +428,19 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static as_t
|
||||||
|
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
|
||||||
|
{
|
||||||
|
as_t as4 = stream_getl (BGP_INPUT(peer));
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
|
||||||
|
peer->host, as4);
|
||||||
|
SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
|
||||||
|
|
||||||
|
return as4;
|
||||||
|
}
|
||||||
|
|
||||||
static struct message capcode_str[] =
|
static struct message capcode_str[] =
|
||||||
{
|
{
|
||||||
{ 0, ""},
|
{ 0, ""},
|
||||||
@ -507,6 +521,7 @@ bgp_capability_parse (struct peer *peer, size_t length, u_char **error)
|
|||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
case CAPABILITY_CODE_ORF_OLD:
|
case CAPABILITY_CODE_ORF_OLD:
|
||||||
case CAPABILITY_CODE_RESTART:
|
case CAPABILITY_CODE_RESTART:
|
||||||
|
case CAPABILITY_CODE_AS4:
|
||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
/* Check length. */
|
/* Check length. */
|
||||||
if (caphdr.length < cap_minsizes[caphdr.code])
|
if (caphdr.length < cap_minsizes[caphdr.code])
|
||||||
@ -566,6 +581,14 @@ bgp_capability_parse (struct peer *peer, size_t length, u_char **error)
|
|||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
|
SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_AS4:
|
||||||
|
/* Already handled as a special-case parsing of the capabilities
|
||||||
|
* at the beginning of OPEN processing. So we care not a jot
|
||||||
|
* for the value really, only error case.
|
||||||
|
*/
|
||||||
|
if (!bgp_capability_as4 (peer, &caphdr))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (caphdr.code > 128)
|
if (caphdr.code > 128)
|
||||||
{
|
{
|
||||||
@ -615,6 +638,86 @@ strict_capability_same (struct peer *peer)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
|
||||||
|
* Returns 0 if no as4 found, as4cap value otherwise.
|
||||||
|
*/
|
||||||
|
as_t
|
||||||
|
peek_for_as4_capability (struct peer *peer, u_char length)
|
||||||
|
{
|
||||||
|
struct stream *s = BGP_INPUT (peer);
|
||||||
|
size_t orig_getp = stream_get_getp (s);
|
||||||
|
size_t end = orig_getp + length;
|
||||||
|
as_t as4 = 0;
|
||||||
|
|
||||||
|
/* The full capability parser will better flag the error.. */
|
||||||
|
if (STREAM_READABLE(s) < length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
|
||||||
|
" peeking for as4",
|
||||||
|
peer->host, length);
|
||||||
|
/* the error cases we DONT handle, we ONLY try to read as4 out of
|
||||||
|
* correctly formatted options.
|
||||||
|
*/
|
||||||
|
while (stream_get_getp(s) < end)
|
||||||
|
{
|
||||||
|
u_char opt_type;
|
||||||
|
u_char opt_length;
|
||||||
|
|
||||||
|
/* Check the length. */
|
||||||
|
if (stream_get_getp (s) + 2 > end)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Fetch option type and length. */
|
||||||
|
opt_type = stream_getc (s);
|
||||||
|
opt_length = stream_getc (s);
|
||||||
|
|
||||||
|
/* Option length check. */
|
||||||
|
if (stream_get_getp (s) + opt_length > end)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (opt_type == BGP_OPEN_OPT_CAP)
|
||||||
|
{
|
||||||
|
unsigned long capd_start = stream_get_getp (s);
|
||||||
|
unsigned long capd_end = capd_start + opt_length;
|
||||||
|
|
||||||
|
assert (capd_end <= end);
|
||||||
|
|
||||||
|
while (stream_get_getp (s) < capd_end)
|
||||||
|
{
|
||||||
|
struct capability_header hdr;
|
||||||
|
|
||||||
|
if (stream_get_getp (s) + 2 > capd_end)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
hdr.code = stream_getc (s);
|
||||||
|
hdr.length = stream_getc (s);
|
||||||
|
|
||||||
|
if ((stream_get_getp(s) + hdr.length) > capd_end)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (hdr.code == CAPABILITY_CODE_AS4)
|
||||||
|
{
|
||||||
|
if (hdr.length != CAPABILITY_CODE_AS4_LEN)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_info ("[AS4] found AS4 capability, about to parse");
|
||||||
|
as4 = bgp_capability_as4 (peer, &hdr);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
stream_forward_getp (s, hdr.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
stream_set_getp (s, orig_getp);
|
||||||
|
return as4;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse open option */
|
/* Parse open option */
|
||||||
int
|
int
|
||||||
bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
|
bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
|
||||||
@ -815,6 +918,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
|||||||
unsigned long cp;
|
unsigned long cp;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
|
as_t local_as;
|
||||||
|
|
||||||
/* Remember current pointer for Opt Parm Len. */
|
/* Remember current pointer for Opt Parm Len. */
|
||||||
cp = stream_get_endp (s);
|
cp = stream_get_endp (s);
|
||||||
@ -901,6 +1005,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
|||||||
stream_putc (s, CAPABILITY_CODE_REFRESH);
|
stream_putc (s, CAPABILITY_CODE_REFRESH);
|
||||||
stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
|
stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
|
||||||
|
|
||||||
|
/* AS4 */
|
||||||
|
SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
|
||||||
|
stream_putc (s, BGP_OPEN_OPT_CAP);
|
||||||
|
stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
|
||||||
|
stream_putc (s, CAPABILITY_CODE_AS4);
|
||||||
|
stream_putc (s, CAPABILITY_CODE_AS4_LEN);
|
||||||
|
if ( peer->change_local_as )
|
||||||
|
local_as = peer->change_local_as;
|
||||||
|
else
|
||||||
|
local_as = peer->local_as;
|
||||||
|
stream_putl (s, local_as );
|
||||||
|
|
||||||
/* ORF capability. */
|
/* ORF capability. */
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
|
||||||
|
@ -48,6 +48,11 @@ struct capability_orf_entry
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
struct capability_as4
|
||||||
|
{
|
||||||
|
uint32_t as4;
|
||||||
|
};
|
||||||
|
|
||||||
struct graceful_restart_af
|
struct graceful_restart_af
|
||||||
{
|
{
|
||||||
u_int16_t afi;
|
u_int16_t afi;
|
||||||
@ -100,6 +105,7 @@ struct capability_gr
|
|||||||
extern int bgp_open_option_parse (struct peer *, u_char, int *);
|
extern int bgp_open_option_parse (struct peer *, u_char, int *);
|
||||||
extern void bgp_open_capability (struct stream *, struct peer *);
|
extern void bgp_open_capability (struct stream *, struct peer *);
|
||||||
extern void bgp_capability_vty_out (struct vty *, struct peer *);
|
extern void bgp_capability_vty_out (struct vty *, struct peer *);
|
||||||
|
extern as_t peek_for_as4_capability (struct peer *, u_char);
|
||||||
extern int bgp_afi_safi_valid_indices (afi_t, safi_t *);
|
extern int bgp_afi_safi_valid_indices (afi_t, safi_t *);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_OPEN_H */
|
#endif /* _QUAGGA_BGP_OPEN_H */
|
||||||
|
@ -804,7 +804,8 @@ bgp_open_send (struct peer *peer)
|
|||||||
|
|
||||||
/* Set open packet values. */
|
/* Set open packet values. */
|
||||||
stream_putc (s, BGP_VERSION_4); /* BGP version */
|
stream_putc (s, BGP_VERSION_4); /* BGP version */
|
||||||
stream_putw (s, local_as); /* My Autonomous System*/
|
stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
|
||||||
|
: BGP_AS_TRANS);
|
||||||
stream_putw (s, send_holdtime); /* Hold Time */
|
stream_putw (s, send_holdtime); /* Hold Time */
|
||||||
stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
|
stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
|
||||||
|
|
||||||
@ -1168,6 +1169,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||||||
u_int16_t holdtime;
|
u_int16_t holdtime;
|
||||||
u_int16_t send_holdtime;
|
u_int16_t send_holdtime;
|
||||||
as_t remote_as;
|
as_t remote_as;
|
||||||
|
as_t as4 = 0;
|
||||||
struct peer *realpeer;
|
struct peer *realpeer;
|
||||||
struct in_addr remote_id;
|
struct in_addr remote_id;
|
||||||
int capability;
|
int capability;
|
||||||
@ -1186,10 +1188,75 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||||||
|
|
||||||
/* Receive OPEN message log */
|
/* Receive OPEN message log */
|
||||||
if (BGP_DEBUG (normal, NORMAL))
|
if (BGP_DEBUG (normal, NORMAL))
|
||||||
zlog_debug ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",
|
zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %d,"
|
||||||
|
" holdtime %d, id %s",
|
||||||
peer->host, version, remote_as, holdtime,
|
peer->host, version, remote_as, holdtime,
|
||||||
inet_ntoa (remote_id));
|
inet_ntoa (remote_id));
|
||||||
|
|
||||||
|
/* BEGIN to read the capability here, but dont do it yet */
|
||||||
|
capability = 0;
|
||||||
|
optlen = stream_getc (peer->ibuf);
|
||||||
|
|
||||||
|
if (optlen != 0)
|
||||||
|
{
|
||||||
|
/* We need the as4 capability value *right now* because
|
||||||
|
* if it is there, we have not got the remote_as yet, and without
|
||||||
|
* that we do not know which peer is connecting to us now.
|
||||||
|
*/
|
||||||
|
as4 = peek_for_as4_capability (peer, optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just in case we have a silly peer who sends AS4 capability set to 0 */
|
||||||
|
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
|
||||||
|
{
|
||||||
|
zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
|
||||||
|
peer->host);
|
||||||
|
bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
|
||||||
|
BGP_NOTIFY_OPEN_BAD_PEER_AS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote_as == BGP_AS_TRANS)
|
||||||
|
{
|
||||||
|
/* Take the AS4 from the capability. We must have received the
|
||||||
|
* capability now! Otherwise we have a asn16 peer who uses
|
||||||
|
* BGP_AS_TRANS, for some unknown reason.
|
||||||
|
*/
|
||||||
|
if (as4 == BGP_AS_TRANS)
|
||||||
|
{
|
||||||
|
zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
|
||||||
|
peer->host);
|
||||||
|
bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
|
||||||
|
BGP_NOTIFY_OPEN_BAD_PEER_AS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!as4 && BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
|
||||||
|
" Odd, but proceeding.", peer->host);
|
||||||
|
else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
|
||||||
|
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 fits "
|
||||||
|
"in 2-bytes, very odd peer.", peer->host, as4);
|
||||||
|
if (as4)
|
||||||
|
remote_as = as4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
|
||||||
|
/* If we have got the capability, peer->as4cap must match remote_as */
|
||||||
|
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
|
||||||
|
&& as4 != remote_as)
|
||||||
|
{
|
||||||
|
/* raise error, log this, close session */
|
||||||
|
zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
|
||||||
|
" mismatch with 16bit 'myasn' %u in open",
|
||||||
|
peer->host, as4, remote_as);
|
||||||
|
bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
|
||||||
|
BGP_NOTIFY_OPEN_BAD_PEER_AS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Lookup peer from Open packet. */
|
/* Lookup peer from Open packet. */
|
||||||
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
|
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
|
||||||
{
|
{
|
||||||
@ -1364,8 +1431,6 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||||||
peer->v_keepalive = peer->v_holdtime / 3;
|
peer->v_keepalive = peer->v_holdtime / 3;
|
||||||
|
|
||||||
/* Open option part parse. */
|
/* Open option part parse. */
|
||||||
capability = 0;
|
|
||||||
optlen = stream_getc (peer->ibuf);
|
|
||||||
if (optlen != 0)
|
if (optlen != 0)
|
||||||
{
|
{
|
||||||
ret = bgp_open_option_parse (peer, optlen, &capability);
|
ret = bgp_open_option_parse (peer, optlen, &capability);
|
||||||
@ -2049,8 +2114,8 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
|
|||||||
if (!bgp_afi_safi_valid_indices (afi, &safi))
|
if (!bgp_afi_safi_valid_indices (afi, &safi))
|
||||||
{
|
{
|
||||||
if (BGP_DEBUG (normal, NORMAL))
|
if (BGP_DEBUG (normal, NORMAL))
|
||||||
zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid",
|
zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
|
||||||
peer->host, afi, safi);
|
"(%u/%u)", peer->host, afi, safi);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2097,7 +2162,6 @@ int
|
|||||||
bgp_capability_receive (struct peer *peer, bgp_size_t size)
|
bgp_capability_receive (struct peer *peer, bgp_size_t size)
|
||||||
{
|
{
|
||||||
u_char *pnt;
|
u_char *pnt;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Fetch pointer. */
|
/* Fetch pointer. */
|
||||||
pnt = stream_pnt (peer->ibuf);
|
pnt = stream_pnt (peer->ibuf);
|
||||||
@ -2113,7 +2177,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
|
|||||||
bgp_notify_send (peer,
|
bgp_notify_send (peer,
|
||||||
BGP_NOTIFY_HEADER_ERR,
|
BGP_NOTIFY_HEADER_ERR,
|
||||||
BGP_NOTIFY_HEADER_BAD_MESTYPE);
|
BGP_NOTIFY_HEADER_BAD_MESTYPE);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status must be Established. */
|
/* Status must be Established. */
|
||||||
@ -2122,7 +2186,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
|
|||||||
plog_err (peer->log,
|
plog_err (peer->log,
|
||||||
"%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
|
"%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
|
||||||
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
|
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse packet. */
|
/* Parse packet. */
|
||||||
|
@ -3337,7 +3337,7 @@ DEFUN (no_set_atomic_aggregate,
|
|||||||
|
|
||||||
DEFUN (set_aggregator_as,
|
DEFUN (set_aggregator_as,
|
||||||
set_aggregator_as_cmd,
|
set_aggregator_as_cmd,
|
||||||
"set aggregator as <1-65535> A.B.C.D",
|
"set aggregator as CMD_AS_RANGE A.B.C.D",
|
||||||
SET_STR
|
SET_STR
|
||||||
"BGP aggregator attribute\n"
|
"BGP aggregator attribute\n"
|
||||||
"AS number of aggregator\n"
|
"AS number of aggregator\n"
|
||||||
@ -3349,7 +3349,7 @@ DEFUN (set_aggregator_as,
|
|||||||
struct in_addr address;
|
struct in_addr address;
|
||||||
char *argstr;
|
char *argstr;
|
||||||
|
|
||||||
VTY_GET_INTEGER_RANGE ("AS Path", as, argv[0], 1, BGP_AS_MAX);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
ret = inet_aton (argv[1], &address);
|
ret = inet_aton (argv[1], &address);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@ -3386,7 +3386,7 @@ DEFUN (no_set_aggregator_as,
|
|||||||
if (argv == 0)
|
if (argv == 0)
|
||||||
return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
|
return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
|
||||||
|
|
||||||
VTY_GET_INTEGER_RANGE ("AS Path", as, argv[0], 1, BGP_AS_MAX);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
ret = inet_aton (argv[1], &address);
|
ret = inet_aton (argv[1], &address);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@ -3409,7 +3409,7 @@ DEFUN (no_set_aggregator_as,
|
|||||||
|
|
||||||
ALIAS (no_set_aggregator_as,
|
ALIAS (no_set_aggregator_as,
|
||||||
no_set_aggregator_as_val_cmd,
|
no_set_aggregator_as_val_cmd,
|
||||||
"no set aggregator as <1-65535> A.B.C.D",
|
"no set aggregator as CMD_AS_RANGE A.B.C.D",
|
||||||
NO_STR
|
NO_STR
|
||||||
SET_STR
|
SET_STR
|
||||||
"BGP aggregator attribute\n"
|
"BGP aggregator attribute\n"
|
||||||
|
159
bgpd/bgp_vty.c
159
bgpd/bgp_vty.c
@ -308,7 +308,7 @@ DEFUN_DEPRECATED (neighbor_version,
|
|||||||
/* "router bgp" commands. */
|
/* "router bgp" commands. */
|
||||||
DEFUN (router_bgp,
|
DEFUN (router_bgp,
|
||||||
router_bgp_cmd,
|
router_bgp_cmd,
|
||||||
"router bgp <1-65535>",
|
"router bgp CMD_AS_RANGE",
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
AS_STR)
|
AS_STR)
|
||||||
@ -318,7 +318,7 @@ DEFUN (router_bgp,
|
|||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
|
||||||
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
@ -348,7 +348,7 @@ DEFUN (router_bgp,
|
|||||||
|
|
||||||
ALIAS (router_bgp,
|
ALIAS (router_bgp,
|
||||||
router_bgp_view_cmd,
|
router_bgp_view_cmd,
|
||||||
"router bgp <1-65535> view WORD",
|
"router bgp CMD_AS_RANGE view WORD",
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
AS_STR
|
AS_STR
|
||||||
@ -358,7 +358,7 @@ ALIAS (router_bgp,
|
|||||||
/* "no router bgp" commands. */
|
/* "no router bgp" commands. */
|
||||||
DEFUN (no_router_bgp,
|
DEFUN (no_router_bgp,
|
||||||
no_router_bgp_cmd,
|
no_router_bgp_cmd,
|
||||||
"no router bgp <1-65535>",
|
"no router bgp CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -368,7 +368,7 @@ DEFUN (no_router_bgp,
|
|||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
|
||||||
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
@ -388,7 +388,7 @@ DEFUN (no_router_bgp,
|
|||||||
|
|
||||||
ALIAS (no_router_bgp,
|
ALIAS (no_router_bgp,
|
||||||
no_router_bgp_view_cmd,
|
no_router_bgp_view_cmd,
|
||||||
"no router bgp <1-65535> view WORD",
|
"no router bgp CMD_AS_RANGE view WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -539,7 +539,7 @@ ALIAS (no_bgp_cluster_id,
|
|||||||
|
|
||||||
DEFUN (bgp_confederation_identifier,
|
DEFUN (bgp_confederation_identifier,
|
||||||
bgp_confederation_identifier_cmd,
|
bgp_confederation_identifier_cmd,
|
||||||
"bgp confederation identifier <1-65535>",
|
"bgp confederation identifier CMD_AS_RANGE",
|
||||||
"BGP specific commands\n"
|
"BGP specific commands\n"
|
||||||
"AS confederation parameters\n"
|
"AS confederation parameters\n"
|
||||||
"AS number\n"
|
"AS number\n"
|
||||||
@ -550,7 +550,7 @@ DEFUN (bgp_confederation_identifier,
|
|||||||
|
|
||||||
bgp = vty->index;
|
bgp = vty->index;
|
||||||
|
|
||||||
VTY_GET_INTEGER ("AS", as, argv[0]);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
bgp_confederation_id_set (bgp, as);
|
bgp_confederation_id_set (bgp, as);
|
||||||
|
|
||||||
@ -571,7 +571,7 @@ DEFUN (no_bgp_confederation_identifier,
|
|||||||
bgp = vty->index;
|
bgp = vty->index;
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
VTY_GET_INTEGER ("AS", as, argv[0]);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
bgp_confederation_id_unset (bgp);
|
bgp_confederation_id_unset (bgp);
|
||||||
|
|
||||||
@ -580,7 +580,7 @@ DEFUN (no_bgp_confederation_identifier,
|
|||||||
|
|
||||||
ALIAS (no_bgp_confederation_identifier,
|
ALIAS (no_bgp_confederation_identifier,
|
||||||
no_bgp_confederation_identifier_arg_cmd,
|
no_bgp_confederation_identifier_arg_cmd,
|
||||||
"no bgp confederation identifier <1-65535>",
|
"no bgp confederation identifier CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
"BGP specific commands\n"
|
"BGP specific commands\n"
|
||||||
"AS confederation parameters\n"
|
"AS confederation parameters\n"
|
||||||
@ -589,7 +589,7 @@ ALIAS (no_bgp_confederation_identifier,
|
|||||||
|
|
||||||
DEFUN (bgp_confederation_peers,
|
DEFUN (bgp_confederation_peers,
|
||||||
bgp_confederation_peers_cmd,
|
bgp_confederation_peers_cmd,
|
||||||
"bgp confederation peers .<1-65535>",
|
"bgp confederation peers .CMD_AS_RANGE",
|
||||||
"BGP specific commands\n"
|
"BGP specific commands\n"
|
||||||
"AS confederation parameters\n"
|
"AS confederation parameters\n"
|
||||||
"Peer ASs in BGP confederation\n"
|
"Peer ASs in BGP confederation\n"
|
||||||
@ -603,7 +603,7 @@ DEFUN (bgp_confederation_peers,
|
|||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
if (bgp->as == as)
|
if (bgp->as == as)
|
||||||
{
|
{
|
||||||
@ -619,7 +619,7 @@ DEFUN (bgp_confederation_peers,
|
|||||||
|
|
||||||
DEFUN (no_bgp_confederation_peers,
|
DEFUN (no_bgp_confederation_peers,
|
||||||
no_bgp_confederation_peers_cmd,
|
no_bgp_confederation_peers_cmd,
|
||||||
"no bgp confederation peers .<1-65535>",
|
"no bgp confederation peers .CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
"BGP specific commands\n"
|
"BGP specific commands\n"
|
||||||
"AS confederation parameters\n"
|
"AS confederation parameters\n"
|
||||||
@ -634,7 +634,7 @@ DEFUN (no_bgp_confederation_peers,
|
|||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
|
VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
bgp_confederation_peers_remove (bgp, as);
|
bgp_confederation_peers_remove (bgp, as);
|
||||||
}
|
}
|
||||||
@ -1249,7 +1249,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
|
|||||||
bgp = vty->index;
|
bgp = vty->index;
|
||||||
|
|
||||||
/* Get AS number. */
|
/* Get AS number. */
|
||||||
VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, 65535);
|
VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
/* If peer is peer group, call proper function. */
|
/* If peer is peer group, call proper function. */
|
||||||
ret = str2sockunion (peer_str, &su);
|
ret = str2sockunion (peer_str, &su);
|
||||||
@ -1288,7 +1288,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str,
|
|||||||
|
|
||||||
DEFUN (neighbor_remote_as,
|
DEFUN (neighbor_remote_as,
|
||||||
neighbor_remote_as_cmd,
|
neighbor_remote_as_cmd,
|
||||||
NEIGHBOR_CMD2 "remote-as <1-65535>",
|
NEIGHBOR_CMD2 "remote-as CMD_AS_RANGE",
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Specify a BGP neighbor\n"
|
"Specify a BGP neighbor\n"
|
||||||
@ -1352,7 +1352,7 @@ DEFUN (no_neighbor,
|
|||||||
|
|
||||||
ALIAS (no_neighbor,
|
ALIAS (no_neighbor,
|
||||||
no_neighbor_remote_as_cmd,
|
no_neighbor_remote_as_cmd,
|
||||||
NO_NEIGHBOR_CMD "remote-as <1-65535>",
|
NO_NEIGHBOR_CMD "remote-as CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR
|
NEIGHBOR_ADDR_STR
|
||||||
@ -1382,7 +1382,7 @@ DEFUN (no_neighbor_peer_group,
|
|||||||
|
|
||||||
DEFUN (no_neighbor_peer_group_remote_as,
|
DEFUN (no_neighbor_peer_group_remote_as,
|
||||||
no_neighbor_peer_group_remote_as_cmd,
|
no_neighbor_peer_group_remote_as_cmd,
|
||||||
"no neighbor WORD remote-as <1-65535>",
|
"no neighbor WORD remote-as CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
"Neighbor tag\n"
|
"Neighbor tag\n"
|
||||||
@ -1404,7 +1404,7 @@ DEFUN (no_neighbor_peer_group_remote_as,
|
|||||||
|
|
||||||
DEFUN (neighbor_local_as,
|
DEFUN (neighbor_local_as,
|
||||||
neighbor_local_as_cmd,
|
neighbor_local_as_cmd,
|
||||||
NEIGHBOR_CMD2 "local-as <1-65535>",
|
NEIGHBOR_CMD2 "local-as CMD_AS_RANGE",
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Specify a local-as number\n"
|
"Specify a local-as number\n"
|
||||||
@ -1423,7 +1423,7 @@ DEFUN (neighbor_local_as,
|
|||||||
|
|
||||||
DEFUN (neighbor_local_as_no_prepend,
|
DEFUN (neighbor_local_as_no_prepend,
|
||||||
neighbor_local_as_no_prepend_cmd,
|
neighbor_local_as_no_prepend_cmd,
|
||||||
NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
|
NEIGHBOR_CMD2 "local-as CMD_AS_RANGE no-prepend",
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
"Specify a local-as number\n"
|
"Specify a local-as number\n"
|
||||||
@ -1462,7 +1462,7 @@ DEFUN (no_neighbor_local_as,
|
|||||||
|
|
||||||
ALIAS (no_neighbor_local_as,
|
ALIAS (no_neighbor_local_as,
|
||||||
no_neighbor_local_as_val_cmd,
|
no_neighbor_local_as_val_cmd,
|
||||||
NO_NEIGHBOR_CMD2 "local-as <1-65535>",
|
NO_NEIGHBOR_CMD2 "local-as CMD_AS_RANGE",
|
||||||
NO_STR
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
@ -1471,7 +1471,7 @@ ALIAS (no_neighbor_local_as,
|
|||||||
|
|
||||||
ALIAS (no_neighbor_local_as,
|
ALIAS (no_neighbor_local_as,
|
||||||
no_neighbor_local_as_val2_cmd,
|
no_neighbor_local_as_val2_cmd,
|
||||||
NO_NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
|
NO_NEIGHBOR_CMD2 "local-as CMD_AS_RANGE no-prepend",
|
||||||
NO_STR
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
NEIGHBOR_ADDR_STR2
|
NEIGHBOR_ADDR_STR2
|
||||||
@ -4037,7 +4037,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
||||||
}
|
}
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear specified neighbors. */
|
/* Clear specified neighbors. */
|
||||||
@ -4051,13 +4051,13 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
vty_out (vty, "Malformed address: %s%s", arg, VTY_NEWLINE);
|
vty_out (vty, "Malformed address: %s%s", arg, VTY_NEWLINE);
|
||||||
return -1;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
peer = peer_lookup (bgp, &su);
|
peer = peer_lookup (bgp, &su);
|
||||||
if (! peer)
|
if (! peer)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE);
|
vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE);
|
||||||
return -1;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stype == BGP_CLEAR_SOFT_NONE)
|
if (stype == BGP_CLEAR_SOFT_NONE)
|
||||||
@ -4068,7 +4068,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
||||||
|
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all peer-group members. */
|
/* Clear all peer-group members. */
|
||||||
@ -4080,7 +4080,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (! group)
|
if (! group)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%%BGP: No such peer-group %s%s", arg, VTY_NEWLINE);
|
vty_out (vty, "%%BGP: No such peer-group %s%s", arg, VTY_NEWLINE);
|
||||||
return -1;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
|
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
|
||||||
@ -4099,7 +4099,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
||||||
}
|
}
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort == clear_external)
|
if (sort == clear_external)
|
||||||
@ -4117,22 +4117,21 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
bgp_clear_vty_error (vty, peer, afi, safi, ret);
|
||||||
}
|
}
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort == clear_as)
|
if (sort == clear_as)
|
||||||
{
|
{
|
||||||
as_t as;
|
as_t as;
|
||||||
unsigned long as_ul;
|
unsigned long as_ul;
|
||||||
char *endptr = NULL;
|
|
||||||
int find = 0;
|
int find = 0;
|
||||||
|
|
||||||
as_ul = strtoul(arg, &endptr, 10);
|
VTY_GET_LONG ("AS", as_ul, arg);
|
||||||
|
|
||||||
if ((as_ul == ULONG_MAX) || (*endptr != '\0') || (as_ul > USHRT_MAX))
|
if (!as_ul)
|
||||||
{
|
{
|
||||||
vty_out (vty, "Invalid AS number%s", VTY_NEWLINE);
|
vty_out (vty, "Invalid AS number%s", VTY_NEWLINE);
|
||||||
return -1;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
as = (as_t) as_ul;
|
as = (as_t) as_ul;
|
||||||
|
|
||||||
@ -4153,10 +4152,10 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (! find)
|
if (! find)
|
||||||
vty_out (vty, "%%BGP: No peer is configured with AS %s%s", arg,
|
vty_out (vty, "%%BGP: No peer is configured with AS %s%s", arg,
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -4164,7 +4163,6 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi,
|
|||||||
enum clear_sort sort, enum bgp_clear_type stype,
|
enum clear_sort sort, enum bgp_clear_type stype,
|
||||||
const char *arg)
|
const char *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
|
|
||||||
/* BGP structure lookup. */
|
/* BGP structure lookup. */
|
||||||
@ -4187,11 +4185,7 @@ bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bgp_clear (vty, bgp, afi, safi, sort, stype, arg);
|
return bgp_clear (vty, bgp, afi, safi, sort, stype, arg);
|
||||||
if (ret < 0)
|
|
||||||
return CMD_WARNING;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (clear_ip_bgp_all,
|
DEFUN (clear_ip_bgp_all,
|
||||||
@ -4328,7 +4322,7 @@ ALIAS (clear_ip_bgp_external,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as,
|
DEFUN (clear_ip_bgp_as,
|
||||||
clear_ip_bgp_as_cmd,
|
clear_ip_bgp_as_cmd,
|
||||||
"clear ip bgp <1-65535>",
|
"clear ip bgp CMD_AS_RANGE",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4339,14 +4333,14 @@ DEFUN (clear_ip_bgp_as,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as,
|
ALIAS (clear_ip_bgp_as,
|
||||||
clear_bgp_as_cmd,
|
clear_bgp_as_cmd,
|
||||||
"clear bgp <1-65535>",
|
"clear bgp CMD_AS_RANGE",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n")
|
"Clear peers with the AS number\n")
|
||||||
|
|
||||||
ALIAS (clear_ip_bgp_as,
|
ALIAS (clear_ip_bgp_as,
|
||||||
clear_bgp_ipv6_as_cmd,
|
clear_bgp_ipv6_as_cmd,
|
||||||
"clear bgp ipv6 <1-65535>",
|
"clear bgp ipv6 CMD_AS_RANGE",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -4858,7 +4852,7 @@ ALIAS (clear_bgp_external_soft_out,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_soft_out,
|
DEFUN (clear_ip_bgp_as_soft_out,
|
||||||
clear_ip_bgp_as_soft_out_cmd,
|
clear_ip_bgp_as_soft_out_cmd,
|
||||||
"clear ip bgp <1-65535> soft out",
|
"clear ip bgp CMD_AS_RANGE soft out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4872,7 +4866,7 @@ DEFUN (clear_ip_bgp_as_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_soft_out,
|
ALIAS (clear_ip_bgp_as_soft_out,
|
||||||
clear_ip_bgp_as_out_cmd,
|
clear_ip_bgp_as_out_cmd,
|
||||||
"clear ip bgp <1-65535> out",
|
"clear ip bgp CMD_AS_RANGE out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4881,7 +4875,7 @@ ALIAS (clear_ip_bgp_as_soft_out,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_ipv4_soft_out,
|
DEFUN (clear_ip_bgp_as_ipv4_soft_out,
|
||||||
clear_ip_bgp_as_ipv4_soft_out_cmd,
|
clear_ip_bgp_as_ipv4_soft_out_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) soft out",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) soft out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4902,7 +4896,7 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_ipv4_soft_out,
|
ALIAS (clear_ip_bgp_as_ipv4_soft_out,
|
||||||
clear_ip_bgp_as_ipv4_out_cmd,
|
clear_ip_bgp_as_ipv4_out_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) out",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4914,7 +4908,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_out,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
|
DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
|
||||||
clear_ip_bgp_as_vpnv4_soft_out_cmd,
|
clear_ip_bgp_as_vpnv4_soft_out_cmd,
|
||||||
"clear ip bgp <1-65535> vpnv4 unicast soft out",
|
"clear ip bgp CMD_AS_RANGE vpnv4 unicast soft out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4930,7 +4924,7 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
|
ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
|
||||||
clear_ip_bgp_as_vpnv4_out_cmd,
|
clear_ip_bgp_as_vpnv4_out_cmd,
|
||||||
"clear ip bgp <1-65535> vpnv4 unicast out",
|
"clear ip bgp CMD_AS_RANGE vpnv4 unicast out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -4941,7 +4935,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
|
|||||||
|
|
||||||
DEFUN (clear_bgp_as_soft_out,
|
DEFUN (clear_bgp_as_soft_out,
|
||||||
clear_bgp_as_soft_out_cmd,
|
clear_bgp_as_soft_out_cmd,
|
||||||
"clear bgp <1-65535> soft out",
|
"clear bgp CMD_AS_RANGE soft out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -4954,7 +4948,7 @@ DEFUN (clear_bgp_as_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_out,
|
ALIAS (clear_bgp_as_soft_out,
|
||||||
clear_bgp_ipv6_as_soft_out_cmd,
|
clear_bgp_ipv6_as_soft_out_cmd,
|
||||||
"clear bgp ipv6 <1-65535> soft out",
|
"clear bgp ipv6 CMD_AS_RANGE soft out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -4964,7 +4958,7 @@ ALIAS (clear_bgp_as_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_out,
|
ALIAS (clear_bgp_as_soft_out,
|
||||||
clear_bgp_as_out_cmd,
|
clear_bgp_as_out_cmd,
|
||||||
"clear bgp <1-65535> out",
|
"clear bgp CMD_AS_RANGE out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -4972,7 +4966,7 @@ ALIAS (clear_bgp_as_soft_out,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_out,
|
ALIAS (clear_bgp_as_soft_out,
|
||||||
clear_bgp_ipv6_as_out_cmd,
|
clear_bgp_ipv6_as_out_cmd,
|
||||||
"clear bgp ipv6 <1-65535> out",
|
"clear bgp ipv6 CMD_AS_RANGE out",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -5762,7 +5756,7 @@ ALIAS (clear_bgp_external_in_prefix_filter,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_soft_in,
|
DEFUN (clear_ip_bgp_as_soft_in,
|
||||||
clear_ip_bgp_as_soft_in_cmd,
|
clear_ip_bgp_as_soft_in_cmd,
|
||||||
"clear ip bgp <1-65535> soft in",
|
"clear ip bgp CMD_AS_RANGE soft in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5776,7 +5770,7 @@ DEFUN (clear_ip_bgp_as_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_soft_in,
|
ALIAS (clear_ip_bgp_as_soft_in,
|
||||||
clear_ip_bgp_as_in_cmd,
|
clear_ip_bgp_as_in_cmd,
|
||||||
"clear ip bgp <1-65535> in",
|
"clear ip bgp CMD_AS_RANGE in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5785,7 +5779,7 @@ ALIAS (clear_ip_bgp_as_soft_in,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_in_prefix_filter,
|
DEFUN (clear_ip_bgp_as_in_prefix_filter,
|
||||||
clear_ip_bgp_as_in_prefix_filter_cmd,
|
clear_ip_bgp_as_in_prefix_filter_cmd,
|
||||||
"clear ip bgp <1-65535> in prefix-filter",
|
"clear ip bgp CMD_AS_RANGE in prefix-filter",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5799,7 +5793,7 @@ DEFUN (clear_ip_bgp_as_in_prefix_filter,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_ipv4_soft_in,
|
DEFUN (clear_ip_bgp_as_ipv4_soft_in,
|
||||||
clear_ip_bgp_as_ipv4_soft_in_cmd,
|
clear_ip_bgp_as_ipv4_soft_in_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) soft in",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) soft in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5820,7 +5814,7 @@ DEFUN (clear_ip_bgp_as_ipv4_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_ipv4_soft_in,
|
ALIAS (clear_ip_bgp_as_ipv4_soft_in,
|
||||||
clear_ip_bgp_as_ipv4_in_cmd,
|
clear_ip_bgp_as_ipv4_in_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) in",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5832,7 +5826,7 @@ ALIAS (clear_ip_bgp_as_ipv4_soft_in,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
|
DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
|
||||||
clear_ip_bgp_as_ipv4_in_prefix_filter_cmd,
|
clear_ip_bgp_as_ipv4_in_prefix_filter_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) in prefix-filter",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) in prefix-filter",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5853,7 +5847,7 @@ DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
|
DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
|
||||||
clear_ip_bgp_as_vpnv4_soft_in_cmd,
|
clear_ip_bgp_as_vpnv4_soft_in_cmd,
|
||||||
"clear ip bgp <1-65535> vpnv4 unicast soft in",
|
"clear ip bgp CMD_AS_RANGE vpnv4 unicast soft in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5869,7 +5863,7 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
|
ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
|
||||||
clear_ip_bgp_as_vpnv4_in_cmd,
|
clear_ip_bgp_as_vpnv4_in_cmd,
|
||||||
"clear ip bgp <1-65535> vpnv4 unicast in",
|
"clear ip bgp CMD_AS_RANGE vpnv4 unicast in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -5880,7 +5874,7 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
|
|||||||
|
|
||||||
DEFUN (clear_bgp_as_soft_in,
|
DEFUN (clear_bgp_as_soft_in,
|
||||||
clear_bgp_as_soft_in_cmd,
|
clear_bgp_as_soft_in_cmd,
|
||||||
"clear bgp <1-65535> soft in",
|
"clear bgp CMD_AS_RANGE soft in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -5893,7 +5887,7 @@ DEFUN (clear_bgp_as_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_in,
|
ALIAS (clear_bgp_as_soft_in,
|
||||||
clear_bgp_ipv6_as_soft_in_cmd,
|
clear_bgp_ipv6_as_soft_in_cmd,
|
||||||
"clear bgp ipv6 <1-65535> soft in",
|
"clear bgp ipv6 CMD_AS_RANGE soft in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -5903,7 +5897,7 @@ ALIAS (clear_bgp_as_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_in,
|
ALIAS (clear_bgp_as_soft_in,
|
||||||
clear_bgp_as_in_cmd,
|
clear_bgp_as_in_cmd,
|
||||||
"clear bgp <1-65535> in",
|
"clear bgp CMD_AS_RANGE in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -5911,7 +5905,7 @@ ALIAS (clear_bgp_as_soft_in,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft_in,
|
ALIAS (clear_bgp_as_soft_in,
|
||||||
clear_bgp_ipv6_as_in_cmd,
|
clear_bgp_ipv6_as_in_cmd,
|
||||||
"clear bgp ipv6 <1-65535> in",
|
"clear bgp ipv6 CMD_AS_RANGE in",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -5920,7 +5914,7 @@ ALIAS (clear_bgp_as_soft_in,
|
|||||||
|
|
||||||
DEFUN (clear_bgp_as_in_prefix_filter,
|
DEFUN (clear_bgp_as_in_prefix_filter,
|
||||||
clear_bgp_as_in_prefix_filter_cmd,
|
clear_bgp_as_in_prefix_filter_cmd,
|
||||||
"clear bgp <1-65535> in prefix-filter",
|
"clear bgp CMD_AS_RANGE in prefix-filter",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -5933,7 +5927,7 @@ DEFUN (clear_bgp_as_in_prefix_filter,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_in_prefix_filter,
|
ALIAS (clear_bgp_as_in_prefix_filter,
|
||||||
clear_bgp_ipv6_as_in_prefix_filter_cmd,
|
clear_bgp_ipv6_as_in_prefix_filter_cmd,
|
||||||
"clear bgp ipv6 <1-65535> in prefix-filter",
|
"clear bgp ipv6 CMD_AS_RANGE in prefix-filter",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -6248,7 +6242,7 @@ ALIAS (clear_bgp_external_soft,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_soft,
|
DEFUN (clear_ip_bgp_as_soft,
|
||||||
clear_ip_bgp_as_soft_cmd,
|
clear_ip_bgp_as_soft_cmd,
|
||||||
"clear ip bgp <1-65535> soft",
|
"clear ip bgp CMD_AS_RANGE soft",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -6261,7 +6255,7 @@ DEFUN (clear_ip_bgp_as_soft,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_ipv4_soft,
|
DEFUN (clear_ip_bgp_as_ipv4_soft,
|
||||||
clear_ip_bgp_as_ipv4_soft_cmd,
|
clear_ip_bgp_as_ipv4_soft_cmd,
|
||||||
"clear ip bgp <1-65535> ipv4 (unicast|multicast) soft",
|
"clear ip bgp CMD_AS_RANGE ipv4 (unicast|multicast) soft",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -6281,7 +6275,7 @@ DEFUN (clear_ip_bgp_as_ipv4_soft,
|
|||||||
|
|
||||||
DEFUN (clear_ip_bgp_as_vpnv4_soft,
|
DEFUN (clear_ip_bgp_as_vpnv4_soft,
|
||||||
clear_ip_bgp_as_vpnv4_soft_cmd,
|
clear_ip_bgp_as_vpnv4_soft_cmd,
|
||||||
"clear ip bgp <1-65535> vpnv4 unicast soft",
|
"clear ip bgp CMD_AS_RANGE vpnv4 unicast soft",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -6296,7 +6290,7 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft,
|
|||||||
|
|
||||||
DEFUN (clear_bgp_as_soft,
|
DEFUN (clear_bgp_as_soft,
|
||||||
clear_bgp_as_soft_cmd,
|
clear_bgp_as_soft_cmd,
|
||||||
"clear bgp <1-65535> soft",
|
"clear bgp CMD_AS_RANGE soft",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear peers with the AS number\n"
|
"Clear peers with the AS number\n"
|
||||||
@ -6308,7 +6302,7 @@ DEFUN (clear_bgp_as_soft,
|
|||||||
|
|
||||||
ALIAS (clear_bgp_as_soft,
|
ALIAS (clear_bgp_as_soft,
|
||||||
clear_bgp_ipv6_as_soft_cmd,
|
clear_bgp_ipv6_as_soft_cmd,
|
||||||
"clear bgp ipv6 <1-65535> soft",
|
"clear bgp ipv6 CMD_AS_RANGE soft",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
"Address family\n"
|
"Address family\n"
|
||||||
@ -7271,6 +7265,18 @@ bgp_show_peer (struct vty *vty, struct peer *p)
|
|||||||
{
|
{
|
||||||
vty_out (vty, " Neighbor capabilities:%s", VTY_NEWLINE);
|
vty_out (vty, " Neighbor capabilities:%s", VTY_NEWLINE);
|
||||||
|
|
||||||
|
/* AS4 */
|
||||||
|
if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV)
|
||||||
|
|| CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV))
|
||||||
|
{
|
||||||
|
vty_out (vty, " 4 Byte AS:");
|
||||||
|
if (CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV))
|
||||||
|
vty_out (vty, " advertised");
|
||||||
|
if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV))
|
||||||
|
vty_out (vty, " %sreceived",
|
||||||
|
CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : "");
|
||||||
|
vty_out (vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
/* Dynamic */
|
/* Dynamic */
|
||||||
if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
|
if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
|
||||||
|| CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
|
|| CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
|
||||||
@ -7389,16 +7395,13 @@ bgp_show_peer (struct vty *vty, struct peer *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->t_gr_restart)
|
if (p->t_gr_restart)
|
||||||
{
|
|
||||||
vty_out (vty, " The remaining time of restart timer is %ld%s",
|
vty_out (vty, " The remaining time of restart timer is %ld%s",
|
||||||
thread_timer_remain_second (p->t_gr_restart), VTY_NEWLINE);
|
thread_timer_remain_second (p->t_gr_restart), VTY_NEWLINE);
|
||||||
}
|
|
||||||
if (p->t_gr_stale)
|
if (p->t_gr_stale)
|
||||||
{
|
|
||||||
vty_out (vty, " The remaining time of stalepath timer is %ld%s",
|
vty_out (vty, " The remaining time of stalepath timer is %ld%s",
|
||||||
thread_timer_remain_second (p->t_gr_stale), VTY_NEWLINE);
|
thread_timer_remain_second (p->t_gr_stale), VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Packet counts. */
|
/* Packet counts. */
|
||||||
vty_out (vty, " Message statistics:%s", VTY_NEWLINE);
|
vty_out (vty, " Message statistics:%s", VTY_NEWLINE);
|
||||||
@ -7907,7 +7910,7 @@ bgp_write_rsclient_summary (struct vty *vty, struct peer *rsclient,
|
|||||||
|
|
||||||
vty_out (vty, "4 ");
|
vty_out (vty, "4 ");
|
||||||
|
|
||||||
vty_out (vty, "%5d ", rsclient->as);
|
vty_out (vty, "%11d ", rsclient->as);
|
||||||
|
|
||||||
rmname = ROUTE_MAP_EXPORT_NAME(&rsclient->filter[afi][safi]);
|
rmname = ROUTE_MAP_EXPORT_NAME(&rsclient->filter[afi][safi]);
|
||||||
if ( rmname && strlen (rmname) > 13 )
|
if ( rmname && strlen (rmname) > 13 )
|
||||||
|
@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#ifndef _QUAGGA_BGP_VTY_H
|
#ifndef _QUAGGA_BGP_VTY_H
|
||||||
#define _QUAGGA_BGP_VTY_H
|
#define _QUAGGA_BGP_VTY_H
|
||||||
|
|
||||||
|
#define CMD_AS_RANGE "<1-4294967295>"
|
||||||
|
|
||||||
extern void bgp_vty_init (void);
|
extern void bgp_vty_init (void);
|
||||||
extern const char *afi_safi_print (afi_t, safi_t);
|
extern const char *afi_safi_print (afi_t, safi_t);
|
||||||
|
|
||||||
|
12
bgpd/bgpd.h
12
bgpd/bgpd.h
@ -25,7 +25,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||||||
#include "sockunion.h"
|
#include "sockunion.h"
|
||||||
|
|
||||||
/* Typedef BGP specific types. */
|
/* Typedef BGP specific types. */
|
||||||
typedef u_int16_t as_t;
|
typedef u_int32_t as_t;
|
||||||
|
typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
|
||||||
typedef u_int16_t bgp_size_t;
|
typedef u_int16_t bgp_size_t;
|
||||||
|
|
||||||
/* BGP master for system wide configurations and variables. */
|
/* BGP master for system wide configurations and variables. */
|
||||||
@ -287,6 +288,9 @@ struct peer
|
|||||||
int status;
|
int status;
|
||||||
int ostatus;
|
int ostatus;
|
||||||
|
|
||||||
|
/* Peer index, used for dumping TABLE_DUMP_V2 format */
|
||||||
|
uint16_t table_dump_index;
|
||||||
|
|
||||||
/* Peer information */
|
/* Peer information */
|
||||||
int fd; /* File descriptor */
|
int fd; /* File descriptor */
|
||||||
int ttl; /* TTL of TCP connection to the peer. */
|
int ttl; /* TTL of TCP connection to the peer. */
|
||||||
@ -316,7 +320,7 @@ struct peer
|
|||||||
u_char afc_recv[AFI_MAX][SAFI_MAX];
|
u_char afc_recv[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
/* Capability flags (reset in bgp_stop) */
|
/* Capability flags (reset in bgp_stop) */
|
||||||
u_char cap;
|
u_int16_t cap;
|
||||||
#define PEER_CAP_REFRESH_ADV (1 << 0) /* refresh advertised */
|
#define PEER_CAP_REFRESH_ADV (1 << 0) /* refresh advertised */
|
||||||
#define PEER_CAP_REFRESH_OLD_RCV (1 << 1) /* refresh old received */
|
#define PEER_CAP_REFRESH_OLD_RCV (1 << 1) /* refresh old received */
|
||||||
#define PEER_CAP_REFRESH_NEW_RCV (1 << 2) /* refresh rfc received */
|
#define PEER_CAP_REFRESH_NEW_RCV (1 << 2) /* refresh rfc received */
|
||||||
@ -324,6 +328,8 @@ struct peer
|
|||||||
#define PEER_CAP_DYNAMIC_RCV (1 << 4) /* dynamic received */
|
#define PEER_CAP_DYNAMIC_RCV (1 << 4) /* dynamic received */
|
||||||
#define PEER_CAP_RESTART_ADV (1 << 5) /* restart advertised */
|
#define PEER_CAP_RESTART_ADV (1 << 5) /* restart advertised */
|
||||||
#define PEER_CAP_RESTART_RCV (1 << 6) /* restart received */
|
#define PEER_CAP_RESTART_RCV (1 << 6) /* restart received */
|
||||||
|
#define PEER_CAP_AS4_ADV (1 << 7) /* as4 advertised */
|
||||||
|
#define PEER_CAP_AS4_RCV (1 << 8) /* as4 received */
|
||||||
|
|
||||||
/* Capability flags (reset in bgp_stop) */
|
/* Capability flags (reset in bgp_stop) */
|
||||||
u_int16_t af_cap[AFI_MAX][SAFI_MAX];
|
u_int16_t af_cap[AFI_MAX][SAFI_MAX];
|
||||||
@ -591,6 +597,8 @@ struct bgp_nlri
|
|||||||
#define BGP_ATTR_MP_REACH_NLRI 14
|
#define BGP_ATTR_MP_REACH_NLRI 14
|
||||||
#define BGP_ATTR_MP_UNREACH_NLRI 15
|
#define BGP_ATTR_MP_UNREACH_NLRI 15
|
||||||
#define BGP_ATTR_EXT_COMMUNITIES 16
|
#define BGP_ATTR_EXT_COMMUNITIES 16
|
||||||
|
#define BGP_ATTR_AS4_PATH 17
|
||||||
|
#define BGP_ATTR_AS4_AGGREGATOR 18
|
||||||
#define BGP_ATTR_AS_PATHLIMIT 21
|
#define BGP_ATTR_AS_PATHLIMIT 21
|
||||||
|
|
||||||
/* BGP update origin. */
|
/* BGP update origin. */
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
14 MP_REACH_NLRI [RFC 2283]
|
14 MP_REACH_NLRI [RFC 2283]
|
||||||
15 MP_UNREACH_NLRI [RFC 2283]
|
15 MP_UNREACH_NLRI [RFC 2283]
|
||||||
16 EXT_COMMUNITIES [draft-ramachandra-bgp-ext-communities-09.txt]
|
16 EXT_COMMUNITIES [draft-ramachandra-bgp-ext-communities-09.txt]
|
||||||
|
17 AS4_PATH [RFC 4893]
|
||||||
|
18 AS4_AGGREGATOR [RFC 4893]
|
||||||
254 RCID_PATH [RFC 1863]
|
254 RCID_PATH [RFC 1863]
|
||||||
255 ADVERTISER [RFC 1863]
|
255 ADVERTISER [RFC 1863]
|
||||||
=========================================================================
|
=========================================================================
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
|
2007-09-27 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* aspath_test.c: Test dupe-weeding from sets.
|
||||||
|
Test that reconciliation merges AS_PATH and AS4_PATH where
|
||||||
|
former is shorter than latter.
|
||||||
|
|
||||||
|
2007-09-26 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* aspath_test.c: Test AS4_PATH reconcilation where length
|
||||||
|
of AS_PATH and AS4_PATH is same.
|
||||||
|
|
||||||
|
2007-09-25 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* bgp_capability_test.c: (general) Extend tests to validate
|
||||||
|
peek_for_as4_capability.
|
||||||
|
Add test of full OPEN Option block, with multiple capabilities,
|
||||||
|
both as a series of Option, and a single option.
|
||||||
|
Add some crap to beginning of stream, to prevent code depending
|
||||||
|
on getp == 0.
|
||||||
|
|
||||||
|
2007-09-18 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* bgp_capability_test.c: (parse_test) update for changes to
|
||||||
|
peek_for_as4_capability
|
||||||
|
|
||||||
2007-09-17 Paul Jakma <paul.jakma@sun.com>
|
2007-09-17 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
* bgp_capability_test.c: Test that peer's adv_recv and adv_nego get
|
* bgp_capability_test.c: Test that peer's adv_recv and adv_nego get
|
||||||
@ -9,6 +34,17 @@
|
|||||||
* bgp_capability_test.c: new, capability parser unit tests.
|
* bgp_capability_test.c: new, capability parser unit tests.
|
||||||
* Makefile.am: add previous.
|
* Makefile.am: add previous.
|
||||||
|
|
||||||
|
2007-07-25 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
|
* aspath_test.c: Exercise 32bit parsing. Test reconcile
|
||||||
|
function.
|
||||||
|
* ecommunity_test.c: New, test AS4 ecommunity changes, positive
|
||||||
|
test only at this time, error cases not tested yet.
|
||||||
|
|
||||||
|
2006-12-01 Juergen Kammer <j.kammer@eurodata.de>
|
||||||
|
|
||||||
|
* aspath_test.c: Support asn32 changes, call aspath_parse with 16 bit.
|
||||||
|
|
||||||
2006-08-26 Paul Jakma <paul.jakma@sun.com>
|
2006-08-26 Paul Jakma <paul.jakma@sun.com>
|
||||||
|
|
||||||
* heavy-wq.c: (slow_func_del,slow_func) update to match workqueue
|
* heavy-wq.c: (slow_func_del,slow_func) update to match workqueue
|
||||||
|
@ -2,7 +2,7 @@ INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
|
|||||||
DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
|
DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||||
|
|
||||||
noinst_PROGRAMS = testsig testbuffer testmemory heavy heavywq heavythread \
|
noinst_PROGRAMS = testsig testbuffer testmemory heavy heavywq heavythread \
|
||||||
aspathtest testprivs teststream testbgpcap
|
aspathtest testprivs teststream testbgpcap ecommtest
|
||||||
testsig_SOURCES = test-sig.c
|
testsig_SOURCES = test-sig.c
|
||||||
testbuffer_SOURCES = test-buffer.c
|
testbuffer_SOURCES = test-buffer.c
|
||||||
testmemory_SOURCES = test-memory.c
|
testmemory_SOURCES = test-memory.c
|
||||||
@ -13,6 +13,7 @@ heavywq_SOURCES = heavy-wq.c main.c
|
|||||||
heavythread_SOURCES = heavy-thread.c main.c
|
heavythread_SOURCES = heavy-thread.c main.c
|
||||||
aspathtest_SOURCES = aspath_test.c
|
aspathtest_SOURCES = aspath_test.c
|
||||||
testbgpcap_SOURCES = bgp_capability_test.c
|
testbgpcap_SOURCES = bgp_capability_test.c
|
||||||
|
ecommtest_SOURCES = ecommunity_test.c
|
||||||
|
|
||||||
testsig_LDADD = ../lib/libzebra.la @LIBCAP@
|
testsig_LDADD = ../lib/libzebra.la @LIBCAP@
|
||||||
testbuffer_LDADD = ../lib/libzebra.la @LIBCAP@
|
testbuffer_LDADD = ../lib/libzebra.la @LIBCAP@
|
||||||
@ -24,3 +25,4 @@ heavywq_LDADD = ../lib/libzebra.la @LIBCAP@ -lm
|
|||||||
heavythread_LDADD = ../lib/libzebra.la @LIBCAP@ -lm
|
heavythread_LDADD = ../lib/libzebra.la @LIBCAP@ -lm
|
||||||
aspathtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
|
aspathtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
|
||||||
testbgpcap_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
|
testbgpcap_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
|
||||||
|
ecommtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a
|
||||||
|
@ -7,6 +7,13 @@
|
|||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_aspath.h"
|
#include "bgpd/bgp_aspath.h"
|
||||||
|
|
||||||
|
#define VT100_RESET "\x1b[0m"
|
||||||
|
#define VT100_RED "\x1b[31m"
|
||||||
|
#define VT100_GREEN "\x1b[32m"
|
||||||
|
#define VT100_YELLOW "\x1b[33m"
|
||||||
|
#define OK VT100_GREEN "OK" VT100_RESET
|
||||||
|
#define FAILED VT100_RED "failed" VT100_RESET
|
||||||
|
|
||||||
/* need these to link in libbgp */
|
/* need these to link in libbgp */
|
||||||
struct zebra_privs_t *bgpd_privs = NULL;
|
struct zebra_privs_t *bgpd_privs = NULL;
|
||||||
struct thread_master *master = NULL;
|
struct thread_master *master = NULL;
|
||||||
@ -312,8 +319,87 @@ static struct test_segment {
|
|||||||
/* We shouldn't ever /generate/ such paths. However, we should
|
/* We shouldn't ever /generate/ such paths. However, we should
|
||||||
* cope with them fine.
|
* cope with them fine.
|
||||||
*/
|
*/
|
||||||
"8466 3 52737 4096 3456 {7099,8153,8153,8153}",
|
"8466 3 52737 4096 3456 {7099,8153}",
|
||||||
"8466 3 52737 4096 3456 {7099,8153,8153,8153}",
|
"8466 3 52737 4096 3456 {7099,8153}",
|
||||||
|
6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 },
|
||||||
|
},
|
||||||
|
{ /* 18 */
|
||||||
|
"reconcile_lead_asp",
|
||||||
|
"seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)",
|
||||||
|
{ 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1,
|
||||||
|
0x1,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0,
|
||||||
|
0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0 },
|
||||||
|
24,
|
||||||
|
{ "6435 59408 21665 {23456} 23456 23456 23456",
|
||||||
|
"6435 59408 21665 {23456} 23456 23456 23456",
|
||||||
|
7, 0, NOT_ALL_PRIVATE, 23456, 1, 6435 },
|
||||||
|
},
|
||||||
|
{ /* 19 */
|
||||||
|
"reconcile_new_asp",
|
||||||
|
"set(2457,61697,4369), seq(1842,41591,51793)",
|
||||||
|
{
|
||||||
|
0x1,0x3, 0x09,0x99, 0xf1,0x01, 0x11,0x11,
|
||||||
|
0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51 },
|
||||||
|
16,
|
||||||
|
{ "{2457,4369,61697} 1842 41591 51793",
|
||||||
|
"{2457,4369,61697} 1842 41591 51793",
|
||||||
|
4, 0, NOT_ALL_PRIVATE, 51793, 1, 2457 },
|
||||||
|
},
|
||||||
|
{ /* 20 */
|
||||||
|
"reconcile_confed",
|
||||||
|
"confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665)"
|
||||||
|
" set(23456,23456,23456), seq(23456,23456,23456)",
|
||||||
|
{ 0x3,0x3, 0x00,0x7b, 0x01,0xc8, 0x03,0x15,
|
||||||
|
0x4,0x3, 0x01,0xc8, 0x00,0x7c, 0x03,0x14,
|
||||||
|
0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1,
|
||||||
|
0x1,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0,
|
||||||
|
0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0 },
|
||||||
|
40,
|
||||||
|
{ "(123 456 789) [124,456,788] 6435 59408 21665"
|
||||||
|
" {23456} 23456 23456 23456",
|
||||||
|
"6435 59408 21665 {23456} 23456 23456 23456",
|
||||||
|
7, 4, NOT_ALL_PRIVATE, 23456, 1, 6435 },
|
||||||
|
},
|
||||||
|
{ /* 21 */
|
||||||
|
"reconcile_start_trans",
|
||||||
|
"seq(23456,23456,23456) seq(6435,59408,21665)",
|
||||||
|
{ 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0,
|
||||||
|
0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, },
|
||||||
|
16,
|
||||||
|
{ "23456 23456 23456 6435 59408 21665",
|
||||||
|
"23456 23456 23456 6435 59408 21665",
|
||||||
|
6, 0, NOT_ALL_PRIVATE, 21665, 1, 23456 },
|
||||||
|
},
|
||||||
|
{ /* 22 */
|
||||||
|
"reconcile_start_trans4",
|
||||||
|
"seq(1842,41591,51793) seq(6435,59408,21665)",
|
||||||
|
{ 0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51,
|
||||||
|
0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, },
|
||||||
|
16,
|
||||||
|
{ "1842 41591 51793 6435 59408 21665",
|
||||||
|
"1842 41591 51793 6435 59408 21665",
|
||||||
|
6, 0, NOT_ALL_PRIVATE, 41591, 1, 1842 },
|
||||||
|
},
|
||||||
|
{ /* 23 */
|
||||||
|
"reconcile_start_trans_error",
|
||||||
|
"seq(23456,23456,23456) seq(6435,59408)",
|
||||||
|
{ 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0,
|
||||||
|
0x2,0x2, 0x19,0x23, 0xe8,0x10, },
|
||||||
|
14,
|
||||||
|
{ "23456 23456 23456 6435 59408",
|
||||||
|
"23456 23456 23456 6435 59408",
|
||||||
|
5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456 },
|
||||||
|
},
|
||||||
|
{ /* 24 */
|
||||||
|
"redundantset2",
|
||||||
|
"seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)",
|
||||||
|
{ 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80,
|
||||||
|
0x1,0x5, 0x1b,0xbb, 0x1f,0xd9, 0x1f,0xd9, 0x1f,0xd9, 0x1b,0xbb,},
|
||||||
|
24,
|
||||||
|
{
|
||||||
|
/* We should weed out duplicate set members. */
|
||||||
|
"8466 3 52737 4096 3456 {7099,8153}",
|
||||||
|
"8466 3 52737 4096 3456 {7099,8153}",
|
||||||
6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 },
|
6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 },
|
||||||
},
|
},
|
||||||
{ NULL, NULL, {0}, 0, { NULL, 0, 0 } }
|
{ NULL, NULL, {0}, 0, { NULL, 0, 0 } }
|
||||||
@ -432,13 +518,43 @@ static struct tests {
|
|||||||
{ NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } },
|
{ NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tests reconcile_tests[] =
|
||||||
|
{
|
||||||
|
{ &test_segments[18], &test_segments[19],
|
||||||
|
{ "6435 59408 21665 {2457,4369,61697} 1842 41591 51793",
|
||||||
|
"6435 59408 21665 {2457,4369,61697} 1842 41591 51793",
|
||||||
|
7, 0, NOT_ALL_PRIVATE, 51793, 1, 6435 },
|
||||||
|
},
|
||||||
|
{ &test_segments[19], &test_segments[18],
|
||||||
|
/* AS_PATH (19) has more hops than NEW_AS_PATH,
|
||||||
|
* so just AS_PATH should be used (though, this practice
|
||||||
|
* is bad imho).
|
||||||
|
*/
|
||||||
|
{ "{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456",
|
||||||
|
"{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456",
|
||||||
|
11, 0, NOT_ALL_PRIVATE, 51793, 1, 6435 },
|
||||||
|
},
|
||||||
|
{ &test_segments[20], &test_segments[19],
|
||||||
|
{ "(123 456 789) [124,456,788] 6435 59408 21665"
|
||||||
|
" {2457,4369,61697} 1842 41591 51793",
|
||||||
|
"6435 59408 21665 {2457,4369,61697} 1842 41591 51793",
|
||||||
|
7, 4, NOT_ALL_PRIVATE, 51793, 1, 6435 },
|
||||||
|
},
|
||||||
|
{ &test_segments[21], &test_segments[22],
|
||||||
|
{ "1842 41591 51793 6435 59408 21665",
|
||||||
|
"1842 41591 51793 6435 59408 21665",
|
||||||
|
6, 0, NOT_ALL_PRIVATE, 51793, 1, 1842 },
|
||||||
|
},
|
||||||
|
{ &test_segments[23], &test_segments[22],
|
||||||
|
{ "23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665",
|
||||||
|
"23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665",
|
||||||
|
11, 0, NOT_ALL_PRIVATE, 51793, 1, 1842 },
|
||||||
|
},
|
||||||
|
{ NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } },
|
||||||
|
};
|
||||||
|
|
||||||
struct tests aggregate_tests[] =
|
struct tests aggregate_tests[] =
|
||||||
{
|
{
|
||||||
{ &test_segments[0], &test_segments[1],
|
|
||||||
{ "{3,4,4096,8466,8722,52737}",
|
|
||||||
"{3,4,4096,8466,8722,52737}",
|
|
||||||
1, 0, NOT_ALL_PRIVATE, 52737, 1, NULL_ASN },
|
|
||||||
},
|
|
||||||
{ &test_segments[0], &test_segments[2],
|
{ &test_segments[0], &test_segments[2],
|
||||||
{ "8466 3 52737 4096 {4,8722}",
|
{ "8466 3 52737 4096 {4,8722}",
|
||||||
"8466 3 52737 4096 {4,8722}",
|
"8466 3 52737 4096 {4,8722}",
|
||||||
@ -459,6 +575,13 @@ struct tests aggregate_tests[] =
|
|||||||
"8466 {2,3,4,4096,8722,52737}",
|
"8466 {2,3,4,4096,8722,52737}",
|
||||||
2, 0, NOT_ALL_PRIVATE, 2, 20000, 8466 },
|
2, 0, NOT_ALL_PRIVATE, 2, 20000, 8466 },
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ &test_segments[5], &test_segments[18],
|
||||||
|
{ "6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}",
|
||||||
|
"6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}",
|
||||||
|
4, 0, NOT_ALL_PRIVATE, 41590, 1, 6435 },
|
||||||
|
},
|
||||||
|
|
||||||
{ NULL, NULL, { NULL, 0, 0} },
|
{ NULL, NULL, { NULL, 0, 0} },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -498,7 +621,7 @@ struct compare_tests
|
|||||||
|
|
||||||
/* make an aspath from a data stream */
|
/* make an aspath from a data stream */
|
||||||
static struct aspath *
|
static struct aspath *
|
||||||
make_aspath (const u_char *data, size_t len)
|
make_aspath (const u_char *data, size_t len, int use32bit)
|
||||||
{
|
{
|
||||||
struct stream *s = NULL;
|
struct stream *s = NULL;
|
||||||
struct aspath *as;
|
struct aspath *as;
|
||||||
@ -508,7 +631,7 @@ make_aspath (const u_char *data, size_t len)
|
|||||||
s = stream_new (len);
|
s = stream_new (len);
|
||||||
stream_put (s, data, len);
|
stream_put (s, data, len);
|
||||||
}
|
}
|
||||||
as = aspath_parse (s, len);
|
as = aspath_parse (s, len, use32bit);
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
stream_free (s);
|
stream_free (s);
|
||||||
@ -535,18 +658,27 @@ printbytes (const u_char *bytes, int len)
|
|||||||
static int
|
static int
|
||||||
validate (struct aspath *as, const struct test_spec *sp)
|
validate (struct aspath *as, const struct test_spec *sp)
|
||||||
{
|
{
|
||||||
size_t bytes;
|
size_t bytes, bytes4;
|
||||||
int fails = 0;
|
int fails = 0;
|
||||||
const u_char *out;
|
const u_char *out;
|
||||||
struct aspath *asinout, *asconfeddel, *asstr;
|
static struct stream *s;
|
||||||
|
struct aspath *asinout, *asconfeddel, *asstr, *as4;
|
||||||
|
|
||||||
out = aspath_snmp_pathseg (as, &bytes);
|
out = aspath_snmp_pathseg (as, &bytes);
|
||||||
asinout = make_aspath (out, bytes);
|
asinout = make_aspath (out, bytes, 0);
|
||||||
|
|
||||||
|
/* Excercise AS4 parsing a bit, with a dogfood test */
|
||||||
|
if (!s)
|
||||||
|
s = stream_new (4096);
|
||||||
|
bytes4 = aspath_put (s, as, 1);
|
||||||
|
as4 = make_aspath (STREAM_DATA(s), bytes4, 1);
|
||||||
|
|
||||||
asstr = aspath_str2aspath (sp->shouldbe);
|
asstr = aspath_str2aspath (sp->shouldbe);
|
||||||
|
|
||||||
asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout));
|
asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout));
|
||||||
|
|
||||||
|
printf ("got: %s\n", aspath_print(as));
|
||||||
|
|
||||||
/* the parsed path should match the specified 'shouldbe' string.
|
/* the parsed path should match the specified 'shouldbe' string.
|
||||||
* We should pass the "eat our own dog food" test, be able to output
|
* We should pass the "eat our own dog food" test, be able to output
|
||||||
* this path and then input it again. Ie the path resulting from:
|
* this path and then input it again. Ie the path resulting from:
|
||||||
@ -562,6 +694,10 @@ validate (struct aspath *as, const struct test_spec *sp)
|
|||||||
*
|
*
|
||||||
* aspath_str2aspath() and shouldbe should match
|
* aspath_str2aspath() and shouldbe should match
|
||||||
*
|
*
|
||||||
|
* We do the same for:
|
||||||
|
*
|
||||||
|
* aspath_parse(aspath_put(as,USE32BIT))
|
||||||
|
*
|
||||||
* Confederation related tests:
|
* Confederation related tests:
|
||||||
* - aspath_delete_confed_seq(aspath) should match shouldbe_confed
|
* - aspath_delete_confed_seq(aspath) should match shouldbe_confed
|
||||||
* - aspath_delete_confed_seq should be idempotent.
|
* - aspath_delete_confed_seq should be idempotent.
|
||||||
@ -571,6 +707,8 @@ validate (struct aspath *as, const struct test_spec *sp)
|
|||||||
|| (aspath_key_make (as) != aspath_key_make (asinout))
|
|| (aspath_key_make (as) != aspath_key_make (asinout))
|
||||||
/* by string */
|
/* by string */
|
||||||
|| strcmp(aspath_print (asinout), sp->shouldbe)
|
|| strcmp(aspath_print (asinout), sp->shouldbe)
|
||||||
|
/* By 4-byte parsing */
|
||||||
|
|| strcmp(aspath_print (as4), sp->shouldbe)
|
||||||
/* by various path counts */
|
/* by various path counts */
|
||||||
|| (aspath_count_hops (as) != sp->hops)
|
|| (aspath_count_hops (as) != sp->hops)
|
||||||
|| (aspath_count_confeds (as) != sp->confeds)
|
|| (aspath_count_confeds (as) != sp->confeds)
|
||||||
@ -580,7 +718,7 @@ validate (struct aspath *as, const struct test_spec *sp)
|
|||||||
failed++;
|
failed++;
|
||||||
fails++;
|
fails++;
|
||||||
printf ("shouldbe:\n%s\n", sp->shouldbe);
|
printf ("shouldbe:\n%s\n", sp->shouldbe);
|
||||||
printf ("got:\n%s\n", aspath_print(as));
|
printf ("as4:\n%s\n", aspath_print (as4));
|
||||||
printf ("hash keys: in: %d out->in: %d\n",
|
printf ("hash keys: in: %d out->in: %d\n",
|
||||||
aspath_key_make (as), aspath_key_make (asinout));
|
aspath_key_make (as), aspath_key_make (asinout));
|
||||||
printf ("hops: %d, counted %d %d\n", sp->hops,
|
printf ("hops: %d, counted %d %d\n", sp->hops,
|
||||||
@ -635,11 +773,13 @@ validate (struct aspath *as, const struct test_spec *sp)
|
|||||||
aspath_private_as_check (as));
|
aspath_private_as_check (as));
|
||||||
}
|
}
|
||||||
aspath_unintern (asinout);
|
aspath_unintern (asinout);
|
||||||
|
aspath_unintern (as4);
|
||||||
|
|
||||||
aspath_free (asconfeddel);
|
aspath_free (asconfeddel);
|
||||||
aspath_free (asstr);
|
aspath_free (asstr);
|
||||||
|
stream_reset (s);
|
||||||
|
|
||||||
return fails;
|
return fails;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -650,9 +790,9 @@ empty_get_test ()
|
|||||||
|
|
||||||
printf ("empty_get_test, as: %s\n",aspath_print (as));
|
printf ("empty_get_test, as: %s\n",aspath_print (as));
|
||||||
if (!validate (as, &sp))
|
if (!validate (as, &sp))
|
||||||
printf ("OK\n");
|
printf ("%s\n", OK);
|
||||||
else
|
else
|
||||||
printf ("failed!\n");
|
printf ("%s!\n", FAILED);
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
|
|
||||||
@ -667,14 +807,14 @@ parse_test (struct test_segment *t)
|
|||||||
|
|
||||||
printf ("%s: %s\n", t->name, t->desc);
|
printf ("%s: %s\n", t->name, t->desc);
|
||||||
|
|
||||||
asp = make_aspath (t->asdata, t->len);
|
asp = make_aspath (t->asdata, t->len, 0);
|
||||||
|
|
||||||
printf ("aspath: %s\nvalidating...:\n", aspath_print (asp));
|
printf ("aspath: %s\nvalidating...:\n", aspath_print (asp));
|
||||||
|
|
||||||
if (!validate (asp, &t->sp))
|
if (!validate (asp, &t->sp))
|
||||||
printf ("OK\n");
|
printf (OK "\n");
|
||||||
else
|
else
|
||||||
printf ("failed\n");
|
printf (FAILED "\n");
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
aspath_unintern (asp);
|
aspath_unintern (asp);
|
||||||
@ -689,8 +829,8 @@ prepend_test (struct tests *t)
|
|||||||
printf ("prepend %s: %s\n", t->test1->name, t->test1->desc);
|
printf ("prepend %s: %s\n", t->test1->name, t->test1->desc);
|
||||||
printf ("to %s: %s\n", t->test2->name, t->test2->desc);
|
printf ("to %s: %s\n", t->test2->name, t->test2->desc);
|
||||||
|
|
||||||
asp1 = make_aspath (t->test1->asdata, t->test1->len);
|
asp1 = make_aspath (t->test1->asdata, t->test1->len, 0);
|
||||||
asp2 = make_aspath (t->test2->asdata, t->test2->len);
|
asp2 = make_aspath (t->test2->asdata, t->test2->len, 0);
|
||||||
|
|
||||||
ascratch = aspath_dup (asp2);
|
ascratch = aspath_dup (asp2);
|
||||||
aspath_unintern (asp2);
|
aspath_unintern (asp2);
|
||||||
@ -700,9 +840,9 @@ prepend_test (struct tests *t)
|
|||||||
printf ("aspath: %s\n", aspath_print (asp2));
|
printf ("aspath: %s\n", aspath_print (asp2));
|
||||||
|
|
||||||
if (!validate (asp2, &t->sp))
|
if (!validate (asp2, &t->sp))
|
||||||
printf ("OK\n");
|
printf ("%s\n", OK);
|
||||||
else
|
else
|
||||||
printf ("failed!\n");
|
printf ("%s!\n", FAILED);
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
aspath_unintern (asp1);
|
aspath_unintern (asp1);
|
||||||
@ -717,7 +857,7 @@ empty_prepend_test (struct test_segment *t)
|
|||||||
|
|
||||||
printf ("empty prepend %s: %s\n", t->name, t->desc);
|
printf ("empty prepend %s: %s\n", t->name, t->desc);
|
||||||
|
|
||||||
asp1 = make_aspath (t->asdata, t->len);
|
asp1 = make_aspath (t->asdata, t->len, 0);
|
||||||
asp2 = aspath_empty ();
|
asp2 = aspath_empty ();
|
||||||
|
|
||||||
ascratch = aspath_dup (asp2);
|
ascratch = aspath_dup (asp2);
|
||||||
@ -728,15 +868,41 @@ empty_prepend_test (struct test_segment *t)
|
|||||||
printf ("aspath: %s\n", aspath_print (asp2));
|
printf ("aspath: %s\n", aspath_print (asp2));
|
||||||
|
|
||||||
if (!validate (asp2, &t->sp))
|
if (!validate (asp2, &t->sp))
|
||||||
printf ("OK\n");
|
printf (OK "\n");
|
||||||
else
|
else
|
||||||
printf ("failed!\n");
|
printf (FAILED "!\n");
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
aspath_unintern (asp1);
|
aspath_unintern (asp1);
|
||||||
aspath_free (asp2);
|
aspath_free (asp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* as2+as4 reconciliation testing */
|
||||||
|
static void
|
||||||
|
as4_reconcile_test (struct tests *t)
|
||||||
|
{
|
||||||
|
struct aspath *asp1, *asp2, *ascratch;
|
||||||
|
|
||||||
|
printf ("reconciling %s:\n %s\n", t->test1->name, t->test1->desc);
|
||||||
|
printf ("with %s:\n %s\n", t->test2->name, t->test2->desc);
|
||||||
|
|
||||||
|
asp1 = make_aspath (t->test1->asdata, t->test1->len, 0);
|
||||||
|
asp2 = make_aspath (t->test2->asdata, t->test2->len, 0);
|
||||||
|
|
||||||
|
ascratch = aspath_reconcile_as4 (asp1, asp2);
|
||||||
|
|
||||||
|
if (!validate (ascratch, &t->sp))
|
||||||
|
printf (OK "\n");
|
||||||
|
else
|
||||||
|
printf (FAILED "!\n");
|
||||||
|
|
||||||
|
printf ("\n");
|
||||||
|
aspath_unintern (asp1);
|
||||||
|
aspath_unintern (asp2);
|
||||||
|
aspath_free (ascratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* aggregation testing */
|
/* aggregation testing */
|
||||||
static void
|
static void
|
||||||
aggregate_test (struct tests *t)
|
aggregate_test (struct tests *t)
|
||||||
@ -746,17 +912,15 @@ aggregate_test (struct tests *t)
|
|||||||
printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc);
|
printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc);
|
||||||
printf ("with %s: %s\n", t->test2->name, t->test2->desc);
|
printf ("with %s: %s\n", t->test2->name, t->test2->desc);
|
||||||
|
|
||||||
asp1 = make_aspath (t->test1->asdata, t->test1->len);
|
asp1 = make_aspath (t->test1->asdata, t->test1->len, 0);
|
||||||
asp2 = make_aspath (t->test2->asdata, t->test2->len);
|
asp2 = make_aspath (t->test2->asdata, t->test2->len, 0);
|
||||||
|
|
||||||
ascratch = aspath_aggregate (asp1, asp2);
|
ascratch = aspath_aggregate (asp1, asp2);
|
||||||
|
|
||||||
printf ("aspath: %s\n", aspath_print (ascratch));
|
|
||||||
|
|
||||||
if (!validate (ascratch, &t->sp))
|
if (!validate (ascratch, &t->sp))
|
||||||
printf ("OK\n");
|
printf (OK "\n");
|
||||||
else
|
else
|
||||||
printf ("failed!\n");
|
printf (FAILED "!\n");
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
aspath_unintern (asp1);
|
aspath_unintern (asp1);
|
||||||
@ -782,8 +946,8 @@ cmp_test ()
|
|||||||
printf ("left cmp %s: %s\n", t1->name, t1->desc);
|
printf ("left cmp %s: %s\n", t1->name, t1->desc);
|
||||||
printf ("and %s: %s\n", t2->name, t2->desc);
|
printf ("and %s: %s\n", t2->name, t2->desc);
|
||||||
|
|
||||||
asp1 = make_aspath (t1->asdata, t1->len);
|
asp1 = make_aspath (t1->asdata, t1->len, 0);
|
||||||
asp2 = make_aspath (t2->asdata, t2->len);
|
asp2 = make_aspath (t2->asdata, t2->len, 0);
|
||||||
|
|
||||||
if (aspath_cmp_left (asp1, asp2) != left_compare[i].shouldbe_cmp
|
if (aspath_cmp_left (asp1, asp2) != left_compare[i].shouldbe_cmp
|
||||||
|| aspath_cmp_left (asp2, asp1) != left_compare[i].shouldbe_cmp
|
|| aspath_cmp_left (asp2, asp1) != left_compare[i].shouldbe_cmp
|
||||||
@ -792,7 +956,8 @@ cmp_test ()
|
|||||||
|| aspath_cmp_left_confed (asp2, asp1)
|
|| aspath_cmp_left_confed (asp2, asp1)
|
||||||
!= left_compare[i].shouldbe_confed)
|
!= left_compare[i].shouldbe_confed)
|
||||||
{
|
{
|
||||||
printf ("failed\n");
|
failed++;
|
||||||
|
printf (FAILED "\n");
|
||||||
printf ("result should be: cmp: %d, confed: %d\n",
|
printf ("result should be: cmp: %d, confed: %d\n",
|
||||||
left_compare[i].shouldbe_cmp,
|
left_compare[i].shouldbe_cmp,
|
||||||
left_compare[i].shouldbe_confed);
|
left_compare[i].shouldbe_confed);
|
||||||
@ -801,10 +966,9 @@ cmp_test ()
|
|||||||
aspath_cmp_left_confed (asp1, asp2));
|
aspath_cmp_left_confed (asp1, asp2));
|
||||||
printf("path1: %s\npath2: %s\n", aspath_print (asp1),
|
printf("path1: %s\npath2: %s\n", aspath_print (asp1),
|
||||||
aspath_print (asp2));
|
aspath_print (asp2));
|
||||||
failed++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf ("OK\n");
|
printf (OK "\n");
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
aspath_unintern (asp1);
|
aspath_unintern (asp1);
|
||||||
@ -831,6 +995,13 @@ main (void)
|
|||||||
while (aggregate_tests[i].test1)
|
while (aggregate_tests[i].test1)
|
||||||
aggregate_test (&aggregate_tests[i++]);
|
aggregate_test (&aggregate_tests[i++]);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
while (reconcile_tests[i].test1)
|
||||||
|
as4_reconcile_test (&reconcile_tests[i++]);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
cmp_test();
|
cmp_test();
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
#define VT100_YELLOW "\x1b[33m"
|
#define VT100_YELLOW "\x1b[33m"
|
||||||
|
|
||||||
|
|
||||||
#define OPEN 0
|
#define CAPABILITY 0
|
||||||
#define DYNCAP 1
|
#define DYNCAP 1
|
||||||
|
#define OPT_PARAM 2
|
||||||
|
|
||||||
/* need these to link in libbgp */
|
/* need these to link in libbgp */
|
||||||
struct zebra_privs_t *bgpd_privs = NULL;
|
struct zebra_privs_t *bgpd_privs = NULL;
|
||||||
@ -34,6 +35,7 @@ static struct test_segment {
|
|||||||
#define SHOULD_PARSE 0
|
#define SHOULD_PARSE 0
|
||||||
#define SHOULD_ERR -1
|
#define SHOULD_ERR -1
|
||||||
int parses; /* whether it should parse or not */
|
int parses; /* whether it should parse or not */
|
||||||
|
int peek_for; /* what peek_for_as4_capability should say */
|
||||||
|
|
||||||
/* AFI/SAFI validation */
|
/* AFI/SAFI validation */
|
||||||
int validate_afi;
|
int validate_afi;
|
||||||
@ -76,54 +78,55 @@ static struct test_segment mp_segments[] =
|
|||||||
{ "MP4",
|
{ "MP4",
|
||||||
"MP IP/Uni",
|
"MP IP/Uni",
|
||||||
{ 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 },
|
{ 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 },
|
||||||
6, SHOULD_PARSE, AFI_IP, SAFI_UNICAST,
|
6, SHOULD_PARSE, 0,
|
||||||
|
1, AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||||
},
|
},
|
||||||
{ "MPv6",
|
{ "MPv6",
|
||||||
"MP IPv6/Uni",
|
"MP IPv6/Uni",
|
||||||
{ 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 },
|
{ 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 },
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 0,
|
||||||
1, AFI_IP6, SAFI_UNICAST, VALID_AFI,
|
1, AFI_IP6, SAFI_UNICAST, VALID_AFI,
|
||||||
},
|
},
|
||||||
/* 5 */
|
/* 5 */
|
||||||
{ "MP2",
|
{ "MP2",
|
||||||
"MP IP/Multicast",
|
"MP IP/Multicast",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 },
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 0,
|
||||||
1, AFI_IP, SAFI_MULTICAST, VALID_AFI,
|
1, AFI_IP, SAFI_MULTICAST, VALID_AFI,
|
||||||
},
|
},
|
||||||
/* 6 */
|
/* 6 */
|
||||||
{ "MP3",
|
{ "MP3",
|
||||||
"MP IP6/VPNv4",
|
"MP IP6/VPNv4",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
|
||||||
6, SHOULD_PARSE, /* parses, but invalid afi,safi */
|
6, SHOULD_PARSE, 0, /* parses, but invalid afi,safi */
|
||||||
1, AFI_IP6, BGP_SAFI_VPNV4, INVALID_AFI,
|
1, AFI_IP6, BGP_SAFI_VPNV4, INVALID_AFI,
|
||||||
},
|
},
|
||||||
/* 7 */
|
/* 7 */
|
||||||
{ "MP5",
|
{ "MP5",
|
||||||
"MP IP6/MPLS-VPN",
|
"MP IP6/MPLS-VPN",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 0,
|
||||||
1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI,
|
1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI,
|
||||||
},
|
},
|
||||||
/* 8 */
|
/* 8 */
|
||||||
{ "MP6",
|
{ "MP6",
|
||||||
"MP IP4/VPNv4",
|
"MP IP4/VPNv4",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 0,
|
||||||
1, AFI_IP, BGP_SAFI_VPNV4, VALID_AFI,
|
1, AFI_IP, BGP_SAFI_VPNV4, VALID_AFI,
|
||||||
},
|
},
|
||||||
/* 9 */
|
/* 9 */
|
||||||
{ "MP7",
|
{ "MP7",
|
||||||
"MP IP4/VPNv6",
|
"MP IP4/VPNv6",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x81 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x81 },
|
||||||
6, SHOULD_PARSE, /* parses, but invalid afi,safi tuple */
|
6, SHOULD_PARSE, 0, /* parses, but invalid afi,safi tuple */
|
||||||
1, AFI_IP, BGP_SAFI_VPNV6, INVALID_AFI,
|
1, AFI_IP, BGP_SAFI_VPNV6, INVALID_AFI,
|
||||||
},
|
},
|
||||||
/* 10 */
|
/* 10 */
|
||||||
{ "MP8",
|
{ "MP8",
|
||||||
"MP unknown AFI",
|
"MP unknown AFI",
|
||||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 },
|
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 },
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 0,
|
||||||
1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */
|
1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */
|
||||||
},
|
},
|
||||||
/* 11 */
|
/* 11 */
|
||||||
@ -136,7 +139,7 @@ static struct test_segment mp_segments[] =
|
|||||||
{ "MP-overflow",
|
{ "MP-overflow",
|
||||||
"MP IP4/Unicast, length too long",
|
"MP IP4/Unicast, length too long",
|
||||||
{ CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 },
|
{ CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 },
|
||||||
6, SHOULD_ERR,
|
6, SHOULD_ERR, 0,
|
||||||
1, AFI_IP, SAFI_UNICAST, VALID_AFI,
|
1, AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||||
},
|
},
|
||||||
{ NULL, NULL, {0}, 0, 0}
|
{ NULL, NULL, {0}, 0, 0}
|
||||||
@ -290,8 +293,8 @@ static struct test_segment misc_segments[] =
|
|||||||
/* 19 */
|
/* 19 */
|
||||||
{ "AS4",
|
{ "AS4",
|
||||||
"AS4 capability",
|
"AS4 capability",
|
||||||
{ 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 },
|
{ 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 }, /* AS: 2882400018 */
|
||||||
6, SHOULD_PARSE,
|
6, SHOULD_PARSE, 2882400018,
|
||||||
},
|
},
|
||||||
/* 20 */
|
/* 20 */
|
||||||
{ "GR",
|
{ "GR",
|
||||||
@ -367,7 +370,7 @@ static struct test_segment misc_segments[] =
|
|||||||
{ NULL, NULL, {0}, 0, 0}
|
{ NULL, NULL, {0}, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DYNAMIC message */
|
||||||
struct test_segment dynamic_cap_msgs[] =
|
struct test_segment dynamic_cap_msgs[] =
|
||||||
{
|
{
|
||||||
{ "DynCap",
|
{ "DynCap",
|
||||||
@ -397,18 +400,97 @@ struct test_segment dynamic_cap_msgs[] =
|
|||||||
},
|
},
|
||||||
{ NULL, NULL, {0}, 0, 0}
|
{ NULL, NULL, {0}, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Entire Optional-Parameters block */
|
||||||
|
struct test_segment opt_params[] =
|
||||||
|
{
|
||||||
|
{ "Cap-singlets",
|
||||||
|
"One capability per Optional-Param",
|
||||||
|
{ 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
|
||||||
|
0x02, 0x02, 0x80, 0x00, /* RR (old) */
|
||||||
|
0x02, 0x02, 0x02, 0x00, /* RR */
|
||||||
|
},
|
||||||
|
24, SHOULD_PARSE,
|
||||||
|
},
|
||||||
|
{ "Cap-series",
|
||||||
|
"Series of capability, one Optional-Param",
|
||||||
|
{ 0x02, 0x10,
|
||||||
|
0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
|
||||||
|
0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
|
||||||
|
0x80, 0x00, /* RR (old) */
|
||||||
|
0x02, 0x00, /* RR */
|
||||||
|
},
|
||||||
|
18, SHOULD_PARSE,
|
||||||
|
},
|
||||||
|
{ "AS4more",
|
||||||
|
"AS4 capability after other caps (singlets)",
|
||||||
|
{ 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
|
||||||
|
0x02, 0x02, 0x80, 0x00, /* RR (old) */
|
||||||
|
0x02, 0x02, 0x02, 0x00, /* RR */
|
||||||
|
0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
|
||||||
|
},
|
||||||
|
32, SHOULD_PARSE, 196614,
|
||||||
|
},
|
||||||
|
{ "AS4series",
|
||||||
|
"AS4 capability, in series of capabilities",
|
||||||
|
{ 0x02, 0x16,
|
||||||
|
0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
|
||||||
|
0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
|
||||||
|
0x80, 0x00, /* RR (old) */
|
||||||
|
0x02, 0x00, /* RR */
|
||||||
|
0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
|
||||||
|
},
|
||||||
|
24, SHOULD_PARSE, 196614,
|
||||||
|
},
|
||||||
|
{ "AS4real",
|
||||||
|
"AS4 capability, in series of capabilities",
|
||||||
|
{
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
|
||||||
|
0x02, 0x02, 0x80, 0x00, /* RR old */
|
||||||
|
0x02, 0x02, 0x02, 0x00, /* RR */
|
||||||
|
0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */
|
||||||
|
},
|
||||||
|
32, SHOULD_PARSE, 196614,
|
||||||
|
},
|
||||||
|
{ "AS4real2",
|
||||||
|
"AS4 capability, in series of capabilities",
|
||||||
|
{
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01,
|
||||||
|
0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01,
|
||||||
|
0x02, 0x02, 0x80, 0x00,
|
||||||
|
0x02, 0x02, 0x02, 0x00,
|
||||||
|
0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03,
|
||||||
|
0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03,
|
||||||
|
0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
|
||||||
|
0x02, 0x02, 0x42, 0x00,
|
||||||
|
},
|
||||||
|
58, SHOULD_PARSE, 64515,
|
||||||
|
},
|
||||||
|
|
||||||
|
{ NULL, NULL, {0}, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
/* basic parsing test */
|
/* basic parsing test */
|
||||||
static void
|
static void
|
||||||
parse_test (struct peer *peer, struct test_segment *t, int type)
|
parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int capability = 0;
|
int capability = 0;
|
||||||
|
as_t as4 = 0;
|
||||||
int oldfailed = failed;
|
int oldfailed = failed;
|
||||||
|
int len = t->len;
|
||||||
|
#define RANDOM_FUZZ 35
|
||||||
|
|
||||||
stream_reset (peer->ibuf);
|
stream_reset (peer->ibuf);
|
||||||
|
stream_put (peer->ibuf, NULL, RANDOM_FUZZ);
|
||||||
|
stream_set_getp (peer->ibuf, RANDOM_FUZZ);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case OPEN:
|
case CAPABILITY:
|
||||||
stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP);
|
stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP);
|
||||||
stream_putc (peer->ibuf, t->len);
|
stream_putc (peer->ibuf, t->len);
|
||||||
break;
|
break;
|
||||||
@ -425,8 +507,17 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
|||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case OPEN:
|
case CAPABILITY:
|
||||||
ret = bgp_open_option_parse (peer, t->len + 2, &capability);
|
len += 2; /* to cover the OPT-Param header */
|
||||||
|
case OPT_PARAM:
|
||||||
|
printf ("len: %u\n", len);
|
||||||
|
/* peek_for_as4 wants getp at capibility*/
|
||||||
|
as4 = peek_for_as4_capability (peer, len);
|
||||||
|
printf ("peek_for_as4: as4 is %u\n", as4);
|
||||||
|
/* and it should leave getp as it found it */
|
||||||
|
assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ);
|
||||||
|
|
||||||
|
ret = bgp_open_option_parse (peer, len, &capability);
|
||||||
break;
|
break;
|
||||||
case DYNCAP:
|
case DYNCAP:
|
||||||
ret = bgp_capability_receive (peer, t->len);
|
ret = bgp_capability_receive (peer, t->len);
|
||||||
@ -458,18 +549,27 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (as4 != t->peek_for)
|
||||||
|
{
|
||||||
|
printf ("as4 %u != %u\n", as4, t->peek_for);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
|
||||||
printf ("parsed?: %s\n", ret ? "no" : "yes");
|
printf ("parsed?: %s\n", ret ? "no" : "yes");
|
||||||
|
|
||||||
if (ret != t->parses)
|
if (ret != t->parses)
|
||||||
failed++;
|
failed++;
|
||||||
|
|
||||||
if (tty)
|
if (tty)
|
||||||
printf ("%s\n", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
|
printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
|
||||||
: VT100_GREEN "OK" VT100_RESET);
|
: VT100_GREEN "OK" VT100_RESET);
|
||||||
else
|
else
|
||||||
printf ("%s\n", (failed > oldfailed) ? "failed!" : "OK" );
|
printf ("%s", (failed > oldfailed) ? "failed!" : "OK" );
|
||||||
|
|
||||||
printf ("\n");
|
if (failed)
|
||||||
|
printf (" (%u)", failed);
|
||||||
|
|
||||||
|
printf ("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bgp *bgp;
|
static struct bgp *bgp;
|
||||||
@ -485,10 +585,12 @@ main (void)
|
|||||||
conf_bgp_debug_events = -1UL;
|
conf_bgp_debug_events = -1UL;
|
||||||
conf_bgp_debug_packet = -1UL;
|
conf_bgp_debug_packet = -1UL;
|
||||||
conf_bgp_debug_normal = -1UL;
|
conf_bgp_debug_normal = -1UL;
|
||||||
|
conf_bgp_debug_as4 = -1UL;
|
||||||
term_bgp_debug_fsm = -1UL;
|
term_bgp_debug_fsm = -1UL;
|
||||||
term_bgp_debug_events = -1UL;
|
term_bgp_debug_events = -1UL;
|
||||||
term_bgp_debug_packet = -1UL;
|
term_bgp_debug_packet = -1UL;
|
||||||
term_bgp_debug_normal = -1UL;
|
term_bgp_debug_normal = -1UL;
|
||||||
|
term_bgp_debug_as4 = -1UL;
|
||||||
|
|
||||||
master = thread_master_create ();
|
master = thread_master_create ();
|
||||||
bgp_master_init ();
|
bgp_master_init ();
|
||||||
@ -500,6 +602,7 @@ main (void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
peer = peer_create_accept (bgp);
|
peer = peer_create_accept (bgp);
|
||||||
|
peer->host = "foo";
|
||||||
|
|
||||||
for (i = AFI_IP; i < AFI_MAX; i++)
|
for (i = AFI_IP; i < AFI_MAX; i++)
|
||||||
for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
|
for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
|
||||||
@ -510,18 +613,22 @@ main (void)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (mp_segments[i].name)
|
while (mp_segments[i].name)
|
||||||
parse_test (peer, &mp_segments[i++], OPEN);
|
parse_test (peer, &mp_segments[i++], CAPABILITY);
|
||||||
|
|
||||||
/* These tests assume mp_segments tests set at least
|
/* These tests assume mp_segments tests set at least
|
||||||
* one of the afc_nego's
|
* one of the afc_nego's
|
||||||
*/
|
*/
|
||||||
i = 0;
|
i = 0;
|
||||||
while (test_segments[i].name)
|
while (test_segments[i].name)
|
||||||
parse_test (peer, &test_segments[i++], OPEN);
|
parse_test (peer, &test_segments[i++], CAPABILITY);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (misc_segments[i].name)
|
while (misc_segments[i].name)
|
||||||
parse_test (peer, &misc_segments[i++], OPEN);
|
parse_test (peer, &misc_segments[i++], CAPABILITY);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (opt_params[i].name)
|
||||||
|
parse_test (peer, &opt_params[i++], OPT_PARAM);
|
||||||
|
|
||||||
SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
|
SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
|
||||||
peer->status = Established;
|
peer->status = Established;
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
precision commands: send to all daemons.
|
precision commands: send to all daemons.
|
||||||
(vtysh_init_vty) Install new log timestamp precision commands.
|
(vtysh_init_vty) Install new log timestamp precision commands.
|
||||||
|
|
||||||
|
2007-02-12 Juergen Kammer <j.kammer@eurodata.de>
|
||||||
|
* extract.pl: AS4 compatibility for router bgp ASNUMBER
|
||||||
|
* extract.pl.in: AS4 compatibility for router bgp ASNUMBER
|
||||||
|
* vtysh.c: AS4 compatibility for router bgp ASNUMBER
|
||||||
|
|
||||||
2006-07-27 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
2006-07-27 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||||
|
|
||||||
* vtysh_main.c: (usage) Add new -d and -E options. And note that
|
* vtysh_main.c: (usage) Add new -d and -E options. And note that
|
||||||
|
@ -37,8 +37,8 @@ $ignore{'"router ripng"'} = "ignore";
|
|||||||
$ignore{'"router ospf"'} = "ignore";
|
$ignore{'"router ospf"'} = "ignore";
|
||||||
$ignore{'"router ospf <0-65535>"'} = "ignore";
|
$ignore{'"router ospf <0-65535>"'} = "ignore";
|
||||||
$ignore{'"router ospf6"'} = "ignore";
|
$ignore{'"router ospf6"'} = "ignore";
|
||||||
$ignore{'"router bgp <1-65535>"'} = "ignore";
|
$ignore{'"router bgp CMD_AS_RANGE"'} = "ignore";
|
||||||
$ignore{'"router bgp <1-65535> view WORD"'} = "ignore";
|
$ignore{'"router bgp CMD_AS_RANGE view WORD"'} = "ignore";
|
||||||
$ignore{'"router isis WORD"'} = "ignore";
|
$ignore{'"router isis WORD"'} = "ignore";
|
||||||
$ignore{'"router zebra"'} = "ignore";
|
$ignore{'"router zebra"'} = "ignore";
|
||||||
$ignore{'"address-family ipv4"'} = "ignore";
|
$ignore{'"address-family ipv4"'} = "ignore";
|
||||||
|
@ -838,7 +838,7 @@ DEFUNSH (VTYSH_ALL,
|
|||||||
DEFUNSH (VTYSH_BGPD,
|
DEFUNSH (VTYSH_BGPD,
|
||||||
router_bgp,
|
router_bgp,
|
||||||
router_bgp_cmd,
|
router_bgp_cmd,
|
||||||
"router bgp <1-65535>",
|
"router bgp CMD_AS_RANGE",
|
||||||
ROUTER_STR
|
ROUTER_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
AS_STR)
|
AS_STR)
|
||||||
|
Loading…
Reference in New Issue
Block a user