2 * bgp_updgrp_packet.c: BGP update group packet handling routines
4 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
6 * @author Avneesh Sachdev <avneesh@sproute.net>
7 * @author Rajesh Varadarajan <rajesh@sproute.net>
8 * @author Pradosh Mohapatra <pradosh@sproute.net>
10 * This file is part of GNU Zebra.
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
17 * GNU Zebra is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Zebra; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 #include "sockunion.h"
43 #include "workqueue.h"
47 #include "bgpd/bgpd.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_fsm.h"
50 #include "bgpd/bgp_route.h"
51 #include "bgpd/bgp_packet.h"
52 #include "bgpd/bgp_advertise.h"
53 #include "bgpd/bgp_updgrp.h"
54 #include "bgpd/bgp_nexthop.h"
55 #include "bgpd/bgp_nht.h"
56 #include "bgpd/bgp_mplsvpn.h"
71 (struct bpacket
*) XCALLOC (MTYPE_BGP_PACKET
, sizeof (struct bpacket
));
77 bpacket_free (struct bpacket
*pkt
)
80 stream_free (pkt
->buffer
);
82 XFREE (MTYPE_BGP_PACKET
, pkt
);
86 bpacket_queue_init (struct bpacket_queue
*q
)
88 TAILQ_INIT (&(q
->pkts
));
92 * bpacket_queue_sanity_check
95 bpacket_queue_sanity_check (struct bpacket_queue
__attribute__ ((__unused__
)) *q
)
100 pkt
= bpacket_queue_last (q
);
102 assert (!pkt
->buffer
);
105 * Make sure the count of packets is correct.
109 pkt
= bpacket_queue_first (q
);
114 if (num_pkts
> q
->curr_count
)
117 pkt
= TAILQ_NEXT (pkt
, pkt_train
);
120 assert (num_pkts
== q
->curr_count
);
125 * bpacket_queue_add_packet
127 * Internal function of bpacket_queue - and adds a
128 * packet entry to the end of the list.
130 * Users of bpacket_queue should use bpacket_queue_add instead.
133 bpacket_queue_add_packet (struct bpacket_queue
*q
, struct bpacket
*pkt
)
135 struct bpacket
*last_pkt
;
137 if (TAILQ_EMPTY (&(q
->pkts
)))
138 TAILQ_INSERT_TAIL (&(q
->pkts
), pkt
, pkt_train
);
141 last_pkt
= bpacket_queue_last (q
);
142 TAILQ_INSERT_AFTER (&(q
->pkts
), last_pkt
, pkt
, pkt_train
);
145 if (q
->hwm_count
< q
->curr_count
)
146 q
->hwm_count
= q
->curr_count
;
150 * Adds a packet to the bpacket_queue.
152 * The stream passed is consumed by this function. So, the caller should
153 * not free or use the stream after
154 * invoking this function.
157 bpacket_queue_add (struct bpacket_queue
*q
, struct stream
*s
,
158 struct bpacket_attr_vec_arr
*vecarrp
)
161 struct bpacket
*last_pkt
;
164 pkt
= bpacket_alloc ();
165 if (TAILQ_EMPTY (&(q
->pkts
)))
170 memcpy (&pkt
->arr
, vecarrp
, sizeof (struct bpacket_attr_vec_arr
));
172 bpacket_attr_vec_arr_reset (&pkt
->arr
);
173 bpacket_queue_add_packet (q
, pkt
);
174 bpacket_queue_sanity_check (q
);
179 * Fill in the new information into the current sentinel and create a
182 bpacket_queue_sanity_check (q
);
183 last_pkt
= bpacket_queue_last (q
);
184 assert (last_pkt
->buffer
== NULL
);
185 last_pkt
->buffer
= s
;
187 memcpy (&last_pkt
->arr
, vecarrp
, sizeof (struct bpacket_attr_vec_arr
));
189 bpacket_attr_vec_arr_reset (&last_pkt
->arr
);
191 pkt
->ver
= last_pkt
->ver
;
193 bpacket_queue_add_packet (q
, pkt
);
195 bpacket_queue_sanity_check (q
);
200 bpacket_queue_first (struct bpacket_queue
*q
)
202 return (TAILQ_FIRST (&(q
->pkts
)));
206 bpacket_queue_last (struct bpacket_queue
*q
)
208 return TAILQ_LAST (&(q
->pkts
), pkt_queue
);
212 bpacket_queue_remove (struct bpacket_queue
*q
)
214 struct bpacket
*first
;
216 first
= bpacket_queue_first (q
);
219 TAILQ_REMOVE (&(q
->pkts
), first
, pkt_train
);
226 bpacket_queue_length (struct bpacket_queue
*q
)
228 return q
->curr_count
- 1;
232 bpacket_queue_hwm_length (struct bpacket_queue
*q
)
234 return q
->hwm_count
- 1;
238 bpacket_queue_is_full (struct bgp
*bgp
, struct bpacket_queue
*q
)
240 if (q
->curr_count
>= bgp
->default_subgroup_pkt_queue_max
)
246 bpacket_add_peer (struct bpacket
*pkt
, struct peer_af
*paf
)
251 LIST_INSERT_HEAD (&(pkt
->peers
), paf
, pkt_train
);
252 paf
->next_pkt_to_send
= pkt
;
256 * bpacket_queue_cleanup
259 bpacket_queue_cleanup (struct bpacket_queue
*q
)
263 while ((pkt
= bpacket_queue_remove (q
)))
270 * bpacket_queue_compact
272 * Delete packets that do not need to be transmitted to any peer from
275 * @return the number of packets deleted.
278 bpacket_queue_compact (struct bpacket_queue
*q
)
281 struct bpacket
*pkt
, *removed_pkt
;
287 pkt
= bpacket_queue_first (q
);
292 * Don't delete the sentinel.
297 if (!LIST_EMPTY (&(pkt
->peers
)))
300 removed_pkt
= bpacket_queue_remove (q
);
301 assert (pkt
== removed_pkt
);
302 bpacket_free (removed_pkt
);
307 bpacket_queue_sanity_check (q
);
312 bpacket_queue_advance_peer (struct peer_af
*paf
)
315 struct bpacket
*old_pkt
;
317 old_pkt
= paf
->next_pkt_to_send
;
318 if (old_pkt
->buffer
== NULL
)
319 /* Already at end of list */
322 LIST_REMOVE (paf
, pkt_train
);
323 pkt
= TAILQ_NEXT (old_pkt
, pkt_train
);
324 bpacket_add_peer (pkt
, paf
);
326 if (!bpacket_queue_compact (PAF_PKTQ (paf
)))
330 * Deleted one or more packets. Check if we can now merge this
331 * peer's subgroup into another subgroup.
333 update_subgroup_check_merge (paf
->subgroup
, "advanced peer in queue");
337 * bpacket_queue_remove_peer
339 * Remove the peer from the packet queue of the subgroup it belongs
343 bpacket_queue_remove_peer (struct peer_af
*paf
)
345 struct bpacket_queue
*q
;
352 LIST_REMOVE (paf
, pkt_train
);
353 paf
->next_pkt_to_send
= NULL
;
355 bpacket_queue_compact (q
);
359 bpacket_queue_virtual_length (struct peer_af
*paf
)
362 struct bpacket
*last
;
363 struct bpacket_queue
*q
;
365 pkt
= paf
->next_pkt_to_send
;
366 if (!pkt
|| (pkt
->buffer
== NULL
))
367 /* Already at end of list */
371 if (TAILQ_EMPTY (&(q
->pkts
)))
374 last
= TAILQ_LAST (&(q
->pkts
), pkt_queue
);
375 if (last
->ver
>= pkt
->ver
)
376 return last
->ver
- pkt
->ver
;
378 /* sequence # rolled over */
379 return (UINT_MAX
- pkt
->ver
+ 1) + last
->ver
;
383 * Dump the bpacket queue
386 bpacket_queue_show_vty (struct bpacket_queue
*q
, struct vty
*vty
)
391 pkt
= bpacket_queue_first (q
);
394 vty_out (vty
, " Packet %p ver %u buffer %p%s", pkt
, pkt
->ver
,
395 pkt
->buffer
, VTY_NEWLINE
);
397 LIST_FOREACH (paf
, &(pkt
->peers
), pkt_train
)
399 vty_out (vty
, " - %s%s", paf
->peer
->host
, VTY_NEWLINE
);
401 pkt
= bpacket_next (pkt
);
407 bpacket_reformat_for_peer (struct bpacket
*pkt
, struct peer_af
*paf
)
409 struct stream
*s
= NULL
;
410 bpacket_attr_vec
*vec
;
415 s
= stream_dup (pkt
->buffer
);
416 peer
= PAF_PEER(paf
);
418 vec
= &pkt
->arr
.entries
[BGP_ATTR_VEC_NH
];
419 if (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_UPDATED
))
422 afi_t nhafi
= AFI_MAX
; /* NH AFI is based on nhlen! */
423 int route_map_sets_nh
;
424 nhlen
= stream_getc_from (s
, vec
->offset
);
425 if (paf
->afi
== AFI_IP
|| paf
->afi
== AFI_IP6
)
427 nhafi
= BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen
);
428 if (peer_cap_enhe(peer
))
430 if (paf
->safi
== SAFI_MPLS_VPN
&& /* if VPN && not global */
431 nhlen
!= BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
)
432 nhafi
= AFI_MAX
; /* no change allowed */
437 struct in_addr v4nh
, *mod_v4nh
;
441 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
) ||
442 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
444 stream_get_from (&v4nh
, s
, vec
->offset
+ 1, 4);
448 * If route-map has set the nexthop, that is always used; if it is
449 * specified as peer-address, the peering address is picked up.
450 * Otherwise, if NH is unavailable from attribute, the peering addr
451 * is picked up; the "NH unavailable" case also covers next-hop-self
452 * and some other scenarios -- see subgroup_announce_check(). In
453 * all other cases, use the nexthop carried in the attribute unless
454 * it is EBGP non-multiaccess and there is no next-hop-unchanged setting.
455 * Note: It is assumed route-map cannot set the nexthop to an
458 if (route_map_sets_nh
)
460 if (CHECK_FLAG(vec
->flags
,
461 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
463 mod_v4nh
= &peer
->nexthop
.v4
;
467 else if (!v4nh
.s_addr
)
469 mod_v4nh
= &peer
->nexthop
.v4
;
472 else if (peer
->sort
== BGP_PEER_EBGP
&&
473 (bgp_multiaccess_check_v4 (v4nh
, peer
) == 0) &&
474 !CHECK_FLAG(vec
->flags
,
475 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
476 !peer_af_flag_check (peer
, nhafi
, paf
->safi
,
477 PEER_FLAG_NEXTHOP_UNCHANGED
))
479 /* NOTE: not handling case where NH has new AFI */
480 mod_v4nh
= &peer
->nexthop
.v4
;
484 if (nh_modified
) /* allow for VPN RD */
485 stream_put_in_addr_at (s
, vec
->offset
+ 1 + nhlen
- 4, mod_v4nh
);
487 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
488 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ nexthop %s%s",
489 PAF_SUBGRP(paf
)->update_group
->id
, PAF_SUBGRP(paf
)->id
,
490 peer
->host
, inet_ntoa (*mod_v4nh
),
491 (nhlen
== 12 ? " and RD" : ""));
493 else if (nhafi
== AFI_IP6
)
495 struct in6_addr v6nhglobal
, *mod_v6nhg
;
496 struct in6_addr v6nhlocal
, *mod_v6nhl
;
497 int gnh_modified
, lnh_modified
;
499 gnh_modified
= lnh_modified
= 0;
500 mod_v6nhg
= &v6nhglobal
;
501 mod_v6nhl
= &v6nhlocal
;
504 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
) ||
505 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
508 * The logic here is rather similar to that for IPv4, the
509 * additional work being to handle 1 or 2 nexthops. Also, 3rd
510 * party nexthop is not propagated for EBGP right now.
512 stream_get_from (&v6nhglobal
, s
, vec
->offset
+ 1, 16);
513 if (route_map_sets_nh
)
515 if (CHECK_FLAG(vec
->flags
,
516 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
518 mod_v6nhg
= &peer
->nexthop
.v6_global
;
522 else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal
))
524 mod_v6nhg
= &peer
->nexthop
.v6_global
;
527 else if (peer
->sort
== BGP_PEER_EBGP
&&
528 !CHECK_FLAG(vec
->flags
,
529 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
530 !peer_af_flag_check (peer
, nhafi
, paf
->safi
,
531 PEER_FLAG_NEXTHOP_UNCHANGED
))
533 /* NOTE: not handling case where NH has new AFI */
534 mod_v6nhg
= &peer
->nexthop
.v6_global
;
539 if (nhlen
== 32 || nhlen
== 48) /* 48 == VPN */
541 stream_get_from (&v6nhlocal
, s
, vec
->offset
+ 1 + (nhlen
-IPV6_MAX_BYTELEN
), IPV6_MAX_BYTELEN
);
542 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal
))
544 mod_v6nhl
= &peer
->nexthop
.v6_local
;
550 stream_put_in6_addr_at (s
, vec
->offset
+ 1, mod_v6nhg
);
552 stream_put_in6_addr_at (s
, vec
->offset
+ 1 + (nhlen
-IPV6_MAX_BYTELEN
), mod_v6nhl
);
554 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
556 if (nhlen
== 32 || nhlen
== 48)
557 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthops %s, %s%s",
558 PAF_SUBGRP(paf
)->update_group
->id
,
561 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
),
562 inet_ntop (AF_INET6
, mod_v6nhl
, buf2
, BUFSIZ
),
563 (nhlen
== 48 ? " and RD" : ""));
565 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthop %s%s",
566 PAF_SUBGRP(paf
)->update_group
->id
,
569 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
),
570 (nhlen
== 24 ? " and RD" : ""));
575 bgp_packet_add (peer
, s
);
580 * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
584 bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr
*vecarr
, size_t pos
)
591 for (i
= 0; i
< BGP_ATTR_VEC_MAX
; i
++)
592 vecarr
->entries
[i
].offset
+= pos
;
596 * Return if there are packets to build for this subgroup.
599 subgroup_packets_to_build (struct update_subgroup
*subgrp
)
601 struct bgp_advertise
*adv
;
606 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
);
610 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
618 bgp_info_addpath_tx_str (int addpath_encode
, u_int32_t addpath_tx_id
,
623 sprintf(buf
, " with addpath ID %d", addpath_tx_id
);
628 /* Make BGP update packet. */
630 subgroup_update_packet (struct update_subgroup
*subgrp
)
632 struct bpacket_attr_vec_arr vecarr
;
636 struct stream
*snlri
;
637 struct stream
*packet
;
638 struct bgp_adj_out
*adj
;
639 struct bgp_advertise
*adv
;
640 struct bgp_node
*rn
= NULL
;
641 struct bgp_info
*binfo
= NULL
;
642 bgp_size_t total_attr_len
= 0;
643 unsigned long attrlen_pos
= 0;
644 size_t mpattrlen_pos
= 0;
645 size_t mpattr_pos
= 0;
648 int space_remaining
= 0;
649 int space_needed
= 0;
650 char send_attr_str
[BUFSIZ
];
651 int send_attr_printed
= 0;
653 int addpath_encode
= 0;
654 u_int32_t addpath_tx_id
= 0;
655 struct prefix_rd
*prd
= NULL
;
660 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
664 peer
= SUBGRP_PEER (subgrp
);
665 afi
= SUBGRP_AFI (subgrp
);
666 safi
= SUBGRP_SAFI (subgrp
);
669 snlri
= subgrp
->scratch
;
670 stream_reset (snlri
);
672 bpacket_attr_vec_arr_reset (&vecarr
);
674 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
676 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
682 addpath_tx_id
= adj
->addpath_tx_id
;
685 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
686 BGP_MAX_PACKET_SIZE_OVERFLOW
;
687 space_needed
= BGP_NLRI_LENGTH
+
688 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
690 /* When remaining space can't include NLRI and it's length. */
691 if (space_remaining
< space_needed
)
694 /* If packet is empty, set attribute. */
695 if (stream_empty (s
))
697 struct peer
*from
= NULL
;
702 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
703 * one byte message type.
705 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
707 /* 2: withdrawn routes length */
710 /* 3: total attributes length - attrlen_pos stores the position */
711 attrlen_pos
= stream_get_endp (s
);
714 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
715 * attribute, according to draft-ietf-idr-error-handling. Save the
718 mpattr_pos
= stream_get_endp (s
);
720 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
721 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
,
722 adv
->baa
->attr
, &vecarr
,
724 from
, NULL
, NULL
, 0, 0);
726 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
727 BGP_MAX_PACKET_SIZE_OVERFLOW
;
728 space_needed
= BGP_NLRI_LENGTH
+
729 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
731 /* If the attributes alone do not leave any room for NLRI then
733 if (space_remaining
< space_needed
)
735 zlog_err ("u%" PRIu64
":s%" PRIu64
" attributes too long, cannot send UPDATE",
736 subgrp
->update_group
->id
, subgrp
->id
);
738 /* Flush the FIFO update queue */
740 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
744 if (BGP_DEBUG (update
, UPDATE_OUT
) ||
745 BGP_DEBUG (update
, UPDATE_PREFIX
))
747 memset (send_attr_str
, 0, BUFSIZ
);
748 send_attr_printed
= 0;
749 bgp_dump_attr (peer
, adv
->baa
->attr
, send_attr_str
, BUFSIZ
);
753 if ((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
754 !peer_cap_enhe(peer
))
755 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
758 /* Encode the prefix in MP_REACH_NLRI attribute */
762 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
763 if (binfo
&& binfo
->extra
)
764 tag
= binfo
->extra
->tag
;
766 if (stream_empty (snlri
))
767 mpattrlen_pos
= bgp_packet_mpattr_start (snlri
, afi
, safi
,
768 (peer_cap_enhe(peer
) ? AFI_IP6
:
769 AFI_MAX
), /* get from NH */
770 &vecarr
, adv
->baa
->attr
);
772 bgp_packet_mpattr_prefix (snlri
, afi
, safi
, &rn
->p
, prd
,
773 tag
, addpath_encode
, addpath_tx_id
, adv
->baa
->attr
);
778 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
780 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
782 if (!send_attr_printed
)
784 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE w/ attr: %s",
785 subgrp
->update_group
->id
, subgrp
->id
, send_attr_str
);
786 if (!stream_empty (snlri
))
791 pkt_afi
= afi_int2iana (afi
);
792 pkt_safi
= safi_int2iana (safi
);
793 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send MP_REACH for afi/safi %d/%d",
794 subgrp
->update_group
->id
, subgrp
->id
, pkt_afi
, pkt_safi
);
797 send_attr_printed
= 1;
800 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s",
801 subgrp
->update_group
->id
, subgrp
->id
,
802 bgp_debug_rdpfxpath2str (prd
, &rn
->p
, addpath_encode
,
804 pfx_buf
, sizeof (pfx_buf
)));
807 /* Synchnorize attribute. */
809 bgp_attr_unintern (&adj
->attr
);
813 adj
->attr
= bgp_attr_intern (adv
->baa
->attr
);
815 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
818 if (!stream_empty (s
))
820 if (!stream_empty (snlri
))
822 bgp_packet_mpattr_end (snlri
, mpattrlen_pos
);
823 total_attr_len
+= stream_get_endp (snlri
);
826 /* set the total attribute length correctly */
827 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
829 if (!stream_empty (snlri
))
831 packet
= stream_dupcat (s
, snlri
, mpattr_pos
);
832 bpacket_attr_vec_arr_update (&vecarr
, mpattr_pos
);
835 packet
= stream_dup (s
);
836 bgp_packet_set_size (packet
);
837 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
838 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE len %zd numpfx %d",
839 subgrp
->update_group
->id
, subgrp
->id
,
840 (stream_get_endp(packet
) - stream_get_getp(packet
)), num_pfx
);
841 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
843 stream_reset (snlri
);
849 /* Make BGP withdraw packet. */
851 16-octet marker | 2-octet length | 1-octet type |
852 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
854 /* For other afi/safis:
855 16-octet marker | 2-octet length | 1-octet type |
856 2-octet withdrawn route length (=0) | 2-octet attrlen |
857 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
860 subgroup_withdraw_packet (struct update_subgroup
*subgrp
)
864 struct bgp_adj_out
*adj
;
865 struct bgp_advertise
*adv
;
868 bgp_size_t unfeasible_len
;
869 bgp_size_t total_attr_len
;
871 size_t attrlen_pos
= 0;
872 size_t mplen_pos
= 0;
873 u_char first_time
= 1;
876 int space_remaining
= 0;
877 int space_needed
= 0;
879 int addpath_encode
= 0;
880 u_int32_t addpath_tx_id
= 0;
881 struct prefix_rd
*prd
= NULL
;
887 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
890 peer
= SUBGRP_PEER (subgrp
);
891 afi
= SUBGRP_AFI (subgrp
);
892 safi
= SUBGRP_SAFI (subgrp
);
895 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
897 while ((adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
)) != NULL
)
902 addpath_tx_id
= adj
->addpath_tx_id
;
904 space_remaining
= STREAM_REMAIN (s
) -
905 BGP_MAX_PACKET_SIZE_OVERFLOW
;
906 space_needed
= BGP_NLRI_LENGTH
+ BGP_TOTAL_ATTR_LEN
+
907 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
909 if (space_remaining
< space_needed
)
912 if (stream_empty (s
))
914 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
915 stream_putw (s
, 0); /* unfeasible routes length */
920 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
921 !peer_cap_enhe(peer
))
922 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
926 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
928 /* If first time, format the MP_UNREACH header */
934 pkt_afi
= afi_int2iana (afi
);
935 pkt_safi
= safi_int2iana (safi
);
937 attrlen_pos
= stream_get_endp (s
);
938 /* total attr length = 0 for now. reevaluate later */
940 mp_start
= stream_get_endp (s
);
941 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
942 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
943 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send MP_UNREACH for afi/safi %d/%d",
944 subgrp
->update_group
->id
, subgrp
->id
, pkt_afi
, pkt_safi
);
947 bgp_packet_mpunreach_prefix (s
, &rn
->p
, afi
, safi
, prd
, NULL
,
948 addpath_encode
, addpath_tx_id
, NULL
);
953 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
955 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
957 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s -- unreachable",
958 subgrp
->update_group
->id
, subgrp
->id
,
959 bgp_debug_rdpfxpath2str (prd
, &rn
->p
,
960 addpath_encode
, addpath_tx_id
,
961 pfx_buf
, sizeof (pfx_buf
)));
966 bgp_adj_out_remove_subgroup (rn
, adj
, subgrp
);
967 bgp_unlock_node (rn
);
970 if (!stream_empty (s
))
972 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
973 !peer_cap_enhe(peer
))
976 = stream_get_endp (s
) - BGP_HEADER_SIZE
- BGP_UNFEASIBLE_LEN
;
977 stream_putw_at (s
, BGP_HEADER_SIZE
, unfeasible_len
);
982 /* Set the mp_unreach attr's length */
983 bgp_packet_mpunreach_end (s
, mplen_pos
);
985 /* Set total path attribute length. */
986 total_attr_len
= stream_get_endp (s
) - mp_start
;
987 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
989 bgp_packet_set_size (s
);
990 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
991 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE (withdraw) len %zd numpfx %d",
992 subgrp
->update_group
->id
, subgrp
->id
,
993 (stream_get_endp(s
) - stream_get_getp(s
)), num_pfx
);
994 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), stream_dup (s
), NULL
);
1003 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
1004 struct attr
*attr
, struct peer
*from
)
1010 bgp_size_t total_attr_len
;
1013 struct bpacket_attr_vec_arr vecarr
;
1014 int addpath_encode
= 0;
1016 if (DISABLE_BGP_ANNOUNCE
)
1022 peer
= SUBGRP_PEER (subgrp
);
1023 afi
= SUBGRP_AFI (subgrp
);
1024 safi
= SUBGRP_SAFI (subgrp
);
1025 bpacket_attr_vec_arr_reset (&vecarr
);
1026 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
1029 str2prefix ("0.0.0.0/0", &p
);
1031 str2prefix ("::/0", &p
);
1033 /* Logging the attribute. */
1034 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1036 char attrstr
[BUFSIZ
];
1037 char buf
[PREFIX_STRLEN
];
1041 bgp_dump_attr (peer
, attr
, attrstr
, BUFSIZ
);
1042 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1043 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s%s %s",
1044 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1045 prefix2str (&p
, buf
, sizeof (buf
)),
1046 tx_id_buf
, attrstr
);
1049 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1051 /* Make BGP update packet. */
1052 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1054 /* Unfeasible Routes Length. */
1057 /* Make place for total attribute length. */
1058 pos
= stream_get_endp (s
);
1060 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
, attr
, &vecarr
, &p
,
1061 afi
, safi
, from
, NULL
, NULL
,
1063 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1065 /* Set Total Path Attribute Length. */
1066 stream_putw_at (s
, pos
, total_attr_len
);
1069 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1070 !peer_cap_enhe(peer
))
1071 stream_put_prefix_addpath (s
, &p
, addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1074 bgp_packet_set_size (s
);
1076 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, &vecarr
);
1077 subgroup_trigger_write(subgrp
);
1081 subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
)
1086 unsigned long attrlen_pos
= 0;
1088 bgp_size_t unfeasible_len
;
1089 bgp_size_t total_attr_len
= 0;
1090 size_t mp_start
= 0;
1091 size_t mplen_pos
= 0;
1094 int addpath_encode
= 0;
1096 if (DISABLE_BGP_ANNOUNCE
)
1099 peer
= SUBGRP_PEER (subgrp
);
1100 afi
= SUBGRP_AFI (subgrp
);
1101 safi
= SUBGRP_SAFI (subgrp
);
1102 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
1105 str2prefix ("0.0.0.0/0", &p
);
1107 str2prefix ("::/0", &p
);
1109 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1111 char buf
[PREFIX_STRLEN
];
1112 char tx_id_buf
[INET6_BUFSIZ
];
1114 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1115 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s%s -- unreachable",
1116 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1117 prefix2str (&p
, buf
, sizeof (buf
)), tx_id_buf
);
1120 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1122 /* Make BGP update packet. */
1123 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1125 /* Unfeasible Routes Length. */ ;
1126 cp
= stream_get_endp (s
);
1129 /* Withdrawn Routes. */
1130 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1131 !peer_cap_enhe(peer
))
1133 stream_put_prefix_addpath (s
, &p
, addpath_encode
,
1134 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1136 unfeasible_len
= stream_get_endp (s
) - cp
- 2;
1138 /* Set unfeasible len. */
1139 stream_putw_at (s
, cp
, unfeasible_len
);
1141 /* Set total path attribute length. */
1146 attrlen_pos
= stream_get_endp (s
);
1148 mp_start
= stream_get_endp (s
);
1149 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
1150 bgp_packet_mpunreach_prefix (s
, &p
, afi
, safi
, NULL
, NULL
,
1152 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, NULL
);
1154 /* Set the mp_unreach attr's length */
1155 bgp_packet_mpunreach_end (s
, mplen_pos
);
1157 /* Set total path attribute length. */
1158 total_attr_len
= stream_get_endp (s
) - mp_start
;
1159 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
1162 bgp_packet_set_size (s
);
1164 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, NULL
);
1165 subgroup_trigger_write(subgrp
);
1169 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr
*vecarr
,
1170 bpacket_attr_vec_type type
,
1173 if (CHECK_FLAG (attr
->rmap_change_flags
,
1174 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
))
1175 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1176 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
);
1178 if (CHECK_FLAG (attr
->rmap_change_flags
, BATTR_REFLECTED
))
1179 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1180 BPKT_ATTRVEC_FLAGS_REFLECTED
);
1182 if (CHECK_FLAG (attr
->rmap_change_flags
,
1183 BATTR_RMAP_NEXTHOP_UNCHANGED
))
1184 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1185 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
);
1187 if (CHECK_FLAG (attr
->rmap_change_flags
,
1188 BATTR_RMAP_IPV4_NHOP_CHANGED
))
1189 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1190 BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
);
1192 if (CHECK_FLAG (attr
->rmap_change_flags
,
1193 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
))
1194 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1195 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
);
1197 if (CHECK_FLAG (attr
->rmap_change_flags
,
1198 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
))
1199 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1200 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED
);
1203 /* Reset the Attributes vector array. The vector array is used to override
1204 * certain output parameters in the packet for a particular peer
1207 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
)
1215 while (i
< BGP_ATTR_VEC_MAX
)
1217 vecarr
->entries
[i
].flags
= 0;
1218 vecarr
->entries
[i
].offset
= 0;
1223 /* Setup a particular node entry in the vecarr */
1225 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
1226 bpacket_attr_vec_type type
, struct stream
*s
,
1231 assert (type
< BGP_ATTR_VEC_MAX
);
1233 SET_FLAG (vecarr
->entries
[type
].flags
, BPKT_ATTRVEC_FLAGS_UPDATED
);
1234 vecarr
->entries
[type
].offset
= stream_get_endp (s
);
1236 bpacket_vec_arr_inherit_attr_flags(vecarr
, type
, attr
);