summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c918
1 files changed, 465 insertions, 453 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 1d9fcc97..b21cec4e 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -29,9 +29,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "sockunion.h" /* for inet_ntop () */
#include "linklist.h"
-#include "plist.h"
#include "bgpd/bgpd.h"
+
+#include "bgpd/bgp_peer.h"
+
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_dump.h"
#include "bgpd/bgp_attr.h"
@@ -47,9 +49,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_route_refresh.h"
int stream_put_prefix (struct stream *, struct prefix *);
-
+
/* Set up BGP packet marker and packet type. */
static int
bgp_packet_set_marker (struct stream *s, u_char type)
@@ -84,21 +87,7 @@ bgp_packet_set_size (struct stream *s)
return cp;
}
-/* Add new packet to the peer. */
-static void
-bgp_packet_add (struct peer *peer, struct stream *s)
-{
- /* Add packet to the end of list. */
- stream_fifo_push (peer->obuf, s);
-}
-
-/* Free first packet. */
-static void
-bgp_packet_delete (struct peer *peer)
-{
- stream_free (stream_fifo_pop (peer->obuf));
-}
-
+#if 0
/* Check file descriptor whether connect is established. */
static void
bgp_connect_check (struct peer *peer)
@@ -121,7 +110,7 @@ bgp_connect_check (struct peer *peer)
zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
BGP_EVENT_ADD (peer, TCP_fatal_error);
return;
- }
+ }
/* When status is 0 then TCP connection is established. */
if (status == 0)
@@ -136,15 +125,22 @@ bgp_connect_check (struct peer *peer)
BGP_EVENT_ADD (peer, TCP_connection_open_failed);
}
}
+#endif
-/* Make BGP update packet. */
+/*------------------------------------------------------------------------------
+ * Construct an update from head of peer->sync[afi][safi]->update.
+ *
+ * Generates complete BGP message in the peer->work stream structure.
+ *
+ * Returns: peer->work -- if have something to be written.
+ * NULL -- otherwise
+ */
static struct stream *
bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
{
struct stream *s;
struct bgp_adj_out *adj;
struct bgp_advertise *adv;
- struct stream *packet;
struct bgp_node *rn = NULL;
struct bgp_info *binfo = NULL;
bgp_size_t total_attr_len = 0;
@@ -154,7 +150,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
s = peer->work;
stream_reset (s);
- adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
+ adv = bgp_advertise_fifo_head(&peer->sync[afi][safi]->update);
while (adv)
{
@@ -174,7 +170,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
struct prefix_rd *prd = NULL;
u_char *tag = NULL;
struct peer *from = NULL;
-
+
if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p;
if (binfo)
@@ -183,21 +179,21 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
if (binfo->extra)
tag = binfo->extra->tag;
}
-
+
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
- stream_putw (s, 0);
+ stream_putw (s, 0);
pos = stream_get_endp (s);
stream_putw (s, 0);
- total_attr_len = bgp_packet_attribute (NULL, peer, s,
+ total_attr_len = bgp_packet_attribute (NULL, peer, s,
adv->baa->attr,
- &rn->p, afi, safi,
+ &rn->p, afi, safi,
from, prd, tag);
stream_putw_at (s, pos, total_attr_len);
}
if (afi == AFI_IP && safi == SAFI_UNICAST)
stream_put_prefix (s, &rn->p);
-
+
if (BGP_DEBUG (update, UPDATE_OUT))
zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
peer->host,
@@ -217,24 +213,26 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
if (! (afi == AFI_IP && safi == SAFI_UNICAST))
break;
}
-
- if (! stream_empty (s))
- {
- bgp_packet_set_size (s);
- packet = stream_dup (s);
- bgp_packet_add (peer, packet);
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
- stream_reset (s);
- return packet;
- }
- return NULL;
+
+ if (stream_empty (s))
+ return NULL ;
+
+ bgp_packet_set_size (s) ;
+ return s ;
}
+/*------------------------------------------------------------------------------
+ * Construct an End-of-RIB update message for given AFI/SAFI.
+ *
+ * Generates complete BGP message in the peer->work stream structure.
+ *
+ * Returns: peer->work -- if have something to be written.
+ * NULL -- otherwise
+ */
static struct stream *
bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
{
struct stream *s;
- struct stream *packet;
if (DISABLE_BGP_ANNOUNCE)
return NULL;
@@ -242,7 +240,8 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = peer->work;
+ stream_reset (s);
/* Make BGP update packet. */
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
@@ -267,18 +266,21 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
}
bgp_packet_set_size (s);
- packet = stream_dup (s);
- bgp_packet_add (peer, packet);
- stream_free (s);
- return packet;
+ return s ;
}
-/* Make BGP withdraw packet. */
+/*------------------------------------------------------------------------------
+ * Construct a withdraw update from from head of peer->sync[afi][safi]->withdraw
+ *
+ * Generates complete BGP message in the peer->work stream structure.
+ *
+ * Returns: peer->work -- if have something to be written.
+ * NULL -- otherwise
+ */
static struct stream *
bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
{
struct stream *s;
- struct stream *packet;
struct bgp_adj_out *adj;
struct bgp_advertise *adv;
struct bgp_node *rn;
@@ -290,13 +292,14 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
s = peer->work;
stream_reset (s);
- while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
+ while ((adv = bgp_advertise_fifo_head(&peer->sync[afi][safi]->withdraw))
+ != NULL)
{
assert (adv->rn);
adj = adv->adj;
rn = adv->rn;
- if (STREAM_REMAIN (s)
+ if (STREAM_REMAIN (s)
< (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
break;
@@ -311,14 +314,14 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
else
{
struct prefix_rd *prd = NULL;
-
+
if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p;
pos = stream_get_endp (s);
stream_putw (s, 0);
total_attr_len
= bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);
-
+
/* Set total path attribute length. */
stream_putw_at (s, pos, total_attr_len);
}
@@ -332,37 +335,38 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
peer->scount[afi][safi]--;
bgp_adj_out_remove (rn, adj, peer, afi, safi);
- bgp_unlock_node (rn);
if (! (afi == AFI_IP && safi == SAFI_UNICAST))
break;
}
- if (! stream_empty (s))
+ if (stream_empty (s))
+ return NULL ;
+
+ if (afi == AFI_IP && safi == SAFI_UNICAST)
{
- if (afi == AFI_IP && safi == SAFI_UNICAST)
- {
- unfeasible_len
+ unfeasible_len
= stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
- stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
- stream_putw (s, 0);
- }
- bgp_packet_set_size (s);
- packet = stream_dup (s);
- bgp_packet_add (peer, packet);
- stream_reset (s);
- return packet;
- }
+ stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
+ stream_putw (s, 0);
+ } ;
- return NULL;
+ bgp_packet_set_size (s);
+ return s ;
}
+/*------------------------------------------------------------------------------
+ * Construct an update for the default route, place it in the obuf queue
+ * and kick write.
+ *
+ * Uses peer->work stream structure, but copies result to new stream, which is
+ * pushed onto the obuf queue.
+ */
void
bgp_default_update_send (struct peer *peer, struct attr *attr,
afi_t afi, safi_t safi, struct peer *from)
{
struct stream *s;
- struct stream *packet;
struct prefix p;
unsigned long pos;
bgp_size_t total_attr_len;
@@ -375,7 +379,7 @@ bgp_default_update_send (struct peer *peer, struct attr *attr,
if (afi == AFI_IP)
str2prefix ("0.0.0.0/0", &p);
#ifdef HAVE_IPV6
- else
+ else
str2prefix ("::/0", &p);
#endif /* HAVE_IPV6 */
@@ -388,7 +392,8 @@ bgp_default_update_send (struct peer *peer, struct attr *attr,
p.prefixlen, attrstr);
}
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = peer->work ;
+ stream_reset (s);
/* Make BGP update packet. */
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
@@ -411,25 +416,26 @@ bgp_default_update_send (struct peer *peer, struct attr *attr,
/* Set size. */
bgp_packet_set_size (s);
- packet = stream_dup (s);
- stream_free (s);
-
/* Dump packet if debug option is set. */
#ifdef DEBUG
- /* bgp_packet_dump (packet); */
+ /* bgp_packet_dump (s); */
#endif /* DEBUG */
/* Add packet to the peer. */
- bgp_packet_add (peer, packet);
-
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ bgp_write(peer, s);
}
+/*------------------------------------------------------------------------------
+ * Construct a withdraw update for the default route, place it in the obuf
+ * queue and kick write.
+ *
+ * Uses peer->work stream structure, but copies result to new stream, which is
+ * pushed onto the obuf queue.
+ */
void
bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
{
struct stream *s;
- struct stream *packet;
struct prefix p;
unsigned long pos;
unsigned long cp;
@@ -443,7 +449,7 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
if (afi == AFI_IP)
str2prefix ("0.0.0.0/0", &p);
#ifdef HAVE_IPV6
- else
+ else
str2prefix ("::/0", &p);
#endif /* HAVE_IPV6 */
@@ -455,7 +461,8 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),
p.prefixlen);
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = peer->work ;
+ stream_reset (s);
/* Make BGP update packet. */
bgp_packet_set_marker (s, BGP_MSG_UPDATE);
@@ -489,16 +496,18 @@ bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
bgp_packet_set_size (s);
- packet = stream_dup (s);
- stream_free (s);
-
/* Add packet to the peer. */
- bgp_packet_add (peer, packet);
-
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ bgp_write(peer, s);
}
-/* Get next packet to be written. */
+/*------------------------------------------------------------------------------
+ * Get next update message to be written.
+ *
+ * Generates complete BGP message in the peer->work stream structure.
+ *
+ * Returns: peer->work -- if have something to be written.
+ * NULL -- otherwise
+ */
static struct stream *
bgp_write_packet (struct peer *peer)
{
@@ -507,14 +516,10 @@ bgp_write_packet (struct peer *peer)
struct stream *s = NULL;
struct bgp_advertise *adv;
- s = stream_fifo_head (peer->obuf);
- if (s)
- return s;
-
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
- adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
+ adv = bgp_advertise_fifo_head(&peer->sync[afi][safi]->withdraw);
if (adv)
{
s = bgp_withdraw_packet (peer, afi, safi);
@@ -522,11 +527,11 @@ bgp_write_packet (struct peer *peer)
return s;
}
}
-
+
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{
- adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
+ adv = bgp_advertise_fifo_head(&peer->sync[afi][safi]->update);
if (adv)
{
if (adv->binfo && adv->binfo->uptime < peer->synctime)
@@ -563,6 +568,7 @@ bgp_write_packet (struct peer *peer)
return NULL;
}
+#if 0
/* Is there partially written packet or updates we can send right
now. */
static int
@@ -588,118 +594,52 @@ bgp_write_proceed (struct peer *peer)
return 0;
}
+#endif
-/* Write packet to the peer. */
+/*------------------------------------------------------------------------------
+ * Write packets to the peer -- subject to the XON flow control.
+ *
+ * Takes an optional stream argument, if not NULL then must be peer->work,
+ * in which there is a message to be sent.
+ *
+ * Then processes the peer->sync structure to generate further updates.
+ *
+ * TODO: work out how bgp_routeadv_timer fits into this.
+ */
int
-bgp_write (struct thread *thread)
+bgp_write (bgp_peer peer, struct stream* s)
{
- struct peer *peer;
- u_char type;
- struct stream *s;
- int num;
- unsigned int count = 0;
-
- /* Yes first of all get peer pointer. */
- peer = THREAD_ARG (thread);
- peer->t_write = NULL;
-
- /* For non-blocking IO check. */
- if (peer->status == Connect)
- {
- bgp_connect_check (peer);
- return 0;
- }
-
- s = bgp_write_packet (peer);
- if (!s)
- return 0; /* nothing to send */
-
- sockopt_cork (peer->fd, 1);
+ if (s != NULL)
+ stream_fifo_push(peer->obuf, stream_dup(s)) ;
- /* Nonblocking write until TCP output buffer is full. */
- do
+ while (bgp_session_is_XON(peer))
{
- int writenum;
+ s = bgp_write_packet(peer); /* uses peer->work */
+ if (s == NULL)
+ break;
- /* Number of bytes to be sent. */
- writenum = stream_get_endp (s) - stream_get_getp (s);
+ stream_fifo_push (peer->obuf, stream_dup(s)) ;
- /* Call write() system call. */
- num = write (peer->fd, STREAM_PNT (s), writenum);
- if (num < 0)
- {
- /* write failed either retry needed or error */
- if (ERRNO_IO_RETRY(errno))
- break;
-
- BGP_EVENT_ADD (peer, TCP_fatal_error);
- return 0;
- }
+ /* Count down flow control, send fifo if hits BGP_XON_KICK */
+ if (bgp_session_dec_flow_count(peer))
+ bgp_session_update_send(peer->session, peer->obuf) ;
+ } ;
- if (num != writenum)
- {
- /* Partial write */
- stream_forward_getp (s, num);
- break;
- }
-
- /* Retrieve BGP packet type. */
- stream_set_getp (s, BGP_MARKER_SIZE + 2);
- type = stream_getc (s);
-
- switch (type)
- {
- case BGP_MSG_OPEN:
- peer->open_out++;
- break;
- case BGP_MSG_UPDATE:
- peer->update_out++;
- break;
- case BGP_MSG_NOTIFY:
- peer->notify_out++;
- /* Double start timer. */
- peer->v_start *= 2;
-
- /* Overflow check. */
- if (peer->v_start >= (60 * 2))
- peer->v_start = (60 * 2);
-
- /* Flush any existing events */
- BGP_EVENT_ADD (peer, BGP_Stop);
- return 0;
- case BGP_MSG_KEEPALIVE:
- peer->keepalive_out++;
- break;
- case BGP_MSG_ROUTE_REFRESH_NEW:
- case BGP_MSG_ROUTE_REFRESH_OLD:
- peer->refresh_out++;
- break;
- case BGP_MSG_CAPABILITY:
- peer->dynamic_cap_out++;
- break;
- }
+ /* In any case, send what's in the FIFO */
+ if (stream_fifo_head(peer->obuf) != NULL)
+ bgp_session_update_send(peer->session, peer->obuf) ;
- /* OK we send packet so delete it. */
- bgp_packet_delete (peer);
- }
- while (++count < BGP_WRITE_PACKET_MAX &&
- (s = bgp_write_packet (peer)) != NULL);
-
- if (bgp_write_proceed (peer))
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
- else
- sockopt_cork (peer->fd, 0);
-
return 0;
}
+#if 0
/* This is only for sending NOTIFICATION message to neighbor. */
static int
bgp_write_notify (struct peer *peer)
{
int ret, val;
u_char type;
- struct stream *s;
+ struct stream *s;
/* There should be at least one packet. */
s = stream_fifo_head (peer->obuf);
@@ -738,7 +678,9 @@ bgp_write_notify (struct peer *peer)
return 0;
}
+#endif
+#if 0
/* Make keepalive packet and send it to the peer. */
void
bgp_keepalive_send (struct peer *peer)
@@ -756,19 +698,20 @@ bgp_keepalive_send (struct peer *peer)
/* Dump packet if debug option is set. */
/* bgp_packet_dump (s); */
-
- if (BGP_DEBUG (keepalive, KEEPALIVE))
- zlog_debug ("%s sending KEEPALIVE", peer->host);
+
+ if (BGP_DEBUG (keepalive, KEEPALIVE))
+ zlog_debug ("%s sending KEEPALIVE", peer->host);
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s send message type %d, length (incl. header) %d",
peer->host, BGP_MSG_KEEPALIVE, length);
/* Add packet to the peer. */
bgp_packet_add (peer, s);
-
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ bgp_write(peer);
}
+#endif
+#if 0
/* Make open packet and send it to the peer. */
void
bgp_open_send (struct peer *peer)
@@ -785,9 +728,9 @@ bgp_open_send (struct peer *peer)
/* local-as Change */
if (peer->change_local_as)
- local_as = peer->change_local_as;
+ local_as = peer->change_local_as;
else
- local_as = peer->local_as;
+ local_as = peer->local_as;
s = stream_new (BGP_MAX_PACKET_SIZE);
@@ -796,7 +739,7 @@ bgp_open_send (struct peer *peer)
/* Set open packet values. */
stream_putc (s, BGP_VERSION_4); /* BGP version */
- stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
+ stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
: BGP_AS_TRANS);
stream_putw (s, send_holdtime); /* Hold Time */
stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
@@ -808,9 +751,9 @@ bgp_open_send (struct peer *peer)
length = bgp_packet_set_size (s);
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
+ zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
peer->host, BGP_VERSION_4, local_as,
- send_holdtime, inet_ntoa (peer->local_id));
+ send_holdtime, safe_inet_ntoa (peer->local_id));
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s send message type %d, length (incl. header) %d",
@@ -821,105 +764,89 @@ bgp_open_send (struct peer *peer)
/* Add packet to the peer. */
bgp_packet_add (peer, s);
-
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ bgp_write(peer);
}
+#endif
+
+/* Send route refresh message to the peer. */
-/* Send BGP notify packet with data potion. */
void
-bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
- u_char *data, size_t datalen)
+bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
+ u_char orf_type, u_char when_to_refresh, int remove)
{
- struct stream *s;
- int length;
-
- /* Allocate new stream. */
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ bgp_route_refresh rr = NULL;
+ struct bgp_filter *filter = NULL;
+ bgp_session session = peer->session;
+ bgp_orf_entry orfpe = NULL;
+ struct prefix_list *plist = NULL;
+ struct orf_prefix orfp;
+ vector_index i;
+ int orf_refresh = 0;
+ enum prefix_list_type pe_type;
- /* Make nitify packet. */
- bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
+ if (DISABLE_BGP_ANNOUNCE)
+ return;
- /* Set notify packet values. */
- stream_putc (s, code); /* BGP notify code */
- stream_putc (s, sub_code); /* BGP notify sub_code */
+ filter = &peer->filter[afi][safi];
- /* If notify data is present. */
- if (data)
- stream_write (s, data, datalen);
-
- /* Set BGP packet length. */
- length = bgp_packet_set_size (s);
-
- /* Add packet to the peer. */
- stream_fifo_clean (peer->obuf);
- bgp_packet_add (peer, s);
+ /* Adjust safi code. */
+ if (safi == SAFI_MPLS_VPN)
+ safi = BGP_SAFI_VPNV4;
- /* For debug */
- {
- struct bgp_notify bgp_notify;
- int first = 0;
- int i;
- char c[4];
+ rr = bgp_route_refresh_new(afi, safi, 1);
+ rr->defer = (when_to_refresh == REFRESH_DEFER);
- bgp_notify.code = code;
- bgp_notify.subcode = sub_code;
- bgp_notify.data = NULL;
- bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
-
- if (bgp_notify.length)
+ if (orf_type == ORF_TYPE_PREFIX
+ || orf_type == ORF_TYPE_PREFIX_OLD)
+ if (remove || filter->plist[FILTER_IN].ref)
{
- bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
- for (i = 0; i < bgp_notify.length; i++)
- if (first)
- {
- sprintf (c, " %02x", data[i]);
- strcat (bgp_notify.data, c);
- }
- else
- {
- first = 1;
- sprintf (c, "%02x", data[i]);
- strcpy (bgp_notify.data, c);
- }
+ orf_refresh = 1;
+ if (remove)
+ {
+ UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
+ bgp_orf_add_remove_all(rr, BGP_ORF_T_PREFIX, bgp_form_none);
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s)"
+ " for afi/safi: %d/%d",
+ peer->host, orf_type,
+ (when_to_refresh == REFRESH_DEFER)
+ ? "defer"
+ : "immediate",
+ afi, safi);
+ }
+ else
+ {
+ SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
+ plist = prefix_list_ref_plist(filter->plist[FILTER_IN].ref) ;
+ for (i = 0; prefix_bgp_orf_get(plist, i, &orfp, &pe_type); ++i)
+ {
+ orfpe = bgp_orf_add(rr, BGP_ORF_T_PREFIX, bgp_form_none, 0,
+ pe_type == PREFIX_DENY);
+ orfpe->body.orf_prefix = orfp;
+ }
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d)"
+ " (%s) for afi/safi: %d/%d",
+ peer->host, orf_type,
+ (when_to_refresh == REFRESH_DEFER)
+ ? "defer"
+ : "immediate",
+ afi, safi);
+ }
}
- bgp_notify_print (peer, &bgp_notify, "sending");
- if (bgp_notify.data)
- XFREE (MTYPE_TMP, bgp_notify.data);
- }
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_NOTIFY, length);
-
- /* peer reset cause */
- if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
{
- if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
- peer->last_reset = PEER_DOWN_USER_RESET;
- else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
- peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
- else
- peer->last_reset = PEER_DOWN_NOTIFY_SEND;
+ if (! orf_refresh)
+ zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
+ peer->host, afi, safi);
}
- /* Call imidiately. */
- BGP_WRITE_OFF (peer->t_write);
-
- bgp_write_notify (peer);
-}
+ bgp_session_route_refresh_send(session, rr);
-/* Send BGP notify packet. */
-void
-bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
-{
- bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
-}
+#if 0
+ /* old code */
-/* Send route refresh message to the peer. */
-void
-bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
- u_char orf_type, u_char when_to_refresh, int remove)
-{
struct stream *s;
struct stream *packet;
int length;
@@ -934,7 +861,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
/* Adjust safi code. */
if (safi == SAFI_MPLS_VPN)
safi = BGP_SAFI_VPNV4;
-
+
s = stream_new (BGP_MAX_PACKET_SIZE);
/* Make BGP update packet. */
@@ -947,15 +874,15 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
stream_putw (s, afi);
stream_putc (s, 0);
stream_putc (s, safi);
-
+
if (orf_type == ORF_TYPE_PREFIX
|| orf_type == ORF_TYPE_PREFIX_OLD)
- if (remove || filter->plist[FILTER_IN].plist)
+ if (remove || filter->plist[FILTER_IN].ref)
{
u_int16_t orf_len;
unsigned long orfp;
- orf_refresh = 1;
+ orf_refresh = 1;
stream_putc (s, when_to_refresh);
stream_putc (s, orf_type);
orfp = stream_get_endp (s);
@@ -966,7 +893,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
+ zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
afi, safi);
@@ -974,11 +901,11 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
else
{
SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
- prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
+ prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].ref,
ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
ORF_COMMON_PART_DENY);
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
+ zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
afi, safi);
@@ -995,7 +922,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
if (BGP_DEBUG (normal, NORMAL))
{
if (! orf_refresh)
- zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
+ zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi);
zlog_debug ("%s send message type %d, length (incl. header) %d",
peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
@@ -1008,24 +935,27 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
/* Add packet to the peer. */
bgp_packet_add (peer, packet);
-
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ bgp_write(peer);
+#endif
}
/* Send capability message to the peer. */
+
+/* TODO: require BGP Engine support for Dynamic Capability messages. */
+
void
bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
int capability_code, int action)
{
struct stream *s;
- struct stream *packet;
int length;
/* Adjust safi code. */
if (safi == SAFI_MPLS_VPN)
safi = BGP_SAFI_VPNV4;
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = peer->work;
+ stream_reset (s);
/* Make BGP update packet. */
bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
@@ -1049,20 +979,15 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
/* Set packet size. */
length = bgp_packet_set_size (s);
- /* Make real packet. */
- packet = stream_dup (s);
- stream_free (s);
-
- /* Add packet to the peer. */
- bgp_packet_add (peer, packet);
-
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s send message type %d, length (incl. header) %d",
- peer->host, BGP_MSG_CAPABILITY, length);
+ peer->host, BGP_MSG_CAPABILITY, length);
- BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+ /* Add packet to the peer. */
+ bgp_write(peer, s);
}
-
+
+#if 0
/* RFC1771 6.8 Connection collision detection. */
static int
bgp_collision_detect (struct peer *new, struct in_addr remote_id)
@@ -1074,7 +999,7 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
bgp = bgp_get_default ();
if (! bgp)
return 0;
-
+
/* Upon receipt of an OPEN message, the local system must examine
all of its connections that are in the OpenConfirm state. A BGP
speaker may also examine connections in an OpenSent state if it
@@ -1118,7 +1043,7 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
OpenConfirm state). */
if (new->fd >= 0)
- bgp_notify_send (new, BGP_NOTIFY_CEASE,
+ bgp_notify_send (new, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
return -1;
}
@@ -1126,7 +1051,9 @@ bgp_collision_detect (struct peer *new, struct in_addr remote_id)
}
return 0;
}
+#endif
+#if 0
static int
bgp_open_receive (struct peer *peer, bgp_size_t size)
{
@@ -1144,7 +1071,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
u_int8_t notify_data_remote_id[4];
realpeer = NULL;
-
+
/* Parse open packet. */
version = stream_getc (peer->ibuf);
memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
@@ -1158,21 +1085,21 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
" holdtime %d, id %s",
peer->host, version, remote_as, holdtime,
- inet_ntoa (remote_id));
-
+ safe_inet_ntoa (remote_id));
+
/* BEGIN to read the capability here, but dont do it yet */
capability = 0;
optlen = stream_getc (peer->ibuf);
-
+
if (optlen != 0)
{
/* We need the as4 capability value *right now* because
* if it is there, we have not got the remote_as yet, and without
* that we do not know which peer is connecting to us now.
- */
+ */
as4 = peek_for_as4_capability (peer, optlen);
}
-
+
/* Just in case we have a silly peer who sends AS4 capability set to 0 */
if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
{
@@ -1182,7 +1109,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
BGP_NOTIFY_OPEN_BAD_PEER_AS);
return -1;
}
-
+
if (remote_as == BGP_AS_TRANS)
{
/* Take the AS4 from the capability. We must have received the
@@ -1197,7 +1124,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
BGP_NOTIFY_OPEN_BAD_PEER_AS);
return -1;
}
-
+
if (!as4 && BGP_DEBUG (as4, AS4))
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
" Odd, but proceeding.", peer->host);
@@ -1206,8 +1133,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
"in 2-bytes, very odd peer.", peer->host, as4);
if (as4)
remote_as = as4;
- }
- else
+ }
+ else
{
/* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
/* If we have got the capability, peer->as4cap must match remote_as */
@@ -1240,8 +1167,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s bad OPEN, wrong router identifier %s",
- peer->host, inet_ntoa (remote_id));
- bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
+ peer->host, safe_inet_ntoa (remote_id));
+ bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
notify_data_remote_id, 4);
}
@@ -1278,7 +1205,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
&& realpeer->status != OpenConfirm
&& realpeer->status != Connect)
{
- /* XXX: This is an awful problem..
+ /* XXX: This is an awful problem..
*
* According to the RFC we should just let this connection (of the
* accepted 'peer') continue on to Established if the other
@@ -1296,7 +1223,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
* Active
* OpenSent OpenSent
* <arrive here,
- * Notify, delete>
+ * Notify, delete>
* Idle Active
* OpenSent OpenSent
* <arrive here,
@@ -1312,13 +1239,13 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
* exacerbated by high-latency (in bgpd and/or the network).
*
* The reason we do this is because our FSM is tied to our peer
- * structure, which carries our configuration information, etc.
+ * structure, which carries our configuration information, etc.
* I.e. we can't let the accepted-peer FSM continue on as it is,
* cause it's not associated with any actual peer configuration -
* it's just a dummy.
*
* It's possible we could hack-fix this by just bgp_stop'ing the
- * realpeer and continueing on with the 'transfer FSM' below.
+ * realpeer and continueing on with the 'transfer FSM' below.
* Ideally, we need to seperate FSMs from struct peer.
*
* Setting one side to passive avoids the race, as a workaround.
@@ -1335,11 +1262,11 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
- peer->host,
+ peer->host,
LOOKUP (bgp_status_msg, realpeer->status));
bgp_stop (realpeer);
-
+
/* Transfer file descriptor. */
realpeer->fd = peer->fd;
peer->fd = -1;
@@ -1353,7 +1280,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Transfer status. */
realpeer->status = peer->status;
bgp_stop (peer);
-
+
/* peer pointer change. Open packet send to neighbor. */
peer = realpeer;
bgp_open_send (peer);
@@ -1373,9 +1300,9 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s bad OPEN, wrong router identifier %s",
- peer->host, inet_ntoa (remote_id));
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_OPEN_ERR,
+ peer->host, safe_inet_ntoa (remote_id));
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
notify_data_remote_id, 4);
return -1;
@@ -1391,8 +1318,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
peer->host, version, BGP_VERSION_4);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_VERSION,
&maxver, 1);
return -1;
@@ -1404,8 +1331,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
peer->host, remote_as, peer->as);
- bgp_notify_send_with_data (peer,
- BGP_NOTIFY_OPEN_ERR,
+ bgp_notify_send_with_data (peer,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
return -1;
@@ -1420,11 +1347,11 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (holdtime < 3 && holdtime != 0)
{
bgp_notify_send (peer,
- BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
return -1;
}
-
+
/* From the rfc: A reasonable maximum time between KEEPALIVE messages
would be one third of the Hold Time interval. KEEPALIVE messages
MUST NOT be sent more frequently than one per second. An
@@ -1444,7 +1371,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
peer->v_keepalive = peer->v_holdtime / 3;
/* Open option part parse. */
- if (optlen != 0)
+ if (optlen != 0)
{
ret = bgp_open_option_parse (peer, optlen, &capability);
if (ret < 0)
@@ -1477,9 +1404,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
return 0;
}
+#endif
/* Parse BGP Update packet and make attribute object. */
-static int
+int
bgp_update_receive (struct peer *peer, bgp_size_t size)
{
int ret;
@@ -1494,13 +1422,14 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
struct bgp_nlri mp_update;
struct bgp_nlri mp_withdraw;
char attrstr[BUFSIZ] = "";
+ bgp_attr_parse_ret_t ap_ret ;
/* Status must be Established. */
- if (peer->status != Established)
+ if (peer->state != bgp_peer_pEstablished)
{
zlog_err ("%s [FSM] Update packet received under status %s",
- peer->host, LOOKUP (bgp_status_msg, peer->status));
- bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+ peer->host, LOOKUP (bgp_peer_status_msg, peer->state));
+ bgp_peer_down_error (peer, BGP_NOTIFY_FSM_ERR, 0);
return -1;
}
@@ -1523,8 +1452,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
zlog_err ("%s [Error] Update packet error"
" (packet length is short for unfeasible length)",
peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
return -1;
}
@@ -1537,8 +1466,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
zlog_err ("%s [Error] Update packet error"
" (packet unfeasible length overflow %d)",
peer->host, withdraw_len);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
return -1;
}
@@ -1558,15 +1487,15 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
withdraw.length = withdraw_len;
stream_forward_getp (s, withdraw_len);
}
-
+
/* Attribute total length check. */
if (stream_pnt (s) + 2 > end)
{
zlog_warn ("%s [Error] Packet Error"
" (update packet is short for attribute length)",
peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
return -1;
}
@@ -1579,42 +1508,41 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
zlog_warn ("%s [Error] Packet Error"
" (update packet attribute length overflow %d)",
peer->host, attribute_len);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_MAL_ATTR);
+ bgp_peer_down_error (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_MAL_ATTR);
return -1;
}
-
+
/* Certain attribute parsing errors should not be considered bad enough
* to reset the session for, most particularly any partial/optional
* attributes that have 'tunneled' over speakers that don't understand
* them. Instead we withdraw only the prefix concerned.
- *
+ *
* Complicates the flow a little though..
*/
- bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
+ ap_ret = BGP_ATTR_PARSE_PROCEED;
+
/* This define morphs the update case into a withdraw when lower levels
* have signalled an error condition where this is best.
*/
-#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
+#define NLRI_ATTR_ARG (ap_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
/* Parse attribute when it exists. */
if (attribute_len)
{
- attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
- &mp_update, &mp_withdraw);
- if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
+ ap_ret = bgp_attr_parse (peer, &attr, attribute_len,
+ &mp_update, &mp_withdraw);
+ if (ap_ret == BGP_ATTR_PARSE_ERROR)
return -1;
}
-
+
/* Logging the attribute. */
- if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
- || BGP_DEBUG (update, UPDATE_IN))
+ if ((ap_ret == BGP_ATTR_PARSE_WITHDRAW) || BGP_DEBUG (update, UPDATE_IN))
{
ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
- int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
- ? LOG_ERR : LOG_DEBUG;
-
- if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+ int lvl = (ap_ret == BGP_ATTR_PARSE_WITHDRAW) ? LOG_ERR : LOG_DEBUG ;
+
+ if (ap_ret == BGP_ATTR_PARSE_WITHDRAW)
zlog (peer->log, LOG_ERR,
"%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
peer->host);
@@ -1623,7 +1551,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
peer->host, attrstr);
}
-
+
/* Network Layer Reachability Information. */
update_len = end - stream_pnt (s);
@@ -1633,9 +1561,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
if (ret < 0)
{
- bgp_attr_unintern_sub (&attr);
- if (attr.extra)
- bgp_attr_extra_free (&attr);
+ bgp_attr_unintern_sub (&attr, true) ; /* true => free extra */
return -1;
}
@@ -1661,9 +1587,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
ret = bgp_attr_check (peer, &attr);
if (ret < 0)
{
- bgp_attr_unintern_sub (&attr);
- if (attr.extra)
- bgp_attr_extra_free (&attr);
+ bgp_attr_unintern_sub (&attr, true) ; /* true => free extra */
return -1;
}
@@ -1671,12 +1595,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
}
if (mp_update.length
- && mp_update.afi == AFI_IP
+ && mp_update.afi == AFI_IP
&& mp_update.safi == SAFI_UNICAST)
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
- && mp_withdraw.afi == AFI_IP
+ && mp_withdraw.afi == AFI_IP
&& mp_withdraw.safi == SAFI_UNICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
@@ -1691,19 +1615,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
if (BGP_DEBUG (normal, NORMAL))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
+ zlog (peer->log, LOG_DEBUG,
+ "rcvd End-of-RIB for IPv4 Unicast from %s",
peer->host);
}
}
if (peer->afc[AFI_IP][SAFI_MULTICAST])
{
if (mp_update.length
- && mp_update.afi == AFI_IP
+ && mp_update.afi == AFI_IP
&& mp_update.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
if (mp_withdraw.length
- && mp_withdraw.afi == AFI_IP
+ && mp_withdraw.afi == AFI_IP
&& mp_withdraw.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
@@ -1721,19 +1646,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
if (BGP_DEBUG (normal, NORMAL))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
+ zlog (peer->log, LOG_DEBUG,
+ "rcvd End-of-RIB for IPv4 Multicast from %s",
peer->host);
}
}
if (peer->afc[AFI_IP6][SAFI_UNICAST])
{
- if (mp_update.length
- && mp_update.afi == AFI_IP6
+ if (mp_update.length
+ && mp_update.afi == AFI_IP6
&& mp_update.safi == SAFI_UNICAST)
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
- if (mp_withdraw.length
- && mp_withdraw.afi == AFI_IP6
+ if (mp_withdraw.length
+ && mp_withdraw.afi == AFI_IP6
&& mp_withdraw.safi == SAFI_UNICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
@@ -1743,26 +1669,28 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
&& mp_withdraw.length == 0)
{
/* End-of-RIB received */
- SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
+ SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST],
+ PEER_STATUS_EOR_RECEIVED);
/* NSF delete stale route */
if (peer->nsf[AFI_IP6][SAFI_UNICAST])
bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
if (BGP_DEBUG (normal, NORMAL))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
+ zlog (peer->log, LOG_DEBUG,
+ "rcvd End-of-RIB for IPv6 Unicast from %s",
peer->host);
}
}
if (peer->afc[AFI_IP6][SAFI_MULTICAST])
{
- if (mp_update.length
- && mp_update.afi == AFI_IP6
+ if (mp_update.length
+ && mp_update.afi == AFI_IP6
&& mp_update.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
- if (mp_withdraw.length
- && mp_withdraw.afi == AFI_IP6
+ if (mp_withdraw.length
+ && mp_withdraw.afi == AFI_IP6
&& mp_withdraw.safi == SAFI_MULTICAST)
bgp_nlri_parse (peer, NULL, &mp_withdraw);
@@ -1778,19 +1706,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
+ zlog (peer->log, LOG_DEBUG,
+ "rcvd End-of-RIB for IPv6 Multicast from %s",
peer->host);
}
}
if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
{
- if (mp_update.length
- && mp_update.afi == AFI_IP
+ if (mp_update.length
+ && mp_update.afi == AFI_IP
&& mp_update.safi == BGP_SAFI_VPNV4)
bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
- if (mp_withdraw.length
- && mp_withdraw.afi == AFI_IP
+ if (mp_withdraw.length
+ && mp_withdraw.afi == AFI_IP
&& mp_withdraw.safi == BGP_SAFI_VPNV4)
bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
@@ -1802,32 +1731,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* End-of-RIB received */
if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
+ zlog (peer->log, LOG_DEBUG,
+ "rcvd End-of-RIB for VPNv4 Unicast from %s",
peer->host);
}
}
/* Everything is done. We unintern temporary structures which
interned in bgp_attr_parse(). */
- bgp_attr_unintern_sub (&attr);
- if (attr.extra)
- bgp_attr_extra_free (&attr);
-
- /* If peering is stopped due to some reason, do not generate BGP
- event. */
- if (peer->status != Established)
- return 0;
-
- /* Increment packet counter. */
- peer->update_in++;
- peer->update_time = bgp_clock ();
-
- /* Generate BGP event. */
- BGP_EVENT_ADD (peer, Receive_UPDATE_message);
+ bgp_attr_unintern_sub (&attr, true) ; /* true => free extra */
return 0;
}
+#if 0
/* Notify message treatment function. */
static void
bgp_notify_receive (struct peer *peer, bgp_size_t size)
@@ -1901,17 +1818,95 @@ bgp_notify_receive (struct peer *peer, bgp_size_t size)
BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
}
+#endif
+#if 0
/* Keepalive treatment function -- get keepalive send keepalive */
static void
bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
{
- if (BGP_DEBUG (keepalive, KEEPALIVE))
- zlog_debug ("%s KEEPALIVE rcvd", peer->host);
-
+ if (BGP_DEBUG (keepalive, KEEPALIVE))
+ zlog_debug ("%s KEEPALIVE rcvd", peer->host);
+
BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
}
+#endif
+
+/* Process incoming route refresh */
+void
+bgp_route_refresh_recv(bgp_peer peer, bgp_route_refresh rr)
+{
+ afi_t afi;
+ safi_t safi;
+ vector_index i;
+ char name[BUFSIZ];
+ int ret;
+
+ afi = rr->afi;
+ safi = rr->safi;
+
+ /* Adjust safi code. */
+ if (safi == BGP_SAFI_VPNV4)
+ safi = SAFI_MPLS_VPN;
+
+ /* ORF prefix-list name */
+ ret = snprintf (name, BUFSIZ, "%s.%d.%d", peer->host, afi, safi);
+ assert(ret < BUFSIZ);
+
+ if (rr->entries.end > 0)
+ {
+ for (i = 0; i < rr->entries.end; ++i)
+ {
+ bgp_orf_entry orfep = vector_slot(&rr->entries, i);
+
+ /* ignore unknown */
+ if (orfep->unknown)
+ continue;
+ if (orfep->orf_type == BGP_ORF_T_PREFIX)
+ {
+ if (orfep->remove_all)
+ {
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s rcvd Remove-All pfxlist ORF request",
+ peer->host);
+ prefix_bgp_orf_remove_all (name);
+ break;
+ }
+
+ ret = prefix_bgp_orf_set (name, afi, &orfep->body.orf_prefix,
+ orfep->deny, orfep->remove);
+
+ if (ret != CMD_SUCCESS)
+ {
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s Received misformatted prefixlist ORF."
+ "Remove All pfxlist", peer->host);
+ prefix_bgp_orf_remove_all (name);
+ break;
+ }
+
+ peer->orf_plist[afi][safi] =
+ prefix_list_lookup (AFI_ORF_PREFIX, name);
+ }
+ }
+
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
+ rr->defer ? "Defer" : "Immediate");
+ if (rr->defer)
+ return;
+ }
+
+ /* First update is deferred until ORF or ROUTE-REFRESH is received */
+ if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
+ UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
+
+ /* Perform route refreshment to the peer */
+ bgp_announce_route (peer, afi, safi);
+}
+
+#if 0
/* Route refresh message is received. */
static void
bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
@@ -1926,24 +1921,23 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
{
plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
peer->host);
- bgp_notify_send (peer,
- BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_BAD_MESTYPE);
+ bgp_peer_down_error (peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_BAD_MESTYPE);
return;
}
/* Status must be Established. */
- if (peer->status != Established)
+ if (peer->status != Established)
{
plog_err (peer->log,
"%s [Error] Route refresh packet received under status %s",
peer->host, LOOKUP (bgp_status_msg, peer->status));
- bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+ bgp_peer_down_error (peer, BGP_NOTIFY_FSM_ERR, 0);
return;
}
s = peer->ibuf;
-
+
/* Parse packet. */
afi = stream_getw (s);
reserved = stream_getc (s);
@@ -1980,7 +1974,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
{
zlog_info ("%s ORF route refresh length error", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0);
return;
}
@@ -1989,9 +1983,9 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
while ((stream_pnt (s) + 2) < end)
{
- orf_type = stream_getc (s);
+ orf_type = stream_getc (s);
orf_len = stream_getw (s);
-
+
/* orf_len in bounds? */
if ((stream_pnt (s) + orf_len) > end)
break; /* XXX: Notify instead?? */
@@ -2018,8 +2012,8 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
* and 7 bytes of ORF Address-filter entry from the stream
*/
if (orf_len < 7)
- break;
-
+ break;
+
/* ORF prefix-list name */
sprintf (name, "%s.%d.%d", peer->host, afi, safi);
@@ -2077,13 +2071,13 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
peer->host,
- (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
+ (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
(common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
- orfp.seq,
+ orfp.seq,
inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, BUFSIZ),
orfp.p.prefixlen, orfp.ge, orfp.le,
ok ? "" : " MALFORMED");
-
+
if (ok)
ret = prefix_bgp_orf_set (name, afi, &orfp,
(common & ORF_COMMON_PART_DENY ? 0 : 1 ),
@@ -2117,6 +2111,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
/* Perform route refreshment to the peer */
bgp_announce_route (peer, afi, safi);
}
+#endif
static int
bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
@@ -2133,24 +2128,26 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
end = pnt + length;
while (pnt < end)
- {
+ {
/* We need at least action, capability code and capability length. */
if (pnt + 3 > end)
{
zlog_info ("%s Capability length error", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ /* TODO: Is this the right notification ?? */
+ bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0);
return -1;
}
action = *pnt;
hdr = (struct capability_header *)(pnt + 1);
-
+
/* Action value check. */
if (action != CAPABILITY_ACTION_SET
&& action != CAPABILITY_ACTION_UNSET)
{
zlog_info ("%s Capability Action Value error %d",
peer->host, action);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ /* TODO: Is this the right notification ?? */
+ bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0);
return -1;
}
@@ -2162,7 +2159,8 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
if ((pnt + hdr->length + 3) > end)
{
zlog_info ("%s Capability length error", peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ /* TODO: Is this the right notification ?? */
+ bgp_peer_down_error (peer, BGP_NOTIFY_CEASE, 0);
return -1;
}
@@ -2178,7 +2176,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
/* Ignore capability when override-capability is set. */
if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
continue;
-
+
if (!bgp_afi_safi_valid_indices (afi, &safi))
{
if (BGP_DEBUG (normal, NORMAL))
@@ -2186,15 +2184,15 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
"(%u/%u)", peer->host, afi, safi);
continue;
}
-
+
/* Address family check. */
if (BGP_DEBUG (normal, NORMAL))
zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
peer->host,
- action == CAPABILITY_ACTION_SET
+ action == CAPABILITY_ACTION_SET
? "Advertising" : "Removing",
ntohs(mpc.afi) , mpc.safi);
-
+
if (action == CAPABILITY_ACTION_SET)
{
peer->afc_recv[afi][safi] = 1;
@@ -2208,11 +2206,20 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
{
peer->afc_recv[afi][safi] = 0;
peer->afc_nego[afi][safi] = 0;
+ bool completed ;
if (peer_active_nego (peer))
- bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
+ completed = bgp_clear_routes (peer, afi, safi, false);
else
+ {
+ completed = true ;
+ /* TODO: only used for unit tests. Test will need fixing */
+#if 0
BGP_EVENT_ADD (peer, BGP_Stop);
+#endif
+ } ;
+ /* if bgp_clear_routes does not complete. what do we do ? */
+ passert(completed) ;
}
}
else
@@ -2225,10 +2232,10 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
return 0;
}
-/* Dynamic Capability is received.
+/* Dynamic Capability is received.
*
* This is exported for unit-test purposes
- */
+ */ extern int bgp_capability_receive(struct peer*, bgp_size_t) ;
int
bgp_capability_receive (struct peer *peer, bgp_size_t size)
{
@@ -2245,25 +2252,26 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
{
plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
peer->host);
- bgp_notify_send (peer,
- BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_BAD_MESTYPE);
+ bgp_peer_down_error (peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_BAD_MESTYPE);
return -1;
}
/* Status must be Established. */
- if (peer->status != Established)
+ if (peer->state != bgp_peer_pEstablished)
{
plog_err (peer->log,
- "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
- bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+ "%s [Error] Dynamic capability packet received under status %s",
+ peer->host, LOOKUP (bgp_status_msg, peer->state));
+ bgp_peer_down_error (peer, BGP_NOTIFY_FSM_ERR, 0);
return -1;
}
/* Parse packet. */
return bgp_capability_msg_parse (peer, pnt, size);
}
-
+
+#if 0
/* BGP read utility function. */
static int
bgp_read_packet (struct peer *peer)
@@ -2281,7 +2289,7 @@ bgp_read_packet (struct peer *peer)
nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
/* If read byte is smaller than zero then error occured. */
- if (nbytes < 0)
+ if (nbytes < 0)
{
/* Transient error should retry */
if (nbytes == -2)
@@ -2290,7 +2298,7 @@ bgp_read_packet (struct peer *peer)
plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
peer->host, safe_strerror (errno));
- if (peer->status == Established)
+ if (peer->status == Established)
{
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
{
@@ -2303,16 +2311,16 @@ bgp_read_packet (struct peer *peer)
BGP_EVENT_ADD (peer, TCP_fatal_error);
return -1;
- }
+ }
/* When read byte is zero : clear bgp peer and return */
- if (nbytes == 0)
+ if (nbytes == 0)
{
if (BGP_DEBUG (events, EVENTS))
plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
peer->host, peer->fd);
- if (peer->status == Established)
+ if (peer->status == Established)
{
if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
{
@@ -2333,7 +2341,9 @@ bgp_read_packet (struct peer *peer)
return 0;
}
+#endif
+#if 0
/* Marker check. */
static int
bgp_marker_all_one (struct stream *s, int length)
@@ -2346,7 +2356,9 @@ bgp_marker_all_one (struct stream *s, int length)
return 1;
}
+#endif
+#if 0
/* Starting point of packet process function. */
int
bgp_read (struct thread *thread)
@@ -2386,7 +2398,7 @@ bgp_read (struct thread *thread)
ret = bgp_read_packet (peer);
/* Header read error or partial read packet. */
- if (ret < 0)
+ if (ret < 0)
goto done;
/* Get size and type. */
@@ -2403,15 +2415,14 @@ bgp_read (struct thread *thread)
if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
&& ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
{
- bgp_notify_send (peer,
- BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_NOT_SYNC);
+ bgp_peer_down_error (peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_NOT_SYNC);
goto done;
}
/* BGP type check. */
- if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
- && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
+ if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
+ && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
&& type != BGP_MSG_ROUTE_REFRESH_NEW
&& type != BGP_MSG_ROUTE_REFRESH_OLD
&& type != BGP_MSG_CAPABILITY)
@@ -2440,7 +2451,7 @@ bgp_read (struct thread *thread)
if (BGP_DEBUG (normal, NORMAL))
plog_debug (peer->log,
"%s bad message length - %d for %s",
- peer->host, size,
+ peer->host, size,
type == 128 ? "ROUTE-REFRESH" :
bgp_type_str[(int) type]);
bgp_notify_send_with_data (peer,
@@ -2455,7 +2466,7 @@ bgp_read (struct thread *thread)
}
ret = bgp_read_packet (peer);
- if (ret < 0)
+ if (ret < 0)
goto done;
/* Get size and type again. */
@@ -2464,11 +2475,11 @@ bgp_read (struct thread *thread)
/* BGP packet dump function. */
bgp_dump_packet (peer, type, peer->ibuf);
-
+
size = (peer->packet_size - BGP_HEADER_SIZE);
/* Read rest of the packet and call each sort of packet routine */
- switch (type)
+ switch (type)
{
case BGP_MSG_OPEN:
peer->open_in++;
@@ -2506,7 +2517,8 @@ bgp_read (struct thread *thread)
{
if (BGP_DEBUG (events, EVENTS))
zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
- peer_delete (peer);
+ bgp_peer_delete (peer);
}
return 0;
}
+#endif