summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_updgrp_packet.c
diff options
context:
space:
mode:
authorwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:03:14 +0200
committerwhitespace / reindent <invalid@invalid.invalid>2017-07-17 14:04:07 +0200
commitd62a17aedeb0eebdba98238874bb13d62c48dbf9 (patch)
tree3b319b1d61c8b85b4d1f06adf8b844bb8a9b5107 /bgpd/bgp_updgrp_packet.c
parent*: add indent control files (diff)
downloadfrr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.tar.xz
frr-d62a17aedeb0eebdba98238874bb13d62c48dbf9.zip
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'` Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'bgpd/bgp_updgrp_packet.c')
-rw-r--r--bgpd/bgp_updgrp_packet.c2025
1 files changed, 1015 insertions, 1010 deletions
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 0ef4d4c0c..d7a4a3698 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -63,37 +63,34 @@
/********************
* PUBLIC FUNCTIONS
********************/
-struct bpacket *
-bpacket_alloc ()
+struct bpacket *bpacket_alloc()
{
- struct bpacket *pkt;
+ struct bpacket *pkt;
- pkt =
- (struct bpacket *) XCALLOC (MTYPE_BGP_PACKET, sizeof (struct bpacket));
+ pkt = (struct bpacket *)XCALLOC(MTYPE_BGP_PACKET,
+ sizeof(struct bpacket));
- return pkt;
+ return pkt;
}
-void
-bpacket_free (struct bpacket *pkt)
+void bpacket_free(struct bpacket *pkt)
{
- if (pkt->buffer)
- stream_free (pkt->buffer);
- pkt->buffer = NULL;
- XFREE (MTYPE_BGP_PACKET, pkt);
+ if (pkt->buffer)
+ stream_free(pkt->buffer);
+ pkt->buffer = NULL;
+ XFREE(MTYPE_BGP_PACKET, pkt);
}
-void
-bpacket_queue_init (struct bpacket_queue *q)
+void bpacket_queue_init(struct bpacket_queue *q)
{
- TAILQ_INIT (&(q->pkts));
+ TAILQ_INIT(&(q->pkts));
}
/*
* bpacket_queue_sanity_check
*/
-void
-bpacket_queue_sanity_check (struct bpacket_queue __attribute__ ((__unused__)) *q)
+void bpacket_queue_sanity_check(struct bpacket_queue __attribute__((__unused__))
+ * q)
{
#if 0
struct bpacket *pkt;
@@ -130,21 +127,20 @@ bpacket_queue_sanity_check (struct bpacket_queue __attribute__ ((__unused__)) *q
*
* Users of bpacket_queue should use bpacket_queue_add instead.
*/
-static void
-bpacket_queue_add_packet (struct bpacket_queue *q, struct bpacket *pkt)
+static void bpacket_queue_add_packet(struct bpacket_queue *q,
+ struct bpacket *pkt)
{
- struct bpacket *last_pkt;
+ struct bpacket *last_pkt;
- if (TAILQ_EMPTY (&(q->pkts)))
- TAILQ_INSERT_TAIL (&(q->pkts), pkt, pkt_train);
- else
- {
- last_pkt = bpacket_queue_last (q);
- TAILQ_INSERT_AFTER (&(q->pkts), last_pkt, pkt, pkt_train);
- }
- q->curr_count++;
- if (q->hwm_count < q->curr_count)
- q->hwm_count = q->curr_count;
+ if (TAILQ_EMPTY(&(q->pkts)))
+ TAILQ_INSERT_TAIL(&(q->pkts), pkt, pkt_train);
+ else {
+ last_pkt = bpacket_queue_last(q);
+ TAILQ_INSERT_AFTER(&(q->pkts), last_pkt, pkt, pkt_train);
+ }
+ q->curr_count++;
+ if (q->hwm_count < q->curr_count)
+ q->hwm_count = q->curr_count;
}
/*
@@ -154,117 +150,107 @@ bpacket_queue_add_packet (struct bpacket_queue *q, struct bpacket *pkt)
* not free or use the stream after
* invoking this function.
*/
-struct bpacket *
-bpacket_queue_add (struct bpacket_queue *q, struct stream *s,
- struct bpacket_attr_vec_arr *vecarrp)
+struct bpacket *bpacket_queue_add(struct bpacket_queue *q, struct stream *s,
+ struct bpacket_attr_vec_arr *vecarrp)
{
- struct bpacket *pkt;
- struct bpacket *last_pkt;
-
-
- pkt = bpacket_alloc ();
- if (TAILQ_EMPTY (&(q->pkts)))
- {
- pkt->ver = 1;
- pkt->buffer = s;
- if (vecarrp)
- memcpy (&pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr));
- else
- bpacket_attr_vec_arr_reset (&pkt->arr);
- bpacket_queue_add_packet (q, pkt);
- bpacket_queue_sanity_check (q);
- return pkt;
- }
+ struct bpacket *pkt;
+ struct bpacket *last_pkt;
+
+
+ pkt = bpacket_alloc();
+ if (TAILQ_EMPTY(&(q->pkts))) {
+ pkt->ver = 1;
+ pkt->buffer = s;
+ if (vecarrp)
+ memcpy(&pkt->arr, vecarrp,
+ sizeof(struct bpacket_attr_vec_arr));
+ else
+ bpacket_attr_vec_arr_reset(&pkt->arr);
+ bpacket_queue_add_packet(q, pkt);
+ bpacket_queue_sanity_check(q);
+ return pkt;
+ }
- /*
- * Fill in the new information into the current sentinel and create a
- * new sentinel.
- */
- bpacket_queue_sanity_check (q);
- last_pkt = bpacket_queue_last (q);
- assert (last_pkt->buffer == NULL);
- last_pkt->buffer = s;
- if (vecarrp)
- memcpy (&last_pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr));
- else
- bpacket_attr_vec_arr_reset (&last_pkt->arr);
-
- pkt->ver = last_pkt->ver;
- pkt->ver++;
- bpacket_queue_add_packet (q, pkt);
-
- bpacket_queue_sanity_check (q);
- return last_pkt;
+ /*
+ * Fill in the new information into the current sentinel and create a
+ * new sentinel.
+ */
+ bpacket_queue_sanity_check(q);
+ last_pkt = bpacket_queue_last(q);
+ assert(last_pkt->buffer == NULL);
+ last_pkt->buffer = s;
+ if (vecarrp)
+ memcpy(&last_pkt->arr, vecarrp,
+ sizeof(struct bpacket_attr_vec_arr));
+ else
+ bpacket_attr_vec_arr_reset(&last_pkt->arr);
+
+ pkt->ver = last_pkt->ver;
+ pkt->ver++;
+ bpacket_queue_add_packet(q, pkt);
+
+ bpacket_queue_sanity_check(q);
+ return last_pkt;
}
-struct bpacket *
-bpacket_queue_first (struct bpacket_queue *q)
+struct bpacket *bpacket_queue_first(struct bpacket_queue *q)
{
- return (TAILQ_FIRST (&(q->pkts)));
+ return (TAILQ_FIRST(&(q->pkts)));
}
-struct bpacket *
-bpacket_queue_last (struct bpacket_queue *q)
+struct bpacket *bpacket_queue_last(struct bpacket_queue *q)
{
- return TAILQ_LAST (&(q->pkts), pkt_queue);
+ return TAILQ_LAST(&(q->pkts), pkt_queue);
}
-struct bpacket *
-bpacket_queue_remove (struct bpacket_queue *q)
+struct bpacket *bpacket_queue_remove(struct bpacket_queue *q)
{
- struct bpacket *first;
+ struct bpacket *first;
- first = bpacket_queue_first (q);
- if (first)
- {
- TAILQ_REMOVE (&(q->pkts), first, pkt_train);
- q->curr_count--;
- }
- return first;
+ first = bpacket_queue_first(q);
+ if (first) {
+ TAILQ_REMOVE(&(q->pkts), first, pkt_train);
+ q->curr_count--;
+ }
+ return first;
}
-unsigned int
-bpacket_queue_length (struct bpacket_queue *q)
+unsigned int bpacket_queue_length(struct bpacket_queue *q)
{
- return q->curr_count - 1;
+ return q->curr_count - 1;
}
-unsigned int
-bpacket_queue_hwm_length (struct bpacket_queue *q)
+unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q)
{
- return q->hwm_count - 1;
+ return q->hwm_count - 1;
}
-int
-bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q)
+int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q)
{
- if (q->curr_count >= bgp->default_subgroup_pkt_queue_max)
- return 1;
- return 0;
+ if (q->curr_count >= bgp->default_subgroup_pkt_queue_max)
+ return 1;
+ return 0;
}
-void
-bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf)
+void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf)
{
- if (!pkt || !paf)
- return;
+ if (!pkt || !paf)
+ return;
- LIST_INSERT_HEAD (&(pkt->peers), paf, pkt_train);
- paf->next_pkt_to_send = pkt;
+ LIST_INSERT_HEAD(&(pkt->peers), paf, pkt_train);
+ paf->next_pkt_to_send = pkt;
}
/*
* bpacket_queue_cleanup
*/
-void
-bpacket_queue_cleanup (struct bpacket_queue *q)
+void bpacket_queue_cleanup(struct bpacket_queue *q)
{
- struct bpacket *pkt;
+ struct bpacket *pkt;
- while ((pkt = bpacket_queue_remove (q)))
- {
- bpacket_free (pkt);
- }
+ while ((pkt = bpacket_queue_remove(q))) {
+ bpacket_free(pkt);
+ }
}
/*
@@ -275,63 +261,60 @@ bpacket_queue_cleanup (struct bpacket_queue *q)
*
* @return the number of packets deleted.
*/
-static int
-bpacket_queue_compact (struct bpacket_queue *q)
+static int bpacket_queue_compact(struct bpacket_queue *q)
{
- int num_deleted;
- struct bpacket *pkt, *removed_pkt;
+ int num_deleted;
+ struct bpacket *pkt, *removed_pkt;
- num_deleted = 0;
+ num_deleted = 0;
- while (1)
- {
- pkt = bpacket_queue_first (q);
- if (!pkt)
- break;
+ while (1) {
+ pkt = bpacket_queue_first(q);
+ if (!pkt)
+ break;
- /*
- * Don't delete the sentinel.
- */
- if (!pkt->buffer)
- break;
+ /*
+ * Don't delete the sentinel.
+ */
+ if (!pkt->buffer)
+ break;
- if (!LIST_EMPTY (&(pkt->peers)))
- break;
+ if (!LIST_EMPTY(&(pkt->peers)))
+ break;
- removed_pkt = bpacket_queue_remove (q);
- assert (pkt == removed_pkt);
- bpacket_free (removed_pkt);
+ removed_pkt = bpacket_queue_remove(q);
+ assert(pkt == removed_pkt);
+ bpacket_free(removed_pkt);
- num_deleted++;
- }
+ num_deleted++;
+ }
- bpacket_queue_sanity_check (q);
- return num_deleted;
+ bpacket_queue_sanity_check(q);
+ return num_deleted;
}
-void
-bpacket_queue_advance_peer (struct peer_af *paf)
+void bpacket_queue_advance_peer(struct peer_af *paf)
{
- struct bpacket *pkt;
- struct bpacket *old_pkt;
-
- old_pkt = paf->next_pkt_to_send;
- if (old_pkt->buffer == NULL)
- /* Already at end of list */
- return;
-
- LIST_REMOVE (paf, pkt_train);
- pkt = TAILQ_NEXT (old_pkt, pkt_train);
- bpacket_add_peer (pkt, paf);
-
- if (!bpacket_queue_compact (PAF_PKTQ (paf)))
- return;
-
- /*
- * Deleted one or more packets. Check if we can now merge this
- * peer's subgroup into another subgroup.
- */
- update_subgroup_check_merge (paf->subgroup, "advanced peer in queue");
+ struct bpacket *pkt;
+ struct bpacket *old_pkt;
+
+ old_pkt = paf->next_pkt_to_send;
+ if (old_pkt->buffer == NULL)
+ /* Already at end of list */
+ return;
+
+ LIST_REMOVE(paf, pkt_train);
+ pkt = TAILQ_NEXT(old_pkt, pkt_train);
+ bpacket_add_peer(pkt, paf);
+
+ if (!bpacket_queue_compact(PAF_PKTQ(paf)))
+ return;
+
+ /*
+ * Deleted one or more packets. Check if we can now merge this
+ * peer's subgroup into another subgroup.
+ */
+ update_subgroup_check_merge(paf->subgroup, "advanced peer in queue");
}
/*
@@ -340,561 +323,587 @@ bpacket_queue_advance_peer (struct peer_af *paf)
* Remove the peer from the packet queue of the subgroup it belongs
* to.
*/
-void
-bpacket_queue_remove_peer (struct peer_af *paf)
+void bpacket_queue_remove_peer(struct peer_af *paf)
{
- struct bpacket_queue *q;
+ struct bpacket_queue *q;
- q = PAF_PKTQ (paf);
- assert (q);
- if (!q)
- return;
+ q = PAF_PKTQ(paf);
+ assert(q);
+ if (!q)
+ return;
- LIST_REMOVE (paf, pkt_train);
- paf->next_pkt_to_send = NULL;
+ LIST_REMOVE(paf, pkt_train);
+ paf->next_pkt_to_send = NULL;
- bpacket_queue_compact (q);
+ bpacket_queue_compact(q);
}
-unsigned int
-bpacket_queue_virtual_length (struct peer_af *paf)
+unsigned int bpacket_queue_virtual_length(struct peer_af *paf)
{
- struct bpacket *pkt;
- struct bpacket *last;
- struct bpacket_queue *q;
+ struct bpacket *pkt;
+ struct bpacket *last;
+ struct bpacket_queue *q;
- pkt = paf->next_pkt_to_send;
- if (!pkt || (pkt->buffer == NULL))
- /* Already at end of list */
- return 0;
+ pkt = paf->next_pkt_to_send;
+ if (!pkt || (pkt->buffer == NULL))
+ /* Already at end of list */
+ return 0;
- q = PAF_PKTQ (paf);
- if (TAILQ_EMPTY (&(q->pkts)))
- return 0;
+ q = PAF_PKTQ(paf);
+ if (TAILQ_EMPTY(&(q->pkts)))
+ return 0;
- last = TAILQ_LAST (&(q->pkts), pkt_queue);
- if (last->ver >= pkt->ver)
- return last->ver - pkt->ver;
+ last = TAILQ_LAST(&(q->pkts), pkt_queue);
+ if (last->ver >= pkt->ver)
+ return last->ver - pkt->ver;
- /* sequence # rolled over */
- return (UINT_MAX - pkt->ver + 1) + last->ver;
+ /* sequence # rolled over */
+ return (UINT_MAX - pkt->ver + 1) + last->ver;
}
/*
* Dump the bpacket queue
*/
-void
-bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty)
+void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty)
{
- struct bpacket *pkt;
- struct peer_af *paf;
-
- pkt = bpacket_queue_first (q);
- while (pkt)
- {
- vty_out (vty, " Packet %p ver %u buffer %p\n", pkt, pkt->ver,
- pkt->buffer);
-
- LIST_FOREACH (paf, &(pkt->peers), pkt_train)
- {
- vty_out (vty, " - %s\n", paf->peer->host);
- }
- pkt = bpacket_next (pkt);
- }
- return;
+ struct bpacket *pkt;
+ struct peer_af *paf;
+
+ pkt = bpacket_queue_first(q);
+ while (pkt) {
+ vty_out(vty, " Packet %p ver %u buffer %p\n", pkt, pkt->ver,
+ pkt->buffer);
+
+ LIST_FOREACH(paf, &(pkt->peers), pkt_train)
+ {
+ vty_out(vty, " - %s\n", paf->peer->host);
+ }
+ pkt = bpacket_next(pkt);
+ }
+ return;
}
-struct stream *
-bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
+struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
+ struct peer_af *paf)
{
- struct stream *s = NULL;
- bpacket_attr_vec *vec;
- struct peer *peer;
- char buf[BUFSIZ];
- char buf2[BUFSIZ];
-
- s = stream_dup (pkt->buffer);
- peer = PAF_PEER(paf);
-
- vec = &pkt->arr.entries[BGP_ATTR_VEC_NH];
- if (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED))
- {
- u_int8_t nhlen;
- afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */
- int route_map_sets_nh;
- nhlen = stream_getc_from (s, vec->offset);
- if (peer_cap_enhe(peer, paf->afi, paf->safi))
- nhafi = AFI_IP6;
- else
- nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
-
- if (nhafi == AFI_IP)
- {
- struct in_addr v4nh, *mod_v4nh;
- int nh_modified = 0;
- size_t offset_nh = vec->offset + 1;
-
- route_map_sets_nh =
- (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED) ||
- CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
-
- switch (nhlen)
- {
- case BGP_ATTR_NHLEN_IPV4:
- break;
- case BGP_ATTR_NHLEN_VPNV4:
- offset_nh += 8;
- break;
- default:
- /* TODO: handle IPv6 nexthops */
- zlog_warn ("%s: %s: invalid MP nexthop length (AFI IP): %u",
- __func__, peer->host, nhlen);
- stream_free (s);
- return NULL;
- }
-
- stream_get_from (&v4nh, s, offset_nh, IPV4_MAX_BYTELEN);
- mod_v4nh = &v4nh;
-
- /*
- * If route-map has set the nexthop, that is always used; if it is
- * specified as peer-address, the peering address is picked up.
- * Otherwise, if NH is unavailable from attribute, the peering addr
- * is picked up; the "NH unavailable" case also covers next-hop-self
- * and some other scenarios -- see subgroup_announce_check(). In
- * all other cases, use the nexthop carried in the attribute unless
- * it is EBGP non-multiaccess and there is no next-hop-unchanged setting.
- * Note: It is assumed route-map cannot set the nexthop to an
- * invalid value.
- */
- if (route_map_sets_nh)
- {
- if (CHECK_FLAG(vec->flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))
- {
- mod_v4nh = &peer->nexthop.v4;
- nh_modified = 1;
- }
- }
- else if (!v4nh.s_addr)
- {
- mod_v4nh = &peer->nexthop.v4;
- nh_modified = 1;
- }
- else if (peer->sort == BGP_PEER_EBGP &&
- paf->safi != SAFI_EVPN &&
- (bgp_multiaccess_check_v4 (v4nh, peer) == 0) &&
- !CHECK_FLAG(vec->flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
- !peer_af_flag_check (peer, nhafi, paf->safi,
- PEER_FLAG_NEXTHOP_UNCHANGED))
- {
- /* NOTE: not handling case where NH has new AFI */
- mod_v4nh = &peer->nexthop.v4;
- nh_modified = 1;
- }
-
- if (nh_modified) /* allow for VPN RD */
- stream_put_in_addr_at (s, offset_nh, mod_v4nh);
-
- if (bgp_debug_update(peer, NULL, NULL, 0))
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s%s",
- PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id,
- peer->host, inet_ntoa (*mod_v4nh),
- (nhlen == 12 ? " and RD" : ""));
+ struct stream *s = NULL;
+ bpacket_attr_vec *vec;
+ struct peer *peer;
+ char buf[BUFSIZ];
+ char buf2[BUFSIZ];
+
+ s = stream_dup(pkt->buffer);
+ peer = PAF_PEER(paf);
+
+ vec = &pkt->arr.entries[BGP_ATTR_VEC_NH];
+ if (CHECK_FLAG(vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED)) {
+ u_int8_t nhlen;
+ afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */
+ int route_map_sets_nh;
+ nhlen = stream_getc_from(s, vec->offset);
+ if (peer_cap_enhe(peer, paf->afi, paf->safi))
+ nhafi = AFI_IP6;
+ else
+ nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
+
+ if (nhafi == AFI_IP) {
+ struct in_addr v4nh, *mod_v4nh;
+ int nh_modified = 0;
+ size_t offset_nh = vec->offset + 1;
+
+ route_map_sets_nh =
+ (CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED)
+ || CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
+
+ switch (nhlen) {
+ case BGP_ATTR_NHLEN_IPV4:
+ break;
+ case BGP_ATTR_NHLEN_VPNV4:
+ offset_nh += 8;
+ break;
+ default:
+ /* TODO: handle IPv6 nexthops */
+ zlog_warn(
+ "%s: %s: invalid MP nexthop length (AFI IP): %u",
+ __func__, peer->host, nhlen);
+ stream_free(s);
+ return NULL;
+ }
+
+ stream_get_from(&v4nh, s, offset_nh, IPV4_MAX_BYTELEN);
+ mod_v4nh = &v4nh;
+
+ /*
+ * If route-map has set the nexthop, that is always
+ * used; if it is
+ * specified as peer-address, the peering address is
+ * picked up.
+ * Otherwise, if NH is unavailable from attribute, the
+ * peering addr
+ * is picked up; the "NH unavailable" case also covers
+ * next-hop-self
+ * and some other scenarios -- see
+ * subgroup_announce_check(). In
+ * all other cases, use the nexthop carried in the
+ * attribute unless
+ * it is EBGP non-multiaccess and there is no
+ * next-hop-unchanged setting.
+ * Note: It is assumed route-map cannot set the nexthop
+ * to an
+ * invalid value.
+ */
+ if (route_map_sets_nh) {
+ if (CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
+ mod_v4nh = &peer->nexthop.v4;
+ nh_modified = 1;
+ }
+ } else if (!v4nh.s_addr) {
+ mod_v4nh = &peer->nexthop.v4;
+ nh_modified = 1;
+ } else if (
+ peer->sort == BGP_PEER_EBGP
+ && paf->safi != SAFI_EVPN
+ && (bgp_multiaccess_check_v4(v4nh, peer) == 0)
+ && !CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED)
+ && !peer_af_flag_check(
+ peer, nhafi, paf->safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)) {
+ /* NOTE: not handling case where NH has new AFI
+ */
+ mod_v4nh = &peer->nexthop.v4;
+ nh_modified = 1;
+ }
+
+ if (nh_modified) /* allow for VPN RD */
+ stream_put_in_addr_at(s, offset_nh, mod_v4nh);
+
+ if (bgp_debug_update(peer, NULL, NULL, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ nexthop %s%s",
+ PAF_SUBGRP(paf)->update_group->id,
+ PAF_SUBGRP(paf)->id, peer->host,
+ inet_ntoa(*mod_v4nh),
+ (nhlen == 12 ? " and RD" : ""));
+ } else if (nhafi == AFI_IP6) {
+ struct in6_addr v6nhglobal, *mod_v6nhg;
+ struct in6_addr v6nhlocal, *mod_v6nhl;
+ int gnh_modified, lnh_modified;
+ size_t offset_nhglobal = vec->offset + 1;
+ size_t offset_nhlocal = vec->offset + 1;
+
+ gnh_modified = lnh_modified = 0;
+ mod_v6nhg = &v6nhglobal;
+ mod_v6nhl = &v6nhlocal;
+
+ route_map_sets_nh =
+ (CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED)
+ || CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
+
+ /*
+ * The logic here is rather similar to that for IPv4,
+ * the
+ * additional work being to handle 1 or 2 nexthops.
+ * Also, 3rd
+ * party nexthop is not propagated for EBGP right now.
+ */
+ switch (nhlen) {
+ case BGP_ATTR_NHLEN_IPV6_GLOBAL:
+ break;
+ case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
+ offset_nhlocal += IPV6_MAX_BYTELEN;
+ break;
+ case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
+ offset_nhglobal += 8;
+ break;
+ case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
+ offset_nhglobal += 8;
+ offset_nhlocal += 8 * 2 + IPV6_MAX_BYTELEN;
+ break;
+ default:
+ /* TODO: handle IPv4 nexthops */
+ zlog_warn(
+ "%s: %s: invalid MP nexthop length (AFI IP6): %u",
+ __func__, peer->host, nhlen);
+ stream_free(s);
+ return NULL;
+ }
+
+ stream_get_from(&v6nhglobal, s, offset_nhglobal,
+ IPV6_MAX_BYTELEN);
+ if (route_map_sets_nh) {
+ if (CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
+ mod_v6nhg = &peer->nexthop.v6_global;
+ gnh_modified = 1;
+ }
+ } else if (IN6_IS_ADDR_UNSPECIFIED(&v6nhglobal)) {
+ mod_v6nhg = &peer->nexthop.v6_global;
+ gnh_modified = 1;
+ } else if (
+ peer->sort == BGP_PEER_EBGP
+ && !CHECK_FLAG(
+ vec->flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED)
+ && !peer_af_flag_check(
+ peer, nhafi, paf->safi,
+ PEER_FLAG_NEXTHOP_UNCHANGED)) {
+ /* NOTE: not handling case where NH has new AFI
+ */
+ mod_v6nhg = &peer->nexthop.v6_global;
+ gnh_modified = 1;
+ }
+
+
+ if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
+ || nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
+ stream_get_from(&v6nhlocal, s, offset_nhlocal,
+ IPV6_MAX_BYTELEN);
+ if (IN6_IS_ADDR_UNSPECIFIED(&v6nhlocal)) {
+ mod_v6nhl = &peer->nexthop.v6_local;
+ lnh_modified = 1;
+ }
+ }
+
+ if (gnh_modified)
+ stream_put_in6_addr_at(s, offset_nhglobal,
+ mod_v6nhg);
+ if (lnh_modified)
+ stream_put_in6_addr_at(s, offset_nhlocal,
+ mod_v6nhl);
+
+ if (bgp_debug_update(peer, NULL, NULL, 0)) {
+ if (nhlen == 32 || nhlen == 48)
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ mp_nexthops %s, %s%s",
+ PAF_SUBGRP(paf)
+ ->update_group->id,
+ PAF_SUBGRP(paf)->id, peer->host,
+ inet_ntop(AF_INET6, mod_v6nhg,
+ buf, BUFSIZ),
+ inet_ntop(AF_INET6, mod_v6nhl,
+ buf2, BUFSIZ),
+ (nhlen == 48 ? " and RD" : ""));
+ else
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ mp_nexthop %s%s",
+ PAF_SUBGRP(paf)
+ ->update_group->id,
+ PAF_SUBGRP(paf)->id, peer->host,
+ inet_ntop(AF_INET6, mod_v6nhg,
+ buf, BUFSIZ),
+ (nhlen == 24 ? " and RD" : ""));
+ }
+ } else if (paf->afi == AFI_L2VPN) {
+ struct in_addr v4nh, *mod_v4nh;
+ int nh_modified = 0;
+
+ stream_get_from(&v4nh, s, vec->offset + 1, 4);
+ mod_v4nh = &v4nh;
+
+ /* No route-map changes allowed for EVPN nexthops. */
+ if (!v4nh.s_addr) {
+ mod_v4nh = &peer->nexthop.v4;
+ nh_modified = 1;
+ }
+
+ if (nh_modified)
+ stream_put_in_addr_at(s, vec->offset + 1,
+ mod_v4nh);
+
+ if (bgp_debug_update(peer, NULL, NULL, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ nexthop %s",
+ PAF_SUBGRP(paf)->update_group->id,
+ PAF_SUBGRP(paf)->id, peer->host,
+ inet_ntoa(*mod_v4nh));
+ }
}
- else if (nhafi == AFI_IP6)
- {
- struct in6_addr v6nhglobal, *mod_v6nhg;
- struct in6_addr v6nhlocal, *mod_v6nhl;
- int gnh_modified, lnh_modified;
- size_t offset_nhglobal = vec->offset + 1;
- size_t offset_nhlocal = vec->offset + 1;
-
- gnh_modified = lnh_modified = 0;
- mod_v6nhg = &v6nhglobal;
- mod_v6nhl = &v6nhlocal;
-
- route_map_sets_nh =
- (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED) ||
- CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
-
- /*
- * The logic here is rather similar to that for IPv4, the
- * additional work being to handle 1 or 2 nexthops. Also, 3rd
- * party nexthop is not propagated for EBGP right now.
- */
- switch (nhlen)
- {
- case BGP_ATTR_NHLEN_IPV6_GLOBAL:
- break;
- case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- offset_nhlocal += IPV6_MAX_BYTELEN;
- break;
- case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
- offset_nhglobal += 8;
- break;
- case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
- offset_nhglobal += 8;
- offset_nhlocal += 8 * 2 + IPV6_MAX_BYTELEN;
- break;
- default:
- /* TODO: handle IPv4 nexthops */
- zlog_warn ("%s: %s: invalid MP nexthop length (AFI IP6): %u",
- __func__, peer->host, nhlen);
- stream_free (s);
- return NULL;
- }
-
- stream_get_from (&v6nhglobal, s, offset_nhglobal, IPV6_MAX_BYTELEN);
- if (route_map_sets_nh)
- {
- if (CHECK_FLAG(vec->flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))
- {
- mod_v6nhg = &peer->nexthop.v6_global;
- gnh_modified = 1;
- }
- }
- else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal))
- {
- mod_v6nhg = &peer->nexthop.v6_global;
- gnh_modified = 1;
- }
- else if (peer->sort == BGP_PEER_EBGP &&
- !CHECK_FLAG(vec->flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
- !peer_af_flag_check (peer, nhafi, paf->safi,
- PEER_FLAG_NEXTHOP_UNCHANGED))
- {
- /* NOTE: not handling case where NH has new AFI */
- mod_v6nhg = &peer->nexthop.v6_global;
- gnh_modified = 1;
- }
-
-
- if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL ||
- nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
- {
- stream_get_from (&v6nhlocal, s, offset_nhlocal, IPV6_MAX_BYTELEN);
- if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal))
- {
- mod_v6nhl = &peer->nexthop.v6_local;
- lnh_modified = 1;
- }
- }
-
- if (gnh_modified)
- stream_put_in6_addr_at (s, offset_nhglobal, mod_v6nhg);
- if (lnh_modified)
- stream_put_in6_addr_at (s, offset_nhlocal, mod_v6nhl);
-
- if (bgp_debug_update(peer, NULL, NULL, 0))
- {
- if (nhlen == 32 || nhlen == 48)
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthops %s, %s%s",
- PAF_SUBGRP(paf)->update_group->id,
- PAF_SUBGRP(paf)->id,
- peer->host,
- inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ),
- inet_ntop (AF_INET6, mod_v6nhl, buf2, BUFSIZ),
- (nhlen == 48 ? " and RD" : ""));
- else
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthop %s%s",
- PAF_SUBGRP(paf)->update_group->id,
- PAF_SUBGRP(paf)->id,
- peer->host,
- inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ),
- (nhlen == 24 ? " and RD" : ""));
- }
- }
- else if (paf->afi == AFI_L2VPN)
- {
- struct in_addr v4nh, *mod_v4nh;
- int nh_modified = 0;
-
- stream_get_from (&v4nh, s, vec->offset + 1, 4);
- mod_v4nh = &v4nh;
-
- /* No route-map changes allowed for EVPN nexthops. */
- if (!v4nh.s_addr)
- {
- mod_v4nh = &peer->nexthop.v4;
- nh_modified = 1;
- }
-
- if (nh_modified)
- stream_put_in_addr_at (s, vec->offset + 1, mod_v4nh);
-
- if (bgp_debug_update(peer, NULL, NULL, 0))
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s",
- PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id,
- peer->host, inet_ntoa (*mod_v4nh));
-
- }
- }
- bgp_packet_add (peer, s);
- return s;
+ bgp_packet_add(peer, s);
+ return s;
}
/*
* Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
* to each offset.
*/
-static void
-bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr *vecarr, size_t pos)
+static void bpacket_attr_vec_arr_update(struct bpacket_attr_vec_arr *vecarr,
+ size_t pos)
{
- int i;
+ int i;
- if (!vecarr)
- return;
+ if (!vecarr)
+ return;
- for (i = 0; i < BGP_ATTR_VEC_MAX; i++)
- vecarr->entries[i].offset += pos;
+ for (i = 0; i < BGP_ATTR_VEC_MAX; i++)
+ vecarr->entries[i].offset += pos;
}
/*
* Return if there are packets to build for this subgroup.
*/
-int
-subgroup_packets_to_build (struct update_subgroup *subgrp)
+int subgroup_packets_to_build(struct update_subgroup *subgrp)
{
- struct bgp_advertise *adv;
+ struct bgp_advertise *adv;
- if (!subgrp)
- return 0;
+ if (!subgrp)
+ return 0;
- adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw);
- if (adv)
- return 1;
+ adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw);
+ if (adv)
+ return 1;
- adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update);
- if (adv)
- return 1;
+ adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update);
+ if (adv)
+ return 1;
- return 0;
+ return 0;
}
/* Make BGP update packet. */
-struct bpacket *
-subgroup_update_packet (struct update_subgroup *subgrp)
+struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
{
- struct bpacket_attr_vec_arr vecarr;
- struct bpacket *pkt;
- struct peer *peer;
- struct stream *s;
- struct stream *snlri;
- struct stream *packet;
- struct bgp_adj_out *adj;
- struct bgp_advertise *adv;
- struct bgp_node *rn = NULL;
- struct bgp_info *binfo = NULL;
- bgp_size_t total_attr_len = 0;
- unsigned long attrlen_pos = 0;
- size_t mpattrlen_pos = 0;
- size_t mpattr_pos = 0;
- afi_t afi;
- safi_t safi;
- int space_remaining = 0;
- int space_needed = 0;
- char send_attr_str[BUFSIZ];
- int send_attr_printed = 0;
- int num_pfx = 0;
- int addpath_encode = 0;
- u_int32_t addpath_tx_id = 0;
- struct prefix_rd *prd = NULL;
- mpls_label_t label = MPLS_INVALID_LABEL;
-
- if (!subgrp)
- return NULL;
-
- if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
- return NULL;
-
- peer = SUBGRP_PEER (subgrp);
- afi = SUBGRP_AFI (subgrp);
- safi = SUBGRP_SAFI (subgrp);
- s = subgrp->work;
- stream_reset (s);
- snlri = subgrp->scratch;
- stream_reset (snlri);
-
- bpacket_attr_vec_arr_reset (&vecarr);
-
- addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
-
- adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update);
- while (adv)
- {
- assert (adv->rn);
- rn = adv->rn;
- adj = adv->adj;
- addpath_tx_id = adj->addpath_tx_id;
- binfo = adv->binfo;
-
- space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
- BGP_MAX_PACKET_SIZE_OVERFLOW;
- space_needed = BGP_NLRI_LENGTH +
- bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
-
- /* When remaining space can't include NLRI and it's length. */
- if (space_remaining < space_needed)
- break;
-
- /* If packet is empty, set attribute. */
- if (stream_empty (s))
- {
- struct peer *from = NULL;
-
- if (binfo)
- from = binfo->peer;
-
- /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
- * one byte message type.
- */
- bgp_packet_set_marker (s, BGP_MSG_UPDATE);
-
- /* 2: withdrawn routes length */
- stream_putw (s, 0);
-
- /* 3: total attributes length - attrlen_pos stores the position */
- attrlen_pos = stream_get_endp (s);
- stream_putw (s, 0);
-
- /* 4: if there is MP_REACH_NLRI attribute, that should be the first
- * attribute, according to draft-ietf-idr-error-handling. Save the
- * position.
- */
- mpattr_pos = stream_get_endp (s);
-
- /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
- total_attr_len = bgp_packet_attribute (NULL, peer, s,
- adv->baa->attr, &vecarr,
- NULL, afi, safi,
- from, NULL, NULL, 0, 0);
-
- space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
- BGP_MAX_PACKET_SIZE_OVERFLOW;
- space_needed = BGP_NLRI_LENGTH +
- bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
-
- /* If the attributes alone do not leave any room for NLRI then
- * return */
- if (space_remaining < space_needed)
- {
- zlog_err ("u%" PRIu64 ":s%" PRIu64 " attributes too long, cannot send UPDATE",
- subgrp->update_group->id, subgrp->id);
-
- /* Flush the FIFO update queue */
- while (adv)
- adv = bgp_advertise_clean_subgroup (subgrp, adj);
- return NULL;
- }
-
- if (BGP_DEBUG (update, UPDATE_OUT) ||
- BGP_DEBUG (update, UPDATE_PREFIX))
- {
- memset (send_attr_str, 0, BUFSIZ);
- send_attr_printed = 0;
- bgp_dump_attr (adv->baa->attr, send_attr_str, BUFSIZ);
- }
- }
-
- if ((afi == AFI_IP && safi == SAFI_UNICAST) &&
- !peer_cap_enhe(peer, afi, safi))
- stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
- else
- {
- /* Encode the prefix in MP_REACH_NLRI attribute */
- if (rn->prn)
- prd = (struct prefix_rd *) &rn->prn->p;
-
- if (safi == SAFI_LABELED_UNICAST)
- label = bgp_adv_label(rn, binfo, peer, afi, safi);
- else
- if (binfo && binfo->extra)
- label = binfo->extra->label;
-
- if (stream_empty (snlri))
- mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi,
- &vecarr, adv->baa->attr);
-
- bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
- &label, addpath_encode, addpath_tx_id, adv->baa->attr);
- }
-
- num_pfx++;
-
- if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
- {
- char pfx_buf[BGP_PRD_PATH_STRLEN];
-
- if (!send_attr_printed)
- {
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE w/ attr: %s",
- subgrp->update_group->id, subgrp->id, send_attr_str);
- if (!stream_empty (snlri))
- {
- iana_afi_t pkt_afi;
- safi_t pkt_safi;
-
- pkt_afi = afi_int2iana (afi);
- pkt_safi = safi_int2iana (safi);
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_REACH for afi/safi %d/%d",
- subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi);
- }
-
- send_attr_printed = 1;
- }
-
- bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, &label,
- addpath_encode, addpath_tx_id,
- pfx_buf, sizeof (pfx_buf));
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
- subgrp->update_group->id, subgrp->id, pfx_buf);
- }
-
- /* Synchnorize attribute. */
- if (adj->attr)
- bgp_attr_unintern (&adj->attr);
- else
- subgrp->scount++;
-
- adj->attr = bgp_attr_intern (adv->baa->attr);
+ struct bpacket_attr_vec_arr vecarr;
+ struct bpacket *pkt;
+ struct peer *peer;
+ struct stream *s;
+ struct stream *snlri;
+ struct stream *packet;
+ struct bgp_adj_out *adj;
+ struct bgp_advertise *adv;
+ struct bgp_node *rn = NULL;
+ struct bgp_info *binfo = NULL;
+ bgp_size_t total_attr_len = 0;
+ unsigned long attrlen_pos = 0;
+ size_t mpattrlen_pos = 0;
+ size_t mpattr_pos = 0;
+ afi_t afi;
+ safi_t safi;
+ int space_remaining = 0;
+ int space_needed = 0;
+ char send_attr_str[BUFSIZ];
+ int send_attr_printed = 0;
+ int num_pfx = 0;
+ int addpath_encode = 0;
+ u_int32_t addpath_tx_id = 0;
+ struct prefix_rd *prd = NULL;
+ mpls_label_t label = MPLS_INVALID_LABEL;
+
+ if (!subgrp)
+ return NULL;
- adv = bgp_advertise_clean_subgroup (subgrp, adj);
- }
+ if (bpacket_queue_is_full(SUBGRP_INST(subgrp), SUBGRP_PKTQ(subgrp)))
+ return NULL;
- if (!stream_empty (s))
- {
- if (!stream_empty (snlri))
- {
- bgp_packet_mpattr_end (snlri, mpattrlen_pos);
- total_attr_len += stream_get_endp (snlri);
+ peer = SUBGRP_PEER(subgrp);
+ afi = SUBGRP_AFI(subgrp);
+ safi = SUBGRP_SAFI(subgrp);
+ s = subgrp->work;
+ stream_reset(s);
+ snlri = subgrp->scratch;
+ stream_reset(snlri);
+
+ bpacket_attr_vec_arr_reset(&vecarr);
+
+ addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+
+ adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update);
+ while (adv) {
+ assert(adv->rn);
+ rn = adv->rn;
+ adj = adv->adj;
+ addpath_tx_id = adj->addpath_tx_id;
+ binfo = adv->binfo;
+
+ space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
+ - BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(
+ afi, safi, &rn->p);
+
+ /* When remaining space can't include NLRI and it's length. */
+ if (space_remaining < space_needed)
+ break;
+
+ /* If packet is empty, set attribute. */
+ if (stream_empty(s)) {
+ struct peer *from = NULL;
+
+ if (binfo)
+ from = binfo->peer;
+
+ /* 1: Write the BGP message header - 16 bytes marker, 2
+ * bytes length,
+ * one byte message type.
+ */
+ bgp_packet_set_marker(s, BGP_MSG_UPDATE);
+
+ /* 2: withdrawn routes length */
+ stream_putw(s, 0);
+
+ /* 3: total attributes length - attrlen_pos stores the
+ * position */
+ attrlen_pos = stream_get_endp(s);
+ stream_putw(s, 0);
+
+ /* 4: if there is MP_REACH_NLRI attribute, that should
+ * be the first
+ * attribute, according to
+ * draft-ietf-idr-error-handling. Save the
+ * position.
+ */
+ mpattr_pos = stream_get_endp(s);
+
+ /* 5: Encode all the attributes, except MP_REACH_NLRI
+ * attr. */
+ total_attr_len = bgp_packet_attribute(
+ NULL, peer, s, adv->baa->attr, &vecarr, NULL,
+ afi, safi, from, NULL, NULL, 0, 0);
+
+ space_remaining =
+ STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
+ - BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed =
+ BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(
+ afi, safi, &rn->p);
+
+ /* If the attributes alone do not leave any room for
+ * NLRI then
+ * return */
+ if (space_remaining < space_needed) {
+ zlog_err(
+ "u%" PRIu64 ":s%" PRIu64
+ " attributes too long, cannot send UPDATE",
+ subgrp->update_group->id, subgrp->id);
+
+ /* Flush the FIFO update queue */
+ while (adv)
+ adv = bgp_advertise_clean_subgroup(
+ subgrp, adj);
+ return NULL;
+ }
+
+ if (BGP_DEBUG(update, UPDATE_OUT)
+ || BGP_DEBUG(update, UPDATE_PREFIX)) {
+ memset(send_attr_str, 0, BUFSIZ);
+ send_attr_printed = 0;
+ bgp_dump_attr(adv->baa->attr, send_attr_str,
+ BUFSIZ);
+ }
+ }
+
+ if ((afi == AFI_IP && safi == SAFI_UNICAST)
+ && !peer_cap_enhe(peer, afi, safi))
+ stream_put_prefix_addpath(s, &rn->p, addpath_encode,
+ addpath_tx_id);
+ else {
+ /* Encode the prefix in MP_REACH_NLRI attribute */
+ if (rn->prn)
+ prd = (struct prefix_rd *)&rn->prn->p;
+
+ if (safi == SAFI_LABELED_UNICAST)
+ label = bgp_adv_label(rn, binfo, peer, afi,
+ safi);
+ else if (binfo && binfo->extra)
+ label = binfo->extra->label;
+
+ if (stream_empty(snlri))
+ mpattrlen_pos = bgp_packet_mpattr_start(
+ snlri, peer, afi, safi, &vecarr,
+ adv->baa->attr);
+
+ bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd,
+ &label, addpath_encode,
+ addpath_tx_id, adv->baa->attr);
+ }
+
+ num_pfx++;
+
+ if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) {
+ char pfx_buf[BGP_PRD_PATH_STRLEN];
+
+ if (!send_attr_printed) {
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " send UPDATE w/ attr: %s",
+ subgrp->update_group->id, subgrp->id,
+ send_attr_str);
+ if (!stream_empty(snlri)) {
+ iana_afi_t pkt_afi;
+ safi_t pkt_safi;
+
+ pkt_afi = afi_int2iana(afi);
+ pkt_safi = safi_int2iana(safi);
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " send MP_REACH for afi/safi %d/%d",
+ subgrp->update_group->id,
+ subgrp->id, pkt_afi, pkt_safi);
+ }
+
+ send_attr_printed = 1;
+ }
+
+ bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, &label,
+ addpath_encode, addpath_tx_id,
+ pfx_buf, sizeof(pfx_buf));
+ zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
+ subgrp->update_group->id, subgrp->id,
+ pfx_buf);
+ }
+
+ /* Synchnorize attribute. */
+ if (adj->attr)
+ bgp_attr_unintern(&adj->attr);
+ else
+ subgrp->scount++;
+
+ adj->attr = bgp_attr_intern(adv->baa->attr);
+
+ adv = bgp_advertise_clean_subgroup(subgrp, adj);
}
- /* set the total attribute length correctly */
- stream_putw_at (s, attrlen_pos, total_attr_len);
-
- if (!stream_empty (snlri))
- {
- packet = stream_dupcat (s, snlri, mpattr_pos);
- bpacket_attr_vec_arr_update (&vecarr, mpattr_pos);
+ if (!stream_empty(s)) {
+ if (!stream_empty(snlri)) {
+ bgp_packet_mpattr_end(snlri, mpattrlen_pos);
+ total_attr_len += stream_get_endp(snlri);
+ }
+
+ /* set the total attribute length correctly */
+ stream_putw_at(s, attrlen_pos, total_attr_len);
+
+ if (!stream_empty(snlri)) {
+ packet = stream_dupcat(s, snlri, mpattr_pos);
+ bpacket_attr_vec_arr_update(&vecarr, mpattr_pos);
+ } else
+ packet = stream_dup(s);
+ bgp_packet_set_size(packet);
+ if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " send UPDATE len %zd numpfx %d",
+ subgrp->update_group->id, subgrp->id,
+ (stream_get_endp(packet)
+ - stream_get_getp(packet)),
+ num_pfx);
+ pkt = bpacket_queue_add(SUBGRP_PKTQ(subgrp), packet, &vecarr);
+ stream_reset(s);
+ stream_reset(snlri);
+ return pkt;
}
- else
- packet = stream_dup (s);
- bgp_packet_set_size (packet);
- if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE len %zd numpfx %d",
- subgrp->update_group->id, subgrp->id,
- (stream_get_endp(packet) - stream_get_getp(packet)), num_pfx);
- pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), packet, &vecarr);
- stream_reset (s);
- stream_reset (snlri);
- return pkt;
- }
- return NULL;
+ return NULL;
}
/* Make BGP withdraw packet. */
@@ -907,400 +916,396 @@ subgroup_update_packet (struct update_subgroup *subgrp)
2-octet withdrawn route length (=0) | 2-octet attrlen |
mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
*/
-struct bpacket *
-subgroup_withdraw_packet (struct update_subgroup *subgrp)
+struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp)
{
- struct bpacket *pkt;
- struct stream *s;
- struct bgp_adj_out *adj;
- struct bgp_advertise *adv;
- struct peer *peer;
- struct bgp_node *rn;
- bgp_size_t unfeasible_len;
- bgp_size_t total_attr_len;
- size_t mp_start = 0;
- size_t attrlen_pos = 0;
- size_t mplen_pos = 0;
- u_char first_time = 1;
- afi_t afi;
- safi_t safi;
- int space_remaining = 0;
- int space_needed = 0;
- int num_pfx = 0;
- int addpath_encode = 0;
- u_int32_t addpath_tx_id = 0;
- struct prefix_rd *prd = NULL;
-
-
- if (!subgrp)
- return NULL;
-
- if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
- return NULL;
-
- peer = SUBGRP_PEER (subgrp);
- afi = SUBGRP_AFI (subgrp);
- safi = SUBGRP_SAFI (subgrp);
- s = subgrp->work;
- stream_reset (s);
- addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
-
- while ((adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw)) != NULL)
- {
- assert (adv->rn);
- adj = adv->adj;
- rn = adv->rn;
- addpath_tx_id = adj->addpath_tx_id;
-
- space_remaining = STREAM_REMAIN (s) -
- BGP_MAX_PACKET_SIZE_OVERFLOW;
- space_needed = BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN +
- bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
-
- if (space_remaining < space_needed)
- break;
-
- if (stream_empty (s))
- {
- bgp_packet_set_marker (s, BGP_MSG_UPDATE);
- stream_putw (s, 0); /* unfeasible routes length */
- }
- else
- first_time = 0;
-
- if (afi == AFI_IP && safi == SAFI_UNICAST &&
- !peer_cap_enhe(peer, afi, safi))
- stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
- else
- {
- if (rn->prn)
- prd = (struct prefix_rd *) &rn->prn->p;
-
- /* If first time, format the MP_UNREACH header */
- if (first_time)
- {
- iana_afi_t pkt_afi;
- safi_t pkt_safi;
-
- pkt_afi = afi_int2iana (afi);
- pkt_safi = safi_int2iana (safi);
-
- attrlen_pos = stream_get_endp (s);
- /* total attr length = 0 for now. reevaluate later */
- stream_putw (s, 0);
- mp_start = stream_get_endp (s);
- mplen_pos = bgp_packet_mpunreach_start (s, afi, safi);
- if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_UNREACH for afi/safi %d/%d",
- subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi);
- }
-
- bgp_packet_mpunreach_prefix (s, &rn->p, afi, safi, prd, NULL,
- addpath_encode, addpath_tx_id, NULL);
- }
-
- num_pfx++;
+ struct bpacket *pkt;
+ struct stream *s;
+ struct bgp_adj_out *adj;
+ struct bgp_advertise *adv;
+ struct peer *peer;
+ struct bgp_node *rn;
+ bgp_size_t unfeasible_len;
+ bgp_size_t total_attr_len;
+ size_t mp_start = 0;
+ size_t attrlen_pos = 0;
+ size_t mplen_pos = 0;
+ u_char first_time = 1;
+ afi_t afi;
+ safi_t safi;
+ int space_remaining = 0;
+ int space_needed = 0;
+ int num_pfx = 0;
+ int addpath_encode = 0;
+ u_int32_t addpath_tx_id = 0;
+ struct prefix_rd *prd = NULL;
+
+
+ if (!subgrp)
+ return NULL;
- if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
- {
- char pfx_buf[BGP_PRD_PATH_STRLEN];
+ if (bpacket_queue_is_full(SUBGRP_INST(subgrp), SUBGRP_PKTQ(subgrp)))
+ return NULL;
- bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, NULL,
- addpath_encode, addpath_tx_id,
- pfx_buf, sizeof (pfx_buf));
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable",
- subgrp->update_group->id, subgrp->id, pfx_buf);
+ peer = SUBGRP_PEER(subgrp);
+ afi = SUBGRP_AFI(subgrp);
+ safi = SUBGRP_SAFI(subgrp);
+ s = subgrp->work;
+ stream_reset(s);
+ addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+
+ while ((adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw)) != NULL) {
+ assert(adv->rn);
+ adj = adv->adj;
+ rn = adv->rn;
+ addpath_tx_id = adj->addpath_tx_id;
+
+ space_remaining =
+ STREAM_REMAIN(s) - BGP_MAX_PACKET_SIZE_OVERFLOW;
+ space_needed =
+ BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN
+ + bgp_packet_mpattr_prefix_size(afi, safi, &rn->p);
+
+ if (space_remaining < space_needed)
+ break;
+
+ if (stream_empty(s)) {
+ bgp_packet_set_marker(s, BGP_MSG_UPDATE);
+ stream_putw(s, 0); /* unfeasible routes length */
+ } else
+ first_time = 0;
+
+ if (afi == AFI_IP && safi == SAFI_UNICAST
+ && !peer_cap_enhe(peer, afi, safi))
+ stream_put_prefix_addpath(s, &rn->p, addpath_encode,
+ addpath_tx_id);
+ else {
+ if (rn->prn)
+ prd = (struct prefix_rd *)&rn->prn->p;
+
+ /* If first time, format the MP_UNREACH header */
+ if (first_time) {
+ iana_afi_t pkt_afi;
+ safi_t pkt_safi;
+
+ pkt_afi = afi_int2iana(afi);
+ pkt_safi = safi_int2iana(safi);
+
+ attrlen_pos = stream_get_endp(s);
+ /* total attr length = 0 for now. reevaluate
+ * later */
+ stream_putw(s, 0);
+ mp_start = stream_get_endp(s);
+ mplen_pos = bgp_packet_mpunreach_start(s, afi,
+ safi);
+ if (bgp_debug_update(NULL, NULL,
+ subgrp->update_group, 0))
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " send MP_UNREACH for afi/safi %d/%d",
+ subgrp->update_group->id,
+ subgrp->id, pkt_afi, pkt_safi);
+ }
+
+ bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd,
+ NULL, addpath_encode,
+ addpath_tx_id, NULL);
+ }
+
+ num_pfx++;
+
+ if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) {
+ char pfx_buf[BGP_PRD_PATH_STRLEN];
+
+ bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, NULL,
+ addpath_encode, addpath_tx_id,
+ pfx_buf, sizeof(pfx_buf));
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " send UPDATE %s -- unreachable",
+ subgrp->update_group->id, subgrp->id,
+ pfx_buf);
+ }
+
+ subgrp->scount--;
+
+ bgp_adj_out_remove_subgroup(rn, adj, subgrp);
+ bgp_unlock_node(rn);
}
- subgrp->scount--;
-
- bgp_adj_out_remove_subgroup (rn, adj, subgrp);
- bgp_unlock_node (rn);
- }
-
- if (!stream_empty (s))
- {
- if (afi == AFI_IP && safi == SAFI_UNICAST &&
- !peer_cap_enhe(peer, afi, safi))
- {
- 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);
- }
- else
- {
- /* Set the mp_unreach attr's length */
- bgp_packet_mpunreach_end (s, mplen_pos);
-
- /* Set total path attribute length. */
- total_attr_len = stream_get_endp (s) - mp_start;
- stream_putw_at (s, attrlen_pos, total_attr_len);
+ if (!stream_empty(s)) {
+ if (afi == AFI_IP && safi == SAFI_UNICAST
+ && !peer_cap_enhe(peer, afi, safi)) {
+ 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);
+ } else {
+ /* Set the mp_unreach attr's length */
+ bgp_packet_mpunreach_end(s, mplen_pos);
+
+ /* Set total path attribute length. */
+ total_attr_len = stream_get_endp(s) - mp_start;
+ stream_putw_at(s, attrlen_pos, total_attr_len);
+ }
+ bgp_packet_set_size(s);
+ if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " send UPDATE (withdraw) len %zd numpfx %d",
+ subgrp->update_group->id, subgrp->id,
+ (stream_get_endp(s) - stream_get_getp(s)),
+ num_pfx);
+ pkt = bpacket_queue_add(SUBGRP_PKTQ(subgrp), stream_dup(s),
+ NULL);
+ stream_reset(s);
+ return pkt;
}
- bgp_packet_set_size (s);
- if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE (withdraw) len %zd numpfx %d",
- subgrp->update_group->id, subgrp->id,
- (stream_get_endp(s) - stream_get_getp(s)), num_pfx);
- pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), stream_dup (s), NULL);
- stream_reset (s);
- return pkt;
- }
- return NULL;
+ return NULL;
}
-void
-subgroup_default_update_packet (struct update_subgroup *subgrp,
- struct attr *attr, struct peer *from)
+void subgroup_default_update_packet(struct update_subgroup *subgrp,
+ struct attr *attr, struct peer *from)
{
- struct stream *s;
- struct peer *peer;
- struct prefix p;
- unsigned long pos;
- bgp_size_t total_attr_len;
- afi_t afi;
- safi_t safi;
- struct bpacket_attr_vec_arr vecarr;
- int addpath_encode = 0;
-
- if (DISABLE_BGP_ANNOUNCE)
- return;
-
- if (!subgrp)
- return;
-
- peer = SUBGRP_PEER (subgrp);
- afi = SUBGRP_AFI (subgrp);
- safi = SUBGRP_SAFI (subgrp);
- bpacket_attr_vec_arr_reset (&vecarr);
- addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
-
- if (afi == AFI_IP)
- str2prefix ("0.0.0.0/0", &p);
- else
- str2prefix ("::/0", &p);
-
- /* Logging the attribute. */
- if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
- {
- char attrstr[BUFSIZ];
- char buf[PREFIX_STRLEN];
- /* ' with addpath ID ' 17
- * max strlen of uint32 + 10
- * +/- (just in case) + 1
- * null terminator + 1
- * ============================ 29 */
- char tx_id_buf[30];
-
- attrstr[0] = '\0';
-
- bgp_dump_attr (attr, attrstr, BUFSIZ);
-
- if (addpath_encode)
- snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u",
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
-
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s",
- (SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
- prefix2str (&p, buf, sizeof (buf)),
- tx_id_buf, attrstr);
- }
+ struct stream *s;
+ struct peer *peer;
+ struct prefix p;
+ unsigned long pos;
+ bgp_size_t total_attr_len;
+ afi_t afi;
+ safi_t safi;
+ struct bpacket_attr_vec_arr vecarr;
+ int addpath_encode = 0;
+
+ if (DISABLE_BGP_ANNOUNCE)
+ return;
+
+ if (!subgrp)
+ return;
+
+ peer = SUBGRP_PEER(subgrp);
+ afi = SUBGRP_AFI(subgrp);
+ safi = SUBGRP_SAFI(subgrp);
+ bpacket_attr_vec_arr_reset(&vecarr);
+ addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+
+ if (afi == AFI_IP)
+ str2prefix("0.0.0.0/0", &p);
+ else
+ str2prefix("::/0", &p);
+
+ /* Logging the attribute. */
+ if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) {
+ char attrstr[BUFSIZ];
+ char buf[PREFIX_STRLEN];
+ /* ' with addpath ID ' 17
+ * max strlen of uint32 + 10
+ * +/- (just in case) + 1
+ * null terminator + 1
+ * ============================ 29 */
+ char tx_id_buf[30];
+
+ attrstr[0] = '\0';
+
+ bgp_dump_attr(attr, attrstr, BUFSIZ);
+
+ if (addpath_encode)
+ snprintf(tx_id_buf, sizeof(tx_id_buf),
+ " with addpath ID %u",
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+
+ zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s",
+ (SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
+ prefix2str(&p, buf, sizeof(buf)), tx_id_buf,
+ attrstr);
+ }
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = stream_new(BGP_MAX_PACKET_SIZE);
- /* Make BGP update packet. */
- bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+ /* Make BGP update packet. */
+ bgp_packet_set_marker(s, BGP_MSG_UPDATE);
- /* Unfeasible Routes Length. */
- stream_putw (s, 0);
+ /* Unfeasible Routes Length. */
+ stream_putw(s, 0);
- /* Make place for total attribute length. */
- pos = stream_get_endp (s);
- stream_putw (s, 0);
- total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &vecarr, &p,
- afi, safi, from, NULL, NULL,
- addpath_encode,
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+ /* Make place for total attribute length. */
+ pos = stream_get_endp(s);
+ stream_putw(s, 0);
+ total_attr_len = bgp_packet_attribute(
+ NULL, peer, s, attr, &vecarr, &p, afi, safi, from, NULL, NULL,
+ addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
- /* Set Total Path Attribute Length. */
- stream_putw_at (s, pos, total_attr_len);
+ /* Set Total Path Attribute Length. */
+ stream_putw_at(s, pos, total_attr_len);
- /* NLRI set. */
- if (p.family == AF_INET && safi == SAFI_UNICAST &&
- !peer_cap_enhe(peer, afi, safi))
- stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+ /* NLRI set. */
+ if (p.family == AF_INET && safi == SAFI_UNICAST
+ && !peer_cap_enhe(peer, afi, safi))
+ stream_put_prefix_addpath(
+ s, &p, addpath_encode,
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
- /* Set size. */
- bgp_packet_set_size (s);
+ /* Set size. */
+ bgp_packet_set_size(s);
- (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, &vecarr);
- subgroup_trigger_write(subgrp);
+ (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, &vecarr);
+ subgroup_trigger_write(subgrp);
}
-void
-subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
+void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
{
- struct peer *peer;
- struct stream *s;
- struct prefix p;
- unsigned long attrlen_pos = 0;
- unsigned long cp;
- bgp_size_t unfeasible_len;
- bgp_size_t total_attr_len = 0;
- size_t mp_start = 0;
- size_t mplen_pos = 0;
- afi_t afi;
- safi_t safi;
- int addpath_encode = 0;
-
- if (DISABLE_BGP_ANNOUNCE)
- return;
-
- peer = SUBGRP_PEER (subgrp);
- afi = SUBGRP_AFI (subgrp);
- safi = SUBGRP_SAFI (subgrp);
- addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
-
- if (afi == AFI_IP)
- str2prefix ("0.0.0.0/0", &p);
- else
- str2prefix ("::/0", &p);
-
- if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
- {
- char buf[PREFIX_STRLEN];
- /* ' with addpath ID ' 17
- * max strlen of uint32 + 10
- * +/- (just in case) + 1
- * null terminator + 1
- * ============================ 29 */
- char tx_id_buf[30];
-
- if (addpath_encode)
- snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u",
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
-
- zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable",
- (SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
- prefix2str (&p, buf, sizeof (buf)), tx_id_buf);
- }
+ struct peer *peer;
+ struct stream *s;
+ struct prefix p;
+ unsigned long attrlen_pos = 0;
+ unsigned long cp;
+ bgp_size_t unfeasible_len;
+ bgp_size_t total_attr_len = 0;
+ size_t mp_start = 0;
+ size_t mplen_pos = 0;
+ afi_t afi;
+ safi_t safi;
+ int addpath_encode = 0;
+
+ if (DISABLE_BGP_ANNOUNCE)
+ return;
+
+ peer = SUBGRP_PEER(subgrp);
+ afi = SUBGRP_AFI(subgrp);
+ safi = SUBGRP_SAFI(subgrp);
+ addpath_encode = bgp_addpath_encode_tx(peer, afi, safi);
+
+ if (afi == AFI_IP)
+ str2prefix("0.0.0.0/0", &p);
+ else
+ str2prefix("::/0", &p);
+
+ if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) {
+ char buf[PREFIX_STRLEN];
+ /* ' with addpath ID ' 17
+ * max strlen of uint32 + 10
+ * +/- (just in case) + 1
+ * null terminator + 1
+ * ============================ 29 */
+ char tx_id_buf[30];
+
+ if (addpath_encode)
+ snprintf(tx_id_buf, sizeof(tx_id_buf),
+ " with addpath ID %u",
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " send UPDATE %s%s -- unreachable",
+ (SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
+ prefix2str(&p, buf, sizeof(buf)), tx_id_buf);
+ }
- s = stream_new (BGP_MAX_PACKET_SIZE);
+ s = stream_new(BGP_MAX_PACKET_SIZE);
- /* Make BGP update packet. */
- bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+ /* Make BGP update packet. */
+ bgp_packet_set_marker(s, BGP_MSG_UPDATE);
- /* Unfeasible Routes Length. */ ;
- cp = stream_get_endp (s);
- stream_putw (s, 0);
+ /* Unfeasible Routes Length. */;
+ cp = stream_get_endp(s);
+ stream_putw(s, 0);
- /* Withdrawn Routes. */
- if (p.family == AF_INET && safi == SAFI_UNICAST &&
- !peer_cap_enhe(peer, afi, safi))
- {
- stream_put_prefix_addpath (s, &p, addpath_encode,
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
+ /* Withdrawn Routes. */
+ if (p.family == AF_INET && safi == SAFI_UNICAST
+ && !peer_cap_enhe(peer, afi, safi)) {
+ stream_put_prefix_addpath(
+ s, &p, addpath_encode,
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
- unfeasible_len = stream_get_endp (s) - cp - 2;
+ unfeasible_len = stream_get_endp(s) - cp - 2;
- /* Set unfeasible len. */
- stream_putw_at (s, cp, unfeasible_len);
+ /* Set unfeasible len. */
+ stream_putw_at(s, cp, unfeasible_len);
- /* Set total path attribute length. */
- stream_putw (s, 0);
- }
- else
- {
- attrlen_pos = stream_get_endp (s);
- stream_putw (s, 0);
- mp_start = stream_get_endp (s);
- mplen_pos = bgp_packet_mpunreach_start (s, afi, safi);
- bgp_packet_mpunreach_prefix (s, &p, afi, safi, NULL, NULL,
- addpath_encode,
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
-
- /* Set the mp_unreach attr's length */
- bgp_packet_mpunreach_end (s, mplen_pos);
-
- /* Set total path attribute length. */
- total_attr_len = stream_get_endp (s) - mp_start;
- stream_putw_at (s, attrlen_pos, total_attr_len);
- }
+ /* Set total path attribute length. */
+ stream_putw(s, 0);
+ } else {
+ attrlen_pos = stream_get_endp(s);
+ stream_putw(s, 0);
+ mp_start = stream_get_endp(s);
+ mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
+ bgp_packet_mpunreach_prefix(
+ s, &p, afi, safi, NULL, NULL, addpath_encode,
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
- bgp_packet_set_size (s);
+ /* Set the mp_unreach attr's length */
+ bgp_packet_mpunreach_end(s, mplen_pos);
- (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, NULL);
- subgroup_trigger_write(subgrp);
+ /* Set total path attribute length. */
+ total_attr_len = stream_get_endp(s) - mp_start;
+ stream_putw_at(s, attrlen_pos, total_attr_len);
+ }
+
+ bgp_packet_set_size(s);
+
+ (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, NULL);
+ subgroup_trigger_write(subgrp);
}
static void
-bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr *vecarr,
- bpacket_attr_vec_type type,
- struct attr *attr)
+bpacket_vec_arr_inherit_attr_flags(struct bpacket_attr_vec_arr *vecarr,
+ bpacket_attr_vec_type type,
+ struct attr *attr)
{
- if (CHECK_FLAG (attr->rmap_change_flags,
- BATTR_RMAP_NEXTHOP_PEER_ADDRESS))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS);
-
- if (CHECK_FLAG (attr->rmap_change_flags, BATTR_REFLECTED))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_REFLECTED);
-
- if (CHECK_FLAG (attr->rmap_change_flags,
- BATTR_RMAP_NEXTHOP_UNCHANGED))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED);
-
- if (CHECK_FLAG (attr->rmap_change_flags,
- BATTR_RMAP_IPV4_NHOP_CHANGED))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED);
-
- if (CHECK_FLAG (attr->rmap_change_flags,
- BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED);
-
- if (CHECK_FLAG (attr->rmap_change_flags,
- BATTR_RMAP_IPV6_LL_NHOP_CHANGED))
- SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
- BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED);
+ if (CHECK_FLAG(attr->rmap_change_flags,
+ BATTR_RMAP_NEXTHOP_PEER_ADDRESS))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS);
+
+ if (CHECK_FLAG(attr->rmap_change_flags, BATTR_REFLECTED))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_REFLECTED);
+
+ if (CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_UNCHANGED))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED);
+
+ if (CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_IPV4_NHOP_CHANGED))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED);
+
+ if (CHECK_FLAG(attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED);
+
+ if (CHECK_FLAG(attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_LL_NHOP_CHANGED))
+ SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags,
+ BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED);
}
/* Reset the Attributes vector array. The vector array is used to override
* certain output parameters in the packet for a particular peer
*/
-void
-bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr)
+void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr)
{
- int i;
+ int i;
- if (!vecarr)
- return;
+ if (!vecarr)
+ return;
- i = 0;
- while (i < BGP_ATTR_VEC_MAX)
- {
- vecarr->entries[i].flags = 0;
- vecarr->entries[i].offset = 0;
- i++;
- }
+ i = 0;
+ while (i < BGP_ATTR_VEC_MAX) {
+ vecarr->entries[i].flags = 0;
+ vecarr->entries[i].offset = 0;
+ i++;
+ }
}
/* Setup a particular node entry in the vecarr */
-void
-bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr,
- bpacket_attr_vec_type type, struct stream *s,
- struct attr *attr)
+void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr,
+ bpacket_attr_vec_type type, struct stream *s,
+ struct attr *attr)
{
- if (!vecarr)
- return;
- assert (type < BGP_ATTR_VEC_MAX);
-
- SET_FLAG (vecarr->entries[type].flags, BPKT_ATTRVEC_FLAGS_UPDATED);
- vecarr->entries[type].offset = stream_get_endp (s);
- if (attr)
- bpacket_vec_arr_inherit_attr_flags(vecarr, type, attr);
+ if (!vecarr)
+ return;
+ assert(type < BGP_ATTR_VEC_MAX);
+
+ SET_FLAG(vecarr->entries[type].flags, BPKT_ATTRVEC_FLAGS_UPDATED);
+ vecarr->entries[type].offset = stream_get_endp(s);
+ if (attr)
+ bpacket_vec_arr_inherit_attr_flags(vecarr, type, attr);
}