Skip to content

Commit

Permalink
BGP: Add dynamic update group support
Browse files Browse the repository at this point in the history
This patch implements the 'update-groups' functionality in BGP. This is a
function that can significantly improve BGP performance for Update generation
and resultant network convergence. BGP Updates are formed for "groups" of
peers and then replicated and sent out to each peer rather than being formed
for each peer. Thus major BGP operations related to outbound policy
application, adj-out maintenance and actual Update packet formation
are optimized.

BGP update-groups dynamically groups peers together based on configuration
as well as run-time criteria. Thus, it is more flexible than update-formation
based on peer-groups, which relies on operator configuration.

[Note that peer-group based update formation has been introduced into BGP by
Cumulus but is currently intended only for specific releases.]

From 11098af65b2b8f9535484703e7f40330a71cbae4 Mon Sep 17 00:00:00 2001
Subject: [PATCH] updgrp commits
  • Loading branch information
donaldsharp committed May 20, 2015
1 parent 759a13f commit 3f9c736
Show file tree
Hide file tree
Showing 52 changed files with 6,587 additions and 1,296 deletions.
5 changes: 3 additions & 2 deletions bgpd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ libbgp_a_SOURCES = \
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
bgp_nht.c
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c

noinst_HEADERS = \
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_updgrp.h

bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
Expand Down
238 changes: 31 additions & 207 deletions bgpd/bgp_advertise.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "prefix.h"
#include "hash.h"
#include "thread.h"
#include "queue.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
Expand All @@ -36,11 +37,12 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_updgrp.h"

/* BGP advertise attribute is used for pack same attribute update into
one packet. To do that we maintain attribute hash in struct
peer. */
static struct bgp_advertise_attr *
struct bgp_advertise_attr *
baa_new (void)
{
return (struct bgp_advertise_attr *)
Expand All @@ -64,15 +66,15 @@ baa_hash_alloc (void *p)
return baa;
}

static unsigned int
unsigned int
baa_hash_key (void *p)
{
struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;

return attrhash_key_make (baa->attr);
}

static int
int
baa_hash_cmp (const void *p1, const void *p2)
{
const struct bgp_advertise_attr * baa1 = p1;
Expand All @@ -84,22 +86,22 @@ baa_hash_cmp (const void *p1, const void *p2)
/* BGP update and withdraw information is stored in BGP advertise
structure. This structure is referred from BGP adjacency
information. */
static struct bgp_advertise *
struct bgp_advertise *
bgp_advertise_new (void)
{
return (struct bgp_advertise *)
return (struct bgp_advertise *)
XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
}

static void
void
bgp_advertise_free (struct bgp_advertise *adv)
{
if (adv->binfo)
bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
XFREE (MTYPE_BGP_ADVERTISE, adv);
}

static void
void
bgp_advertise_add (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
Expand All @@ -109,7 +111,7 @@ bgp_advertise_add (struct bgp_advertise_attr *baa,
baa->adv = adv;
}

static void
void
bgp_advertise_delete (struct bgp_advertise_attr *baa,
struct bgp_advertise *adv)
{
Expand All @@ -121,7 +123,7 @@ bgp_advertise_delete (struct bgp_advertise_attr *baa,
baa->adv = adv->next;
}

static struct bgp_advertise_attr *
struct bgp_advertise_attr *
bgp_advertise_intern (struct hash *hash, struct attr *attr)
{
struct bgp_advertise_attr ref;
Expand All @@ -134,7 +136,7 @@ bgp_advertise_intern (struct hash *hash, struct attr *attr)
return baa;
}

static void
void
bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
{
if (baa->refcnt)
Expand All @@ -153,216 +155,38 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
}
}

/* BGP adjacency keeps minimal advertisement information. */
static void
bgp_adj_out_free (struct bgp_adj_out *adj)
{
peer_unlock (adj->peer); /* adj_out peer reference */
XFREE (MTYPE_BGP_ADJ_OUT, adj);
}

int
bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
afi_t afi, safi_t safi, struct bgp_node *rn)
struct bgp_adj_out *
bgp_adj_peer_lookup (struct peer *peer, struct bgp_node *rn)
{
struct bgp_adj_out *adj;
struct peer_af *paf;

for (adj = rn->adj_out; adj; adj = adj->next)
if (adj->peer == peer)
break;

if (! adj)
return 0;

return (adj->adv
? (adj->adv->baa ? 1 : 0)
: (adj->attr ? 1 : 0));
}

struct bgp_advertise *
bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
afi_t afi, safi_t safi)
{
struct bgp_advertise *adv;
struct bgp_advertise_attr *baa;
struct bgp_advertise *next;
struct bgp_advertise_fifo *fhead;

adv = adj->adv;
baa = adv->baa;
next = NULL;
fhead = &peer->sync[afi][safi]->withdraw;

if (baa)
{
/* Unlink myself from advertise attribute FIFO. */
bgp_advertise_delete (baa, adv);

/* Fetch next advertise candidate. */
next = baa->adv;

/* Unintern BGP advertise attribute. */
bgp_advertise_unintern (peer->hash[afi][safi], baa);

fhead = &peer->sync[afi][safi]->update;
}

/* Unlink myself from advertisement FIFO. */
BGP_ADV_FIFO_DEL (fhead, adv);

/* Free memory. */
bgp_advertise_free (adj->adv);
adj->adv = NULL;

return next;
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
if (paf->peer == peer)
return adj;
return NULL;
}

void
bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
struct bgp_info *binfo)
{
struct bgp_adj_out *adj = NULL;
struct bgp_advertise *adv;

if (DISABLE_BGP_ANNOUNCE)
return;

/* Look for adjacency information. */
if (rn)
{
for (adj = rn->adj_out; adj; adj = adj->next)
if (adj->peer == peer)
break;
}

if (! adj)
{
adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
adj->peer = peer_lock (peer); /* adj_out peer reference */

if (rn)
{
BGP_ADJ_OUT_ADD (rn, adj);
bgp_lock_node (rn);
}
}

if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);

adj->adv = bgp_advertise_new ();

adv = adj->adv;
adv->rn = rn;

assert (adv->binfo == NULL);
adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */

if (attr)
adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
else
adv->baa = baa_new ();
adv->adj = adj;

/* Add new advertisement to advertisement attribute list. */
bgp_advertise_add (adv->baa, adv);

BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);

/*
* Schedule write thread (by triggering adjustment of MRAI timer) only if
* update FIFO has grown. Otherwise, it will be done upon the work queue
* being fully processed. Only adjust timer if needed.
*/
if (!BGP_ROUTE_ADV_HOLD(peer->bgp) &&
(BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->update) >=
peer->bgp->adv_quanta))
{
if (!peer->radv_adjusted)
{
if (bgp_debug_update(peer, NULL, 0))
zlog_debug("%s scheduling MRAI timer after adj_out_set", peer->host);
bgp_adjust_routeadv(peer);
}
}
}

void
bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p,
afi_t afi, safi_t safi)
int
bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
afi_t afi, safi_t safi, struct bgp_node *rn)
{
struct bgp_adj_out *adj;
struct bgp_advertise *adv;

if (DISABLE_BGP_ANNOUNCE)
return;
struct peer_af *paf;

/* Lookup existing adjacency, if it is not there return immediately. */
for (adj = rn->adj_out; adj; adj = adj->next)
if (adj->peer == peer)
break;

if (! adj)
return;

/* Clearn up previous advertisement. */
if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);

if (adj->attr)
{
/* We need advertisement structure. */
adj->adv = bgp_advertise_new ();
adv = adj->adv;
adv->rn = rn;
adv->adj = adj;

/* Add to synchronization entry for withdraw announcement. */
BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);

/*
* Schedule write thread only if withdraw FIFO has grown. Otherwise,
* it will be done upon the work queue being fully processed.
*/
if (!BGP_ROUTE_ADV_HOLD(peer->bgp) &&
(BGP_ADV_FIFO_COUNT(&peer->sync[afi][safi]->withdraw) >=
peer->bgp->wd_quanta))
{
if (!peer->t_write)
{
if (bgp_debug_update(peer, NULL, 0))
zlog_debug("%s scheduling write thread after adj_out_unset",
peer->host);
BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
}
}
}
else
{
/* Remove myself from adjacency. */
BGP_ADJ_OUT_DEL (rn, adj);

/* Free allocated information. */
bgp_adj_out_free (adj);
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
if (paf->peer == peer)
{
return (adj->adv
? (adj->adv->baa ? 1 : 0)
: (adj->attr ? 1 : 0));
}

bgp_unlock_node (rn);
}
return 0;
}

void
bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
struct peer *peer, afi_t afi, safi_t safi)
{
if (adj->attr)
bgp_attr_unintern (&adj->attr);

if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);

BGP_ADJ_OUT_DEL (rn, adj);
bgp_adj_out_free (adj);
}

void
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
Expand Down
Loading

0 comments on commit 3f9c736

Please sign in to comment.