[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