]> git.puffer.fish Git - mirror/frr.git/commitdiff
BGP: Remove the requirement to rebind a peer to its peer-group under the address...
authorDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 20 Nov 2015 18:53:50 +0000 (18:53 +0000)
committerDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 20 Nov 2015 18:53:50 +0000 (18:53 +0000)
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Ticket: CM-3868

NOTE: Many of the ibgp peers are not up in the 'show ip bgp summ' output below. This
is because ospf was disabled at the time.  The main thing to look for is whether or
not all of the correct peers are listed based on their 'activate' status.

Basic Example
=============

router bgp 10
 bgp router-id 10.0.0.1
 no bgp default ipv4-unicast
 no bgp bestpath as-path multipath-relax
 bgp bestpath compare-routerid
 bgp route-map delay-timer 1
 neighbor EBGP peer-group
 neighbor EBGP advertisement-interval 1
 neighbor IBGP peer-group
 neighbor IBGP remote-as 10
 neighbor IBGP update-source 10.0.0.1
 neighbor IBGP advertisement-interval 1
 neighbor 10.0.0.2 peer-group IBGP
 neighbor 10.0.0.3 peer-group IBGP
 neighbor 10.0.0.4 peer-group IBGP
 neighbor 20.1.1.6 remote-as 20
 neighbor 20.1.1.6 peer-group EBGP
 neighbor 20.1.1.7 remote-as 20
 neighbor 20.1.1.7 peer-group EBGP
 neighbor 40.1.1.2 remote-as 40
 neighbor 40.1.1.2 peer-group EBGP
 neighbor 40.1.1.6 remote-as 40
 neighbor 40.1.1.6 peer-group EBGP
 neighbor 40.1.1.10 remote-as 40
 neighbor 40.1.1.10 peer-group EBGP
!
 address-family ipv4 unicast
  neighbor EBGP activate
  neighbor IBGP activate
  neighbor IBGP next-hop-self
 exit-address-family
!

superm-redxp-05# show ip bgp summ
BGP router identifier 10.0.0.1, local AS number 10
BGP table version 4200
RIB entries 2399, using 281 KiB of memory
Peers 8, using 129 KiB of memory
Peer groups 2, using 112 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
r2(10.0.0.2)    4    10     107     211        0    0    0 00:23:01 Connect
r3(10.0.0.3)    4    10     107     211        0    0    0 00:23:01 Connect
r4(10.0.0.4)    4    10     207     211        0    0    0 00:23:01 Active
r6(20.1.1.6)    4    20     873     975        0    0    0 00:23:29      600
r7(20.1.1.7)    4    20     873     976        0    0    0 00:23:29      600
r8(40.1.1.2)    4    40     874     975        0    0    0 00:23:30      600
r9(40.1.1.6)    4    40     874     975        0    0    0 00:23:30      600
r10(40.1.1.10)  4    40     874     975        0    0    0 00:23:30      600

Total number of neighbors 8
superm-redxp-05#

Example where one member of the peer-group is inactive...we can do this now that
peer-group members can have different outbound policies from the peer-group.
================================================================================
superm-redxp-05# conf t
superm-redxp-05(config)# router bgp 10
superm-redxp-05(config-router)# address-family ipv4 unicast
superm-redxp-05(config-router-af)# no neighbor 10.0.0.3 activate
superm-redxp-05(config-router-af)# do show run
router bgp 10
 bgp router-id 10.0.0.1
 no bgp default ipv4-unicast
 no bgp bestpath as-path multipath-relax
 bgp bestpath compare-routerid
 bgp route-map delay-timer 1
 neighbor EBGP peer-group
 neighbor EBGP advertisement-interval 1
 neighbor IBGP peer-group
 neighbor IBGP remote-as 10
 neighbor IBGP update-source 10.0.0.1
 neighbor IBGP advertisement-interval 1
 neighbor 10.0.0.2 peer-group IBGP
 neighbor 10.0.0.3 peer-group IBGP
 neighbor 10.0.0.4 peer-group IBGP
 neighbor 20.1.1.6 remote-as 20
 neighbor 20.1.1.6 peer-group EBGP
 neighbor 20.1.1.7 remote-as 20
 neighbor 20.1.1.7 peer-group EBGP
 neighbor 40.1.1.2 remote-as 40
 neighbor 40.1.1.2 peer-group EBGP
 neighbor 40.1.1.6 remote-as 40
 neighbor 40.1.1.6 peer-group EBGP
 neighbor 40.1.1.10 remote-as 40
 neighbor 40.1.1.10 peer-group EBGP
!
 address-family ipv4 unicast
  neighbor EBGP activate
  neighbor IBGP activate
  neighbor IBGP next-hop-self
  no neighbor 10.0.0.3 activate
 exit-address-family
!
superm-redxp-05# show ip bgp summ
BGP router identifier 10.0.0.1, local AS number 10
BGP table version 4200
RIB entries 2399, using 281 KiB of memory
Peers 8, using 129 KiB of memory
Peer groups 2, using 112 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
r2(10.0.0.2)    4    10     107     211        0    0    0 00:23:24 Connect
r4(10.0.0.4)    4    10     207     211        0    0    0 00:23:24 Active
r6(20.1.1.6)    4    20     881     983        0    0    0 00:23:52      600
r7(20.1.1.7)    4    20     881     984        0    0    0 00:23:52      600
r8(40.1.1.2)    4    40     881     982        0    0    0 00:23:53      600
r9(40.1.1.6)    4    40     881     982        0    0    0 00:23:53      600
r10(40.1.1.10)  4    40     881     982        0    0    0 00:23:53      600

Total number of neighbors 7
superm-redxp-05#

Example where the peer-group is inactive but a member of the peer-group is active:
==================================================================================
superm-redxp-05(config)# router bgp 10
superm-redxp-05(config-router)# address-family ipv4 unicast
superm-redxp-05(config-router-af)# neighbor 10.0.0.3 activate
superm-redxp-05(config-router-af)# no neighbor IBGP activate
superm-redxp-05(config-router-af)#
superm-redxp-05(config-router-af)# neighbor 10.0.0.4 activate
superm-redxp-05(config-router-af)# end
superm-redxp-05# show run
router bgp 10
 bgp router-id 10.0.0.1
 no bgp default ipv4-unicast
 no bgp bestpath as-path multipath-relax
 bgp bestpath compare-routerid
 bgp route-map delay-timer 1
 neighbor EBGP peer-group
 neighbor EBGP advertisement-interval 1
 neighbor IBGP peer-group
 neighbor IBGP remote-as 10
 neighbor IBGP update-source 10.0.0.1
 neighbor IBGP advertisement-interval 1
 neighbor 10.0.0.2 peer-group IBGP
 neighbor 10.0.0.3 peer-group IBGP
 neighbor 10.0.0.4 peer-group IBGP
 neighbor 20.1.1.6 remote-as 20
 neighbor 20.1.1.6 peer-group EBGP
 neighbor 20.1.1.7 remote-as 20
 neighbor 20.1.1.7 peer-group EBGP
 neighbor 40.1.1.2 remote-as 40
 neighbor 40.1.1.2 peer-group EBGP
 neighbor 40.1.1.6 remote-as 40
 neighbor 40.1.1.6 peer-group EBGP
 neighbor 40.1.1.10 remote-as 40
 neighbor 40.1.1.10 peer-group EBGP
!
 address-family ipv4 unicast
  neighbor EBGP activate
  neighbor IBGP next-hop-self
  neighbor 10.0.0.4 activate
 exit-address-family
!

superm-redxp-05# show ip bgp summ
BGP router identifier 10.0.0.1, local AS number 10
BGP table version 4200
RIB entries 2399, using 281 KiB of memory
Peers 8, using 129 KiB of memory
Peer groups 2, using 112 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
r4(10.0.0.4)    4    10     207     211        0    0    0 00:24:56 Active
r6(20.1.1.6)    4    20     911    1013        0    0    0 00:25:24      600
r7(20.1.1.7)    4    20     911    1014        0    0    0 00:25:24      600
r8(40.1.1.2)    4    40     912    1013        0    0    0 00:25:25      600
r9(40.1.1.6)    4    40     912    1013        0    0    0 00:25:25      600
r10(40.1.1.10)  4    40     912    1013        0    0    0 00:25:25      600

Total number of neighbors 6
superm-redxp-05#

bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 6e218b85b802b2f28c37ede7f8008d9decbe01e7..2c75a6e7e3735b94ca6ba5fab28e529cb25d727f 100644 (file)
@@ -216,15 +216,6 @@ bgp_vty_return (struct vty *vty, int ret)
     case BGP_ERR_PEER_FLAG_CONFLICT:
       str = "Can't set override-capability and strict-capability-match at the same time";
       break;
-    case BGP_ERR_PEER_GROUP_MEMBER_EXISTS:
-      str = "No activate for peergroup can be given only if peer-group has no members";
-      break;
-    case BGP_ERR_PEER_BELONGS_TO_GROUP:
-      str = "No activate for an individual peer-group member is invalid";
-      break;
-    case BGP_ERR_PEER_GROUP_AF_UNCONFIGURED:
-      str = "Activate the peer-group for the address family first";
-      break;
     case BGP_ERR_PEER_GROUP_NO_REMOTE_AS:
       str = "Specify remote-as or peer-group remote AS first";
       break;
@@ -408,7 +399,7 @@ bgp_clear (struct vty *vty, struct bgp *bgp,  afi_t afi, safi_t safi,
              continue;
            }
 
-         if (! peer->af_group[afi][safi])
+         if (! peer->afc[afi][safi])
            continue;
 
          ret = peer_clear_soft (peer, afi, safi, stype);
@@ -3041,14 +3032,17 @@ DEFUN (neighbor_activate,
        NEIGHBOR_ADDR_STR2
        "Enable the Address Family for this Neighbor\n")
 {
+  int ret;
   struct peer *peer;
 
   peer = peer_and_group_lookup_vty (vty, argv[0]);
   if (! peer)
     return CMD_WARNING;
 
-  peer_activate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
+  ret = peer_activate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
 
+  if (ret)
+    return CMD_WARNING;
   return CMD_SUCCESS;
 }
 
@@ -3070,7 +3064,9 @@ DEFUN (no_neighbor_activate,
 
   ret = peer_deactivate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
 
-  return bgp_vty_return (vty, ret);
+  if (ret)
+    return CMD_WARNING;
+  return CMD_SUCCESS;
 }
 
 DEFUN (neighbor_set_peer_group,
@@ -3127,8 +3123,7 @@ DEFUN (neighbor_set_peer_group,
       return CMD_WARNING;
     }
 
-  ret = peer_group_bind (bgp, &su, peer, group, bgp_node_afi (vty),
-                        bgp_node_safi (vty), &as);
+  ret = peer_group_bind (bgp, &su, peer, group, &as);
 
   if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT)
     {
@@ -3166,8 +3161,7 @@ DEFUN (no_neighbor_set_peer_group,
       return CMD_WARNING;
     }
 
-  ret = peer_group_unbind (bgp, peer, group, bgp_node_afi (vty),
-                          bgp_node_safi (vty));
+  ret = peer_group_unbind (bgp, peer, group);
 
   return bgp_vty_return (vty, ret);
 }
@@ -8820,7 +8814,7 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi,
       json_prefB = json_object_new_object();
       filter = &p->filter[afi][safi];
 
-      if (p->af_group[afi][safi])
+      if (peer_group_active(p))
         json_object_string_add(json_addr, "peerGroupMember", p->group->name);
 
       paf = peer_af_find(p, afi, safi);
@@ -9000,7 +8994,7 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi,
       vty_out (vty, " For address family: %s%s", afi_safi_print (afi, safi),
               VTY_NEWLINE);
 
-      if (p->af_group[afi][safi])
+      if (peer_group_active(p))
         vty_out (vty, "  %s peer-group member%s", p->group->name, VTY_NEWLINE);
 
       paf = peer_af_find(p, afi, safi);
@@ -12147,14 +12141,19 @@ bgp_vty_init (void)
   install_element (BGP_IPV6M_NODE, &no_neighbor_activate_cmd);
   install_element (BGP_VPNV4_NODE, &no_neighbor_activate_cmd);
 
-  /* "neighbor peer-group set" commands. */
+  /* "neighbor peer-group" set commands.
+   * Long term we should only accept this command under BGP_NODE and not all of
+   * the afi/safi sub-contexts. For now though we need to accept it for backwards
+   * compatibility. This changed when we stopped requiring that peers be assigned
+   * to their peer-group under each address-family sub-context.
+   */
   install_element (BGP_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_IPV4_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_IPV4M_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_IPV6M_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_VPNV4_NODE, &neighbor_set_peer_group_cmd);
-  
+
   /* "no neighbor peer-group unset" commands. */
   install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd);
   install_element (BGP_IPV4_NODE, &no_neighbor_set_peer_group_cmd);
index 0c92532ba0534215948fa08683ec6248ac5b717d..6ab70e630533ca83718fb92a8992ab6efaafe1a0 100644 (file)
@@ -615,13 +615,19 @@ peer_af_create (struct peer *peer, afi_t afi, safi_t safi)
 
   /* Allocate new peer af */
   af = XCALLOC (MTYPE_BGP_PEER_AF, sizeof (struct peer_af));
+
+  if (af == NULL)
+    {
+      zlog_err("Could not create af structure for peer %s", peer->host);
+      return NULL;
+    }
+
   peer->peer_af_array[afid] = af;
   af->afi = afi;
   af->safi = safi;
   af->afid = afid;
   af->peer = peer;
 
-  //update_group_adjust_peer(af);
   return af;
 }
 
@@ -715,7 +721,7 @@ peergroup_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t fl
           g_peer = peer->group->conf;
 
           /* If this flag is not set for the peer's peer-group then return true */
-          if (!peer->af_group[afi][safi] || !peer_af_flag_check (g_peer, afi, safi, flag))
+          if (!peer_af_flag_check (g_peer, afi, safi, flag))
             {
               return 1;
             }
@@ -1418,10 +1424,7 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
   if (afi && safi)
     {
       peer->afc[afi][safi] = 1;
-      if (peer_af_create(peer, afi, safi) == NULL)
-       {
-         zlog_err("couldn't create af structure for peer %s", peer->host);
-       }
+      peer_af_create(peer, afi, safi);
     }
 
   /* Set up peer's events and timers. */
@@ -1645,82 +1648,102 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if,
   return 0;
 }
 
-/* Activate the peer or peer group for specified AFI and SAFI.  */
-int
-peer_activate (struct peer *peer, afi_t afi, safi_t safi)
+static int
+non_peergroup_activate_af (struct peer *peer, afi_t afi, safi_t safi)
 {
   int active;
 
-  if (peer->afc[afi][safi])
-    return 0;
-
-  /* Activate the address family configuration. */
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
-    peer->afc[afi][safi] = 1;
-  else
     {
-      active = peer_active (peer);
+      zlog_err("%s was called for peer-group %s", __func__, peer->host);
+      return 1;
+    }
 
-      peer->afc[afi][safi] = 1;
+  /* Nothing to do if we've already activated this peer */
+  if (peer->afc[afi][safi])
+    return 0;
 
-      if (peer_af_create(peer, afi, safi) == NULL)
-       {
-         zlog_err("couldn't create af structure for peer %s", peer->host);
-       }
+  if (peer_af_create(peer, afi, safi) == NULL)
+    return 1;
 
-      if (! active && peer_active (peer))
-       bgp_timer_set (peer);
-      else
-       {
-         if (peer->status == Established)
-           {
-             if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
-               {
-                 peer->afc_adv[afi][safi] = 1;
-                 bgp_capability_send (peer, afi, safi,
-                                      CAPABILITY_CODE_MP,
-                                      CAPABILITY_ACTION_SET);
-                 if (peer->afc_recv[afi][safi])
-                   {
-                     peer->afc_nego[afi][safi] = 1;
-                     bgp_announce_route (peer, afi, safi);
-                   }
-               }
-             else
-               {
-                 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
-                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
-               }
-           }
-       }
+  active = peer_active (peer);
+  peer->afc[afi][safi] = 1;
+
+  if (!active && peer_active (peer))
+    {
+      bgp_timer_set (peer);
     }
-  return 0;
+  else
+    {
+      if (peer->status == Established)
+        {
+          if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
+            {
+              peer->afc_adv[afi][safi] = 1;
+              bgp_capability_send (peer, afi, safi,
+                                   CAPABILITY_CODE_MP,
+                                   CAPABILITY_ACTION_SET);
+              if (peer->afc_recv[afi][safi])
+                {
+                  peer->afc_nego[afi][safi] = 1;
+                  bgp_announce_route (peer, afi, safi);
+                }
+            }
+          else
+           {
+             peer->last_reset = PEER_DOWN_AF_ACTIVATE;
+             bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                              BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+           }
+        }
+    }
+
+    return 0;
 }
 
+/* Activate the peer or peer group for specified AFI and SAFI.  */
 int
-peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
+peer_activate (struct peer *peer, afi_t afi, safi_t safi)
 {
+  int ret = 0;
   struct peer_group *group;
-  struct peer *peer1;
   struct listnode *node, *nnode;
+  struct peer *tmp_peer;
 
+  /* Nothing to do if we've already activated this peer */
+  if (peer->afc[afi][safi])
+    return ret;
+
+  /* This is a peer-group so activate all of the members of the
+   * peer-group as well */
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
+      peer->afc[afi][safi] = 1;
       group = peer->group;
 
-      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
-       {
-         if (peer1->af_group[afi][safi])
-           return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
-       }
+      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
+        {
+          ret |= non_peergroup_activate_af (tmp_peer, afi, safi);
+        }
     }
   else
     {
-      if (peer->af_group[afi][safi])
-       return BGP_ERR_PEER_BELONGS_TO_GROUP;
+      ret |= non_peergroup_activate_af (peer, afi, safi);
+    }
+
+    return ret;
+}
+
+static int
+non_peergroup_deactivate_af (struct peer *peer, afi_t afi, safi_t safi)
+{
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      zlog_err("%s was called for peer-group %s", __func__, peer->host);
+      return 1;
     }
 
+  /* Nothing to do if we've already deactivated this peer */
   if (! peer->afc[afi][safi])
     return 0;
 
@@ -1730,43 +1753,79 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
   if (peer_af_delete(peer, afi, safi) != 0)
     {
       zlog_err("couldn't delete af structure for peer %s", peer->host);
+      return 1;
     }
 
-  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
-    {  
-      if (peer->status == Established)
-       {
-         if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
-           {
-             peer->afc_adv[afi][safi] = 0;
-             peer->afc_nego[afi][safi] = 0;
+  if (peer->status == Established)
+    {
+      if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
+        {
+          peer->afc_adv[afi][safi] = 0;
+          peer->afc_nego[afi][safi] = 0;
 
-             if (peer_active_nego (peer))
-               {
-                 bgp_capability_send (peer, afi, safi,
-                                      CAPABILITY_CODE_MP,
-                                      CAPABILITY_ACTION_UNSET);
-                 bgp_clear_route (peer, afi, safi);
-                 peer->pcount[afi][safi] = 0;
-               }
-             else
-               {
-                 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
-                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                                  BGP_NOTIFY_CEASE_CONFIG_CHANGE);
-               }
-           }
-         else
+          if (peer_active_nego (peer))
+            {
+              bgp_capability_send (peer, afi, safi,
+                                   CAPABILITY_CODE_MP,
+                                   CAPABILITY_ACTION_UNSET);
+              bgp_clear_route (peer, afi, safi);
+              peer->pcount[afi][safi] = 0;
+            }
+          else
            {
              peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
              bgp_notify_send (peer, BGP_NOTIFY_CEASE,
                               BGP_NOTIFY_CEASE_CONFIG_CHANGE);
            }
-       }
+        }
+      else
+       {
+         peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
+         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+       }
     }
+
   return 0;
 }
 
+int
+peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
+{
+  int ret = 0;
+  struct peer_group *group;
+  struct peer *tmp_peer;
+  struct listnode *node, *nnode;
+
+  /* Nothing to do if we've already de-activated this peer */
+  if (! peer->afc[afi][safi])
+    return ret;
+
+  /* This is a peer-group so de-activate all of the members of the
+   * peer-group as well */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      peer->afc[afi][safi] = 0;
+      group = peer->group;
+
+      if (peer_af_delete(peer, afi, safi) != 0)
+        {
+          zlog_err("couldn't delete af structure for peer %s", peer->host);
+        }
+
+      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
+        {
+          ret |= non_peergroup_deactivate_af (tmp_peer, afi, safi);
+        }
+    }
+  else
+    {
+      ret |= non_peergroup_deactivate_af (peer, afi, safi);
+    }
+
+  return ret;
+}
+
 static void
 peer_nsf_stop (struct peer *peer)
 {
@@ -2466,173 +2525,194 @@ peer_group_listen_range_del (struct peer_group *group, struct prefix *range)
 /* Bind specified peer to peer group.  */
 int
 peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
-                struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
+                struct peer_group *group, as_t *as)
 {
   int first_member = 0;
-
-  /* Check peer group's address family.  */
-  if (! group->conf->afc[afi][safi])
-    return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
+  afi_t afi;
+  safi_t safi;
 
   /* Lookup the peer.  */
   if (!peer)
-    peer = peer_lookup (bgp, su);
+    peer = peer_lookup (bgp, su); 
 
-  /* Create a new peer. */
-  if (peer)
+  /* The peer exist, bind it to the peer-group */
+  if (peer)
     {
-      if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) {
-       return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
-      }
+      /* When the peer already belongs to peer group, check the consistency.  */
+      if (peer_group_active (peer) && strcmp (peer->group->name, group->name) != 0)
+        return BGP_ERR_PEER_GROUP_MISMATCH;
 
-      peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, afi, safi);
-      peer->group = group;
-      peer->af_group[afi][safi] = 1;
+      /* The peer has not specified a remote-as, inherit it from the
+       * peer-group */
+      if (peer->as_type == AS_UNSPECIFIED)
+        {
+          peer->as_type = group->conf->as_type;
+          peer->as = group->conf->as;
+        }
 
-      peer = peer_lock (peer); /* group->peer list reference */
-      listnode_add (group->peer, peer);
-      peer_group2peer_config_copy (group, peer, afi, safi);
-      SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
+      if (! group->conf->as)
+        {
+          if (peer_sort (group->conf) != BGP_PEER_INTERNAL
+              && peer_sort (group->conf) != peer_sort (peer))
+            {
+              if (as)
+                *as = peer->as;
+              return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
+            }
 
-      return 0;
-    }
+          if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
+            first_member = 1;
+        }
 
-  /* When the peer already belongs to peer group, check the consistency.  */
-  if (peer->af_group[afi][safi])
-    {
-      if (strcmp (peer->group->name, group->name) != 0)
-       return BGP_ERR_PEER_GROUP_CANT_CHANGE;
+      for (afi = AFI_IP; afi < AFI_MAX; afi++)
+        for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+          {
+            if (group->conf->afc[afi][safi])
+              {
+                peer->afc[afi][safi] = 1;
 
-      return 0;
-    }
+                if (peer_af_find(peer, afi, safi) || peer_af_create(peer, afi, safi))
+                  {
+                    peer_group2peer_config_copy (group, peer, afi, safi);
+                  }
+              }
+          }
 
-  /* Check current peer group configuration.  */
-  if (peer_group_active (peer)
-      && strcmp (peer->group->name, group->name) != 0)
-    return BGP_ERR_PEER_GROUP_MISMATCH;
+      if (peer->group)
+        {
+          assert (group && peer->group == group);
+        }
+      else
+        {
+          peer->group = group;
 
-  if (peer->as_type == AS_UNSPECIFIED)
-    {
-      peer->as_type = group->conf->as_type;
-      peer->as = group->conf->as;
-    }
+          peer = peer_lock (peer); /* group->peer list reference */
+          listnode_add (group->peer, peer);
+        }
 
-  if (! group->conf->as)
-    {
-      if (peer_sort (group->conf) != BGP_PEER_INTERNAL
-         && peer_sort (group->conf) != peer_sort (peer))
-       {
-         if (as)
-           *as = peer->as;
-         return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
-       }
+      if (first_member)
+        {
+          /* Advertisement-interval reset */
+          if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
+            {
+              if (peer_sort (group->conf) == BGP_PEER_IBGP)
+                group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+              else
+                group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+            }
 
-      if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
-       first_member = 1;
-    }
+          /* ebgp-multihop reset */
+          if (peer_sort (group->conf) == BGP_PEER_IBGP)
+            group->conf->ttl = 255;
 
-  peer->af_group[afi][safi] = 1;
-  peer->afc[afi][safi] = 1;
-  if (!peer_af_find(peer, afi, safi) &&
-      peer_af_create(peer, afi, safi) == NULL)
-    {
-      zlog_err("couldn't create af structure for peer %s", peer->host);
+          /* local-as reset */
+          if (peer_sort (group->conf) != BGP_PEER_EBGP)
+            {
+              group->conf->change_local_as = 0;
+              UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+              UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+            }
+        }
+
+      SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
+
+      if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+        {
+          peer->last_reset = PEER_DOWN_RMAP_BIND;
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+        }
+      else
+        {
+          bgp_session_reset(peer);
+        }
     }
-  if (! peer->group)
+
+  /* Create a new peer. */
+  else
     {
+      if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as))
+        {
+          return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
+        }
+
+      peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0);
       peer->group = group;
-      
+
       peer = peer_lock (peer); /* group->peer list reference */
       listnode_add (group->peer, peer);
-    }
-  else
-    assert (group && peer->group == group);
-
-  if (first_member)
-    {
-      /* Advertisement-interval reset */
-      if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
-       {
-         if (peer_sort (group->conf) == BGP_PEER_IBGP)
-           group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
-         else
-           group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
-       }
 
-      /* ebgp-multihop reset */
-      if (peer_sort (group->conf) == BGP_PEER_IBGP)
-       group->conf->ttl = 255;
-
-      /* local-as reset */
-      if (peer_sort (group->conf) != BGP_PEER_EBGP)
-       {
-         group->conf->change_local_as = 0;
-         UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
-         UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
-       }
-    }
+      /* If the peer-group is active for this afi/safi then activate for this peer */
+      for (afi = AFI_IP; afi < AFI_MAX; afi++)
+        for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+          if (group->conf->afc[afi][safi])
+            {
+              peer->afc[afi][safi] = 1;
+              peer_af_create(peer, afi, safi);
+              peer_group2peer_config_copy (group, peer, afi, safi);
+            }
 
-  peer_group2peer_config_copy (group, peer, afi, safi);
-  SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
+      SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
 
-  if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
-    {
-      peer->last_reset = PEER_DOWN_RMAP_BIND;
-      bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                      BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+     /* Set up peer's events and timers. */
+     if (peer_active (peer))
+       bgp_timer_set (peer);
     }
-  else
-    bgp_session_reset(peer);
 
   return 0;
 }
 
 int
 peer_group_unbind (struct bgp *bgp, struct peer *peer,
-                  struct peer_group *group, afi_t afi, safi_t safi)
+                  struct peer_group *group)
 {
   struct peer *other;
-
-  if (! peer->af_group[afi][safi])
-      return 0;
+  afi_t afi;
+  safi_t safi;
 
   if (group != peer->group)
     return BGP_ERR_PEER_GROUP_MISMATCH;
 
-  peer->af_group[afi][safi] = 0;
-  peer->afc[afi][safi] = 0;
-  peer_af_flag_reset (peer, afi, safi);
-  if (peer_af_delete(peer, afi, safi) != 0)
-    {
-      zlog_err("couldn't delete af structure for peer %s", peer->host);
-    }
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+        if (peer->afc[afi][safi])
+          {
+            peer->afc[afi][safi] = 0;
+            peer_af_flag_reset (peer, afi, safi);
 
-  if (! peer_group_active (peer))
+            if (peer_af_delete(peer, afi, safi) != 0)
+              {
+                zlog_err("couldn't delete af structure for peer %s", peer->host);
+              }
+          }
+      }
+
+  assert (listnode_lookup (group->peer, peer));
+  peer_unlock (peer); /* peer group list reference */
+  listnode_delete (group->peer, peer);
+  peer->group = NULL;
+  other = peer->doppelganger;
+
+  if (group->conf->as)
     {
-      assert (listnode_lookup (group->peer, peer));
-      peer_unlock (peer); /* peer group list reference */
-      listnode_delete (group->peer, peer);
-      peer->group = NULL;
-      other = peer->doppelganger;
-      if (group->conf->as)
-       {
-         peer_delete (peer);
-         if (other && other->status != Deleted)
-           {
-             if (other->group)
-               {
-                 peer_unlock(other);
-                 listnode_delete(group->peer, other);
-               }
-             other->group = NULL;
-             peer_delete(other);
-           }
-         return 0;
-       }
-      bgp_bfd_deregister_peer(peer);
-      peer_global_config_reset (peer);
+      peer_delete (peer);
+      if (other && other->status != Deleted)
+        {
+          if (other->group)
+            {
+              peer_unlock(other);
+              listnode_delete(group->peer, other);
+            }
+          other->group = NULL;
+          peer_delete(other);
+        }
+      return 0;
     }
 
+  bgp_bfd_deregister_peer(peer);
+  peer_global_config_reset (peer);
+
   if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
     {
       peer->last_reset = PEER_DOWN_RMAP_UNBIND;
@@ -3077,13 +3157,11 @@ peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
       {
         if (!group->conf->afc[afi][safi])
           continue;
-        peer->af_group[afi][safi] = 1;
         peer->afc[afi][safi] = 1;
-        if (!peer_af_find(peer, afi, safi) &&
-            peer_af_create(peer, afi, safi) == NULL)
-          {
-            zlog_err("couldn't create af structure for peer %s", peer->host);
-          }
+
+        if (!peer_af_find(peer, afi, safi))
+          peer_af_create(peer, afi, safi);
+
         peer_group2peer_config_copy (group, peer, afi, safi);
       }
 
@@ -3642,9 +3720,6 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
       
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
        {
-         if (! tmp_peer->af_group[afi][safi])
-           continue;
-
          if (set && CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag) == flag)
            continue;
 
@@ -4818,9 +4893,6 @@ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->dlist[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
       filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
@@ -4846,7 +4918,7 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
   filter = &peer->filter[afi][safi];
 
   /* apply peer-group filter */
-  if (peer->af_group[afi][safi])
+  if (peer_group_active(peer))
     {
       gfilter = &peer->group->conf->filter[afi][safi];
 
@@ -4879,9 +4951,6 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-        continue;
-
       if (filter->dlist[direct].name)
         XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
       filter->dlist[direct].name = NULL;
@@ -4983,9 +5052,6 @@ peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->plist[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
       filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
@@ -5010,7 +5076,7 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
   filter = &peer->filter[afi][safi];
 
   /* apply peer-group filter */
-  if (peer->af_group[afi][safi])
+  if (peer_group_active(peer))
     {
       gfilter = &peer->group->conf->filter[afi][safi];
 
@@ -5043,9 +5109,6 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->plist[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
       filter->plist[direct].name = NULL;
@@ -5147,9 +5210,6 @@ peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->aslist[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
       filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
@@ -5174,7 +5234,7 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
   filter = &peer->filter[afi][safi];
 
   /* apply peer-group filter */
-  if (peer->af_group[afi][safi])
+  if (peer_group_active(peer))
     {
       gfilter = &peer->group->conf->filter[afi][safi];
 
@@ -5207,9 +5267,6 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->aslist[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
       filter->aslist[direct].name = NULL;
@@ -5322,9 +5379,6 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->map[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
       filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
@@ -5350,7 +5404,7 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
   filter = &peer->filter[afi][safi];
 
   /* apply peer-group filter */
-  if (peer->af_group[afi][safi])
+  if (peer_group_active(peer))
     {
       gfilter = &peer->group->conf->filter[afi][safi];
 
@@ -5383,9 +5437,6 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->map[direct].name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
       filter->map[direct].name = NULL;
@@ -5424,9 +5475,6 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->usmap.name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
       filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
@@ -5462,9 +5510,6 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
     {
       filter = &peer->filter[afi][safi];
 
-      if (! peer->af_group[afi][safi])
-       continue;
-
       if (filter->usmap.name)
        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
       filter->usmap.name = NULL;
@@ -5496,9 +5541,6 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
       group = peer->group;
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
        {
-         if (! peer->af_group[afi][safi])
-           continue;
-
          SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
          peer->pmax[afi][safi] = max;
          peer->pmax_threshold[afi][safi] = threshold;
@@ -5528,7 +5570,7 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
   struct listnode *node, *nnode;
 
   /* apply peer-group config */
-  if (peer->af_group[afi][safi])
+  if (peer_group_active(peer))
     {
       if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
          PEER_FLAG_MAX_PREFIX))
@@ -5560,9 +5602,6 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
   group = peer->group;
   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
     {
-      if (! peer->af_group[afi][safi])
-       continue;
-
       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;
@@ -5991,7 +6030,8 @@ bgp_config_write_filter (struct vty *vty, struct peer *peer,
 
   addr = peer->host;
   filter = &peer->filter[afi][safi];
-  if (peer->af_group[afi][safi])
+
+  if (peer_group_active(peer))
     gfilter = &peer->group->conf->filter[afi][safi];
 
   /* distribute-list. */
@@ -6089,9 +6129,6 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
   else
     addr = peer->host;
 
-  if (peer_group_active (peer))
-    g_peer = peer->group->conf;
-
   /************************************
    ****** Global to the neighbor ******
    ************************************/
@@ -6103,31 +6140,12 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
         vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
     }
 
-  /* remote-as */
-  if (! peer_group_active (peer))
+  /* remote-as and peer-group */
+  /* peer is a member of a peer-group */
+  if (peer_group_active (peer))
     {
-      if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
-        {
-          vty_out (vty, " neighbor %s peer-group%s", addr,
-                   VTY_NEWLINE);
-        }
+      g_peer = peer->group->conf;
 
-      if (peer->as_type == AS_SPECIFIED)
-       {
-             vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
-                      VTY_NEWLINE);
-       }
-      else if (peer->as_type == AS_INTERNAL)
-       {
-             vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
-       }
-      else if (peer->as_type == AS_EXTERNAL)
-       {
-             vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
-       }
-    }
-  else
-    {
       if (g_peer->as_type == AS_UNSPECIFIED)
         {
           if (peer->as_type == AS_SPECIFIED)
@@ -6144,10 +6162,33 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
               vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
             }
         }
-      if (peer->af_group[AFI_IP][SAFI_UNICAST])
+
+      vty_out (vty, " neighbor %s peer-group %s%s", addr,
+               peer->group->name, VTY_NEWLINE);
+    }
+
+  /* peer is NOT a member of a peer-group */
+  else
+    {
+      /* peer is a peer-group, declare the peer-group */
+      if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+        {
+          vty_out (vty, " neighbor %s peer-group%s", addr,
+                   VTY_NEWLINE);
+        }
+
+      if (peer->as_type == AS_SPECIFIED)
+        {
+          vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
+                   VTY_NEWLINE);
+        }
+      else if (peer->as_type == AS_INTERNAL)
         {
-          vty_out (vty, " neighbor %s peer-group %s%s", addr,
-                   peer->group->name, VTY_NEWLINE);
+          vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
+        }
+      else if (peer->as_type == AS_EXTERNAL)
+        {
+          vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
         }
     }
 
@@ -6402,32 +6443,53 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
   else
     addr = peer->host;
 
-  if (peer_group_active (peer))
-    g_peer = peer->group->conf;
-
   /************************************
    ****** Per AF to the neighbor ******
    ************************************/
-  if (peer->af_group[afi][safi])
+  if (peer_group_active (peer))
     {
-      afi_header_vty_out (vty, afi, safi, write,
-                          "  neighbor %s peer-group %s%s", addr,
-                          peer->group->name, VTY_NEWLINE);
+      g_peer = peer->group->conf;
+
+      /* If the peer-group is active but peer is not, print a 'no activate' */
+      if (g_peer->afc[afi][safi] && !peer->afc[afi][safi])
+        {
+          afi_header_vty_out (vty, afi, safi, write,
+                              "  no neighbor %s activate%s",
+                              addr, VTY_NEWLINE);
+        }
+
+      /* If the peer-group is not active but peer is, print an 'activate' */
+      else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi])
+        {
+          afi_header_vty_out (vty, afi, safi, write,
+                              "  neighbor %s activate%s",
+                              addr, VTY_NEWLINE);
+        }
     }
   else
-    if (peer->afc[afi][safi])
-      {
-        afi_header_vty_out (vty, afi, safi, write,
-                            "  neighbor %s activate%s",
-                            addr, VTY_NEWLINE);
-      }
+    {
+      if (peer->afc[afi][safi])
+        {
+          afi_header_vty_out (vty, afi, safi, write,
+                              "  neighbor %s activate%s",
+                              addr, VTY_NEWLINE);
+        }
+    }
 
   /* addpath TX knobs */
   if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS))
-    vty_out (vty, "  neighbor %s addpath-tx-all-paths%s", addr, VTY_NEWLINE);
+    {
+      afi_header_vty_out (vty, afi, safi, write,
+                          "  neighbor %s addpath-tx-all-paths%s",
+                          addr, VTY_NEWLINE);
+    }
 
   if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
-    vty_out (vty, "  neighbor %s addpath-tx-bestpath-per-AS%s", addr, VTY_NEWLINE);
+    {
+      afi_header_vty_out (vty, afi, safi, write,
+                          "  neighbor %s addpath-tx-bestpath-per-AS%s",
+                          addr, VTY_NEWLINE);
+    }
 
   /* ORF capability.  */
   if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
@@ -6583,7 +6645,7 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
 
   /* maximum-prefix. */
   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
-    if (! peer->af_group[afi][safi]
+    if (! peer_group_active(peer)
        || 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)
index f64866aed538aa0b47d1749d36ecdcce9fddff89..8256d2a8932c404dce4347c7b3732adfe1b514e1 100644 (file)
@@ -476,7 +476,6 @@ struct peer
 
   /* BGP peer group.  */
   struct peer_group *group;
-  u_char af_group[AFI_MAX][SAFI_MAX];
   u_int64_t version[AFI_MAX][SAFI_MAX];
 
   /* BGP peer_af structures, per configured AF on this peer */
@@ -1054,36 +1053,33 @@ enum bgp_clear_type
 #define BGP_ERR_INVALID_BGP                      -4
 #define BGP_ERR_PEER_GROUP_MEMBER                -5
 #define BGP_ERR_MULTIPLE_INSTANCE_USED           -6
-#define BGP_ERR_PEER_GROUP_MEMBER_EXISTS         -7
-#define BGP_ERR_PEER_BELONGS_TO_GROUP            -8
-#define BGP_ERR_PEER_GROUP_AF_UNCONFIGURED       -9
-#define BGP_ERR_PEER_GROUP_NO_REMOTE_AS         -10
-#define BGP_ERR_PEER_GROUP_CANT_CHANGE          -11
-#define BGP_ERR_PEER_GROUP_MISMATCH             -12
-#define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT  -13
-#define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET       -14
-#define BGP_ERR_AS_MISMATCH                     -15
-#define BGP_ERR_PEER_FLAG_CONFLICT              -16
-#define BGP_ERR_PEER_GROUP_SHUTDOWN             -17
-#define BGP_ERR_PEER_FILTER_CONFLICT            -18
-#define BGP_ERR_NOT_INTERNAL_PEER               -19
-#define BGP_ERR_REMOVE_PRIVATE_AS               -20
-#define BGP_ERR_AF_UNCONFIGURED                 -21
-#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED      -22
-#define BGP_ERR_INSTANCE_MISMATCH               -23
-#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP  -24
-#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS    -25
-#define BGP_ERR_TCPSIG_FAILED                  -26
-#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK  -27
-#define BGP_ERR_NO_IBGP_WITH_TTLHACK           -28
-#define BGP_ERR_NO_INTERFACE_CONFIG             -29
-#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -30
-#define BGP_ERR_AS_OVERRIDE                     -31
-#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -32
-#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS  -33
-#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -34
-#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER        -35
-#define BGP_ERR_MAX                             -36
+#define BGP_ERR_PEER_GROUP_NO_REMOTE_AS          -7
+#define BGP_ERR_PEER_GROUP_CANT_CHANGE           -8
+#define BGP_ERR_PEER_GROUP_MISMATCH              -9
+#define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT  -10
+#define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET       -11
+#define BGP_ERR_AS_MISMATCH                     -12
+#define BGP_ERR_PEER_FLAG_CONFLICT              -13
+#define BGP_ERR_PEER_GROUP_SHUTDOWN             -14
+#define BGP_ERR_PEER_FILTER_CONFLICT            -15
+#define BGP_ERR_NOT_INTERNAL_PEER               -16
+#define BGP_ERR_REMOVE_PRIVATE_AS               -17
+#define BGP_ERR_AF_UNCONFIGURED                 -18
+#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED      -19
+#define BGP_ERR_INSTANCE_MISMATCH               -20
+#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP  -21
+#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS    -22
+#define BGP_ERR_TCPSIG_FAILED                  -23
+#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK  -24
+#define BGP_ERR_NO_IBGP_WITH_TTLHACK           -25
+#define BGP_ERR_NO_INTERFACE_CONFIG             -26
+#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -27
+#define BGP_ERR_AS_OVERRIDE                     -28
+#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -29
+#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS  -30
+#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -31
+#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER        -32
+#define BGP_ERR_MAX                             -33
 
 /*
  * Enumeration of different policy kinds a peer can be configured with.
@@ -1208,9 +1204,8 @@ extern int peer_activate (struct peer *, afi_t, safi_t);
 extern int peer_deactivate (struct peer *, afi_t, safi_t);
 
 extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *,
-                            struct peer_group *, afi_t, safi_t, as_t *);
-extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *,
-                      afi_t, safi_t);
+                            struct peer_group *, as_t *);
+extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *);
 
 extern int peer_flag_set (struct peer *, u_int32_t);
 extern int peer_flag_unset (struct peer *, u_int32_t);
@@ -1339,15 +1334,11 @@ afindex (afi_t afi, safi_t safi)
     }
 }
 
-/* If peer is configured at least one address family return 1. */
+/* If the peer is not a peer-group but is bound to a peer-group return 1 */
 static inline int
 peer_group_active (struct peer *peer)
 {
-  if (peer->af_group[AFI_IP][SAFI_UNICAST]
-      || peer->af_group[AFI_IP][SAFI_MULTICAST]
-      || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
-      || peer->af_group[AFI_IP6][SAFI_UNICAST]
-      || peer->af_group[AFI_IP6][SAFI_MULTICAST])
+  if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) && peer->group)
     return 1;
   return 0;
 }