Browse Source

2005-09-10 Paul Jakma <paul.jakma@sun.com>

	* Makefile.am: bgpd shouldn't list libgp's sources as its own.
	  Use LDADD.
	* bgp_aspath.h:
	  (struct assegment) New struct, abstract representation of a
	  list of AS_PATH segments and the contained ASNs.
	  (struct aspath) Remove the raw-data related
	  fields, reference the abstract struct assegment instead.
	  Remove several other computed fields, it's just a
	  headache to maintain them and they're cheap to compute from
	  struct assegment.
	  (aspath_parse) parse a stream, not a pointer to raw data.
	  (aspath_count_{hops,confeds,size}) helpers to access
	  information formerly directly contained in struct aspath.
	  (aspath_snmp_pathseg) Helper for SNMP, BGP MIB wants
	  to be able to output hex representation of raw data.
	* bgp_aspath.c: (general) partial-rewrite. Store aspath data
	  as an abstract singly-linked list of abstract segments,
          rather than storing the raw data, and parsing it each and
	  every time. Remove several count/size fields which are cheap
	  to compute from the abstract segment structure.
	  (global) Include stream.h, needed for aspath_parse, and
	  others. Couple of helper macros added.
	  (struct assegment_header) Just the header, and only the
	  header.
	  (assegment_data_{new,free}) convenience functions for
	  AS_SEG_DATA allocation, the dynamic, per-segment array of
	  ASNs.
	  (assegment_{new,free,free_all,dup,dup_all}) convenience
	  functions for creating struct assegments. The _all forms will
	  follow the entire chain of segments from the given segment.
	  (assegment_prepend_asns) new function, prepend an ASN N times
	  to segment.
 	  (assegment_append_asns) Append a list (array) of ASNs to
	  segment.
	  (int_cmp) convenience function for the aspath hash.
	  (assegment_normalise) new function. Normalise the given
	  segment chain to meet expectations of Quagga, and to
	  eliminate differing raw representations of the same paths.
	  Merge 'runs' of SEQUENCEs into one segment as our internal
	  segment is not limited by the protocol AS_PATH segment
	  length. Sort ASNs in SETs.
	  (aspath_new) Take void argument to quell warnings. Use the
	  assegment convenience functions.
	  (assegment_count_{asns,confeds,hops}) new functions to
	  compute at runtime values previously held in struct aspath.
	  (aspath_size) ditto.
	  (aspath_make_str_count) rewritten to stringify new
	  representation, and to be slightly easier to understand
	  hopefully.
	  (aspath_str_update) convenience function, update the aspath
	  str. Should investigate removing maintained string from
	  struct aspath, just run-time compute it, as per other fields.
	  It's just a maintenance headache, would save noticeable
	  amount of RAM with possibly not much extra run-time cost.
	  (aspath_dup) use the assegment dup functions.
	  (aspath_hash_alloc) Take void * argument to satisfy gcc. Use
	  the proper helper functions to dup data.
	  (assegments_parse) new function. parse raw AS_PATH data into
	  struct assegments. Normalise and return the head of the list.
	  (aspath_parse) Parse a stream, not pointer to raw data and
	  use assegments_parse to do it.
	  (assegment_data_put) Write out a single segment data in protocol
	  form to stream.
	  (assegment_header_put) ditto but for segment header.
	  (aspath_put) new function. As per previous but for an entire
	  struct aspath.
	  (aspath_snmp_pathseg) wrapper around aspath_put for
	  bgp_snmp.c. Uses a static buffer sadly.
	  (aspath_aggregate_as_set_add) rewritten to use assegments.
	  (aspath_aggregate) ditto
	  (aspath_{firstas,loop,private_as}_check) ditto
	  (aspath_{merge,prepend,add_one_as}) ditto
	  (aspath_cmp_left{_confed}) ditto
	  (aspath_delete_confed_seq) ditto, plus fixed to properly
	  delete all leading confed segments.
	  (aspath_as_add) Just use assegment_append_asns.
	  (aspath_segment_add) updated to use assegments.
	  (enum as_token) Add values for confeds
	  (aspath_gettoken) Add support for confeds
	  (aspath_str2aspath) ditto
	  (aspath_key_make) updated to use as_segments. Also, add
	  segment type into the hash value as appropriate.
	  (aspath_cmp) updated to use as_segments.
	  (aspath_print) don't segfault on NULL argument.
	* bgp_attr.c: (bgp_attr_aspath) aspath_parse wants the stream
	  now. No need for manual forwarding of stream.
	  (bgp_packet_attribute) empty aspath is now denoted by NULL
	  segment field, length is gone.
	  Use aspath_size() to determine size.
	  (bgp_attr_init) Fix declaration, explicitely specify void
	  arg.
	  (bgp_dump_routes_attr) Use aspath_size() to determine size.
	* bgp_route.c: (bgp_info_cmp) use the aspath_count_* functions.
	  (bgp_rib_withdraw) remove unused variable. Use
	  aspath_count_hops.
	* bgp_snmp.c: (bgp4PathAttrTable) raw data is gone, use
	  aspath_snmp_pathseg to get the representation.
paul 14 years ago
parent
commit
fe69a505f7
7 changed files with 992 additions and 561 deletions
  1. 100 0
      bgpd/ChangeLog
  2. 2 4
      bgpd/Makefile.am
  3. 832 511
      bgpd/bgp_aspath.c
  4. 19 12
      bgpd/bgp_aspath.h
  5. 17 14
      bgpd/bgp_attr.c
  6. 21 18
      bgpd/bgp_route.c
  7. 1 2
      bgpd/bgp_snmp.c

+ 100 - 0
bgpd/ChangeLog

@@ -1,5 +1,105 @@
 2005-09-10 Paul Jakma <paul.jakma@sun.com>
 
+	* Makefile.am: bgpd shouldn't list libgp's sources as its own.
+	  Use LDADD.
+	* bgp_aspath.h:	
+	  (struct assegment) New struct, abstract representation of a
+	  list of AS_PATH segments and the contained ASNs.	  
+	  (struct aspath) Remove the raw-data related
+	  fields, reference the abstract struct assegment instead. 
+	  Remove several other computed fields, it's just a
+	  headache to maintain them and they're cheap to compute from
+	  struct assegment.
+	  (aspath_parse) parse a stream, not a pointer to raw data.
+	  (aspath_count_{hops,confeds,size}) helpers to access
+	  information formerly directly contained in struct aspath.
+	  (aspath_snmp_pathseg) Helper for SNMP, BGP MIB wants
+	  to be able to output hex representation of raw data.
+	* bgp_aspath.c: (general) partial-rewrite. Store aspath data
+	  as an abstract singly-linked list of abstract segments,
+          rather than storing the raw data, and parsing it each and
+	  every time. Remove several count/size fields which are cheap
+	  to compute from the abstract segment structure.
+	  (global) Include stream.h, needed for aspath_parse, and
+	  others. Couple of helper macros added.
+	  (struct assegment_header) Just the header, and only the
+	  header.
+	  (assegment_data_{new,free}) convenience functions for
+	  AS_SEG_DATA allocation, the dynamic, per-segment array of
+	  ASNs.
+	  (assegment_{new,free,free_all,dup,dup_all}) convenience
+	  functions for creating struct assegments. The _all forms will
+	  follow the entire chain of segments from the given segment.
+	  (assegment_prepend_asns) new function, prepend an ASN N times
+	  to segment.
+ 	  (assegment_append_asns) Append a list (array) of ASNs to
+	  segment.
+	  (int_cmp) convenience function for the aspath hash.
+	  (assegment_normalise) new function. Normalise the given
+	  segment chain to meet expectations of Quagga, and to
+	  eliminate differing raw representations of the same paths.
+	  Merge 'runs' of SEQUENCEs into one segment as our internal
+	  segment is not limited by the protocol AS_PATH segment
+	  length. Sort ASNs in SETs. 
+	  (aspath_new) Take void argument to quell warnings. Use the
+	  assegment convenience functions.
+	  (assegment_count_{asns,confeds,hops}) new functions to
+	  compute at runtime values previously held in struct aspath.
+	  (aspath_size) ditto.
+	  (aspath_make_str_count) rewritten to stringify new
+	  representation, and to be slightly easier to understand
+	  hopefully.
+	  (aspath_str_update) convenience function, update the aspath
+	  str. Should investigate removing maintained string from
+	  struct aspath, just run-time compute it, as per other fields.
+	  It's just a maintenance headache, would save noticeable
+	  amount of RAM with possibly not much extra run-time cost.
+	  (aspath_dup) use the assegment dup functions.
+	  (aspath_hash_alloc) Take void * argument to satisfy gcc. Use
+	  the proper helper functions to dup data.
+	  (assegments_parse) new function. parse raw AS_PATH data into
+	  struct assegments. Normalise and return the head of the list.
+	  (aspath_parse) Parse a stream, not pointer to raw data and
+	  use assegments_parse to do it.
+	  (assegment_data_put) Write out a single segment data in protocol
+	  form to stream.
+	  (assegment_header_put) ditto but for segment header.
+	  (aspath_put) new function. As per previous but for an entire
+	  struct aspath.
+	  (aspath_snmp_pathseg) wrapper around aspath_put for
+	  bgp_snmp.c. Uses a static buffer sadly.
+	  (aspath_aggregate_as_set_add) rewritten to use assegments.
+	  (aspath_aggregate) ditto
+	  (aspath_{firstas,loop,private_as}_check) ditto
+	  (aspath_{merge,prepend,add_one_as}) ditto
+	  (aspath_cmp_left{_confed}) ditto
+	  (aspath_delete_confed_seq) ditto, plus fixed to properly
+	  delete all leading confed segments.
+	  (aspath_as_add) Just use assegment_append_asns.
+	  (aspath_segment_add) updated to use assegments.
+	  (enum as_token) Add values for confeds
+	  (aspath_gettoken) Add support for confeds
+	  (aspath_str2aspath) ditto
+	  (aspath_key_make) updated to use as_segments. Also, add
+	  segment type into the hash value as appropriate.
+	  (aspath_cmp) updated to use as_segments.
+	  (aspath_print) don't segfault on NULL argument.
+	* bgp_attr.c: (bgp_attr_aspath) aspath_parse wants the stream
+	  now. No need for manual forwarding of stream.
+	  (bgp_packet_attribute) empty aspath is now denoted by NULL
+	  segment field, length is gone.
+	  Use aspath_size() to determine size.
+	  (bgp_attr_init) Fix declaration, explicitely specify void
+	  arg.
+	  (bgp_dump_routes_attr) Use aspath_size() to determine size.
+	* bgp_route.c: (bgp_info_cmp) use the aspath_count_* functions.
+	  (bgp_rib_withdraw) remove unused variable. Use
+	  aspath_count_hops.
+	* bgp_snmp.c: (bgp4PathAttrTable) raw data is gone, use 
+	  aspath_snmp_pathseg to get the representation.
+
+2005-09-10 Paul Jakma <paul.jakma@sun.com>
+
 	* bgp_vty.c: (bgp_vty_init) gcc 4 compile fix. static
 	  function declarations shouldn't be inside functions.
 	* bgp_dump.c: (bgp_dump_interval_add) ditto.

+ 2 - 4
bgpd/Makefile.am

@@ -21,10 +21,8 @@ noinst_HEADERS = \
 	bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
 	bgp_advertise.h bgp_snmp.h bgp_vty.h
 
-bgpd_SOURCES = \
-	bgp_main.c $(libbgp_a_SOURCES)
-
-bgpd_LDADD = ../lib/libzebra.la @LIBCAP@
+bgpd_SOURCES = bgp_main.c
+bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@
 
 examplesdir = $(exampledir)
 dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2

File diff suppressed because it is too large
+ 832 - 511
bgpd/bgp_aspath.c


+ 19 - 12
bgpd/bgp_aspath.h

@@ -33,24 +33,24 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 #define BGP_AS_MAX		 65535U
 
+/* AS_PATH segment data in abstracted form, no limit is placed on length */
+struct assegment
+{
+  struct assegment *next;
+  as_t *as;
+  u_short length;
+  u_char type;
+};
+
 /* AS path may be include some AsSegments.  */
 struct aspath 
 {
   /* Reference count to this aspath.  */
   unsigned long refcnt;
 
-  /* Rawdata length.  */
-  int length;
-
-  /* AS count.  */
-  int count;
-
-  /* Confederation set/segment AS count. */
-  int confed_count;
+  /* segment data */
+  struct assegment *segments;
   
-  /* Rawdata.  */
-  caddr_t data;
-
   /* String expression of AS path.  This string is used by vty output
      and AS path regular expression match.  */
   char *str;
@@ -60,7 +60,7 @@ struct aspath
 
 /* Prototypes. */
 extern void aspath_init (void);
-extern struct aspath *aspath_parse (caddr_t, int);
+extern struct aspath *aspath_parse (struct stream *, size_t);
 extern struct aspath *aspath_dup (struct aspath *);
 extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
 extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
@@ -83,5 +83,12 @@ extern int aspath_loop_check (struct aspath *, as_t);
 extern int aspath_private_as_check (struct aspath *);
 extern int aspath_firstas_check (struct aspath *, as_t);
 extern unsigned long aspath_count (void);
+extern unsigned int aspath_count_hops (struct aspath *);
+extern unsigned int aspath_count_confeds (struct aspath *);
+extern unsigned int aspath_size (struct aspath *);
+extern void aspath_put (struct stream *, struct aspath *);
+
+/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
+extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
 
 #endif /* _QUAGGA_BGP_ASPATH_H */

+ 17 - 14
bgpd/bgp_attr.c

@@ -663,7 +663,7 @@ bgp_attr_aspath (struct peer *peer, bgp_size_t length,
     }
 
   /* In case of IBGP, length will be zero. */
-  attr->aspath = aspath_parse (stream_pnt (peer->ibuf), length);
+  attr->aspath = aspath_parse (peer->ibuf, length);
   if (! attr->aspath)
     {
       zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
@@ -701,7 +701,7 @@ bgp_attr_aspath (struct peer *peer, bgp_size_t length,
     }
 
   /* Forward pointer. */
-  stream_forward_getp (peer->ibuf, length);
+/*  stream_forward_getp (peer->ibuf, length);*/
 
   /* Set aspath attribute flag. */
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
@@ -1341,7 +1341,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
 		      afi_t afi, safi_t safi, struct peer *from,
 		      struct prefix_rd *prd, char *tag)
 {
-  unsigned long cp;
+  size_t cp;
+  unsigned int aspath_data_size;
   struct aspath *aspath;
 
   if (! bgp)
@@ -1361,7 +1362,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
   /* If remote-peer is EBGP */
   if (peer_sort (peer) == BGP_PEER_EBGP
       && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
-	  || attr->aspath->length == 0)
+	  || attr->aspath->segments == NULL)
       && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
     {    
       aspath = aspath_dup (attr->aspath);
@@ -1390,19 +1391,20 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
     aspath = attr->aspath;
 
   /* AS path attribute extended length bit check. */
-  if (aspath->length > 255)
+  aspath_data_size = aspath_size (aspath);
+  if (aspath_data_size > 255)
     {
       stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
       stream_putc (s, BGP_ATTR_AS_PATH);
-      stream_putw (s, aspath->length);
+      stream_putw (s, aspath_data_size);
     }
   else
     {
       stream_putc (s, BGP_ATTR_FLAG_TRANS);
-      stream_putc(s, BGP_ATTR_AS_PATH);
-      stream_putc (s, aspath->length);
+      stream_putc (s, BGP_ATTR_AS_PATH);
+      stream_putc (s, aspath_data_size);
     }
-  stream_put (s, aspath->data, aspath->length);
+  aspath_put (s, aspath);
 
   if (aspath != attr->aspath)
     aspath_free (aspath);
@@ -1735,7 +1737,7 @@ bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
 
 /* Initialization of attribute. */
 void
-bgp_attr_init ()
+bgp_attr_init (void)
 {
   void attrhash_init ();
 
@@ -1754,6 +1756,7 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
 {
   unsigned long cp;
   unsigned long len;
+  unsigned int aspathlen;
   struct aspath *aspath;
 
   /* Remember current pointer. */
@@ -1770,19 +1773,19 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
 
   aspath = attr->aspath;
 
-  if (aspath->length > 255)
+  if ( (aspathlen = aspath_size (aspath)) > 255 )
     {
       stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
       stream_putc (s, BGP_ATTR_AS_PATH);
-      stream_putw (s, aspath->length);
+      stream_putw (s, aspathlen);
     }
   else
     {
       stream_putc (s, BGP_ATTR_FLAG_TRANS);
       stream_putc (s, BGP_ATTR_AS_PATH);
-      stream_putc (s, aspath->length);
+      stream_putc (s, aspathlen);
     }
-  stream_put (s, aspath->data, aspath->length);
+  aspath_put (s, aspath);
 
   /* Nexthop attribute. */
   /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */

+ 21 - 18
bgpd/bgp_route.c

@@ -268,24 +268,28 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
   /* 4. AS path length check. */
   if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
     {
+      int exist_hops = aspath_count_hops (exist->attr->aspath);
+      int exist_confeds = aspath_count_confeds (exist->attr->aspath);
+      
       if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
 	{
-	  if ((new->attr->aspath->count +
-	       new->attr->aspath->confed_count)
-	      < (exist->attr->aspath->count +
-		 exist->attr->aspath->confed_count))
+	  int aspath_hops;
+	  
+	  aspath_hops = aspath_count_hops (new->attr->aspath);
+          aspath_hops += aspath_count_confeds (new->attr->aspath);
+          
+	  if ( aspath_hops < (exist_hops + exist_confeds))
 	    return 1;
-	  if ((new->attr->aspath->count +
-	       new->attr->aspath->confed_count)
-	      > (exist->attr->aspath->count +
-		 exist->attr->aspath->confed_count))
+	  if ( aspath_hops > (exist_hops + exist_confeds))
 	    return 0;
 	}
       else
 	{
-	  if (new->attr->aspath->count < exist->attr->aspath->count)
+	  int newhops = aspath_count_hops (new->attr->aspath);
+	  
+	  if (newhops < exist_hops)
 	    return 1;
-          if (new->attr->aspath->count > exist->attr->aspath->count)
+          if (newhops > exist_hops)
 	    return 0;
 	}
     }
@@ -297,12 +301,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
     return 0;
 
   /* 6. MED check. */
-  internal_as_route = (new->attr->aspath->length == 0
-		      && exist->attr->aspath->length == 0);
-  confed_as_route = (new->attr->aspath->length > 0
-		    && exist->attr->aspath->length > 0
-		    && new->attr->aspath->count == 0
-		    && exist->attr->aspath->count == 0);
+  internal_as_route = (aspath_count_hops (new->attr->aspath) == 0
+		      && aspath_count_hops (exist->attr->aspath) == 0);
+  confed_as_route = (aspath_count_confeds (new->attr->aspath) > 0
+		    && aspath_count_confeds (exist->attr->aspath) > 0
+		    && aspath_count_hops (new->attr->aspath) == 0
+		    && aspath_count_hops (exist->attr->aspath) == 0);
   
   if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
       || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
@@ -1573,7 +1577,6 @@ static void
 bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
 		  afi_t afi, safi_t safi)
 {
-  int valid;
   int status = BGP_DAMP_NONE;
 
   if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)
@@ -5371,7 +5374,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (attr->aspath)
 	{
 	  vty_out (vty, "  ");
-	  if (attr->aspath->length == 0)
+	  if (aspath_count_hops (attr->aspath) == 0)
 	    vty_out (vty, "Local");
 	  else
 	    aspath_print_vty (vty, attr->aspath);

+ 1 - 2
bgpd/bgp_snmp.c

@@ -782,8 +782,7 @@ bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
       return SNMP_INTEGER (binfo->attr->origin);
       break;
     case BGP4PATHATTRASPATHSEGMENT: /* 5 */
-      *var_len = binfo->attr->aspath->length;
-      return (u_char *) binfo->attr->aspath->data;
+      return aspath_snmp_pathseg (binfo->attr->aspath, var_len);
       break;
     case BGP4PATHATTRNEXTHOP:	/* 6 */
       return SNMP_IPADDRESS (binfo->attr->nexthop);