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"
44 #include "workqueue.h"
48 #include "bgpd/bgpd.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_fsm.h"
51 #include "bgpd/bgp_route.h"
52 #include "bgpd/bgp_packet.h"
53 #include "bgpd/bgp_advertise.h"
54 #include "bgpd/bgp_updgrp.h"
55 #include "bgpd/bgp_nexthop.h"
56 #include "bgpd/bgp_nht.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 int route_map_sets_nh
;
423 nhlen
= stream_getc_from (s
, vec
->offset
);
425 if (paf
->afi
== AFI_IP
&& !peer_cap_enhe(peer
))
427 struct in_addr v4nh
, *mod_v4nh
;
431 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
) ||
432 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
434 stream_get_from (&v4nh
, s
, vec
->offset
+ 1, 4);
438 * If route-map has set the nexthop, that is always used; if it is
439 * specified as peer-address, the peering address is picked up.
440 * Otherwise, if NH is unavailable from attribute, the peering addr
441 * is picked up; the "NH unavailable" case also covers next-hop-self
442 * and some other scenarios -- see subgroup_announce_check(). In
443 * all other cases, use the nexthop carried in the attribute unless
444 * it is EBGP non-multiaccess and there is no next-hop-unchanged setting.
445 * Note: It is assumed route-map cannot set the nexthop to an
448 if (route_map_sets_nh
)
450 if (CHECK_FLAG(vec
->flags
,
451 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
453 mod_v4nh
= &peer
->nexthop
.v4
;
457 else if (!v4nh
.s_addr
)
459 mod_v4nh
= &peer
->nexthop
.v4
;
462 else if (peer
->sort
== BGP_PEER_EBGP
&&
463 (bgp_multiaccess_check_v4 (v4nh
, peer
) == 0) &&
464 !CHECK_FLAG(vec
->flags
,
465 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
466 !peer_af_flag_check (peer
, paf
->afi
, paf
->safi
,
467 PEER_FLAG_NEXTHOP_UNCHANGED
))
469 mod_v4nh
= &peer
->nexthop
.v4
;
474 stream_put_in_addr_at (s
, vec
->offset
+ 1, mod_v4nh
);
476 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
477 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ nexthop %s",
478 PAF_SUBGRP(paf
)->update_group
->id
, PAF_SUBGRP(paf
)->id
,
479 peer
->host
, inet_ntoa (*mod_v4nh
));
482 else if (paf
->afi
== AFI_IP6
|| peer_cap_enhe(peer
))
484 struct in6_addr v6nhglobal
, *mod_v6nhg
;
485 struct in6_addr v6nhlocal
, *mod_v6nhl
;
486 int gnh_modified
, lnh_modified
;
488 gnh_modified
= lnh_modified
= 0;
489 mod_v6nhg
= &v6nhglobal
;
490 mod_v6nhl
= &v6nhlocal
;
493 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
) ||
494 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
497 * The logic here is rather similar to that for IPv4, the
498 * additional work being to handle 1 or 2 nexthops. Also, 3rd
499 * party nexthop is not propagated for EBGP right now.
501 stream_get_from (&v6nhglobal
, s
, vec
->offset
+ 1, 16);
502 if (route_map_sets_nh
)
504 if (CHECK_FLAG(vec
->flags
,
505 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
507 mod_v6nhg
= &peer
->nexthop
.v6_global
;
511 else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal
))
513 mod_v6nhg
= &peer
->nexthop
.v6_global
;
516 else if (peer
->sort
== BGP_PEER_EBGP
&&
517 !CHECK_FLAG(vec
->flags
,
518 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
519 !peer_af_flag_check (peer
, paf
->afi
, paf
->safi
,
520 PEER_FLAG_NEXTHOP_UNCHANGED
))
522 mod_v6nhg
= &peer
->nexthop
.v6_global
;
529 stream_get_from (&v6nhlocal
, s
, vec
->offset
+ 1 + 16, 16);
530 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal
))
532 mod_v6nhl
= &peer
->nexthop
.v6_local
;
538 stream_put_in6_addr_at (s
, vec
->offset
+ 1, mod_v6nhg
);
540 stream_put_in6_addr_at (s
, vec
->offset
+ 1 + 16, mod_v6nhl
);
542 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
545 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthops %s, %s",
546 PAF_SUBGRP(paf
)->update_group
->id
,
549 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
),
550 inet_ntop (AF_INET6
, mod_v6nhl
, buf2
, BUFSIZ
));
552 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthop %s",
553 PAF_SUBGRP(paf
)->update_group
->id
,
556 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
));
561 bgp_packet_add (peer
, s
);
566 * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
570 bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr
*vecarr
, size_t pos
)
577 for (i
= 0; i
< BGP_ATTR_VEC_MAX
; i
++)
578 vecarr
->entries
[i
].offset
+= pos
;
582 * Return if there are packets to build for this subgroup.
585 subgroup_packets_to_build (struct update_subgroup
*subgrp
)
587 struct bgp_advertise
*adv
;
592 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
);
596 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
604 bgp_info_addpath_tx_str (int addpath_encode
, u_int32_t addpath_tx_id
,
608 sprintf(buf
, " with addpath ID %d", addpath_tx_id
);
611 /* Make BGP update packet. */
613 subgroup_update_packet (struct update_subgroup
*subgrp
)
615 struct bpacket_attr_vec_arr vecarr
;
619 struct stream
*snlri
;
620 struct stream
*packet
;
621 struct bgp_adj_out
*adj
;
622 struct bgp_advertise
*adv
;
623 struct bgp_node
*rn
= NULL
;
624 struct bgp_info
*binfo
= NULL
;
625 bgp_size_t total_attr_len
= 0;
626 unsigned long attrlen_pos
= 0;
627 size_t mpattrlen_pos
= 0;
628 size_t mpattr_pos
= 0;
631 int space_remaining
= 0;
632 int space_needed
= 0;
633 char send_attr_str
[BUFSIZ
];
634 int send_attr_printed
= 0;
636 int addpath_encode
= 0;
637 u_int32_t addpath_tx_id
= 0;
642 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
646 peer
= SUBGRP_PEER (subgrp
);
647 afi
= SUBGRP_AFI (subgrp
);
648 safi
= SUBGRP_SAFI (subgrp
);
651 snlri
= subgrp
->scratch
;
652 stream_reset (snlri
);
654 bpacket_attr_vec_arr_reset (&vecarr
);
656 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
658 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
664 addpath_tx_id
= adj
->addpath_tx_id
;
667 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
668 BGP_MAX_PACKET_SIZE_OVERFLOW
;
669 space_needed
= BGP_NLRI_LENGTH
+
670 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
672 /* When remaining space can't include NLRI and it's length. */
673 if (space_remaining
< space_needed
)
676 /* If packet is empty, set attribute. */
677 if (stream_empty (s
))
679 struct peer
*from
= NULL
;
684 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
685 * one byte message type.
687 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
689 /* 2: withdrawn routes length */
692 /* 3: total attributes length - attrlen_pos stores the position */
693 attrlen_pos
= stream_get_endp (s
);
696 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
697 * attribute, according to draft-ietf-idr-error-handling. Save the
700 mpattr_pos
= stream_get_endp (s
);
702 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
703 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
,
704 adv
->baa
->attr
, &vecarr
,
706 from
, NULL
, NULL
, 0, 0);
708 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
709 BGP_MAX_PACKET_SIZE_OVERFLOW
;
710 space_needed
= BGP_NLRI_LENGTH
+
711 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
713 /* If the attributes alone do not leave any room for NLRI then
715 if (space_remaining
< space_needed
)
717 zlog_err ("u%" PRIu64
":s%" PRIu64
" attributes too long, cannot send UPDATE",
718 subgrp
->update_group
->id
, subgrp
->id
);
720 /* Flush the FIFO update queue */
722 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
726 if (BGP_DEBUG (update
, UPDATE_OUT
) ||
727 BGP_DEBUG (update
, UPDATE_PREFIX
))
729 memset (send_attr_str
, 0, BUFSIZ
);
730 send_attr_printed
= 0;
731 bgp_dump_attr (peer
, adv
->baa
->attr
, send_attr_str
, BUFSIZ
);
735 if ((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
736 !peer_cap_enhe(peer
))
737 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
740 /* Encode the prefix in MP_REACH_NLRI attribute */
741 struct prefix_rd
*prd
= NULL
;
745 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
746 if (binfo
&& binfo
->extra
)
747 tag
= binfo
->extra
->tag
;
749 if (stream_empty (snlri
))
750 mpattrlen_pos
= bgp_packet_mpattr_start (snlri
, afi
, safi
,
751 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
752 &vecarr
, adv
->baa
->attr
);
753 bgp_packet_mpattr_prefix (snlri
, afi
, safi
, &rn
->p
, prd
, tag
,
754 addpath_encode
, addpath_tx_id
);
759 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
761 char buf
[INET6_BUFSIZ
];
764 if (!send_attr_printed
)
766 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE w/ attr: %s",
767 subgrp
->update_group
->id
, subgrp
->id
, send_attr_str
);
768 send_attr_printed
= 1;
771 bgp_info_addpath_tx_str (addpath_encode
, addpath_tx_id
, tx_id_buf
);
772 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s",
773 subgrp
->update_group
->id
, subgrp
->id
,
774 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
, INET6_BUFSIZ
),
775 rn
->p
.prefixlen
, tx_id_buf
);
778 /* Synchnorize attribute. */
780 bgp_attr_unintern (&adj
->attr
);
784 adj
->attr
= bgp_attr_intern (adv
->baa
->attr
);
786 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
789 if (!stream_empty (s
))
791 if (!stream_empty (snlri
))
793 bgp_packet_mpattr_end (snlri
, mpattrlen_pos
);
794 total_attr_len
+= stream_get_endp (snlri
);
797 /* set the total attribute length correctly */
798 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
800 if (!stream_empty (snlri
))
802 packet
= stream_dupcat (s
, snlri
, mpattr_pos
);
803 bpacket_attr_vec_arr_update (&vecarr
, mpattr_pos
);
806 packet
= stream_dup (s
);
807 bgp_packet_set_size (packet
);
808 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
809 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE len %zd numpfx %d",
810 subgrp
->update_group
->id
, subgrp
->id
,
811 (stream_get_endp(packet
) - stream_get_getp(packet
)), num_pfx
);
812 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
814 stream_reset (snlri
);
820 /* Make BGP withdraw packet. */
822 16-octet marker | 2-octet length | 1-octet type |
823 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
825 /* For other afi/safis:
826 16-octet marker | 2-octet length | 1-octet type |
827 2-octet withdrawn route length (=0) | 2-octet attrlen |
828 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
831 subgroup_withdraw_packet (struct update_subgroup
*subgrp
)
835 struct bgp_adj_out
*adj
;
836 struct bgp_advertise
*adv
;
839 bgp_size_t unfeasible_len
;
840 bgp_size_t total_attr_len
;
842 size_t attrlen_pos
= 0;
843 size_t mplen_pos
= 0;
844 u_char first_time
= 1;
847 int space_remaining
= 0;
848 int space_needed
= 0;
850 int addpath_encode
= 0;
851 u_int32_t addpath_tx_id
= 0;
856 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
859 peer
= SUBGRP_PEER (subgrp
);
860 afi
= SUBGRP_AFI (subgrp
);
861 safi
= SUBGRP_SAFI (subgrp
);
864 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
866 while ((adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
)) != NULL
)
871 addpath_tx_id
= adj
->addpath_tx_id
;
873 space_remaining
= STREAM_REMAIN (s
) -
874 BGP_MAX_PACKET_SIZE_OVERFLOW
;
875 space_needed
= BGP_NLRI_LENGTH
+ BGP_TOTAL_ATTR_LEN
+
876 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
878 if (space_remaining
< space_needed
)
881 if (stream_empty (s
))
883 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
884 stream_putw (s
, 0); /* unfeasible routes length */
889 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
890 !peer_cap_enhe(peer
))
891 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
894 struct prefix_rd
*prd
= NULL
;
897 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
899 /* If first time, format the MP_UNREACH header */
902 attrlen_pos
= stream_get_endp (s
);
903 /* total attr length = 0 for now. reevaluate later */
905 mp_start
= stream_get_endp (s
);
906 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
909 bgp_packet_mpunreach_prefix (s
, &rn
->p
, afi
, safi
, prd
, NULL
,
910 addpath_encode
, addpath_tx_id
);
915 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
917 char buf
[INET6_BUFSIZ
];
919 bgp_info_addpath_tx_str (addpath_encode
, addpath_tx_id
, tx_id_buf
);
920 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s -- unreachable",
921 subgrp
->update_group
->id
, subgrp
->id
,
922 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
, INET6_BUFSIZ
),
923 rn
->p
.prefixlen
, tx_id_buf
);
928 bgp_adj_out_remove_subgroup (rn
, adj
, subgrp
);
929 bgp_unlock_node (rn
);
932 if (!stream_empty (s
))
934 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
935 !peer_cap_enhe(peer
))
938 = stream_get_endp (s
) - BGP_HEADER_SIZE
- BGP_UNFEASIBLE_LEN
;
939 stream_putw_at (s
, BGP_HEADER_SIZE
, unfeasible_len
);
944 /* Set the mp_unreach attr's length */
945 bgp_packet_mpunreach_end (s
, mplen_pos
);
947 /* Set total path attribute length. */
948 total_attr_len
= stream_get_endp (s
) - mp_start
;
949 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
951 bgp_packet_set_size (s
);
952 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
953 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE (withdraw) len %zd numpfx %d",
954 subgrp
->update_group
->id
, subgrp
->id
,
955 (stream_get_endp(s
) - stream_get_getp(s
)), num_pfx
);
956 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), stream_dup (s
), NULL
);
965 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
966 struct attr
*attr
, struct peer
*from
)
972 bgp_size_t total_attr_len
;
975 struct bpacket_attr_vec_arr vecarr
;
976 int addpath_encode
= 0;
978 if (DISABLE_BGP_ANNOUNCE
)
984 peer
= SUBGRP_PEER (subgrp
);
985 afi
= SUBGRP_AFI (subgrp
);
986 safi
= SUBGRP_SAFI (subgrp
);
987 bpacket_attr_vec_arr_reset (&vecarr
);
988 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
991 str2prefix ("0.0.0.0/0", &p
);
994 str2prefix ("::/0", &p
);
995 #endif /* HAVE_IPV6 */
997 /* Logging the attribute. */
998 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1000 char attrstr
[BUFSIZ
];
1001 char buf
[INET6_BUFSIZ
];
1005 bgp_dump_attr (peer
, attr
, attrstr
, BUFSIZ
);
1006 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1007 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s %s",
1008 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1009 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
1010 p
.prefixlen
, tx_id_buf
, attrstr
);
1013 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1015 /* Make BGP update packet. */
1016 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1018 /* Unfeasible Routes Length. */
1021 /* Make place for total attribute length. */
1022 pos
= stream_get_endp (s
);
1024 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
, attr
, &vecarr
, &p
,
1025 afi
, safi
, from
, NULL
, NULL
,
1027 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1029 /* Set Total Path Attribute Length. */
1030 stream_putw_at (s
, pos
, total_attr_len
);
1033 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1034 !peer_cap_enhe(peer
))
1035 stream_put_prefix_addpath (s
, &p
, addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1038 bgp_packet_set_size (s
);
1040 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, &vecarr
);
1041 subgroup_trigger_write(subgrp
);
1045 subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
)
1050 unsigned long attrlen_pos
= 0;
1052 bgp_size_t unfeasible_len
;
1053 bgp_size_t total_attr_len
= 0;
1054 size_t mp_start
= 0;
1055 size_t mplen_pos
= 0;
1058 int addpath_encode
= 0;
1060 if (DISABLE_BGP_ANNOUNCE
)
1063 peer
= SUBGRP_PEER (subgrp
);
1064 afi
= SUBGRP_AFI (subgrp
);
1065 safi
= SUBGRP_SAFI (subgrp
);
1066 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
1069 str2prefix ("0.0.0.0/0", &p
);
1072 str2prefix ("::/0", &p
);
1073 #endif /* HAVE_IPV6 */
1075 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1077 char buf
[INET6_BUFSIZ
];
1078 char tx_id_buf
[INET6_BUFSIZ
];
1080 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1081 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s -- unreachable",
1082 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1083 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
1084 p
.prefixlen
, tx_id_buf
);
1087 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1089 /* Make BGP update packet. */
1090 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1092 /* Unfeasible Routes Length. */ ;
1093 cp
= stream_get_endp (s
);
1096 /* Withdrawn Routes. */
1097 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1098 !peer_cap_enhe(peer
))
1100 stream_put_prefix_addpath (s
, &p
, addpath_encode
,
1101 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1103 unfeasible_len
= stream_get_endp (s
) - cp
- 2;
1105 /* Set unfeasible len. */
1106 stream_putw_at (s
, cp
, unfeasible_len
);
1108 /* Set total path attribute length. */
1113 attrlen_pos
= stream_get_endp (s
);
1115 mp_start
= stream_get_endp (s
);
1116 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
1117 bgp_packet_mpunreach_prefix (s
, &p
, afi
, safi
, NULL
, NULL
,
1119 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1121 /* Set the mp_unreach attr's length */
1122 bgp_packet_mpunreach_end (s
, mplen_pos
);
1124 /* Set total path attribute length. */
1125 total_attr_len
= stream_get_endp (s
) - mp_start
;
1126 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
1129 bgp_packet_set_size (s
);
1131 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, NULL
);
1132 subgroup_trigger_write(subgrp
);
1136 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr
*vecarr
,
1137 bpacket_attr_vec_type type
,
1140 if (CHECK_FLAG (attr
->rmap_change_flags
,
1141 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
))
1142 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1143 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
);
1145 if (CHECK_FLAG (attr
->rmap_change_flags
, BATTR_REFLECTED
))
1146 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1147 BPKT_ATTRVEC_FLAGS_REFLECTED
);
1149 if (CHECK_FLAG (attr
->rmap_change_flags
,
1150 BATTR_RMAP_NEXTHOP_UNCHANGED
))
1151 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1152 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
);
1154 if (CHECK_FLAG (attr
->rmap_change_flags
,
1155 BATTR_RMAP_IPV4_NHOP_CHANGED
))
1156 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1157 BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
);
1159 if (CHECK_FLAG (attr
->rmap_change_flags
,
1160 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
))
1161 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1162 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
);
1164 if (CHECK_FLAG (attr
->rmap_change_flags
,
1165 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
))
1166 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1167 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED
);
1170 /* Reset the Attributes vector array. The vector array is used to override
1171 * certain output parameters in the packet for a particular peer
1174 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
)
1182 while (i
< BGP_ATTR_VEC_MAX
)
1184 vecarr
->entries
[i
].flags
= 0;
1185 vecarr
->entries
[i
].offset
= 0;
1190 /* Setup a particular node entry in the vecarr */
1192 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
1193 bpacket_attr_vec_type type
, struct stream
*s
,
1198 assert (type
< BGP_ATTR_VEC_MAX
);
1200 SET_FLAG (vecarr
->entries
[type
].flags
, BPKT_ATTRVEC_FLAGS_UPDATED
);
1201 vecarr
->entries
[type
].offset
= stream_get_endp (s
);
1203 bpacket_vec_arr_inherit_attr_flags(vecarr
, type
, attr
);