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"
70 (struct bpacket
*) XCALLOC (MTYPE_BGP_PACKET
, sizeof (struct bpacket
));
76 bpacket_free (struct bpacket
*pkt
)
79 stream_free (pkt
->buffer
);
81 XFREE (MTYPE_BGP_PACKET
, pkt
);
85 bpacket_queue_init (struct bpacket_queue
*q
)
87 TAILQ_INIT (&(q
->pkts
));
91 * bpacket_queue_sanity_check
94 bpacket_queue_sanity_check (struct bpacket_queue
__attribute__ ((__unused__
)) *q
)
99 pkt
= bpacket_queue_last (q
);
101 assert (!pkt
->buffer
);
104 * Make sure the count of packets is correct.
108 pkt
= bpacket_queue_first (q
);
113 if (num_pkts
> q
->curr_count
)
116 pkt
= TAILQ_NEXT (pkt
, pkt_train
);
119 assert (num_pkts
== q
->curr_count
);
124 * bpacket_queue_add_packet
126 * Internal function of bpacket_queue - and adds a
127 * packet entry to the end of the list.
129 * Users of bpacket_queue should use bpacket_queue_add instead.
132 bpacket_queue_add_packet (struct bpacket_queue
*q
, struct bpacket
*pkt
)
134 struct bpacket
*last_pkt
;
136 if (TAILQ_EMPTY (&(q
->pkts
)))
137 TAILQ_INSERT_TAIL (&(q
->pkts
), pkt
, pkt_train
);
140 last_pkt
= bpacket_queue_last (q
);
141 TAILQ_INSERT_AFTER (&(q
->pkts
), last_pkt
, pkt
, pkt_train
);
144 if (q
->hwm_count
< q
->curr_count
)
145 q
->hwm_count
= q
->curr_count
;
149 * Adds a packet to the bpacket_queue.
151 * The stream passed is consumed by this function. So, the caller should
152 * not free or use the stream after
153 * invoking this function.
156 bpacket_queue_add (struct bpacket_queue
*q
, struct stream
*s
,
157 struct bpacket_attr_vec_arr
*vecarrp
)
160 struct bpacket
*last_pkt
;
163 pkt
= bpacket_alloc ();
164 if (TAILQ_EMPTY (&(q
->pkts
)))
169 memcpy (&pkt
->arr
, vecarrp
, sizeof (struct bpacket_attr_vec_arr
));
171 bpacket_attr_vec_arr_reset (&pkt
->arr
);
172 bpacket_queue_add_packet (q
, pkt
);
173 bpacket_queue_sanity_check (q
);
178 * Fill in the new information into the current sentinel and create a
181 bpacket_queue_sanity_check (q
);
182 last_pkt
= bpacket_queue_last (q
);
183 assert (last_pkt
->buffer
== NULL
);
184 last_pkt
->buffer
= s
;
186 memcpy (&last_pkt
->arr
, vecarrp
, sizeof (struct bpacket_attr_vec_arr
));
188 bpacket_attr_vec_arr_reset (&last_pkt
->arr
);
190 pkt
->ver
= last_pkt
->ver
;
192 bpacket_queue_add_packet (q
, pkt
);
194 bpacket_queue_sanity_check (q
);
199 bpacket_queue_first (struct bpacket_queue
*q
)
201 return (TAILQ_FIRST (&(q
->pkts
)));
205 bpacket_queue_last (struct bpacket_queue
*q
)
207 return TAILQ_LAST (&(q
->pkts
), pkt_queue
);
211 bpacket_queue_remove (struct bpacket_queue
*q
)
213 struct bpacket
*first
;
215 first
= bpacket_queue_first (q
);
218 TAILQ_REMOVE (&(q
->pkts
), first
, pkt_train
);
225 bpacket_queue_length (struct bpacket_queue
*q
)
227 return q
->curr_count
- 1;
231 bpacket_queue_hwm_length (struct bpacket_queue
*q
)
233 return q
->hwm_count
- 1;
237 bpacket_queue_is_full (struct bgp
*bgp
, struct bpacket_queue
*q
)
239 if (q
->curr_count
>= bgp
->default_subgroup_pkt_queue_max
)
245 bpacket_add_peer (struct bpacket
*pkt
, struct peer_af
*paf
)
250 LIST_INSERT_HEAD (&(pkt
->peers
), paf
, pkt_train
);
251 paf
->next_pkt_to_send
= pkt
;
255 * bpacket_queue_cleanup
258 bpacket_queue_cleanup (struct bpacket_queue
*q
)
262 while ((pkt
= bpacket_queue_remove (q
)))
269 * bpacket_queue_compact
271 * Delete packets that do not need to be transmitted to any peer from
274 * @return the number of packets deleted.
277 bpacket_queue_compact (struct bpacket_queue
*q
)
280 struct bpacket
*pkt
, *removed_pkt
;
286 pkt
= bpacket_queue_first (q
);
291 * Don't delete the sentinel.
296 if (!LIST_EMPTY (&(pkt
->peers
)))
299 removed_pkt
= bpacket_queue_remove (q
);
300 assert (pkt
== removed_pkt
);
301 bpacket_free (removed_pkt
);
306 bpacket_queue_sanity_check (q
);
311 bpacket_queue_advance_peer (struct peer_af
*paf
)
314 struct bpacket
*old_pkt
;
316 old_pkt
= paf
->next_pkt_to_send
;
317 if (old_pkt
->buffer
== NULL
)
318 /* Already at end of list */
321 LIST_REMOVE (paf
, pkt_train
);
322 pkt
= TAILQ_NEXT (old_pkt
, pkt_train
);
323 bpacket_add_peer (pkt
, paf
);
325 if (!bpacket_queue_compact (PAF_PKTQ (paf
)))
329 * Deleted one or more packets. Check if we can now merge this
330 * peer's subgroup into another subgroup.
332 update_subgroup_check_merge (paf
->subgroup
, "advanced peer in queue");
336 * bpacket_queue_remove_peer
338 * Remove the peer from the packet queue of the subgroup it belongs
342 bpacket_queue_remove_peer (struct peer_af
*paf
)
344 struct bpacket_queue
*q
;
351 LIST_REMOVE (paf
, pkt_train
);
352 paf
->next_pkt_to_send
= NULL
;
354 bpacket_queue_compact (q
);
358 bpacket_queue_virtual_length (struct peer_af
*paf
)
361 struct bpacket
*last
;
362 struct bpacket_queue
*q
;
364 pkt
= paf
->next_pkt_to_send
;
365 if (!pkt
|| (pkt
->buffer
== NULL
))
366 /* Already at end of list */
370 if (TAILQ_EMPTY (&(q
->pkts
)))
373 last
= TAILQ_LAST (&(q
->pkts
), pkt_queue
);
374 if (last
->ver
>= pkt
->ver
)
375 return last
->ver
- pkt
->ver
;
377 /* sequence # rolled over */
378 return (UINT_MAX
- pkt
->ver
+ 1) + last
->ver
;
382 * Dump the bpacket queue
385 bpacket_queue_show_vty (struct bpacket_queue
*q
, struct vty
*vty
)
390 pkt
= bpacket_queue_first (q
);
393 vty_out (vty
, " Packet %p ver %u buffer %p%s", pkt
, pkt
->ver
,
394 pkt
->buffer
, VTY_NEWLINE
);
396 LIST_FOREACH (paf
, &(pkt
->peers
), pkt_train
)
398 vty_out (vty
, " - %s%s", paf
->peer
->host
, VTY_NEWLINE
);
400 pkt
= bpacket_next (pkt
);
406 bpacket_reformat_for_peer (struct bpacket
*pkt
, struct peer_af
*paf
)
408 struct stream
*s
= NULL
;
409 bpacket_attr_vec
*vec
;
414 s
= stream_dup (pkt
->buffer
);
415 peer
= PAF_PEER(paf
);
417 vec
= &pkt
->arr
.entries
[BGP_ATTR_VEC_NH
];
418 if (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_UPDATED
))
421 int route_map_sets_nh
;
422 nhlen
= stream_getc_from (s
, vec
->offset
);
424 if (paf
->afi
== AFI_IP
&& !peer_cap_enhe(peer
))
426 struct in_addr v4nh
, *mod_v4nh
;
430 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
) ||
431 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
433 stream_get_from (&v4nh
, s
, vec
->offset
+ 1, 4);
437 * If route-map has set the nexthop, that is always used; if it is
438 * specified as peer-address, the peering address is picked up.
439 * Otherwise, if NH is unavailable from attribute, the peering addr
440 * is picked up; the "NH unavailable" case also covers next-hop-self
441 * and some other scenarios -- see subgroup_announce_check(). In
442 * all other cases, use the nexthop carried in the attribute unless
443 * it is EBGP non-multiaccess and there is no next-hop-unchanged setting.
444 * Note: It is assumed route-map cannot set the nexthop to an
447 if (route_map_sets_nh
)
449 if (CHECK_FLAG(vec
->flags
,
450 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
452 mod_v4nh
= &peer
->nexthop
.v4
;
456 else if (!v4nh
.s_addr
)
458 mod_v4nh
= &peer
->nexthop
.v4
;
461 else if (peer
->sort
== BGP_PEER_EBGP
&&
462 (bgp_multiaccess_check_v4 (v4nh
, peer
) == 0) &&
463 !CHECK_FLAG(vec
->flags
,
464 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
465 !peer_af_flag_check (peer
, paf
->afi
, paf
->safi
,
466 PEER_FLAG_NEXTHOP_UNCHANGED
))
468 mod_v4nh
= &peer
->nexthop
.v4
;
473 stream_put_in_addr_at (s
, vec
->offset
+ 1, mod_v4nh
);
475 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
476 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ nexthop %s",
477 PAF_SUBGRP(paf
)->update_group
->id
, PAF_SUBGRP(paf
)->id
,
478 peer
->host
, inet_ntoa (*mod_v4nh
));
481 else if (paf
->afi
== AFI_IP6
|| peer_cap_enhe(peer
))
483 struct in6_addr v6nhglobal
, *mod_v6nhg
;
484 struct in6_addr v6nhlocal
, *mod_v6nhl
;
485 int gnh_modified
, lnh_modified
;
487 gnh_modified
= lnh_modified
= 0;
488 mod_v6nhg
= &v6nhglobal
;
489 mod_v6nhl
= &v6nhlocal
;
492 (CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
) ||
493 CHECK_FLAG (vec
->flags
, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
));
496 * The logic here is rather similar to that for IPv4, the
497 * additional work being to handle 1 or 2 nexthops. Also, 3rd
498 * party nexthop is not propagated for EBGP right now.
500 stream_get_from (&v6nhglobal
, s
, vec
->offset
+ 1, 16);
501 if (route_map_sets_nh
)
503 if (CHECK_FLAG(vec
->flags
,
504 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
506 mod_v6nhg
= &peer
->nexthop
.v6_global
;
510 else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal
))
512 mod_v6nhg
= &peer
->nexthop
.v6_global
;
515 else if (peer
->sort
== BGP_PEER_EBGP
&&
516 !CHECK_FLAG(vec
->flags
,
517 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
518 !peer_af_flag_check (peer
, paf
->afi
, paf
->safi
,
519 PEER_FLAG_NEXTHOP_UNCHANGED
))
521 mod_v6nhg
= &peer
->nexthop
.v6_global
;
528 stream_get_from (&v6nhlocal
, s
, vec
->offset
+ 1 + 16, 16);
529 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal
))
531 mod_v6nhl
= &peer
->nexthop
.v6_local
;
537 stream_put_in6_addr_at (s
, vec
->offset
+ 1, mod_v6nhg
);
539 stream_put_in6_addr_at (s
, vec
->offset
+ 1 + 16, mod_v6nhl
);
541 if (bgp_debug_update(peer
, NULL
, NULL
, 0))
544 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthops %s, %s",
545 PAF_SUBGRP(paf
)->update_group
->id
,
548 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
),
549 inet_ntop (AF_INET6
, mod_v6nhl
, buf2
, BUFSIZ
));
551 zlog_debug ("u%" PRIu64
":s%" PRIu64
" %s send UPDATE w/ mp_nexthop %s",
552 PAF_SUBGRP(paf
)->update_group
->id
,
555 inet_ntop (AF_INET6
, mod_v6nhg
, buf
, BUFSIZ
));
560 bgp_packet_add (peer
, s
);
565 * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
569 bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr
*vecarr
, size_t pos
)
576 for (i
= 0; i
< BGP_ATTR_VEC_MAX
; i
++)
577 vecarr
->entries
[i
].offset
+= pos
;
581 * Return if there are packets to build for this subgroup.
584 subgroup_packets_to_build (struct update_subgroup
*subgrp
)
586 struct bgp_advertise
*adv
;
591 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
);
595 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
603 bgp_info_addpath_tx_str (int addpath_encode
, u_int32_t addpath_tx_id
,
607 sprintf(buf
, " with addpath ID %d", addpath_tx_id
);
610 /* Make BGP update packet. */
612 subgroup_update_packet (struct update_subgroup
*subgrp
)
614 struct bpacket_attr_vec_arr vecarr
;
618 struct stream
*snlri
;
619 struct stream
*packet
;
620 struct bgp_adj_out
*adj
;
621 struct bgp_advertise
*adv
;
622 struct bgp_node
*rn
= NULL
;
623 struct bgp_info
*binfo
= NULL
;
624 bgp_size_t total_attr_len
= 0;
625 unsigned long attrlen_pos
= 0;
626 size_t mpattrlen_pos
= 0;
627 size_t mpattr_pos
= 0;
630 int space_remaining
= 0;
631 int space_needed
= 0;
632 char send_attr_str
[BUFSIZ
];
633 int send_attr_printed
= 0;
635 int addpath_encode
= 0;
636 u_int32_t addpath_tx_id
= 0;
641 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
645 peer
= SUBGRP_PEER (subgrp
);
646 afi
= SUBGRP_AFI (subgrp
);
647 safi
= SUBGRP_SAFI (subgrp
);
650 snlri
= subgrp
->scratch
;
651 stream_reset (snlri
);
653 bpacket_attr_vec_arr_reset (&vecarr
);
655 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
657 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
663 addpath_tx_id
= adj
->addpath_tx_id
;
666 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
667 BGP_MAX_PACKET_SIZE_OVERFLOW
;
668 space_needed
= BGP_NLRI_LENGTH
+
669 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
671 /* When remaining space can't include NLRI and it's length. */
672 if (space_remaining
< space_needed
)
675 /* If packet is empty, set attribute. */
676 if (stream_empty (s
))
678 struct peer
*from
= NULL
;
683 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
684 * one byte message type.
686 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
688 /* 2: withdrawn routes length */
691 /* 3: total attributes length - attrlen_pos stores the position */
692 attrlen_pos
= stream_get_endp (s
);
695 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
696 * attribute, according to draft-ietf-idr-error-handling. Save the
699 mpattr_pos
= stream_get_endp (s
);
701 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
702 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
,
703 adv
->baa
->attr
, &vecarr
,
705 from
, NULL
, NULL
, 0, 0);
707 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
708 BGP_MAX_PACKET_SIZE_OVERFLOW
;
709 space_needed
= BGP_NLRI_LENGTH
+
710 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
712 /* If the attributes alone do not leave any room for NLRI then
714 if (space_remaining
< space_needed
)
716 zlog_err ("u%" PRIu64
":s%" PRIu64
" attributes too long, cannot send UPDATE",
717 subgrp
->update_group
->id
, subgrp
->id
);
719 /* Flush the FIFO update queue */
721 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
725 if (BGP_DEBUG (update
, UPDATE_OUT
) ||
726 BGP_DEBUG (update
, UPDATE_PREFIX
))
728 memset (send_attr_str
, 0, BUFSIZ
);
729 send_attr_printed
= 0;
730 bgp_dump_attr (peer
, adv
->baa
->attr
, send_attr_str
, BUFSIZ
);
734 if ((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
735 !peer_cap_enhe(peer
))
736 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
739 /* Encode the prefix in MP_REACH_NLRI attribute */
740 struct prefix_rd
*prd
= NULL
;
744 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
745 if (binfo
&& binfo
->extra
)
746 tag
= binfo
->extra
->tag
;
748 if (stream_empty (snlri
))
749 mpattrlen_pos
= bgp_packet_mpattr_start (snlri
, afi
, safi
,
750 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
751 &vecarr
, adv
->baa
->attr
);
752 bgp_packet_mpattr_prefix (snlri
, afi
, safi
, &rn
->p
, prd
, tag
,
753 addpath_encode
, addpath_tx_id
);
758 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
760 char buf
[INET6_BUFSIZ
];
763 if (!send_attr_printed
)
765 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE w/ attr: %s",
766 subgrp
->update_group
->id
, subgrp
->id
, send_attr_str
);
767 send_attr_printed
= 1;
770 bgp_info_addpath_tx_str (addpath_encode
, addpath_tx_id
, tx_id_buf
);
771 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s",
772 subgrp
->update_group
->id
, subgrp
->id
,
773 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
, INET6_BUFSIZ
),
774 rn
->p
.prefixlen
, tx_id_buf
);
777 /* Synchnorize attribute. */
779 bgp_attr_unintern (&adj
->attr
);
783 adj
->attr
= bgp_attr_intern (adv
->baa
->attr
);
785 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
788 if (!stream_empty (s
))
790 if (!stream_empty (snlri
))
792 bgp_packet_mpattr_end (snlri
, mpattrlen_pos
);
793 total_attr_len
+= stream_get_endp (snlri
);
796 /* set the total attribute length correctly */
797 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
799 if (!stream_empty (snlri
))
801 packet
= stream_dupcat (s
, snlri
, mpattr_pos
);
802 bpacket_attr_vec_arr_update (&vecarr
, mpattr_pos
);
805 packet
= stream_dup (s
);
806 bgp_packet_set_size (packet
);
807 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
808 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE len %zd numpfx %d",
809 subgrp
->update_group
->id
, subgrp
->id
,
810 (stream_get_endp(packet
) - stream_get_getp(packet
)), num_pfx
);
811 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
813 stream_reset (snlri
);
819 /* Make BGP withdraw packet. */
821 16-octet marker | 2-octet length | 1-octet type |
822 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
824 /* For other afi/safis:
825 16-octet marker | 2-octet length | 1-octet type |
826 2-octet withdrawn route length (=0) | 2-octet attrlen |
827 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
830 subgroup_withdraw_packet (struct update_subgroup
*subgrp
)
834 struct bgp_adj_out
*adj
;
835 struct bgp_advertise
*adv
;
838 bgp_size_t unfeasible_len
;
839 bgp_size_t total_attr_len
;
841 size_t attrlen_pos
= 0;
842 size_t mplen_pos
= 0;
843 u_char first_time
= 1;
846 int space_remaining
= 0;
847 int space_needed
= 0;
849 int addpath_encode
= 0;
850 u_int32_t addpath_tx_id
= 0;
855 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
858 peer
= SUBGRP_PEER (subgrp
);
859 afi
= SUBGRP_AFI (subgrp
);
860 safi
= SUBGRP_SAFI (subgrp
);
863 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
865 while ((adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
)) != NULL
)
870 addpath_tx_id
= adj
->addpath_tx_id
;
872 space_remaining
= STREAM_REMAIN (s
) -
873 BGP_MAX_PACKET_SIZE_OVERFLOW
;
874 space_needed
= BGP_NLRI_LENGTH
+ BGP_TOTAL_ATTR_LEN
+
875 bgp_packet_mpattr_prefix_size (afi
, safi
, &rn
->p
);
877 if (space_remaining
< space_needed
)
880 if (stream_empty (s
))
882 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
883 stream_putw (s
, 0); /* unfeasible routes length */
888 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
889 !peer_cap_enhe(peer
))
890 stream_put_prefix_addpath (s
, &rn
->p
, addpath_encode
, addpath_tx_id
);
893 struct prefix_rd
*prd
= NULL
;
896 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
898 /* If first time, format the MP_UNREACH header */
901 attrlen_pos
= stream_get_endp (s
);
902 /* total attr length = 0 for now. reevaluate later */
904 mp_start
= stream_get_endp (s
);
905 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
908 bgp_packet_mpunreach_prefix (s
, &rn
->p
, afi
, safi
, prd
, NULL
,
909 addpath_encode
, addpath_tx_id
);
914 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
916 char buf
[INET6_BUFSIZ
];
918 bgp_info_addpath_tx_str (addpath_encode
, addpath_tx_id
, tx_id_buf
);
919 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s -- unreachable",
920 subgrp
->update_group
->id
, subgrp
->id
,
921 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
, INET6_BUFSIZ
),
922 rn
->p
.prefixlen
, tx_id_buf
);
927 bgp_adj_out_remove_subgroup (rn
, adj
, subgrp
);
928 bgp_unlock_node (rn
);
931 if (!stream_empty (s
))
933 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
934 !peer_cap_enhe(peer
))
937 = stream_get_endp (s
) - BGP_HEADER_SIZE
- BGP_UNFEASIBLE_LEN
;
938 stream_putw_at (s
, BGP_HEADER_SIZE
, unfeasible_len
);
943 /* Set the mp_unreach attr's length */
944 bgp_packet_mpunreach_end (s
, mplen_pos
);
946 /* Set total path attribute length. */
947 total_attr_len
= stream_get_endp (s
) - mp_start
;
948 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
950 bgp_packet_set_size (s
);
951 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
952 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE (withdraw) len %zd numpfx %d",
953 subgrp
->update_group
->id
, subgrp
->id
,
954 (stream_get_endp(s
) - stream_get_getp(s
)), num_pfx
);
955 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), stream_dup (s
), NULL
);
964 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
965 struct attr
*attr
, struct peer
*from
)
971 bgp_size_t total_attr_len
;
974 struct bpacket_attr_vec_arr vecarr
;
975 int addpath_encode
= 0;
977 if (DISABLE_BGP_ANNOUNCE
)
983 peer
= SUBGRP_PEER (subgrp
);
984 afi
= SUBGRP_AFI (subgrp
);
985 safi
= SUBGRP_SAFI (subgrp
);
986 bpacket_attr_vec_arr_reset (&vecarr
);
987 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
990 str2prefix ("0.0.0.0/0", &p
);
993 str2prefix ("::/0", &p
);
994 #endif /* HAVE_IPV6 */
996 /* Logging the attribute. */
997 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
999 char attrstr
[BUFSIZ
];
1000 char buf
[INET6_BUFSIZ
];
1004 bgp_dump_attr (peer
, attr
, attrstr
, BUFSIZ
);
1005 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1006 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s %s",
1007 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1008 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
1009 p
.prefixlen
, tx_id_buf
, attrstr
);
1012 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1014 /* Make BGP update packet. */
1015 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1017 /* Unfeasible Routes Length. */
1020 /* Make place for total attribute length. */
1021 pos
= stream_get_endp (s
);
1023 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
, attr
, &vecarr
, &p
,
1024 afi
, safi
, from
, NULL
, NULL
,
1026 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1028 /* Set Total Path Attribute Length. */
1029 stream_putw_at (s
, pos
, total_attr_len
);
1032 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1033 !peer_cap_enhe(peer
))
1034 stream_put_prefix_addpath (s
, &p
, addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1037 bgp_packet_set_size (s
);
1039 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, &vecarr
);
1040 subgroup_trigger_write(subgrp
);
1044 subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
)
1049 unsigned long attrlen_pos
= 0;
1051 bgp_size_t unfeasible_len
;
1052 bgp_size_t total_attr_len
= 0;
1053 size_t mp_start
= 0;
1054 size_t mplen_pos
= 0;
1057 int addpath_encode
= 0;
1059 if (DISABLE_BGP_ANNOUNCE
)
1062 peer
= SUBGRP_PEER (subgrp
);
1063 afi
= SUBGRP_AFI (subgrp
);
1064 safi
= SUBGRP_SAFI (subgrp
);
1065 addpath_encode
= bgp_addpath_encode_tx (peer
, afi
, safi
);
1068 str2prefix ("0.0.0.0/0", &p
);
1071 str2prefix ("::/0", &p
);
1072 #endif /* HAVE_IPV6 */
1074 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1076 char buf
[INET6_BUFSIZ
];
1077 char tx_id_buf
[INET6_BUFSIZ
];
1079 bgp_info_addpath_tx_str (addpath_encode
, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
, tx_id_buf
);
1080 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d%s -- unreachable",
1081 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
1082 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
1083 p
.prefixlen
, tx_id_buf
);
1086 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1088 /* Make BGP update packet. */
1089 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1091 /* Unfeasible Routes Length. */ ;
1092 cp
= stream_get_endp (s
);
1095 /* Withdrawn Routes. */
1096 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1097 !peer_cap_enhe(peer
))
1099 stream_put_prefix_addpath (s
, &p
, addpath_encode
,
1100 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1102 unfeasible_len
= stream_get_endp (s
) - cp
- 2;
1104 /* Set unfeasible len. */
1105 stream_putw_at (s
, cp
, unfeasible_len
);
1107 /* Set total path attribute length. */
1112 attrlen_pos
= stream_get_endp (s
);
1114 mp_start
= stream_get_endp (s
);
1115 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
1116 bgp_packet_mpunreach_prefix (s
, &p
, afi
, safi
, NULL
, NULL
,
1118 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE
);
1120 /* Set the mp_unreach attr's length */
1121 bgp_packet_mpunreach_end (s
, mplen_pos
);
1123 /* Set total path attribute length. */
1124 total_attr_len
= stream_get_endp (s
) - mp_start
;
1125 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
1128 bgp_packet_set_size (s
);
1130 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), s
, NULL
);
1131 subgroup_trigger_write(subgrp
);
1135 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr
*vecarr
,
1136 bpacket_attr_vec_type type
,
1139 if (CHECK_FLAG (attr
->rmap_change_flags
,
1140 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
))
1141 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1142 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
);
1144 if (CHECK_FLAG (attr
->rmap_change_flags
, BATTR_REFLECTED
))
1145 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1146 BPKT_ATTRVEC_FLAGS_REFLECTED
);
1148 if (CHECK_FLAG (attr
->rmap_change_flags
,
1149 BATTR_RMAP_NEXTHOP_UNCHANGED
))
1150 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1151 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
);
1153 if (CHECK_FLAG (attr
->rmap_change_flags
,
1154 BATTR_RMAP_IPV4_NHOP_CHANGED
))
1155 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1156 BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
);
1158 if (CHECK_FLAG (attr
->rmap_change_flags
,
1159 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
))
1160 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1161 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
);
1163 if (CHECK_FLAG (attr
->rmap_change_flags
,
1164 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
))
1165 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1166 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED
);
1169 /* Reset the Attributes vector array. The vector array is used to override
1170 * certain output parameters in the packet for a particular peer
1173 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
)
1181 while (i
< BGP_ATTR_VEC_MAX
)
1183 vecarr
->entries
[i
].flags
= 0;
1184 vecarr
->entries
[i
].offset
= 0;
1189 /* Setup a particular node entry in the vecarr */
1191 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
1192 bpacket_attr_vec_type type
, struct stream
*s
,
1197 assert (type
< BGP_ATTR_VEC_MAX
);
1199 SET_FLAG (vecarr
->entries
[type
].flags
, BPKT_ATTRVEC_FLAGS_UPDATED
);
1200 vecarr
->entries
[type
].offset
= stream_get_endp (s
);
1202 bpacket_vec_arr_inherit_attr_flags(vecarr
, type
, attr
);