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
;
412 s
= stream_dup (pkt
->buffer
);
414 vec
= &pkt
->arr
.entries
[BGP_ATTR_VEC_NH
];
415 if (CHECK_FLAG (vec
->flags
, BPACKET_ATTRVEC_FLAGS_UPDATED
))
418 int route_map_sets_nh
;
419 nhlen
= stream_getc_from (s
, vec
->offset
);
421 route_map_sets_nh
= CHECK_FLAG (vec
->flags
,
422 BPACKET_ATTRVEC_FLAGS_RMAP_CHANGED
);
424 if (paf
->afi
== AFI_IP
)
428 stream_get_from (&v4nh
, s
, vec
->offset
+ 1, 4);
430 /* If NH unavailable from attribute or the route-map has set it to
431 * be the peering address, use peer's NH. The "NH unavailable" case
432 * also covers next-hop-self and some other scenarios -- see
433 * subgroup_announce_check(). The only other case where we use the
434 * peer's NH is if it is an EBGP multiaccess scenario and there is
435 * no next-hop-unchanged setting.
438 (route_map_sets_nh
&&
439 CHECK_FLAG(vec
->flags
,
440 BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
)))
441 stream_put_in_addr_at (s
, vec
->offset
+ 1, &paf
->peer
->nexthop
.v4
);
442 else if (!CHECK_FLAG(vec
->flags
,
443 BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
444 paf
->peer
->sort
== BGP_PEER_EBGP
&&
445 !peer_af_flag_check (paf
->peer
, paf
->afi
, paf
->safi
,
446 PEER_FLAG_NEXTHOP_UNCHANGED
))
448 if (bgp_multiaccess_check_v4 (v4nh
, paf
->peer
) == 0)
449 stream_put_in_addr_at (s
, vec
->offset
+ 1,
450 &paf
->peer
->nexthop
.v4
);
455 nhtouse
= paf
->peer
->nexthop
.v4
;
458 * If NH is available from attribute (which is after outbound
459 * policy application), always use it if it has been specified
460 * by the policy. Otherwise, the decision to make is whether
461 * we need to set ourselves as the next-hop or not. Here are
462 * the conditions for that (1 OR 2):
464 * (1) if the configuration says: 'next-hop-self'
465 * (2) if the peer is EBGP AND not a third-party-nexthop type
467 * There are some exceptions even if the above conditions apply.
469 * (a) if the configuration says: 'next-hop-unchanged'. Honor that
470 * always. Not set 'self' as next-hop.
471 * (b) if we are reflecting the routes (IBGP->IBGP) and the config
472 * is _not_ forcing next-hop-self. We should pass on the
473 * next-hop unchanged for reflected routes.
475 if (route_map_sets_nh
)
478 * If address is specified, nothing to do; if specified as
479 * 'peer-address', compute the value to use.
481 * NOTE: If we are reflecting routes, the policy could have set
482 * this only if outbound policy has been allowed for route
483 * reflection -- handled in announce_check().
485 if (CHECK_FLAG(vec
->flags
,
486 BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
))
487 nhtouse
= paf
->peer
->nexthop
.v4
;
489 else if (peer_af_flag_check (paf
->peer
, paf
->afi
, paf
->safi
,
490 PEER_FLAG_NEXTHOP_SELF
)
491 || (paf
->peer
->sort
== BGP_PEER_EBGP
&&
492 (bgp_multiaccess_check_v4 (v4nh
, paf
->peer
) == 0)))
494 if (!(peer_af_flag_check (paf
->peer
, paf
->afi
, paf
->safi
,
495 PEER_FLAG_NEXTHOP_UNCHANGED
)
496 || (CHECK_FLAG(vec
->flags
, BPACKET_ATTRVEC_FLAGS_REFLECTED
) &&
497 !peer_af_flag_check(paf
->peer
, paf
->afi
, paf
->safi
,
498 PEER_FLAG_FORCE_NEXTHOP_SELF
))))
499 nhtouse
= paf
->peer
->nexthop
.v4
;
504 else if (paf
->afi
== AFI_IP6
)
506 struct in6_addr v6nhglobal
;
507 struct in6_addr v6nhlocal
;
510 * The logic here is rather similar to that for IPv4, the
511 * additional work being to handle 1 or 2 nexthops.
513 stream_get_from (&v6nhglobal
, s
, vec
->offset
+ 1, 16);
514 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal
) ||
515 (route_map_sets_nh
&&
516 CHECK_FLAG(vec
->flags
,
517 BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
)))
518 stream_put_in6_addr_at (s
, vec
->offset
+ 1,
519 &paf
->peer
->nexthop
.v6_global
);
520 else if (!CHECK_FLAG(vec
->flags
,
521 BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
) &&
522 paf
->peer
->sort
== BGP_PEER_EBGP
&&
523 !peer_af_flag_check (paf
->peer
, paf
->afi
, paf
->safi
,
524 PEER_FLAG_NEXTHOP_UNCHANGED
))
526 stream_put_in6_addr_at (s
, vec
->offset
+ 1,
527 &paf
->peer
->nexthop
.v6_global
);
532 stream_get_from (&v6nhlocal
, s
, vec
->offset
+ 1 + 16, 16);
533 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal
))
534 stream_put_in6_addr_at (s
, vec
->offset
+ 1 + 16,
535 &paf
->peer
->nexthop
.v6_local
);
540 bgp_packet_add (paf
->peer
, s
);
545 * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
549 bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr
*vecarr
, size_t pos
)
556 for (i
= 0; i
< BGP_ATTR_VEC_MAX
; i
++)
557 vecarr
->entries
[i
].offset
+= pos
;
561 * Return if there are packets to build for this subgroup.
564 subgroup_packets_to_build (struct update_subgroup
*subgrp
)
566 struct bgp_advertise
*adv
;
571 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
);
575 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
582 /* Make BGP update packet. */
584 subgroup_update_packet (struct update_subgroup
*subgrp
)
586 struct bpacket_attr_vec_arr vecarr
;
590 struct stream
*snlri
;
591 struct stream
*packet
;
592 struct bgp_adj_out
*adj
;
593 struct bgp_advertise
*adv
;
594 struct bgp_node
*rn
= NULL
;
595 struct bgp_info
*binfo
= NULL
;
596 bgp_size_t total_attr_len
= 0;
597 unsigned long attrlen_pos
= 0;
598 size_t mpattrlen_pos
= 0;
599 size_t mpattr_pos
= 0;
602 int space_remaining
= 0;
603 int space_needed
= 0;
604 char send_attr_str
[BUFSIZ
];
605 int send_attr_printed
;
612 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
616 peer
= SUBGRP_PEER (subgrp
);
617 afi
= SUBGRP_AFI (subgrp
);
618 safi
= SUBGRP_SAFI (subgrp
);
621 snlri
= subgrp
->scratch
;
622 stream_reset (snlri
);
624 bpacket_attr_vec_arr_reset (&vecarr
);
626 adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->update
);
635 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
636 BGP_MAX_PACKET_SIZE_OVERFLOW
;
637 space_needed
= BGP_NLRI_LENGTH
+ PSIZE (rn
->p
.prefixlen
);
639 /* When remaining space can't include NLRI and it's length. */
640 if (space_remaining
< space_needed
)
643 /* If packet is empty, set attribute. */
644 if (stream_empty (s
))
646 struct peer
*from
= NULL
;
651 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
652 * one byte message type.
654 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
656 /* 2: withdrawn routes length */
659 /* 3: total attributes length - attrlen_pos stores the position */
660 attrlen_pos
= stream_get_endp (s
);
663 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
664 * attribute, according to draft-ietf-idr-error-handling. Save the
667 mpattr_pos
= stream_get_endp (s
);
669 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
670 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
,
671 adv
->baa
->attr
, &vecarr
,
675 space_remaining
= STREAM_CONCAT_REMAIN (s
, snlri
, STREAM_SIZE(s
)) -
676 BGP_MAX_PACKET_SIZE_OVERFLOW
;
677 space_needed
= BGP_NLRI_LENGTH
+ PSIZE (rn
->p
.prefixlen
);
679 /* If the attributes alone do not leave any room for NLRI then
681 if (space_remaining
< space_needed
)
683 zlog_err ("u%llu:s%llu attributes too long, cannot send UPDATE",
684 subgrp
->update_group
->id
, subgrp
->id
);
686 /* Flush the FIFO update queue */
688 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
692 if (BGP_DEBUG (update
, UPDATE_OUT
) ||
693 BGP_DEBUG (update
, UPDATE_PREFIX
))
695 memset (send_attr_str
, 0, BUFSIZ
);
696 send_attr_printed
= 0;
697 bgp_dump_attr (peer
, adv
->baa
->attr
, send_attr_str
, BUFSIZ
);
701 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
702 stream_put_prefix (s
, &rn
->p
);
705 /* Encode the prefix in MP_REACH_NLRI attribute */
706 struct prefix_rd
*prd
= NULL
;
710 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
711 if (binfo
&& binfo
->extra
)
712 tag
= binfo
->extra
->tag
;
714 if (stream_empty (snlri
))
715 mpattrlen_pos
= bgp_packet_mpattr_start (snlri
, afi
, safi
,
716 &vecarr
, adv
->baa
->attr
);
717 bgp_packet_mpattr_prefix (snlri
, afi
, safi
, &rn
->p
, prd
, tag
);
722 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
724 char buf
[INET6_BUFSIZ
];
726 if (!send_attr_printed
)
728 zlog_debug ("u%llu:s%llu send UPDATE w/ attr: %s",
729 subgrp
->update_group
->id
, subgrp
->id
, send_attr_str
);
730 send_attr_printed
= 1;
733 zlog_debug ("u%llu:s%llu send UPDATE %s/%d",
734 subgrp
->update_group
->id
, subgrp
->id
,
735 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
,
736 INET6_BUFSIZ
), rn
->p
.prefixlen
);
739 /* Synchnorize attribute. */
741 bgp_attr_unintern (&adj
->attr
);
745 adj
->attr
= bgp_attr_intern (adv
->baa
->attr
);
747 adv
= bgp_advertise_clean_subgroup (subgrp
, adj
);
750 if (!stream_empty (s
))
752 if (!stream_empty (snlri
))
754 bgp_packet_mpattr_end (snlri
, mpattrlen_pos
);
755 total_attr_len
+= stream_get_endp (snlri
);
758 /* set the total attribute length correctly */
759 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
761 if (!stream_empty (snlri
))
763 packet
= stream_dupcat (s
, snlri
, mpattr_pos
);
764 bpacket_attr_vec_arr_update (&vecarr
, mpattr_pos
);
767 packet
= stream_dup (s
);
768 bgp_packet_set_size (packet
);
769 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
770 zlog_debug ("u%llu:s%llu UPDATE len %d numpfx %d",
771 subgrp
->update_group
->id
, subgrp
->id
,
772 (stream_get_endp(packet
) - stream_get_getp(packet
)), num_pfx
);
773 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
775 stream_reset (snlri
);
781 /* Make BGP withdraw packet. */
783 16-octet marker | 2-octet length | 1-octet type |
784 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
786 /* For other afi/safis:
787 16-octet marker | 2-octet length | 1-octet type |
788 2-octet withdrawn route length (=0) | 2-octet attrlen |
789 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
792 subgroup_withdraw_packet (struct update_subgroup
*subgrp
)
796 struct bgp_adj_out
*adj
;
797 struct bgp_advertise
*adv
;
800 bgp_size_t unfeasible_len
;
801 bgp_size_t total_attr_len
;
803 size_t attrlen_pos
= 0;
804 size_t mplen_pos
= 0;
805 u_char first_time
= 1;
808 int space_remaining
= 0;
809 int space_needed
= 0;
815 if (bpacket_queue_is_full (SUBGRP_INST (subgrp
), SUBGRP_PKTQ (subgrp
)))
819 peer
= SUBGRP_PEER (subgrp
);
820 afi
= SUBGRP_AFI (subgrp
);
821 safi
= SUBGRP_SAFI (subgrp
);
825 while ((adv
= BGP_ADV_FIFO_HEAD (&subgrp
->sync
->withdraw
)) != NULL
)
831 space_remaining
= STREAM_REMAIN (s
) -
832 BGP_MAX_PACKET_SIZE_OVERFLOW
;
833 space_needed
= (BGP_NLRI_LENGTH
+ BGP_TOTAL_ATTR_LEN
+
834 PSIZE (rn
->p
.prefixlen
));
836 if (space_remaining
< space_needed
)
839 if (stream_empty (s
))
841 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
842 stream_putw (s
, 0); /* unfeasible routes length */
847 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
848 stream_put_prefix (s
, &rn
->p
);
851 struct prefix_rd
*prd
= NULL
;
854 prd
= (struct prefix_rd
*) &rn
->prn
->p
;
856 /* If first time, format the MP_UNREACH header */
859 attrlen_pos
= stream_get_endp (s
);
860 /* total attr length = 0 for now. reevaluate later */
862 mp_start
= stream_get_endp (s
);
863 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
866 bgp_packet_mpunreach_prefix (s
, &rn
->p
, afi
, safi
, prd
, NULL
);
871 if (bgp_debug_update(NULL
, &rn
->p
, subgrp
->update_group
, 0))
873 char buf
[INET6_BUFSIZ
];
875 zlog_debug ("u%llu:s%llu send UPDATE %s/%d -- unreachable",
876 subgrp
->update_group
->id
, subgrp
->id
,
877 inet_ntop (rn
->p
.family
, &(rn
->p
.u
.prefix
), buf
,
878 INET6_BUFSIZ
), rn
->p
.prefixlen
);
883 bgp_adj_out_remove_subgroup (rn
, adj
, subgrp
);
884 bgp_unlock_node (rn
);
887 if (!stream_empty (s
))
889 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
)
892 = stream_get_endp (s
) - BGP_HEADER_SIZE
- BGP_UNFEASIBLE_LEN
;
893 stream_putw_at (s
, BGP_HEADER_SIZE
, unfeasible_len
);
898 /* Set the mp_unreach attr's length */
899 bgp_packet_mpunreach_end (s
, mplen_pos
);
901 /* Set total path attribute length. */
902 total_attr_len
= stream_get_endp (s
) - mp_start
;
903 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
905 bgp_packet_set_size (s
);
906 if (bgp_debug_update(NULL
, NULL
, subgrp
->update_group
, 0))
907 zlog_debug ("u%llu:s%llu UPDATE (withdraw) len %d numpfx %d",
908 subgrp
->update_group
->id
, subgrp
->id
,
909 (stream_get_endp(s
) - stream_get_getp(s
)), num_pfx
);
910 pkt
= bpacket_queue_add (SUBGRP_PKTQ (subgrp
), stream_dup (s
), NULL
);
919 subgroup_default_update_packet (struct update_subgroup
*subgrp
,
920 struct attr
*attr
, struct peer
*from
)
923 struct stream
*packet
;
927 bgp_size_t total_attr_len
;
930 struct bpacket_attr_vec_arr vecarr
;
932 if (DISABLE_BGP_ANNOUNCE
)
938 peer
= SUBGRP_PEER (subgrp
);
939 afi
= SUBGRP_AFI (subgrp
);
940 safi
= SUBGRP_SAFI (subgrp
);
941 bpacket_attr_vec_arr_reset (&vecarr
);
944 str2prefix ("0.0.0.0/0", &p
);
947 str2prefix ("::/0", &p
);
948 #endif /* HAVE_IPV6 */
950 /* Logging the attribute. */
951 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
953 char attrstr
[BUFSIZ
];
954 char buf
[INET6_BUFSIZ
];
957 bgp_dump_attr (peer
, attr
, attrstr
, BUFSIZ
);
958 zlog_debug ("u%llu:s%llu send UPDATE %s/%d %s",
959 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
,
960 inet_ntop (p
.family
, &(p
.u
.prefix
), buf
, INET6_BUFSIZ
),
961 p
.prefixlen
, attrstr
);
964 s
= stream_new (BGP_MAX_PACKET_SIZE
);
966 /* Make BGP update packet. */
967 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
969 /* Unfeasible Routes Length. */
972 /* Make place for total attribute length. */
973 pos
= stream_get_endp (s
);
975 total_attr_len
= bgp_packet_attribute (NULL
, peer
, s
, attr
, &vecarr
, &p
,
976 afi
, safi
, from
, NULL
, NULL
);
978 /* Set Total Path Attribute Length. */
979 stream_putw_at (s
, pos
, total_attr_len
);
982 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
)
983 stream_put_prefix (s
, &p
);
986 bgp_packet_set_size (s
);
988 packet
= stream_dup (s
);
990 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, &vecarr
);
991 subgroup_trigger_write(subgrp
);
995 subgroup_default_withdraw_packet (struct update_subgroup
*subgrp
)
999 struct stream
*packet
;
1001 unsigned long attrlen_pos
= 0;
1003 bgp_size_t unfeasible_len
;
1004 bgp_size_t total_attr_len
;
1005 size_t mp_start
= 0;
1006 size_t mplen_pos
= 0;
1010 if (DISABLE_BGP_ANNOUNCE
)
1013 peer
= SUBGRP_PEER (subgrp
);
1014 afi
= SUBGRP_AFI (subgrp
);
1015 safi
= SUBGRP_SAFI (subgrp
);
1018 str2prefix ("0.0.0.0/0", &p
);
1021 str2prefix ("::/0", &p
);
1022 #endif /* HAVE_IPV6 */
1026 if (bgp_debug_update(NULL
, &p
, subgrp
->update_group
, 0))
1028 char buf
[INET6_BUFSIZ
];
1030 zlog_debug ("u%llu:s%llu send UPDATE %s/%d -- unreachable",
1031 (SUBGRP_UPDGRP (subgrp
))->id
, subgrp
->id
, inet_ntop (p
.family
,
1039 s
= stream_new (BGP_MAX_PACKET_SIZE
);
1041 /* Make BGP update packet. */
1042 bgp_packet_set_marker (s
, BGP_MSG_UPDATE
);
1044 /* Unfeasible Routes Length. */ ;
1045 cp
= stream_get_endp (s
);
1048 /* Withdrawn Routes. */
1049 if (p
.family
== AF_INET
&& safi
== SAFI_UNICAST
)
1051 stream_put_prefix (s
, &p
);
1053 unfeasible_len
= stream_get_endp (s
) - cp
- 2;
1055 /* Set unfeasible len. */
1056 stream_putw_at (s
, cp
, unfeasible_len
);
1058 /* Set total path attribute length. */
1063 attrlen_pos
= stream_get_endp (s
);
1065 mp_start
= stream_get_endp (s
);
1066 mplen_pos
= bgp_packet_mpunreach_start (s
, afi
, safi
);
1067 bgp_packet_mpunreach_prefix (s
, &p
, afi
, safi
, NULL
, NULL
);
1069 /* Set the mp_unreach attr's length */
1070 bgp_packet_mpunreach_end (s
, mplen_pos
);
1072 /* Set total path attribute length. */
1073 total_attr_len
= stream_get_endp (s
) - mp_start
;
1074 stream_putw_at (s
, attrlen_pos
, total_attr_len
);
1077 bgp_packet_set_size (s
);
1079 packet
= stream_dup (s
);
1082 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp
), packet
, NULL
);
1083 subgroup_trigger_write(subgrp
);
1087 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr
*vecarr
,
1088 bpacket_attr_vec_type type
,
1091 if (CHECK_FLAG (attr
->rmap_change_flags
,
1092 BATTR_RMAP_NEXTHOP_CHANGED
))
1093 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1094 BPACKET_ATTRVEC_FLAGS_RMAP_CHANGED
);
1096 if (CHECK_FLAG (attr
->rmap_change_flags
,
1097 BATTR_RMAP_NEXTHOP_PEER_ADDRESS
))
1098 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1099 BPACKET_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS
);
1101 if (CHECK_FLAG (attr
->rmap_change_flags
, BATTR_REFLECTED
))
1102 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1103 BPACKET_ATTRVEC_FLAGS_REFLECTED
);
1105 if (CHECK_FLAG (attr
->rmap_change_flags
,
1106 BATTR_RMAP_NEXTHOP_UNCHANGED
))
1107 SET_FLAG (vecarr
->entries
[BGP_ATTR_VEC_NH
].flags
,
1108 BPACKET_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED
);
1111 /* Reset the Attributes vector array. The vector array is used to override
1112 * certain output parameters in the packet for a particular peer
1115 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr
*vecarr
)
1123 while (i
< BGP_ATTR_VEC_MAX
)
1125 vecarr
->entries
[i
].flags
= 0;
1126 vecarr
->entries
[i
].offset
= 0;
1131 /* Setup a particular node entry in the vecarr */
1133 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr
*vecarr
,
1134 bpacket_attr_vec_type type
, struct stream
*s
,
1139 assert (type
< BGP_ATTR_VEC_MAX
);
1141 SET_FLAG (vecarr
->entries
[type
].flags
, BPACKET_ATTRVEC_FLAGS_UPDATED
);
1142 vecarr
->entries
[type
].offset
= stream_get_endp (s
);
1144 bpacket_vec_arr_inherit_attr_flags(vecarr
, type
, attr
);