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
);
603 /* Make BGP update packet. */
605 subgroup_update_packet (struct update_subgroup
*subgrp
)
607 struct bpacket_attr_vec_arr vecarr
;
611 struct stream
*snlri
;
612 struct stream
*packet
;
613 struct bgp_adj_out
*adj
;
614 struct bgp_advertise
*adv
;
615 struct bgp_node
*rn
= NULL
;
616 struct bgp_info
*binfo
= NULL
;
617 bgp_size_t total_attr_len
= 0;
618 unsigned long attrlen_pos
= 0;
619 size_t mpattrlen_pos
= 0;
620 size_t mpattr_pos
= 0;
623 int space_remaining
= 0;
624 int space_needed
= 0;
625 char send_attr_str
[BUFSIZ
];
626 int send_attr_printed
= 0;
633 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
637 peer
= SUBGRP_PEER (subgrp
);
638 afi
= SUBGRP_AFI (subgrp
);
639 safi
= SUBGRP_SAFI (subgrp
);
642 snlri
= subgrp
->scratch
;
643 stream_reset (snlri
);
645 bpacket_attr_vec_arr_reset (&vecarr
);
647 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
656 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
657 BGP_MAX_PACKET_SIZE_OVERFLOW
;
658 space_needed
= BGP_NLRI_LENGTH
+ PSIZE (rn
->p
.prefixlen
);
660 /* When remaining space can't include NLRI and it's length. */
661 if (space_remaining
< space_needed
)
664 /* If packet is empty, set attribute. */
665 if (stream_empty (s
))
667 struct peer
*from
= NULL
;
672 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
673 * one byte message type.
675 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
677 /* 2: withdrawn routes length */
680 /* 3: total attributes length - attrlen_pos stores the position */
681 attrlen_pos
= stream_get_endp (s
);
684 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
685 * attribute, according to draft-ietf-idr-error-handling. Save the
688 mpattr_pos
= stream_get_endp (s
);
690 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
691 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
,
692 adv
->baa
->attr
, &vecarr
,
696 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
697 BGP_MAX_PACKET_SIZE_OVERFLOW
;
698 space_needed
= BGP_NLRI_LENGTH
+ PSIZE (rn
->p
.prefixlen
);
700 /* If the attributes alone do not leave any room for NLRI then
702 if (space_remaining
< space_needed
)
704 zlog_err ("u%" PRIu64
":s%" PRIu64
" attributes too long, cannot send UPDATE",
705 subgrp
->update_group
->id
, subgrp
->id
);
707 /* Flush the FIFO update queue */
709 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
713 if (BGP_DEBUG (update
, UPDATE_OUT
) ||
714 BGP_DEBUG (update
, UPDATE_PREFIX
))
716 memset (send_attr_str
, 0, BUFSIZ
);
717 send_attr_printed
= 0;
718 bgp_dump_attr (peer
, adv
->baa
->attr
, send_attr_str
, BUFSIZ
);
722 if ((afi
== AFI_IP
&& safi
== SAFI_UNICAST
) &&
723 !peer_cap_enhe(peer
))
724 stream_put_prefix (s
, &rn
->p
);
727 /* Encode the prefix in MP_REACH_NLRI attribute */
728 struct prefix_rd
*prd
= NULL
;
732 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
733 if (binfo
&& binfo
->extra
)
734 tag
= binfo
->extra
->tag
;
736 if (stream_empty (snlri
))
737 mpattrlen_pos
= bgp_packet_mpattr_start (snlri
, afi
, safi
,
738 (peer_cap_enhe(peer
) ? AFI_IP6
: afi
),
739 &vecarr
, adv
->baa
->attr
);
740 bgp_packet_mpattr_prefix (snlri
, afi
, safi
, &rn
->p
, prd
, tag
);
745 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
747 char buf
[INET6_BUFSIZ
];
749 if (!send_attr_printed
)
751 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE w/ attr: %s",
752 subgrp
->update_group
->id
, subgrp
->id
, send_attr_str
);
753 send_attr_printed
= 1;
756 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d",
757 subgrp
->update_group
->id
, subgrp
->id
,
758 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
,
759 INET6_BUFSIZ
), rn
->p
.prefixlen
);
762 /* Synchnorize attribute. */
764 bgp_attr_unintern (&adj
->attr
);
768 adj
->attr
= bgp_attr_intern (adv
->baa
->attr
);
770 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
773 if (!stream_empty (s
))
775 if (!stream_empty (snlri
))
777 bgp_packet_mpattr_end (snlri
, mpattrlen_pos
);
778 total_attr_len
+= stream_get_endp (snlri
);
781 /* set the total attribute length correctly */
782 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
784 if (!stream_empty (snlri
))
786 packet
= stream_dupcat (s
, snlri
, mpattr_pos
);
787 bpacket_attr_vec_arr_update (&vecarr
, mpattr_pos
);
790 packet
= stream_dup (s
);
791 bgp_packet_set_size (packet
);
792 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
793 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE len %zd numpfx %d",
794 subgrp
->update_group
->id
, subgrp
->id
,
795 (stream_get_endp(packet
) - stream_get_getp(packet
)), num_pfx
);
796 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
798 stream_reset (snlri
);
804 /* Make BGP withdraw packet. */
806 16-octet marker | 2-octet length | 1-octet type |
807 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
809 /* For other afi/safis:
810 16-octet marker | 2-octet length | 1-octet type |
811 2-octet withdrawn route length (=0) | 2-octet attrlen |
812 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
815 subgroup_withdraw_packet (struct update_subgroup
*subgrp
)
819 struct bgp_adj_out
*adj
;
820 struct bgp_advertise
*adv
;
823 bgp_size_t unfeasible_len
;
824 bgp_size_t total_attr_len
;
826 size_t attrlen_pos
= 0;
827 size_t mplen_pos
= 0;
828 u_char first_time
= 1;
831 int space_remaining
= 0;
832 int space_needed
= 0;
838 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
841 peer
= SUBGRP_PEER (subgrp
);
842 afi
= SUBGRP_AFI (subgrp
);
843 safi
= SUBGRP_SAFI (subgrp
);
847 while ((adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
)) != NULL
)
853 space_remaining
= STREAM_REMAIN (s
) -
854 BGP_MAX_PACKET_SIZE_OVERFLOW
;
855 space_needed
= (BGP_NLRI_LENGTH
+ BGP_TOTAL_ATTR_LEN
+
856 PSIZE (rn
->p
.prefixlen
));
858 if (space_remaining
< space_needed
)
861 if (stream_empty (s
))
863 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
864 stream_putw (s
, 0); /* unfeasible routes length */
869 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
870 !peer_cap_enhe(peer
))
871 stream_put_prefix (s
, &rn
->p
);
874 struct prefix_rd
*prd
= NULL
;
877 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
879 /* If first time, format the MP_UNREACH header */
882 attrlen_pos
= stream_get_endp (s
);
883 /* total attr length = 0 for now. reevaluate later */
885 mp_start
= stream_get_endp (s
);
886 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
889 bgp_packet_mpunreach_prefix (s
, &rn
->p
, afi
, safi
, prd
, NULL
);
894 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
896 char buf
[INET6_BUFSIZ
];
898 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d -- unreachable",
899 subgrp
->update_group
->id
, subgrp
->id
,
900 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
,
901 INET6_BUFSIZ
), rn
->p
.prefixlen
);
906 bgp_adj_out_remove_subgroup (rn
, adj
, subgrp
);
907 bgp_unlock_node (rn
);
910 if (!stream_empty (s
))
912 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
&&
913 !peer_cap_enhe(peer
))
916 = stream_get_endp (s
) - BGP_HEADER_SIZE
- BGP_UNFEASIBLE_LEN
;
917 stream_putw_at (s
, BGP_HEADER_SIZE
, unfeasible_len
);
922 /* Set the mp_unreach attr's length */
923 bgp_packet_mpunreach_end (s
, mplen_pos
);
925 /* Set total path attribute length. */
926 total_attr_len
= stream_get_endp (s
) - mp_start
;
927 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
929 bgp_packet_set_size (s
);
930 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
931 zlog_debug ("u%" PRIu64
":s%" PRIu64
" UPDATE (withdraw) len %zd numpfx %d",
932 subgrp
->update_group
->id
, subgrp
->id
,
933 (stream_get_endp(s
) - stream_get_getp(s
)), num_pfx
);
934 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), stream_dup (s
), NULL
);
943 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
944 struct attr
*attr
, struct peer
*from
)
947 struct stream
*packet
;
951 bgp_size_t total_attr_len
;
954 struct bpacket_attr_vec_arr vecarr
;
956 if (DISABLE_BGP_ANNOUNCE
)
962 peer
= SUBGRP_PEER (subgrp
);
963 afi
= SUBGRP_AFI (subgrp
);
964 safi
= SUBGRP_SAFI (subgrp
);
965 bpacket_attr_vec_arr_reset (&vecarr
);
968 str2prefix ("0.0.0.0/0", &p
);
971 str2prefix ("::/0", &p
);
972 #endif /* HAVE_IPV6 */
974 /* Logging the attribute. */
975 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
977 char attrstr
[BUFSIZ
];
978 char buf
[INET6_BUFSIZ
];
981 bgp_dump_attr (peer
, attr
, attrstr
, BUFSIZ
);
982 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d %s",
983 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
984 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
985 p
.prefixlen
, attrstr
);
988 s
= stream_new (BGP_MAX_PACKET_SIZE
);
990 /* Make BGP update packet. */
991 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
993 /* Unfeasible Routes Length. */
996 /* Make place for total attribute length. */
997 pos
= stream_get_endp (s
);
999 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
, attr
, &vecarr
, &p
,
1000 afi
, safi
, from
, NULL
, NULL
);
1002 /* Set Total Path Attribute Length. */
1003 stream_putw_at (s
, pos
, total_attr_len
);
1006 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1007 !peer_cap_enhe(peer
))
1008 stream_put_prefix (s
, &p
);
1011 bgp_packet_set_size (s
);
1013 packet
= stream_dup (s
);
1015 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
1016 subgroup_trigger_write(subgrp
);
1020 subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
)
1024 struct stream
*packet
;
1026 unsigned long attrlen_pos
= 0;
1028 bgp_size_t unfeasible_len
;
1029 bgp_size_t total_attr_len
;
1030 size_t mp_start
= 0;
1031 size_t mplen_pos
= 0;
1035 if (DISABLE_BGP_ANNOUNCE
)
1038 peer
= SUBGRP_PEER (subgrp
);
1039 afi
= SUBGRP_AFI (subgrp
);
1040 safi
= SUBGRP_SAFI (subgrp
);
1043 str2prefix ("0.0.0.0/0", &p
);
1046 str2prefix ("::/0", &p
);
1047 #endif /* HAVE_IPV6 */
1051 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1053 char buf
[INET6_BUFSIZ
];
1055 zlog_debug ("u%" PRIu64
":s%" PRIu64
" send UPDATE %s/%d -- unreachable",
1056 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
, inet_ntop (p
.family
,
1064 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1066 /* Make BGP update packet. */
1067 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1069 /* Unfeasible Routes Length. */ ;
1070 cp
= stream_get_endp (s
);
1073 /* Withdrawn Routes. */
1074 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
&&
1075 !peer_cap_enhe(peer
))
1077 stream_put_prefix (s
, &p
);
1079 unfeasible_len
= stream_get_endp (s
) - cp
- 2;
1081 /* Set unfeasible len. */
1082 stream_putw_at (s
, cp
, unfeasible_len
);
1084 /* Set total path attribute length. */
1089 attrlen_pos
= stream_get_endp (s
);
1091 mp_start
= stream_get_endp (s
);
1092 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
1093 bgp_packet_mpunreach_prefix (s
, &p
, afi
, safi
, NULL
, NULL
);
1095 /* Set the mp_unreach attr's length */
1096 bgp_packet_mpunreach_end (s
, mplen_pos
);
1098 /* Set total path attribute length. */
1099 total_attr_len
= stream_get_endp (s
) - mp_start
;
1100 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
1103 bgp_packet_set_size (s
);
1105 packet
= stream_dup (s
);
1108 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, NULL
);
1109 subgroup_trigger_write(subgrp
);
1113 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr
*vecarr
,
1114 bpacket_attr_vec_type type
,
1117 if (CHECK_FLAG (attr
->rmap_change_flags
,
1118 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
))
1119 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1120 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
);
1122 if (CHECK_FLAG (attr
->rmap_change_flags
, BATTR_REFLECTED
))
1123 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1124 BPKT_ATTRVEC_FLAGS_REFLECTED
);
1126 if (CHECK_FLAG (attr
->rmap_change_flags
,
1127 BATTR_RMAP_NEXTHOP_UNCHANGED
))
1128 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1129 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
);
1131 if (CHECK_FLAG (attr
->rmap_change_flags
,
1132 BATTR_RMAP_IPV4_NHOP_CHANGED
))
1133 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1134 BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED
);
1136 if (CHECK_FLAG (attr
->rmap_change_flags
,
1137 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED
))
1138 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1139 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED
);
1141 if (CHECK_FLAG (attr
->rmap_change_flags
,
1142 BATTR_RMAP_IPV6_LL_NHOP_CHANGED
))
1143 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1144 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED
);
1147 /* Reset the Attributes vector array. The vector array is used to override
1148 * certain output parameters in the packet for a particular peer
1151 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
)
1159 while (i
< BGP_ATTR_VEC_MAX
)
1161 vecarr
->entries
[i
].flags
= 0;
1162 vecarr
->entries
[i
].offset
= 0;
1167 /* Setup a particular node entry in the vecarr */
1169 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
1170 bpacket_attr_vec_type type
, struct stream
*s
,
1175 assert (type
< BGP_ATTR_VEC_MAX
);
1177 SET_FLAG (vecarr
->entries
[type
].flags
, BPKT_ATTRVEC_FLAGS_UPDATED
);
1178 vecarr
->entries
[type
].offset
= stream_get_endp (s
);
1180 bpacket_vec_arr_inherit_attr_flags(vecarr
, type
, attr
);