[prev in list] [next in list] [prev in thread] [next in thread] 

List:       quagga-dev
Subject:    [quagga-dev 10997] [PATCH] bgpd: Dynamic Neighbors feature
From:       Paul Noll <pn6490 () att ! com>
Date:       2014-01-22 13:13:30
Message-ID: 477B4D6812C5F240B4F2049D9B79954618CA2C99D0 () exc-aus-0001
[Download RAW message or body]

Hello

Sorry if this is appearing twice. I tried this message yesterday from a dif=
ferent e-mail address but it doesn't appear to have worked.

Please see the attached patch for an implementation of the Cisco IOS Dynami=
c Neighbors feature (http://www.cisco.com/en/US/docs/ios/iproute_bgp/config=
uration/guide/irg_neighbor.html#wp1054174).

All testing has been on Debian.

Thanks,
Paul

["bgpd_dynamic_neighbor.patch" (application/octet-stream)]

From ff9c4e3d26d9e7920bc71f2756ed3b2c291dc27a Mon Sep 17 00:00:00 2001
From: Paul Noll <pn6490@att.com>
Date: Tue, 17 Dec 2013 18:12:16 -0600
Subject: [PATCH]     bgpd: Support for Cisco's BGP Dynamic Neighbors feature

    This features allows BGP peering within ranges of IPv4 addresses
    assigned to a peer group. When a remote peer initiates a TCP
    session from an address within a range, a BGP neighbor is
    dynamically created as a neighbor of that group.

       neighbor <WORD> peer-group
       bgp listen range <A.B.C.D/M> peer-group <WORD>

    The maximum number of dynamic neighbors for a BGP instance defaults
    to 100. The current number of dynamic neighbors is incremented
    when a new BGP session is established and decremented when a
    session is terminated. The limit can be increased via the
    "listen limit" command:

      router bgp <ASN>
       bgp listen limit <1-5000>

    To reset the limit back to the default value:

       no bgp listen limit

    The output of the following is modified to align with
    with Cisco's extensions for this feature:

       show ip bgp summary
       show ip bgp neighbors [PEER]

    An implementation is provided for showing peer group(s), along
    with Cisco's extensions for this feature:

       show ip bgp peer-group [WORD]

    * bgpd/bgpd.h
      * struct bgp: add int dynamic_neighbors_limit and
        dynamic_neighbors_count
      * struct peer_group: add list listen_range
      * struct peer: define PEER_FLAG_DYNAMIC_NEIGHBOR for af_flags
      * Add BGP_DYNAMIC_NEIGHBORS_LIMIT_MIN and
        BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX
      * Add BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT and
        BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS
      * Reset BGP_ERR_MAX to be true maximum and adjust
        BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS accordingly
      * Add externs for new methods (see bgpd.c)
    * bgpd/bgpd.c
      * Add methods:
        * bgp_listen_limit_set()
        * bgp_listen_limit_unset()
        * peer_drop_dynamic_neighbor()
        * peer_dynamic_neighbor()
        * peer_dynamic_neighbor_family()
        * peer_group_listen_range_add()
        * peer_group_lookup_dynamic_neighbor()
        * peer_group_lookup_dynamic_neighbor_range()
        * peer_lookup_dynamic_neighbor()
      * peer_delete(): drop a dynamic neighbor if applicable
      * peer_group_get(): initialize listen_range to empty list
      * peer_group_delete(): free listen_range nodes
      * bgp_create(): initialize dynamic_neighbors_limit
        and dynamic_neighbors_count
    * bgpd/bgp_network.c
      * bgp_accept(): When regular peer lookup fails, create a
        dynamic neighbor if applicable
    * bgpd/bgp_fsm.c
      * bgp_stop_with_error(): clean up a peer dynamic neighbor
      * bgp_stop_with_notify(): clean up a peer dynamic neighbor
      * bgp_connect_fail(): clean up a peer dynamic neighbor
    * bgpd/bgp_vty.h
      * Define DYNAMIC_NEIGHBOR_LIMIT_RANGE
    * bgpd/bgp_vty.c
      * Add DEFUNs:
        * bgp_listen_limit
        * bgp_listen_range
        * no_bgp_listen_limit
        * show_ip_bgp_instance_peer_group
        * show_ip_bgp_instance_peer_groups
        * show_ip_bgp_peer_group
        * show_ip_bgp_peer_groups
      * Add methods:
        * bgp_show_one_peer_group()
        * bgp_show_one_peer_group_members()
        * bgp_show_peer_group()
        * bgp_show_peer_group_vty()
        * bgp_show_summary_dynamic_neighbors()
      * Add enum show_group_type
      * bgp_vty_return(): Add cases for
        BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT and
        BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS
      * bgp_show_summary(): Extra output for dynamic neighbors
      * bgp_show_peer(): Extra output if dynamic neighbor
      * bgp_vty_init(): install elements for new DEFUNs
    * doc/bgpd.texi
      * Add section BGP Dynamic Neighbor Limit
      * Add subsection BGP Listening Range to BGP Peer Group
      * Add definition for show ip bgp summary
      * Add definition for show ip bgp neighbors
      * Add defintion for new command show ip bgp peer-group
---
 bgpd/bgp_fsm.c     |   22 +++
 bgpd/bgp_network.c |    4 +
 bgpd/bgp_vty.c     |  394 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 bgpd/bgp_vty.h     |    1 +
 bgpd/bgpd.c        |  206 +++++++++++++++++++++++++++
 bgpd/bgpd.h        |   34 +++++-
 doc/bgpd.texi      |  150 ++++++++++++++++++++-
 7 files changed, 802 insertions(+), 9 deletions(-)

diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index fba9427..360942f 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -587,6 +587,13 @@ bgp_stop_with_error (struct peer *peer)
   if (peer->v_start >= (60 * 2))
     peer->v_start = (60 * 2);
 
+  if (peer_dynamic_neighbor(peer))
+    {
+      zlog_info ("%s [Event] BGP dynamic neighbor is deleted", peer->host);
+      peer_delete (peer);
+      return -1;
+    }
+
   bgp_stop (peer);
 
   return 0;
@@ -608,6 +615,14 @@ bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code)
       return -1;
     }
 
+  /* Clean up a dynamic neighbor */
+  if (peer_dynamic_neighbor(peer))
+    {
+      zlog_info ("%s [Event] BGP dynamic neighbor is deleted", peer->host);
+      peer_delete (peer);
+      return -1;
+    }
+
   /* Clear start timer value to default. */
   peer->v_start = BGP_INIT_START_TIMER;
 
@@ -655,6 +670,13 @@ bgp_connect_success (struct peer *peer)
 static int
 bgp_connect_fail (struct peer *peer)
 {
+  if (peer_dynamic_neighbor(peer))
+    {
+      zlog_info ("%s [Event] BGP dynamic neighbor is deleted", peer->host);
+      peer_delete (peer);
+      return -1;
+    }
+
   bgp_stop (peer);
   return 0;
 }
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 79d5d27..6f3142c 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -158,6 +158,10 @@ bgp_accept (struct thread *thread)
   
   /* Check remote IP address */
   peer1 = peer_lookup (NULL, &su);
+
+  if (! peer1)
+    peer1 = peer_lookup_dynamic_neighbor (NULL, &su);
+
   if (! peer1 || peer1->status == Idle)
     {
       if (BGP_DEBUG (events, EVENTS))
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 0f28894..d27f071 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -220,6 +220,12 @@ bgp_vty_return (struct vty *vty, int ret)
     case BGP_ERR_NO_IBGP_WITH_TTLHACK:
       str = "ttl-security only allowed for EBGP peers";
       break;
+    case BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT:
+      str = "Invalid limit for number of dynamic neighbors";
+      break;
+    case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS:
+      str = "Dynamic neighbor listen range already exists";
+      break;
     }
   if (str)
     {
@@ -1390,6 +1396,68 @@ ALIAS (no_bgp_default_local_preference,
        "local preference (higher=more preferred)\n"
        "Configure default local preference value\n")
 
+DEFUN (bgp_listen_limit,
+       bgp_listen_limit_cmd,
+       "bgp listen limit " DYNAMIC_NEIGHBOR_LIMIT_RANGE,
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "maximum number of BGP Dynamic Neighbors that can be created\n"
+       "Configure Dynamic Neighbors listen limit value\n")
+{
+  struct bgp *bgp;
+  int listen_limit;
+
+  bgp = vty->index;
+
+  VTY_GET_INTEGER_RANGE ("listen limit", listen_limit, argv[0],
+                         BGP_DYNAMIC_NEIGHBORS_LIMIT_MIN,
+                         BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX);
+
+  bgp_listen_limit_set (bgp, listen_limit);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_listen_limit,
+       no_bgp_listen_limit_cmd,
+       "no bgp listen limit",
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "unset maximum number of BGP Dynamic Neighbors that can be created\n"
+       "Configure Dynamic Neighbors listen limit value to default\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_listen_limit_unset (bgp);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_listen_range,
+       bgp_listen_range_cmd,
+       "bgp listen range A.B.C.D/M peer-group WORD" ,
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "add a listening range for Dynamic Neighbors\n"
+       "Configure Dynamic Neighbors listening range\n")
+{
+  struct bgp *bgp;
+  struct prefix_ipv4 range;
+  struct peer_group *group;
+
+  bgp = vty->index;
+
+  VTY_GET_IPV4_PREFIX ("listen range", range, argv[0]);
+
+  group = peer_group_lookup (bgp, argv[1]);
+  if (! group)
+    return CMD_WARNING;
+
+  peer_group_listen_range_add(group, (struct prefix *)&range);
+
+  return CMD_SUCCESS;
+}
+
 static int
 peer_remote_as_vty (struct vty *vty, const char *peer_str, 
                     const char *as_str, afi_t afi, safi_t safi)
@@ -6889,14 +6957,53 @@ DEFUN (show_bgp_memory,
   return CMD_SUCCESS;
 }
 
+/* Show BGP dynamic neighbor summary information. */
+static int
+bgp_show_summary_dynamic_neighbors (struct vty *vty, struct bgp *bgp)
+{
+  int sr_count = 0;
+  struct peer_group *group;
+  struct prefix *range;
+  struct listnode *node, *nnode, *rnode, *nrnode;
+  char buf[128];
+
+  for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+    {
+      if (group->listen_range)
+        sr_count += listcount(group->listen_range);
+    }
+
+  vty_out(vty,
+          "Dynamically created neighbors: %d/(%d max), Subnet ranges: %d%s",
+          bgp->dynamic_neighbors_count, bgp->dynamic_neighbors_limit, sr_count,
+          VTY_NEWLINE);
+
+  for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+    {
+      if (group->listen_range)
+        {
+          vty_out(vty, "BGP peergroup %s listen range group members:%s",
+                  group->name, VTY_NEWLINE);
+
+          for (ALL_LIST_ELEMENTS (group->listen_range, rnode, nrnode,
+                                  range))
+            {
+              prefix2str(range, buf, sizeof(buf));
+              vty_out(vty, "  %s%s", buf, VTY_NEWLINE);
+            }
+        }
+    }
+  return CMD_SUCCESS;
+}
+
 /* Show BGP peer's summary information. */
 static int
 bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
 {
   struct peer *peer;
   struct listnode *node, *nnode;
-  unsigned int count = 0;
-  char timebuf[BGP_UPTIME_LEN];
+  unsigned int count = 0, dn_count = 0;
+  char timebuf[BGP_UPTIME_LEN], dn_flag[2];
   int len;
 
   /* Header string for each address family. */
@@ -6951,7 +7058,14 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
           
 	  count++;
 
-	  len = vty_out (vty, "%s", peer->host);
+      memset(dn_flag, '\0', sizeof(dn_flag));
+      if (peer_dynamic_neighbor_family(peer, afi, safi))
+        {
+          dn_count++;
+          dn_flag[0] = '*';
+        }
+
+      len = vty_out (vty, "%s%s", dn_flag, peer->host);
 	  len = 16 - len;
 	  if (len < 1)
 	    vty_out (vty, "%s%*s", VTY_NEWLINE, 16, " ");
@@ -6996,6 +7110,13 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
   else
     vty_out (vty, "No %s neighbor is configured%s",
 	     afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
+
+  if (dn_count)
+    {
+      vty_out(vty, "* Dynamically created based on a listen range command%s",
+              VTY_NEWLINE);
+      bgp_show_summary_dynamic_neighbors (vty, bgp);
+    }
   return CMD_SUCCESS;
 }
 
@@ -7519,13 +7640,18 @@ bgp_show_peer (struct vty *vty, struct peer *p)
   struct bgp *bgp;
   char buf1[BUFSIZ];
   char timebuf[BGP_UPTIME_LEN];
+  char dn_flag[2];
   afi_t afi;
   safi_t safi;
 
   bgp = p->bgp;
 
   /* Configured IP address. */
-  vty_out (vty, "BGP neighbor is %s, ", p->host);
+  memset(dn_flag, '\0', sizeof(dn_flag));
+  if (peer_dynamic_neighbor(p))
+    dn_flag[0] = '*';
+
+  vty_out (vty, "BGP neighbor is %s%s, ", dn_flag, p->host);
   vty_out (vty, "remote AS %u, ", p->as);
   vty_out (vty, "local AS %u%s%s, ",
 	   p->change_local_as ? p->change_local_as : p->local_as,
@@ -7543,8 +7669,26 @@ bgp_show_peer (struct vty *vty, struct peer *p)
   
   /* Peer-group */
   if (p->group)
-    vty_out (vty, " Member of peer-group %s for session parameters%s",
-	     p->group->name, VTY_NEWLINE);
+    {
+      vty_out (vty, " Member of peer-group %s for session parameters%s",
+               p->group->name, VTY_NEWLINE);
+
+      if (dn_flag[0])
+        {
+          struct prefix *prefix = NULL, *range = NULL;
+
+          prefix = sockunion2hostprefix(&(p->su));
+          if (prefix)
+            range = peer_group_lookup_dynamic_neighbor_range (p->group,
+                                                              prefix);
+          if (range)
+            {
+              prefix2str(range, buf1, sizeof(buf1));
+              vty_out (vty, " Belongs to the subnet range group: %s%s",
+                       buf1, VTY_NEWLINE);
+            }
+        }
+    }
 
   /* Administrative shutdown. */
   if (CHECK_FLAG (p->flags, PEER_FLAG_SHUTDOWN))
@@ -8548,6 +8692,231 @@ ALIAS (show_bgp_instance_ipv6_safi_rsclient_summary,
 
 #endif /* HAVE IPV6 */
 
+static int
+bgp_show_one_peer_group_members (struct vty *vty, struct peer_group *group,
+                                 int range_count, afi_t afi, safi_t safi)
+{
+  struct listnode *node, *nnode;
+  struct peer *peer;
+  char member[64], fmt[5];
+  int len = 2, width;
+
+  /* Allow 17 characters for an IPv4 addresses and 41 for IPv6 */
+  if (AFI_IP == afi)
+    {
+      width = 17;
+      strcpy(fmt, "%17s");
+    }
+  else
+    {
+      width = 41;
+      strcpy(fmt, "%41s");
+    }
+
+  vty_out (vty, " For address family: %s%s", afi_safi_print (afi, safi),
+           VTY_NEWLINE);
+
+  if (! range_count)
+    vty_out (vty, "  BGP neighbor is %s, peer-group internal, members:%s  ",
+             group->name, VTY_NEWLINE);
+  else
+    vty_out (vty, "  BGP neighbor is %s, peer-group external, members:%s  ",
+             group->name, VTY_NEWLINE);
+
+  for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+    if (peer->af_group[afi][safi])
+      {
+        if ((80 - len) < width)
+          {
+            vty_out (vty, "%s  ", VTY_NEWLINE);
+            len = 2;
+          }
+
+        memset(member, '\0', sizeof(member));
+        if (peer_dynamic_neighbor_family(peer, afi, safi))
+          {
+            member[0] = '*';
+            strncpy(&member[1], peer->host, sizeof(member));
+          }
+        else
+          strncpy(member, peer->host, sizeof(member));
+
+        len += vty_out (vty, fmt, member);
+      }
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+static int
+bgp_show_one_peer_group (struct vty *vty, struct peer_group *group)
+{
+  struct listnode *node, *nnode;
+  struct prefix *range;
+  struct peer *conf;
+  char buf[128];
+  int range_count = 0;
+  afi_t afi;
+  safi_t safi;
+
+  conf = group->conf;
+
+  vty_out (vty, "%sBGP peer-group is %s,  remote AS %d%s",
+           VTY_NEWLINE, group->name, (conf ? conf->as : 0), VTY_NEWLINE);
+
+  if (group->listen_range)
+    {
+      range_count = listcount(group->listen_range);
+
+      if (range_count)
+        {
+          vty_out (vty, "  BGP peergroup %s listen range group members:%s",
+                   group->name, VTY_NEWLINE);
+
+          for (ALL_LIST_ELEMENTS (group->listen_range, node, nnode, range))
+            {
+              prefix2str(range, buf, sizeof(buf));
+              vty_out (vty, "  %s%s", buf, VTY_NEWLINE);
+            }
+        }
+    }
+
+  vty_out (vty, "  BGP version 4%s", VTY_NEWLINE);
+
+  if (! range_count)
+      vty_out (vty,
+               "  Minimum time between advertisement runs is %d seconds%s",
+               (conf ? conf->v_routeadv : 0), VTY_NEWLINE);
+  else
+      vty_out (vty,
+           "  Default minimum time between advertisement runs is %d seconds%s",
+               (conf ? conf->v_routeadv : 0), VTY_NEWLINE);
+
+  if (conf)
+    {
+      for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+        for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+          if (conf->af_group[afi][safi])
+            bgp_show_one_peer_group_members(vty, group, range_count, afi,
+                                            safi);
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Show BGP peer group's information. */
+enum show_group_type
+{
+  show_all_groups,
+  show_peer_group
+};
+
+static int
+bgp_show_peer_group (struct vty *vty, struct bgp *bgp,
+                     enum show_group_type type, const char *group_name)
+{
+  struct listnode *node, *nnode;
+  struct peer_group *group;
+  int find = 0;
+
+  for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+    {
+      switch (type)
+	{
+	case show_all_groups:
+	  bgp_show_one_peer_group (vty, group);
+	  break;
+	case show_peer_group:
+          if (group_name && (strcmp(group->name, group_name) == 0))
+            {
+              find = 1;
+              bgp_show_one_peer_group (vty, group);
+	    }
+	  break;
+	}
+    }
+
+  if (type == show_peer_group && ! find)
+    vty_out (vty, "%% No such peer-groupr%s", VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+static int
+bgp_show_peer_group_vty (struct vty *vty, const char *name,
+                         enum show_group_type type, const char *group_name)
+{
+  struct bgp *bgp;
+  int ret = CMD_SUCCESS;
+
+  if (name)
+    {
+      bgp = bgp_lookup_by_name (name);
+
+      if (! bgp)
+        {
+          vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+
+  bgp = bgp_get_default ();
+
+  if (bgp)
+    ret = bgp_show_peer_group (vty, bgp, type, group_name);
+
+  return ret;
+}
+
+DEFUN (show_ip_bgp_peer_groups,
+       show_ip_bgp_peer_groups_cmd,
+       "show ip bgp peer-group",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on all BGP peer groups\n")
+{
+  return bgp_show_peer_group_vty (vty, NULL, show_all_groups, NULL);
+}
+
+DEFUN (show_ip_bgp_instance_peer_groups,
+       show_ip_bgp_instance_peer_groups_cmd,
+       "show ip bgp view WORD peer-group",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP View\n"
+       "Detailed information on all BGP peer groups\n")
+{
+  return bgp_show_peer_group_vty (vty, argv[0], show_all_groups, NULL);
+}
+
+DEFUN (show_ip_bgp_peer_group,
+       show_ip_bgp_peer_group_cmd,
+       "show ip bgp peer-group WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP peer-group name\n"
+       "Detailed information on a BGP peer group\n")
+{
+  return bgp_show_peer_group_vty (vty, NULL, show_peer_group, argv[0]);
+}
+
+DEFUN (show_ip_bgp_instance_peer_group,
+       show_ip_bgp_instance_peer_group_cmd,
+       "show ip bgp view WORD peer-group WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP View\n"
+       "BGP peer-group name\n"
+       "Detailed information on a BGP peer group\n")
+{
+  return bgp_show_peer_group_vty (vty, argv[0], show_peer_group, argv[1]);
+}
+
 /* Redistribute VTY commands.  */
 
 DEFUN (bgp_redistribute_ipv4,
@@ -9197,6 +9566,13 @@ bgp_vty_init (void)
   install_element (BGP_NODE, &no_bgp_default_local_preference_cmd);
   install_element (BGP_NODE, &no_bgp_default_local_preference_val_cmd);
 
+  /* "bgp listen limit" commands. */
+  install_element (BGP_NODE, &bgp_listen_limit_cmd);
+  install_element (BGP_NODE, &no_bgp_listen_limit_cmd);
+
+  /* "bgp listen range" commands. */
+  install_element (BGP_NODE, &bgp_listen_range_cmd);
+
   /* "neighbor remote-as" commands. */
   install_element (BGP_NODE, &neighbor_remote_as_cmd);
   install_element (BGP_NODE, &no_neighbor_cmd);
@@ -10093,6 +10469,12 @@ bgp_vty_init (void)
   install_element (ENABLE_NODE, &show_ipv6_mbgp_summary_cmd);
 #endif /* HAVE_IPV6 */
 
+  /* "show ip bgp peer-group" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_peer_groups_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_peer_groups_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_peer_group_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_peer_group_cmd);
+
   /* "show ip bgp rsclient" commands. */
   install_element (VIEW_NODE, &show_ip_bgp_rsclient_summary_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_instance_rsclient_summary_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 2df8aaa..fc9b5b3 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -22,6 +22,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #define _QUAGGA_BGP_VTY_H
 
 #define CMD_AS_RANGE "<1-4294967295>"
+#define DYNAMIC_NEIGHBOR_LIMIT_RANGE "<1-5000>"
 
 extern void bgp_vty_init (void);
 extern const char *afi_safi_print (afi_t, safi_t);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index c9a04ff..bf86c02 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -509,6 +509,29 @@ bgp_default_local_preference_unset (struct bgp *bgp)
   return 0;
 }
 
+/* Listen limit configuration.  */
+int
+bgp_listen_limit_set (struct bgp *bgp, int listen_limit)
+{
+  if (! bgp)
+    return -1;
+
+  bgp->dynamic_neighbors_limit = listen_limit;
+
+  return 0;
+}
+
+int
+bgp_listen_limit_unset (struct bgp *bgp)
+{
+  if (! bgp)
+    return -1;
+
+  bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
+
+  return 0;
+}
+
 /* If peer is RSERVER_CLIENT in at least one address family and is not member
     of a peer_group for that family, return 1.
     Used to check wether the peer is included in list bgp->rsclient. */
@@ -1208,6 +1231,9 @@ peer_delete (struct peer *peer)
      relationship.  */
   if (peer->group)
     {
+      if (peer_dynamic_neighbor(peer))
+        peer_drop_dynamic_neighbor(peer);
+
       if ((pn = listnode_lookup (peer->group->peer, peer)))
         {
           peer = peer_unlock (peer); /* group->peer list reference */
@@ -1383,6 +1409,7 @@ peer_group_get (struct bgp *bgp, const char *name)
   group->bgp = bgp;
   group->name = strdup (name);
   group->peer = list_new ();
+  group->listen_range = list_new ();
   group->conf = peer_new (bgp);
   if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
     group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
@@ -1691,6 +1718,7 @@ peer_group_delete (struct peer_group *group)
 {
   struct bgp *bgp;
   struct peer *peer;
+  struct prefix *prefix;
   struct listnode *node, *nnode;
 
   bgp = group->bgp;
@@ -1702,6 +1730,12 @@ peer_group_delete (struct peer_group *group)
     }
   list_delete (group->peer);
 
+  for (ALL_LIST_ELEMENTS (group->listen_range, node, nnode, prefix))
+    {
+      prefix_free(prefix);
+    }
+  list_delete (group->listen_range);
+
   free (group->name);
   group->name = NULL;
 
@@ -1737,6 +1771,25 @@ peer_group_remote_as_delete (struct peer_group *group)
   return 0;
 }
 
+int
+peer_group_listen_range_add (struct peer_group *group, struct prefix *range)
+{
+  struct prefix *prefix;
+  struct listnode *node, *nnode;
+
+  for (ALL_LIST_ELEMENTS (group->listen_range, node, nnode, prefix))
+    {
+      if (prefix_same(range, prefix))
+        return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS;
+    }
+
+  prefix = prefix_new();
+  prefix_copy(prefix, range);
+  listnode_add(group->listen_range, prefix);
+  group->conf->af_group[AFI_IP][SAFI_UNICAST] = 1;
+  return 0;
+}
+
 /* Bind specified peer to peer group.  */
 int
 peer_group_bind (struct bgp *bgp, union sockunion *su,
@@ -1944,6 +1997,8 @@ bgp_create (as_t *as, const char *name)
 
   bgp->group = list_new ();
   bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
+  bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
+  bgp->dynamic_neighbors_count = 0;
 
   bgp->rsclient = list_new ();
   bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
@@ -2230,6 +2285,157 @@ peer_lookup_with_open (union sockunion *su, as_t remote_as,
   return NULL;
 }
 
+struct prefix *
+peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
+                                          struct prefix * prefix)
+{
+  struct listnode *node, *nnode;
+  struct prefix *range;
+
+  if (group->listen_range)
+    for (ALL_LIST_ELEMENTS (group->listen_range, node, nnode, range))
+      if (prefix_match(range, prefix))
+        return range;
+
+  return NULL;
+}
+
+struct peer_group *
+peer_group_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
+{
+  struct prefix *prefix, *range = NULL;
+  struct peer_group *group = NULL;
+  struct listnode *node, *nnode;
+
+  prefix = sockunion2hostprefix(su);
+
+  if (! prefix)
+    return NULL;
+
+  if (bgp != NULL)
+    {
+      for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+        if (group->conf && peer_group_active(group->conf) &&
+            (range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
+          break;
+    }
+  else if (bm->bgp != NULL)
+    {
+      struct listnode *bgpnode, *nbgpnode;
+
+      for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
+        for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
+          if (group->conf && peer_group_active(group->conf) &&
+              (range =
+               peer_group_lookup_dynamic_neighbor_range(group, prefix)))
+            break;
+    }
+  return (group && range) ? group : NULL;
+}
+
+struct peer *
+peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
+{
+  struct peer_group *group;
+  struct bgp *gbgp;
+  struct peer *peer;
+  int ret, dncount;
+  safi_t safi;
+  as_t as;
+
+  group = peer_group_lookup_dynamic_neighbor (bgp, su);
+
+  if (! group)
+    return NULL;
+
+  gbgp = group->bgp;
+
+  if (! gbgp)
+    return NULL;
+
+  dncount = gbgp->dynamic_neighbors_count;
+
+  if (dncount >= gbgp->dynamic_neighbors_limit)
+    {
+      if (BGP_DEBUG (events, EVENTS))
+        zlog_debug ("Dynamic Neighbor rejected - at limit %d",
+                    gbgp->dynamic_neighbors_limit);
+      return NULL;
+    }
+
+  /* The Dynamic Neighbors feature is only supported for IPv4. */
+  for (safi=SAFI_UNICAST; safi < SAFI_MAX; safi++)
+    if (group->conf->afc[AFI_IP][safi])
+      {
+        break;
+      }
+
+  if (SAFI_MAX == safi)
+    {
+      if (BGP_DEBUG (events, EVENTS))
+        zlog_debug ("Dynamic Neighbor rejected - no SAFI for group %s",
+                    group->name);
+      return NULL;
+    }
+
+  ret = peer_group_bind (gbgp, su, group, AFI_IP, safi, &as);
+
+  if (ret)
+    {
+      if (BGP_DEBUG (events, EVENTS))
+        zlog_debug ("Dynamic Neighbor rejected - peer_group_bind ret=%d", ret);
+      return NULL;
+    }
+
+  /* Set the Dynamic Neighbor flag for the peer entry */
+  peer = peer_lookup (bgp, su);
+
+  if (peer)
+    {
+      SET_FLAG (peer->af_flags[AFI_IP][safi], PEER_FLAG_DYNAMIC_NEIGHBOR);
+      gbgp->dynamic_neighbors_count = ++dncount;
+
+      if (BGP_DEBUG (events, EVENTS))
+        zlog_debug ("%s Dynamic Neighbor added, count=%d", peer->host, dncount);
+    }
+
+  return peer;
+}
+
+void peer_drop_dynamic_neighbor (struct peer *peer)
+{
+  int dncount = -1;
+  if (peer->group && peer->group->bgp)
+    {
+      dncount = peer->group->bgp->dynamic_neighbors_count;
+      if (dncount)
+        peer->group->bgp->dynamic_neighbors_count = --dncount;
+    }
+  if (BGP_DEBUG (events, EVENTS))
+    zlog_debug ("%s Dynamic Neighbor dropped, count=%d", peer->host, dncount);
+}
+
+/* If peer is dynamic neighbor for family return 1 */
+int
+peer_dynamic_neighbor_family (struct peer *peer, afi_t afi, safi_t safi)
+{
+  return (CHECK_FLAG(peer->af_flags[AFI_IP][safi],
+                     PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0;
+}
+
+/* If peer is dynamic neighbor return 1 */
+int
+peer_dynamic_neighbor (struct peer *peer)
+{
+  safi_t safi;
+
+  for (safi=SAFI_UNICAST; safi < SAFI_MAX; safi++)
+    if (peer_dynamic_neighbor_family(peer, AFI_IP, safi))
+      return 1;
+  return 0;
+}
+
+
 /* If peer is configured at least one address family return 1. */
 int
 peer_active (struct peer *peer)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0746f0d..5118f31 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -83,6 +83,12 @@ struct bgp
   /* BGP peer group.  */
   struct list *group;
 
+  /* The maximum number of BGP dynamic neighbors that can be created */
+  int dynamic_neighbors_limit;
+
+    /* The current number of BGP dynamic neighbors */
+  int dynamic_neighbors_count;
+
   /* BGP route-server-clients. */
   struct list *rsclient;
 
@@ -183,6 +189,9 @@ struct peer_group
   /* Peer-group client list. */
   struct list *peer;
 
+  /** Dynamic neighbor listening ranges */
+  struct list *listen_range;
+
   /* Peer-group config */
   struct peer *conf;
 };
@@ -405,6 +414,7 @@ struct peer
 #define PEER_FLAG_MAX_PREFIX                (1 << 14) /* maximum prefix */
 #define PEER_FLAG_MAX_PREFIX_WARNING        (1 << 15) /* maximum prefix warning-only */
 #define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED   (1 << 16) /* leave link-local nexthop unchanged */
+#define PEER_FLAG_DYNAMIC_NEIGHBOR          (1 << 17) /* dynamic neighbor */
 
   /* MD5 password */
   char *password;
@@ -763,6 +773,11 @@ struct bgp_nlri
 /* Check AS path loop when we send NLRI.  */
 /* #define BGP_SEND_ASPATH_CHECK */
 
+/* BGP Dynamic Neighbors feature */
+#define BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT    100
+#define BGP_DYNAMIC_NEIGHBORS_LIMIT_MIN          1
+#define BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX       5000
+
 /* Flag for peer_clear_soft().  */
 enum bgp_clear_type
 {
@@ -814,8 +829,10 @@ enum bgp_clear_type
 #define BGP_ERR_TCPSIG_FAILED			-29
 #define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK	-30
 #define BGP_ERR_NO_IBGP_WITH_TTLHACK		-31
-#define BGP_ERR_MAX				-32
-#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -33
+#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -32
+#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -33
+#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS  -34
+#define BGP_ERR_MAX                             -35
 
 extern struct bgp_master *bm;
 
@@ -836,6 +853,15 @@ extern struct peer_group *peer_group_lookup (struct bgp *, const char *);
 extern struct peer_group *peer_group_get (struct bgp *, const char *);
 extern struct peer *peer_lookup_with_open (union sockunion *, as_t, struct in_addr *,
 				    int *);
+extern struct prefix *peer_group_lookup_dynamic_neighbor_range (
+                     struct peer_group *, struct prefix *);
+extern struct peer_group *peer_group_lookup_dynamic_neighbor (struct bgp *,
+                     union sockunion *);
+extern struct peer *peer_lookup_dynamic_neighbor (struct bgp *,
+                     union sockunion *);
+extern void peer_drop_dynamic_neighbor (struct peer *);
+extern int peer_dynamic_neighbor_family (struct peer *, afi_t, safi_t);
+extern int peer_dynamic_neighbor (struct peer *);
 extern struct peer *peer_lock (struct peer *);
 extern struct peer *peer_unlock (struct peer *);
 extern bgp_peer_sort_t peer_sort (struct peer *peer);
@@ -883,6 +909,9 @@ extern int bgp_timers_unset (struct bgp *);
 extern int bgp_default_local_preference_set (struct bgp *, u_int32_t);
 extern int bgp_default_local_preference_unset (struct bgp *);
 
+extern int bgp_listen_limit_set (struct bgp *, int);
+extern int bgp_listen_limit_unset (struct bgp *);
+
 extern int peer_rsclient_active (struct peer *);
 
 extern int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
@@ -890,6 +919,7 @@ extern int peer_group_remote_as (struct bgp *, const char *, as_t *);
 extern int peer_delete (struct peer *peer);
 extern int peer_group_delete (struct peer_group *);
 extern int peer_group_remote_as_delete (struct peer_group *);
+extern int peer_group_listen_range_add(struct peer_group *, struct prefix *);
 
 extern int peer_activate (struct peer *, afi_t, safi_t);
 extern int peer_deactivate (struct peer *, afi_t, safi_t);
diff --git a/doc/bgpd.texi b/doc/bgpd.texi
index dd37d3e..ba3cd59 100644
--- a/doc/bgpd.texi
+++ b/doc/bgpd.texi
@@ -21,6 +21,7 @@ BGP-4.
 * BGP network::                 
 * BGP Peer::                    
 * BGP Peer Group::              
+* BGP Dynamic Neighbor Limit::
 * BGP Address Family::          
 * Autonomous System::           
 * BGP Communities Attribute::   
@@ -383,6 +384,10 @@ Apply a route-map on the neighbor.  @var{direct} must be @code{in} or
 @node BGP Peer Group
 @section BGP Peer Group
 
+@menu
+* BGP Listening Range::
+@end menu
+
 @deffn {BGP} {neighbor @var{word} peer-group} {}
 This command defines a new peer group.
 @end deffn
@@ -391,6 +396,41 @@ This command defines a new peer group.
 This command bind specific peer to peer group @var{word}.
 @end deffn
 
+@node BGP Listening Range
+@subsection BGP Listening Range
+@deffn {BGP} {listen range @var{A.B.C.D/M} peer-group @var{word}} {}
+Adds a Dynamic Neighbor IPv4 listening range to a BGP peer group. A BGP
+session will be allowed for a peer that initiates a TCP connection from an IP
+address within the listening range.
+@example
+@group
+router bgp 65501
+ neighbor DynaPeers peer-group
+ bgp listen range 10.0.2.0/24 peer-group DynaPeers
+@end group
+@end example
+@end deffn
+
+@c -----------------------------------------------------------------------
+@node BGP Dynamic Neighbor Limit
+@section BGP Dynamic Neighbor Limit
+
+@deffn {BGP} {listen limit @var{<1-5000>}} {}
+Configure the maximum number of BGP Dynamic Neighbors that can be created.
+Defaults to 100 if this directive is not employed.
+@example
+@group
+router bgp 1
+ bgp listen limit 300
+@end group
+@end example
+@end deffn
+
+@deffn {BGP} {no bgp listen limit} {}
+Restores the maximum number of BGP Dynamic Neighbors to the default value of 100.
+@end deffn
+
+@c -----------------------------------------------------------------------
 @node BGP Address Family
 @section BGP Address Family
 
@@ -960,9 +1000,117 @@ BGP Routes by Community}).
 @end deffn
 
 @deffn {Command} {show ip bgp summary} {}
+This command displays a summary of all BGP connections.
+
+An example that includes a mix of dynamic and non-dynamic neighbors:
+@example
+BGP router identifier 10.0.3.15, local AS number 65001
+RIB entries 1, using 112 bytes of memory
+Peers 3, using 13 KiB of memory
+Peer groups 1, using 40 bytes of memory
+
+Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
+*10.0.2.130     4 65200      56      56        0    0    0 00:53:11        1
+*10.0.2.162     4 65200      56      57        0    0    0 00:53:11        1
+172.33.111.34   4 65300      56      57        0    0    0 00:53:05        1
+
+Total number of neighbors 3
+* Dynamically created based on a listen range command
+Dynamically created neighbors: 2/(300 max), Subnet ranges: 1
+BGP peergroup DynaPeers listen range group members:
+  10.0.2.0/24
+@end example
 @end deffn
 
-@deffn {Command} {show ip bgp neighbor [@var{peer}]} {}
+@deffn {Command} {show ip bgp peer-group [@var{peer}]} {}
+This command displays information about BGP peer groups.
+
+An example of a peer-group that utilizes a listening range for dynamic
+neighbors:
+@example
+BGP peer-group is DynaPeers,  remote AS 65200
+  BGP peergroup DynaPeers listen range group members:
+  10.0.2.0/24
+  BGP version 4
+  Default minimum time between advertisement runs is 30 seconds
+ For address family: IPv4 Unicast
+  BGP neighbor is DynaPeers, peer-group external, members:
+    *10.0.2.130      *10.0.2.162
+@end example
+@end deffn
+
+@deffn {Command} {show ip bgp neighbors [@var{peer}]} {}
+This command displays information on the TCP/BGP connections to neighbors.
+
+An example of a non-established, non-dynamic neighbor:
+@example
+BGP neighbor is 172.33.111.34, remote AS 65300, local AS 65501, external link
+  BGP version 4, remote router ID 0.0.0.0
+  BGP state = Active
+  Last read 00:05:26, hold time is 180, keepalive interval is 60 seconds
+  Message statistics:
+    Inq depth is 0
+    Outq depth is 0
+                         Sent       Rcvd
+    Opens:                  0          0
+    Notifications:          0          0
+    Updates:                0          0
+    Keepalives:             0          0
+    Route Refresh:          0          0
+    Capability:             0          0
+    Total:                  0          0
+  Minimum time between advertisement runs is 30 seconds
+
+ For address family: IPv4 Unicast
+  Community attribute sent to this neighbor(both)
+  0 accepted prefixes
+
+  Connections established 0; dropped 0
+  Last reset never
+Next connect timer due in 47 seconds
+Read thread: off  Write thread: off
+@end example
+
+An example of a dynamic neighbor:
+@example
+BGP neighbor is *10.0.2.16, remote AS 65200, local AS 65501, external link
+ Member of peer-group DynaPeers for session parameters
+ Belongs to the subnet range group: 10.0.2.0/24
+  BGP version 4, remote router ID 10.0.2.16
+  BGP state = Established, up for 00:05:04
+  Last read 10:12:03, hold time is 180, keepalive interval is 60 seconds
+  Neighbor capabilities:
+    4 Byte AS: advertised and received
+    Route refresh: advertised and received(old & new)
+    Address family IPv4 Unicast: advertised and received
+  Message statistics:
+    Inq depth is 0
+    Outq depth is 0
+                         Sent       Rcvd
+    Opens:                  1          1
+    Notifications:          0          0
+    Updates:                0          1
+    Keepalives:             7          6
+    Route Refresh:          0          0
+    Capability:             0          0
+    Total:                  8          8
+  Minimum time between advertisement runs is 30 seconds
+
+ For address family: IPv4 Unicast
+  DynaPeers peer-group member
+  Community attribute sent to this neighbor(both)
+  1 accepted prefixes
+
+  Connections established 1; dropped 0
+  Last reset never
+Local host: 10.0.3.15, Local port: 36776
+Foreign host: 10.0.2.16, Foreign port: 179
+Nexthop: 10.0.3.15
+Nexthop global: fe80::a00:27ff:fe5e:b403
+Nexthop local: ::
+BGP connection: non shared network
+Read thread: on  Write thread: off
+@end example
 @end deffn
 
 @deffn {Command} {clear ip bgp @var{peer}} {}
-- 
1.7.9



_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
http://lists.quagga.net/mailman/listinfo/quagga-dev


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic