* bgpd.texi: Document new "bgp bestpath as-path confed" command.
	* bgp_aspath.[ch], bgp_route.c, bgp_vty.c, bgpd.[ch]: Allow to enable
	  the length of confederation path segments to be included during the
	  as-path length check in the best path decision.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 4c18fc3..6dc1e7e 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,9 @@
+2005-04-08 Martin Ling <martin-quagga@earth.li>
+
+	* bgp_aspath.[ch], bgp_route.c, bgp_vty.c, bgpd.[ch]: Allow to enable
+	  the length of confederation path segments to be included during the
+	  as-path length check in the best path decision.
+
 2005-04-02 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
 	* bgp_zebra.c: (bgp_interface_delete) After deleting, set ifp->ifindex
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 5d49775..0c50f6a 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -138,6 +138,7 @@
   int str_pnt;
   char *str_buf;
   int count = 0;
+  int confed_count = 0;
 
   /* Empty aspath. */
   if (as->length == 0)
@@ -145,6 +146,7 @@
       str_buf = XMALLOC (MTYPE_AS_STR, 1);
       str_buf[0] = '\0';
       as->count = count;
+      as->confed_count = confed_count;
       return str_buf;
     }
 
@@ -208,14 +210,21 @@
 
       space = 0;
 
-      /* Increment count - ignoring CONFED SETS/SEQUENCES */
-      if (assegment->type != AS_CONFED_SEQUENCE
-	  && assegment->type != AS_CONFED_SET)
+      /* Increment counts */
+      switch (assegment->type)
 	{
-	  if (assegment->type == AS_SEQUENCE)
-	    count += assegment->length;
-	  else if (assegment->type == AS_SET)
-	    count++;
+	case AS_SEQUENCE:
+	  count += assegment->length;
+	  break;
+	case AS_SET:
+	  count++;
+	  break;
+	case AS_CONFED_SEQUENCE:
+	  confed_count += assegment->length;
+	  break;
+	case AS_CONFED_SET:
+	  confed_count++;
+	  break;
 	}
 
       for (i = 0; i < assegment->length; i++)
@@ -247,6 +256,7 @@
   str_buf[str_pnt] = '\0';
 
   as->count = count;
+  as->confed_count = confed_count;
 
   return str_buf;
 }
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 3f7858b..bfe4f5e 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -42,6 +42,9 @@
   /* AS count.  */
   int count;
 
+  /* Confederation set/segment AS count. */
+  int confed_count;
+  
   /* Rawdata.  */
   caddr_t data;
 
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4f3847d..8d99249 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -213,10 +213,26 @@
   /* 4. AS path length check. */
   if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
     {
-      if (new->attr->aspath->count < exist->attr->aspath->count)
-	return 1;
-      if (new->attr->aspath->count > exist->attr->aspath->count)
-	return 0;
+      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))
+	    return 1;
+	  if ((new->attr->aspath->count +
+	       new->attr->aspath->confed_count)
+	      > (exist->attr->aspath->count +
+		 exist->attr->aspath->confed_count))
+	    return 0;
+	}
+      else
+	{
+	  if (new->attr->aspath->count < exist->attr->aspath->count)
+	    return 1;
+          if (new->attr->aspath->count > exist->attr->aspath->count)
+	    return 0;
+	}
     }
 
   /* 5. Origin check. */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 52025b7..f7a41f5 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -971,6 +971,38 @@
   return CMD_SUCCESS;
 }
 
+/* "bgp bestpath as-path confed" configuration.  */
+DEFUN (bgp_bestpath_aspath_confed,
+       bgp_bestpath_aspath_confed_cmd,
+       "bgp bestpath as-path confed",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "AS-path attribute\n"
+       "Compare path lengths including confederation sets & sequences in selecting a route\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_ASPATH_CONFED);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_aspath_confed,
+       no_bgp_bestpath_aspath_confed_cmd,
+       "no bgp bestpath as-path confed",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "AS-path attribute\n"
+       "Compare path lengths including confederation sets & sequences in selecting a route\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_ASPATH_CONFED);
+  return CMD_SUCCESS;
+}
+
 /* "bgp log-neighbor-changes" configuration.  */
 DEFUN (bgp_log_neighbor_changes,
        bgp_log_neighbor_changes_cmd,
@@ -8626,6 +8658,10 @@
   install_element (BGP_NODE, &bgp_bestpath_aspath_ignore_cmd);
   install_element (BGP_NODE, &no_bgp_bestpath_aspath_ignore_cmd);
 
+  /* "bgp bestpath as-path confed" commands */
+  install_element (BGP_NODE, &bgp_bestpath_aspath_confed_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_aspath_confed_cmd);
+
   /* "bgp log-neighbor-changes" commands */
   install_element (BGP_NODE, &bgp_log_neighbor_changes_cmd);
   install_element (BGP_NODE, &no_bgp_log_neighbor_changes_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d1e8d96..0d1689a 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4751,6 +4751,8 @@
       /* BGP bestpath method. */
       if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
 	vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
+      if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
+	vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
       if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
 	vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
       if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index a6c11ff..a0cf7e8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -101,6 +101,7 @@
 #define BGP_FLAG_NO_FAST_EXT_FAILOVER     (1 << 10)
 #define BGP_FLAG_LOG_NEIGHBOR_CHANGES     (1 << 11)
 #define BGP_FLAG_GRACEFUL_RESTART         (1 << 12)
+#define BGP_FLAG_ASPATH_CONFED            (1 << 13)
 
   /* BGP Per AF flags */
   u_int16_t af_flags[AFI_MAX][SAFI_MAX];