Merge bgpd changeset 1176 from Zebra repository by Rivo Nurges.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 98bf90c..cdcd83b 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,8 @@
+2005-05-20 Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* *: Maximum prefix threshold support.
+	* *: Reset notification fixups.
+
 2004-05-08 Paul Jakma <paul@dishone.st>
 
 	* bgp_zebra.c: (bgp_interface_address_add) sync to zclient changes
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index 0a120a7..7a8fb03 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -607,6 +607,10 @@
 
   as_list_delete (aslist);
 
+  /* Run hook function. */
+  if (as_list_master.delete_hook)
+    (*as_list_master.delete_hook) ();
+
   return CMD_SUCCESS;
 }
 
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 5c8224c..d28cd93 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -307,6 +307,33 @@
   peer->uptime = time (NULL);
 }
 
+/* BGP Peer Down Cause */
+char *peer_down_str[] =
+{
+  "",
+  "Router ID changed",
+  "Remote AS changed",
+  "Local AS change",
+  "Cluster ID changed",
+  "Confederation identifier changed",
+  "Confederation peer changed",
+  "RR client config change",
+  "RS client config change",
+  "Update source change",
+  "Address family activated",
+  "Admin. shutdown",
+  "User reset",
+  "BGP Notification received",
+  "BGP Notification send",
+  "Peer closed the session",
+  "Neighbor deleted",
+  "Peer-group add member",
+  "Peer-group delete member",
+  "Capability changed",
+  "Passive config change",
+  "Multihop config change"
+};
+
 /* Administrative BGP peer stop event. */
 int
 bgp_stop (struct peer *peer)
@@ -325,7 +352,8 @@
 
       /* bgp log-neighbor-changes of neighbor Down */
       if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
-	zlog_info ("%%ADJCHANGE: neighbor %s Down", peer->host);
+	zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
+                   peer_down_str [(int) peer->last_reset]);
 
       /* set last reset time */
       peer->resettime = time (NULL);
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index f051aaa..ce816e2 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -40,3 +40,4 @@
 int bgp_stop (struct peer *peer);
 void bgp_timer_set (struct peer *);
 void bgp_fsm_change_status (struct peer *peer, int status);
+extern char *peer_down_str[];
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 4f43b9d..e94ecf2 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -451,11 +451,11 @@
 	continue;
 
       if (peer->afc[AFI_IP][SAFI_UNICAST])
-	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_UNICAST);
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_UNICAST, 1);
       if (peer->afc[AFI_IP][SAFI_MULTICAST])
-	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MULTICAST);
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MULTICAST, 1);
       if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
-	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MPLS_VPN);
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MPLS_VPN, 1);
     }
 
   for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]); rn;
@@ -550,9 +550,9 @@
 	continue;
 
       if (peer->afc[AFI_IP6][SAFI_UNICAST])
-	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_UNICAST);
+	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_UNICAST, 1);
       if (peer->afc[AFI_IP6][SAFI_MULTICAST])
-	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_MULTICAST);
+	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_MULTICAST, 1);
     }
 
   for (rn = bgp_table_top (bgp->rib[AFI_IP6][SAFI_UNICAST]); rn;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 48879f3..9995c02 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -849,6 +849,17 @@
     zlog_info ("%s send message type %d, length (incl. header) %d",
 	       peer->host, BGP_MSG_NOTIFY, length);
 
+  /* peer reset cause */
+  if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
+    {
+      if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
+      peer->last_reset = PEER_DOWN_USER_RESET;
+      else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
+      peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
+      else
+      peer->last_reset = PEER_DOWN_NOTIFY_SEND;
+    }
+
   /* Call imidiately. */
   BGP_WRITE_OFF (peer->t_write);
 
@@ -1094,7 +1105,7 @@
 		 connection initiated by the remote system. */
 
 	      if (peer->fd >= 0)
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
 	      return 1;
 	    }
 	  else
@@ -1106,7 +1117,7 @@
 		 OpenConfirm state). */
 
 	      if (new->fd >= 0)
-		bgp_notify_send (new, BGP_NOTIFY_CEASE, 0);
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
 	      return -1;
 	    }
 	}
@@ -1643,6 +1654,9 @@
   /* peer count update */
   peer->notify_in++;
 
+  if (peer->status == Established)
+    peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
+
   /* We have to check for Notify with Unsupported Optional Parameter.
      in that case we fallback to open without the capability option.
      But this done in bgp_stop. We just mark it here to avoid changing
@@ -2051,6 +2065,10 @@
       if (BGP_DEBUG (events, EVENTS))
 	plog_info (peer->log, "%s [Event] BGP connection closed fd %d",
 		   peer->host, peer->fd);
+
+      if (peer->status == Established) 
+       peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+
       BGP_EVENT_ADD (peer, TCP_connection_closed);
       return -1;
     }
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 97636ef..b8af869 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -875,38 +875,61 @@
 }
 
 int
-bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi)
+bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi, int always)
 {
-  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
+  if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
+    return 0;
+
+  if (peer->pcount[afi][safi] > peer->pmax[afi][safi])
     {
-      if (peer->pcount[afi][safi] > peer->pmax[afi][safi])
-	{
-	  zlog (peer->log, LOG_INFO,
-		"MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld", peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);
-	  if (! CHECK_FLAG (peer->af_flags[afi][safi],
-			    PEER_FLAG_MAX_PREFIX_WARNING))
-	    {
-	      char ndata[7];
+      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT)
+         && ! always)
+       return 0;
 
-	      ndata[0] = (u_char)(afi >>  8);
-	      ndata[1] = (u_char) afi;
-	      ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24);
-	      ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16);
-	      ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8);
-	      ndata[6] = (u_char)(peer->pmax[afi][safi]);
+      zlog (peer->log, LOG_INFO,
+           "%%MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld",
+           peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);
+      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
 
-	      if (safi == SAFI_MPLS_VPN)
-		safi = BGP_SAFI_VPNV4;
-	      ndata[2] = (u_char) safi;
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
+       return 0;
 
-	      SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
-	      bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE,
-					 BGP_NOTIFY_CEASE_MAX_PREFIX,
-					 ndata, 7);
-	      return 1;
-	    }
-	}
+      {
+       char ndata[7];
+
+       ndata[0] = (u_char)(afi >>  8);
+       ndata[1] = (u_char) afi;
+       ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24);
+       ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16);
+       ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8);
+       ndata[6] = (u_char)(peer->pmax[afi][safi]);
+
+       if (safi == SAFI_MPLS_VPN)
+         safi = BGP_SAFI_VPNV4;
+       ndata[2] = (u_char) safi;
+
+       SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
+       bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE,
+                                  BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7);
+      }
+      return 1;
     }
+  else
+    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
+
+  if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100))
+    {
+      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD)
+         && ! always)
+       return 0;
+
+      zlog (peer->log, LOG_INFO,
+           "%%MAXPFX: No. of prefix received from %s (afi %d) reaches %ld, max %ld",
+           peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);
+      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);
+    }
+  else
+    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);
   return 0;
 }
 
@@ -1232,9 +1255,8 @@
 
   /* If maximum prefix count is configured and current prefix
      count exeed it. */
-  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
-    if (bgp_maximum_prefix_overflow (peer, afi, safi))
-      return -1;
+  if (bgp_maximum_prefix_overflow (peer, afi, safi, 0))
+    return -1;
 
   /* Process change. */
   bgp_process (bgp, rn, afi, safi);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index fd97617..273ed41 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -131,7 +131,7 @@
 int bgp_nlri_sanity_check (struct peer *, int, u_char *, bgp_size_t);
 int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
 
-int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t);
+int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
 
 void bgp_redistribute_add (struct prefix *, struct in_addr *, u_int32_t, u_char);
 void bgp_redistribute_delete (struct prefix *, u_char);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index c4735f1..dda4029 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -34,6 +34,7 @@
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_community.h"
 #include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_fsm.h"
 #include "bgpd/bgp_mplsvpn.h"
 #include "bgpd/bgp_open.h"
 #include "bgpd/bgp_route.h"
@@ -3367,19 +3368,25 @@
 
 int
 peer_maximum_prefix_set_vty (struct vty *vty, char *ip_str, afi_t afi,
-			     safi_t safi, char *num_str, int warning)
+			     safi_t safi, char *num_str,  char *threshold_str,
+                             int warning)
 {
   int ret;
   struct peer *peer;
   u_int32_t max;
+  u_char threshold;
 
   peer = peer_and_group_lookup_vty (vty, ip_str);
   if (! peer)
     return CMD_WARNING;
 
   VTY_GET_INTEGER ("maxmum number", max, num_str);
+  if (threshold_str)
+    threshold = atoi (threshold_str);
+  else
+    threshold = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
 
-  ret = peer_maximum_prefix_set (peer, afi, safi, max, warning);
+  ret = peer_maximum_prefix_set (peer, afi, safi, max, threshold, warning);
 
   return bgp_vty_return (vty, ret);
 }
@@ -3412,9 +3419,22 @@
        "maximum no. of prefix limit\n")
 {
   return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
-				      bgp_node_safi (vty), argv[1], 0);
+                                     bgp_node_safi (vty), argv[1], NULL, 0);
 }
 
+DEFUN (neighbor_maximum_prefix_threshold,
+       neighbor_maximum_prefix_threshold_cmd,
+       NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> <1-100>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n"
+       "Threshold value (%) at which to generate a warning msg\n")
+{
+  return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
+                                     bgp_node_safi (vty), argv[1], argv[2], 0);
+ }
+
 DEFUN (neighbor_maximum_prefix_warning,
        neighbor_maximum_prefix_warning_cmd,
        NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> warning-only",
@@ -3425,9 +3445,23 @@
        "Only give warning message when limit is exceeded\n")
 {
   return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
-				      bgp_node_safi (vty), argv[1], 1);
+                                     bgp_node_safi (vty), argv[1], NULL, 1);
 }
 
+DEFUN (neighbor_maximum_prefix_threshold_warning,
+       neighbor_maximum_prefix_threshold_warning_cmd,
+       NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> <1-100> warning-only",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n"
+       "Threshold value (%) at which to generate a warning msg\n"
+       "Only give warning message when limit is exceeded\n")
+{
+  return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
+                                     bgp_node_safi (vty), argv[1], argv[2], 1);
+ }
+
 DEFUN (no_neighbor_maximum_prefix,
        no_neighbor_maximum_prefix_cmd,
        NO_NEIGHBOR_CMD2 "maximum-prefix",
@@ -3451,6 +3485,17 @@
 
 ALIAS (no_neighbor_maximum_prefix,
        no_neighbor_maximum_prefix_val2_cmd,
+       NO_NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> <1-100> warning-only",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n"
+       "Threshold value (%) at which to generate a warning msg\n"
+       "Only give warning message when limit is exceeded\n")
+
+ALIAS (no_neighbor_maximum_prefix,
+       no_neighbor_maximum_prefix_val3_cmd,
        NO_NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> warning-only",
        NO_STR
        NEIGHBOR_STR
@@ -6419,17 +6464,17 @@
 	     filter->usmap.name, VTY_NEWLINE);
 
   /* Receive prefix count */
-  vty_out (vty, "  %ld accepted prefixes",
-	   p->pcount[afi][safi]);
+  vty_out (vty, "  %ld accepted prefixes%s", p->pcount[afi][safi], VTY_NEWLINE);
+
   /* Maximum prefix */
   if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
     {
-      vty_out (vty, ", maximum limit %ld%s",
-	       p->pmax[afi][safi],
+      vty_out (vty, "  maximum limit %ld%s%s", p->pmax[afi][safi],
 	       CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
-	       ? " (warning-only)" : "");
+               ? " (warning-only)" : "", VTY_NEWLINE);
+      vty_out (vty, "  Threshold for warning message %d%%%s", p->pmax_threshold [afi][safi],
+              VTY_NEWLINE);
     }
-  vty_out (vty, "%s", VTY_NEWLINE);
 
   vty_out (vty, "%s", VTY_NEWLINE);
 }
@@ -6476,7 +6521,8 @@
 	   VTY_NEWLINE);
 
   /* Confederation */
-  if (bgp_confederation_peers_check (bgp, p->as)) 
+  if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)
+      && bgp_confederation_peers_check (bgp, p->as))
     vty_out (vty, "  Neighbor under common administration%s", VTY_NEWLINE);
   
   /* Status. */
@@ -6688,8 +6734,12 @@
 	   p->established, p->dropped,
 	   VTY_NEWLINE);
 
-  vty_out (vty, "  Last reset %s%s", p->dropped ? peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN) : "never",
-	   VTY_NEWLINE);
+  if (! p->dropped)
+    vty_out (vty, "  Last reset never%s", VTY_NEWLINE);
+  else
+    vty_out (vty, "  Last reset %s, due to %s%s",
+            peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN),
+            peer_down_str[(int) p->last_reset], VTY_NEWLINE);
 
   if (CHECK_FLAG (p->sflags, PEER_STATUS_PREFIX_OVERFLOW))
     {
@@ -8254,30 +8304,45 @@
 
   /* "neighbor maximum-prefix" commands. */
   install_element (BGP_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_NODE, &neighbor_maximum_prefix_threshold_cmd);
   install_element (BGP_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
   install_element (BGP_NODE, &no_neighbor_maximum_prefix_cmd);
   install_element (BGP_NODE, &no_neighbor_maximum_prefix_val_cmd);
   install_element (BGP_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_NODE, &no_neighbor_maximum_prefix_val3_cmd);
   install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_cmd);
   install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
   install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_cmd);
   install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_val_cmd);
   install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_val3_cmd);
   install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_cmd);
   install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
   install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd);
   install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_val_cmd);
   install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_val3_cmd);
   install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_cmd);
   install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
   install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_cmd);
   install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_val_cmd);
   install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_val3_cmd);
   install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_cmd);
   install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
   install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_cmd);
   install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_val_cmd);
   install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_val3_cmd);
 
   /* "neighbor allowas-in" */
   install_element (BGP_NODE, &neighbor_allowas_in_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index e9d81de..510e296 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -173,8 +173,11 @@
       IPV4_ADDR_COPY (&peer->local_id, id);
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_RID_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
   return 0;
 }
@@ -205,8 +208,11 @@
   LIST_LOOP (bgp->peer, peer, nn)
     {
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_RID_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
 
   return 0;
@@ -233,8 +239,11 @@
 	continue;
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_CLID_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
   return 0;
 }
@@ -258,8 +267,11 @@
 	continue;
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_CLID_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
   return 0;
 }
@@ -313,8 +325,12 @@
 	    {
 	      peer->local_as = as;
 	      if (peer->status == Established)
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                              BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
+
 	      else
 		BGP_EVENT_ADD (peer, BGP_Stop);
 	    }
@@ -329,8 +345,11 @@
 	      if (peer_sort (peer) == BGP_PEER_EBGP)
 		peer->local_as = as;
 	      if (peer->status == Established)
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                              BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
 	      else
 		BGP_EVENT_ADD (peer, BGP_Stop);
 	    }
@@ -355,8 +374,12 @@
 	{
 	  peer->local_as = bgp->as;
 	  if (peer->status == Established)
-	    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+           {
+             peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
+             bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                              BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+           }
+
 	  else
 	    BGP_EVENT_ADD (peer, BGP_Stop);
 	}
@@ -415,8 +438,11 @@
 	    {
 	      peer->local_as = bgp->as;
 	      if (peer->status == Established)
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
 	      else
 	        BGP_EVENT_ADD (peer, BGP_Stop);
 	    }
@@ -468,8 +494,11 @@
 	    {
 	      peer->local_as = bgp->confed_id;
 	      if (peer->status == Established)
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
 	      else
 		BGP_EVENT_ADD (peer, BGP_Stop);
 	    }
@@ -587,6 +616,7 @@
 
   /* Clear neighbor maximum-prefix */
   peer->pmax[afi][safi] = 0;
+  peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
 }
 
 /* peer global config reset */
@@ -792,8 +822,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -948,8 +981,11 @@
 		    }
 		}
 	      else
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
 	    }
 	}
     }
@@ -1004,12 +1040,18 @@
 		  peer->pcount[afi][safi] = 0;
 		}
 	      else
-		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               {
+                 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
+                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+               }
 	    }
 	  else
-	    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+           {
+             peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
+             bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                              BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+           }
 	}
     }
   return 0;
@@ -1038,6 +1080,7 @@
   /* Withdraw all information from routing table.  We can not use
      BGP_EVENT_ADD (peer, BGP_Stop) at here.  Because the event is
      executed after peer structure is deleted. */
+  peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
   bgp_stop (peer);
   bgp_fsm_change_status (peer, Idle);
 
@@ -1254,6 +1297,7 @@
 
   /* maximum-prefix */
   peer->pmax[afi][safi] = conf->pmax[afi][safi];
+  peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
 
   /* allowas-in */
   peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
@@ -1562,8 +1606,11 @@
   peer_group2peer_config_copy (group, peer, afi, safi);
 
   if (peer->status == Established)
-    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-		     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    {
+      peer->last_reset = PEER_DOWN_RMAP_BIND;
+      bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                      BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
   else
     BGP_EVENT_ADD (peer, BGP_Stop);
 
@@ -1597,8 +1644,11 @@
     }
 
   if (peer->status == Established)
-    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-		     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    {
+      peer->last_reset = PEER_DOWN_RMAP_UNBIND;
+      bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                      BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
   else
     BGP_EVENT_ADD (peer, BGP_Stop);
 
@@ -1924,6 +1974,9 @@
 
   /* Action when the flag is changed.  */
   enum peer_change_type type;
+
+  /* Peer down cause */
+  u_char peer_down;
 };
 
 struct peer_flag_action peer_flag_action_list[] = 
@@ -2042,8 +2095,19 @@
 			       CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
 	}
       else
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP)
+           peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+         else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
+           peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+         else if (flag == PEER_FLAG_PASSIVE)
+           peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
+         else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
+           peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
+
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
   else
     BGP_EVENT_ADD (peer, BGP_Stop);
@@ -2216,7 +2280,19 @@
       if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
 	bgp_clear_adj_in (peer, afi, safi);
       else
-	peer_change_action (peer, afi, safi, action.type);
+       {
+         if (flag == PEER_FLAG_REFLECTOR_CLIENT)
+           peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
+         else if (flag == PEER_FLAG_RSERVER_CLIENT)
+           peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
+         else if (flag == PEER_FLAG_ORF_PREFIX_SM)
+           peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+         else if (flag == PEER_FLAG_ORF_PREFIX_RM)
+           peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+
+         peer_change_action (peer, afi, safi, action.type);
+       }
+
     }
 
   /* Peer group member updates.  */
@@ -2245,7 +2321,18 @@
 	      if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
 		bgp_clear_adj_in (peer, afi, safi);
 	      else
-		peer_change_action (peer, afi, safi, action.type);
+               {
+                 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
+                   peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
+                 else if (flag == PEER_FLAG_RSERVER_CLIENT)
+                   peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
+                 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
+                   peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+                 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
+                   peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
+
+                 peer_change_action (peer, afi, safi, action.type);
+               }
 	    }
 	}
     }
@@ -2385,8 +2472,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
       return 0;
@@ -2414,8 +2504,11 @@
       peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -2448,8 +2541,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
       return 0;
@@ -2476,8 +2572,11 @@
       peer->update_source = sockunion_dup (su);
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -2524,8 +2623,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
       return 0;
@@ -2551,8 +2653,11 @@
 	}
 
       if (peer->status == Established)
-	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
 	BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -2995,8 +3100,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
         BGP_EVENT_ADD (peer, BGP_Stop);
 
@@ -3013,8 +3121,11 @@
 	UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
 
       if (peer->status == Established)
-        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
         BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -3040,8 +3151,11 @@
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       if (peer->status == Established)
-        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
         BGP_EVENT_ADD (peer, BGP_Stop);
 
@@ -3055,8 +3169,11 @@
       UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
 
       if (peer->status == Established)
-        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       {
+         peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
       else
         BGP_EVENT_ADD (peer, BGP_Stop);
     }
@@ -3720,7 +3837,7 @@
 
 int
 peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
-			 u_int32_t max, int warning)
+			 u_int32_t max, u_char threshold, int warning)
 {
   struct peer_group *group;
   struct listnode *nn;
@@ -3730,6 +3847,7 @@
 
   SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
   peer->pmax[afi][safi] = max;
+  peer->pmax_threshold[afi][safi] = threshold;
   if (warning)
     SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
   else
@@ -3746,6 +3864,7 @@
 
       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
       peer->pmax[afi][safi] = max;
+      peer->pmax_threshold[afi][safi] = threshold;
       if (warning)
 	SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
       else
@@ -3779,12 +3898,14 @@
 	UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
 
       peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
+      peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
       return 0;
     }
 
   UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
   UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
   peer->pmax[afi][safi] = 0;
+  peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     return 0;
@@ -3798,6 +3919,7 @@
       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
       peer->pmax[afi][safi] = 0;
+      peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
     }
   return 0;
 }
@@ -4266,12 +4388,17 @@
   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
     if (! peer->af_group[afi][safi]
 	|| g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
+        || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
 	|| CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
 	   != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
-      vty_out (vty, " neighbor %s maximum-prefix %ld%s%s",
-	       addr, peer->pmax[afi][safi],
-	       CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
-	       ? " warning-only" : "", VTY_NEWLINE);
+      {
+       vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
+       if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
+         vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
+       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
+         vty_out (vty, " warning-only");
+       vty_out (vty, "%s", VTY_NEWLINE);
+      }
 
   /* Route server client. */
   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
@@ -4460,25 +4587,22 @@
 	vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
 		 VTY_NEWLINE);
 
-      /* Confederation Information */
+      /* Confederation identifier*/
       if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
+       vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
+                VTY_NEWLINE);
+
+      /* Confederation peer */
+      if (bgp->confed_peers_cnt > 0)
 	{
-	  vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
-		   VTY_NEWLINE);
-	  if (bgp->confed_peers_cnt > 0)
-	    {
-	      int i;
+	  int i;
 
-	      vty_out (vty, " bgp confederation peers");
+	  vty_out (vty, " bgp confederation peers");
 
-	      for (i = 0; i < bgp->confed_peers_cnt; i++)
-		{
-		  vty_out(vty, " ");
-		  vty_out(vty, "%d", bgp->confed_peers[i]);
-		}
+         for (i = 0; i < bgp->confed_peers_cnt; i++)
+           vty_out(vty, " %d", bgp->confed_peers[i]);
 
-	      vty_out (vty, "%s", VTY_NEWLINE);
-	    }
+          vty_out (vty, "%s", VTY_NEWLINE);
 	}
 
       /* BGP enforce-first-as. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index b10e6b6..b40a68c 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -352,6 +352,9 @@
 #define PEER_STATUS_ORF_PREFIX_SEND   (1 << 0) /* prefix-list send peer */
 #define PEER_STATUS_ORF_WAIT_REFRESH  (1 << 1) /* wait refresh received peer */
 #define PEER_STATUS_DEFAULT_ORIGINATE (1 << 2) /* default-originate peer */
+#define PEER_STATUS_PREFIX_THRESHOLD  (1 << 3) /* exceed prefix-threshold */
+#define PEER_STATUS_PREFIX_LIMIT      (1 << 4) /* exceed prefix-limit */
+
 
   /* Default attribute value for the peer. */
   u_int32_t config;
@@ -429,10 +432,36 @@
 
   /* Max prefix count. */
   unsigned long pmax[AFI_MAX][SAFI_MAX];
+  u_char pmax_threshold[AFI_MAX][SAFI_MAX];
+#define MAXIMUM_PREFIX_THRESHOLD_DEFAULT 75
 
   /* allowas-in. */
   char allowas_in[AFI_MAX][SAFI_MAX];
 
+  /* peer reset cause */
+  char last_reset;
+#define PEER_DOWN_RID_CHANGE             1 /* bgp router-id command */
+#define PEER_DOWN_REMOTE_AS_CHANGE       2 /* neighbor remote-as command */
+#define PEER_DOWN_LOCAL_AS_CHANGE        3 /* neighbor local-as command */
+#define PEER_DOWN_CLID_CHANGE            4 /* bgp cluster-id command */
+#define PEER_DOWN_CONFED_ID_CHANGE       5 /* bgp confederation identifier command */
+#define PEER_DOWN_CONFED_PEER_CHANGE     6 /* bgp confederation peer command */
+#define PEER_DOWN_RR_CLIENT_CHANGE       7 /* neighbor route-reflector-client command */
+#define PEER_DOWN_RS_CLIENT_CHANGE       8 /* neighbor route-server-client command */
+#define PEER_DOWN_UPDATE_SOURCE_CHANGE   9 /* neighbor update-source command */
+#define PEER_DOWN_AF_ACTIVATE           10 /* neighbor activate command */
+#define PEER_DOWN_USER_SHUTDOWN         11 /* neighbor shutdown command */
+#define PEER_DOWN_USER_RESET            12 /* clear ip bgp command */
+#define PEER_DOWN_NOTIFY_RECEIVED       13 /* notification received */
+#define PEER_DOWN_NOTIFY_SEND           14 /* notification send */
+#define PEER_DOWN_CLOSE_SESSION         15 /* tcp session close */
+#define PEER_DOWN_NEIGHBOR_DELETE       16 /* neghbor delete */
+#define PEER_DOWN_RMAP_BIND             17 /* neghbor peer-group command */
+#define PEER_DOWN_RMAP_UNBIND           18 /* no neighbor peer-group command */
+#define PEER_DOWN_CAPABILITY_CHANGE     19 /* neighbor capability command */
+#define PEER_DOWN_PASSIVE_CHANGE        20 /* neighbor passive command */
+#define PEER_DOWN_MULTIHOP_CHANGE       21 /* neighbor multihop command */
+
   /* The kind of route-map Flags.*/
   u_char rmap_type;
 #define PEER_RMAP_TYPE_IN             (1 << 0) /* neighbor route-map in */
@@ -830,7 +859,7 @@
 int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, char *);
 int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
 
-int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, int);
+int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int);
 int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
 
 int peer_clear (struct peer *);