summaryrefslogtreecommitdiff
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c142
1 files changed, 132 insertions, 10 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 5c17c370..b9537169 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -26,6 +26,7 @@
#include "nest/cli.h"
#include "bgp.h"
+#include "proto/bmp/bmp.h"
#define BGP_RR_REQUEST 0
@@ -166,6 +167,7 @@ bgp_create_notification(struct bgp_conn *conn, byte *buf)
buf[0] = conn->notify_code;
buf[1] = conn->notify_subcode;
memcpy(buf+2, conn->notify_data, conn->notify_size);
+ bmp_peer_down(p, BE_NONE, buf, conn->notify_size + 2);
return buf + 2 + conn->notify_size;
}
@@ -975,6 +977,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE);
bgp_start_timer(conn->hold_timer, conn->hold_time);
bgp_conn_enter_openconfirm_state(conn);
+ bmp_put_recv_bgp_open_msg(p, pkt, len);
}
@@ -1563,7 +1566,10 @@ bgp_encode_nlri_ip4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
memcpy(pos, &a, b);
ADVANCE(pos, size, b);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -1648,7 +1654,10 @@ bgp_encode_nlri_ip6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
memcpy(pos, &a, b);
ADVANCE(pos, size, b);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -1736,7 +1745,10 @@ bgp_encode_nlri_vpn4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
memcpy(pos, &a, b);
ADVANCE(pos, size, b);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -1833,7 +1845,10 @@ bgp_encode_nlri_vpn6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
memcpy(pos, &a, b);
ADVANCE(pos, size, b);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -1920,7 +1935,10 @@ bgp_encode_nlri_flow4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
memcpy(pos, net->data, flen);
ADVANCE(pos, size, flen);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -2012,7 +2030,10 @@ bgp_encode_nlri_flow6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
memcpy(pos, net->data, flen);
ADVANCE(pos, size, flen);
- bgp_free_prefix(s->channel, px);
+ if (!s->sham)
+ bgp_free_prefix(s->channel, px);
+ else
+ rem_node(&px->buck_node);
}
return pos - buf;
@@ -2256,7 +2277,8 @@ bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
if (la < 0)
{
/* Attribute list too long */
- bgp_withdraw_bucket(s->channel, buck);
+ if (!s->sham)
+ bgp_withdraw_bucket(s->channel, buck);
return NULL;
}
@@ -2303,7 +2325,8 @@ bgp_create_mp_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
if (la < 0)
{
/* Attribute list too long */
- bgp_withdraw_bucket(s->channel, buck);
+ if (!s->sham)
+ bgp_withdraw_bucket(s->channel, buck);
return NULL;
}
@@ -2384,6 +2407,94 @@ bgp_create_mp_unreach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
return buf+11+len;
}
+
+#ifdef CONFIG_BMP
+
+static byte *
+bgp_create_update_bmp(struct bgp_channel *c, byte *buf, struct bgp_bucket *buck, bool update)
+{
+ struct bgp_proto *p = (void *) c->c.proto;
+ byte *end = buf + (BGP_MAX_EXT_MSG_LENGTH - BGP_HEADER_LENGTH);
+ /* FIXME: must be a bit shorter */
+
+ struct bgp_caps *peer = p->conn->remote_caps;
+ const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi);
+ struct bgp_write_state s = {
+ .proto = p,
+ .channel = c,
+ .pool = tmp_linpool,
+ .mp_reach = (c->afi != BGP_AF_IPV4) || rem->ext_next_hop,
+ .as4_session = 1,
+ .add_path = c->add_path_rx,
+ .mpls = c->desc->mpls,
+ .sham = 1,
+ };
+
+ if (!update)
+ {
+ return !s.mp_reach ?
+ bgp_create_ip_unreach(&s, buck, buf, end):
+ bgp_create_mp_unreach(&s, buck, buf, end);
+ }
+ else
+ {
+ return !s.mp_reach ?
+ bgp_create_ip_reach(&s, buck, buf, end):
+ bgp_create_mp_reach(&s, buck, buf, end);
+ }
+}
+
+static byte *
+bgp_bmp_prepare_bgp_hdr(byte *buf, const u16 msg_size, const u8 msg_type)
+{
+ memset(buf + BGP_MSG_HDR_MARKER_POS, 0xff, BGP_MSG_HDR_MARKER_SIZE);
+ put_u16(buf + BGP_MSG_HDR_LENGTH_POS, msg_size);
+ put_u8(buf + BGP_MSG_HDR_TYPE_POS, msg_type);
+
+ return buf + BGP_MSG_HDR_TYPE_POS + BGP_MSG_HDR_TYPE_SIZE;
+}
+
+void
+bgp_rte_update_in_notify(struct channel *C, const net_addr *n,
+ const struct rte *new, const struct rte_src *src)
+{
+// struct bgp_proto *p = (void *) C->proto;
+ struct bgp_channel *c = (void *) C;
+
+ byte buf[BGP_MAX_EXT_MSG_LENGTH];
+ byte *pkt = buf + BGP_HEADER_LENGTH;
+
+ ea_list *attrs = new ? new->attrs->eattrs : NULL;
+ uint ea_size = new ? (sizeof(ea_list) + attrs->count * sizeof(eattr)) : 0;
+ uint bucket_size = sizeof(struct bgp_bucket) + ea_size;
+ uint prefix_size = sizeof(struct bgp_prefix) + n->length;
+
+ /* Sham bucket */
+ struct bgp_bucket *b = alloca(bucket_size);
+ *b = (struct bgp_bucket) { };
+ init_list(&b->prefixes);
+
+ if (attrs)
+ memcpy(b->eattrs, attrs, ea_size);
+
+ /* Sham prefix */
+ struct bgp_prefix *px = alloca(prefix_size);
+ *px = (struct bgp_prefix) { };
+ px->path_id = src->private_id;
+ net_copy(px->net, n);
+ add_tail(&b->prefixes, &px->buck_node);
+
+ byte *end = bgp_create_update_bmp(c, pkt, b, !!new);
+ if (!end)
+ return;
+
+ bgp_bmp_prepare_bgp_hdr(buf, end - buf, PKT_UPDATE);
+ bmp_route_monitor_put_update_in_pre_msg(buf, end - buf);
+}
+
+#endif /* CONFIG_BMP */
+
+
static byte *
bgp_create_update(struct bgp_channel *c, byte *buf)
{
@@ -2484,7 +2595,7 @@ bgp_create_mp_end_mark(struct bgp_channel *c, byte *buf)
return buf+10;
}
-static byte *
+byte *
bgp_create_end_mark(struct bgp_channel *c, byte *buf)
{
struct bgp_proto *p = (void *) c->c.proto;
@@ -2635,6 +2746,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
s.ip_reach_len = len - pos;
s.ip_reach_nlri = pkt + pos;
+ bmp_route_monitor_update_in_pre_begin();
if (s.attr_len)
ea = bgp_decode_attrs(&s, s.attrs, s.attr_len);
@@ -2666,6 +2778,9 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
bgp_decode_nlri(&s, s.mp_reach_af, s.mp_reach_nlri, s.mp_reach_len,
ea, s.mp_next_hop_data, s.mp_next_hop_len);
+ bmp_route_monitor_update_in_pre_commit(p);
+ bmp_route_monitor_update_in_pre_end();
+
done:
rta_free(s.cached_rta);
lp_restore(tmp_linpool, &tmpp);
@@ -2917,7 +3032,12 @@ bgp_fire_tx(struct bgp_conn *conn)
{
conn->packets_to_send &= ~(1 << PKT_OPEN);
end = bgp_create_open(conn, pkt);
- return bgp_send(conn, PKT_OPEN, end - buf);
+ int rv = bgp_send(conn, PKT_OPEN, end - buf);
+ if (rv >= 0)
+ {
+ bmp_put_sent_bgp_open_msg(p, pkt, end - buf);
+ }
+ return rv;
}
else if (s & (1 << PKT_KEEPALIVE))
{
@@ -3216,6 +3336,8 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len)
p->p.disabled = 1;
}
}
+
+ bmp_peer_down(p, BE_NONE, pkt, len);
}
static void