]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_updgrp_packet.c
bgpd: labeled unicast config
[mirror_frr.git] / bgpd / bgp_updgrp_packet.c
1 /**
2 * bgp_updgrp_packet.c: BGP update group packet handling routines
3 *
4 * @copyright Copyright (C) 2014 Cumulus Networks, Inc.
5 *
6 * @author Avneesh Sachdev <avneesh@sproute.net>
7 * @author Rajesh Varadarajan <rajesh@sproute.net>
8 * @author Pradosh Mohapatra <pradosh@sproute.net>
9 *
10 * This file is part of GNU Zebra.
11 *
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
15 * later version.
16 *
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.
21 *
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
25 * 02111-1307, USA.
26 */
27
28 #include <zebra.h>
29
30 #include "prefix.h"
31 #include "thread.h"
32 #include "buffer.h"
33 #include "stream.h"
34 #include "command.h"
35 #include "sockunion.h"
36 #include "network.h"
37 #include "memory.h"
38 #include "filter.h"
39 #include "routemap.h"
40 #include "log.h"
41 #include "plist.h"
42 #include "linklist.h"
43 #include "workqueue.h"
44 #include "hash.h"
45 #include "queue.h"
46
47 #include "bgpd/bgpd.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_fsm.h"
50 #include "bgpd/bgp_route.h"
51 #include "bgpd/bgp_packet.h"
52 #include "bgpd/bgp_advertise.h"
53 #include "bgpd/bgp_updgrp.h"
54 #include "bgpd/bgp_nexthop.h"
55 #include "bgpd/bgp_nht.h"
56 #include "bgpd/bgp_mplsvpn.h"
57
58 /********************
59 * PRIVATE FUNCTIONS
60 ********************/
61
62 /********************
63 * PUBLIC FUNCTIONS
64 ********************/
65 struct bpacket *
66 bpacket_alloc ()
67 {
68 struct bpacket *pkt;
69
70 pkt =
71 (struct bpacket *) XCALLOC (MTYPE_BGP_PACKET, sizeof (struct bpacket));
72
73 return pkt;
74 }
75
76 void
77 bpacket_free (struct bpacket *pkt)
78 {
79 if (pkt->buffer)
80 stream_free (pkt->buffer);
81 pkt->buffer = NULL;
82 XFREE (MTYPE_BGP_PACKET, pkt);
83 }
84
85 void
86 bpacket_queue_init (struct bpacket_queue *q)
87 {
88 TAILQ_INIT (&(q->pkts));
89 }
90
91 /*
92 * bpacket_queue_sanity_check
93 */
94 void
95 bpacket_queue_sanity_check (struct bpacket_queue __attribute__ ((__unused__)) *q)
96 {
97 #if 0
98 struct bpacket *pkt;
99
100 pkt = bpacket_queue_last (q);
101 assert (pkt);
102 assert (!pkt->buffer);
103
104 /*
105 * Make sure the count of packets is correct.
106 */
107 int num_pkts = 0;
108
109 pkt = bpacket_queue_first (q);
110 while (pkt)
111 {
112 num_pkts++;
113
114 if (num_pkts > q->curr_count)
115 assert (0);
116
117 pkt = TAILQ_NEXT (pkt, pkt_train);
118 }
119
120 assert (num_pkts == q->curr_count);
121 #endif
122 }
123
124 /*
125 * bpacket_queue_add_packet
126 *
127 * Internal function of bpacket_queue - and adds a
128 * packet entry to the end of the list.
129 *
130 * Users of bpacket_queue should use bpacket_queue_add instead.
131 */
132 static void
133 bpacket_queue_add_packet (struct bpacket_queue *q, struct bpacket *pkt)
134 {
135 struct bpacket *last_pkt;
136
137 if (TAILQ_EMPTY (&(q->pkts)))
138 TAILQ_INSERT_TAIL (&(q->pkts), pkt, pkt_train);
139 else
140 {
141 last_pkt = bpacket_queue_last (q);
142 TAILQ_INSERT_AFTER (&(q->pkts), last_pkt, pkt, pkt_train);
143 }
144 q->curr_count++;
145 if (q->hwm_count < q->curr_count)
146 q->hwm_count = q->curr_count;
147 }
148
149 /*
150 * Adds a packet to the bpacket_queue.
151 *
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.
155 */
156 struct bpacket *
157 bpacket_queue_add (struct bpacket_queue *q, struct stream *s,
158 struct bpacket_attr_vec_arr *vecarrp)
159 {
160 struct bpacket *pkt;
161 struct bpacket *last_pkt;
162
163
164 pkt = bpacket_alloc ();
165 if (TAILQ_EMPTY (&(q->pkts)))
166 {
167 pkt->ver = 1;
168 pkt->buffer = s;
169 if (vecarrp)
170 memcpy (&pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr));
171 else
172 bpacket_attr_vec_arr_reset (&pkt->arr);
173 bpacket_queue_add_packet (q, pkt);
174 bpacket_queue_sanity_check (q);
175 return pkt;
176 }
177
178 /*
179 * Fill in the new information into the current sentinel and create a
180 * new sentinel.
181 */
182 bpacket_queue_sanity_check (q);
183 last_pkt = bpacket_queue_last (q);
184 assert (last_pkt->buffer == NULL);
185 last_pkt->buffer = s;
186 if (vecarrp)
187 memcpy (&last_pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr));
188 else
189 bpacket_attr_vec_arr_reset (&last_pkt->arr);
190
191 pkt->ver = last_pkt->ver;
192 pkt->ver++;
193 bpacket_queue_add_packet (q, pkt);
194
195 bpacket_queue_sanity_check (q);
196 return last_pkt;
197 }
198
199 struct bpacket *
200 bpacket_queue_first (struct bpacket_queue *q)
201 {
202 return (TAILQ_FIRST (&(q->pkts)));
203 }
204
205 struct bpacket *
206 bpacket_queue_last (struct bpacket_queue *q)
207 {
208 return TAILQ_LAST (&(q->pkts), pkt_queue);
209 }
210
211 struct bpacket *
212 bpacket_queue_remove (struct bpacket_queue *q)
213 {
214 struct bpacket *first;
215
216 first = bpacket_queue_first (q);
217 if (first)
218 {
219 TAILQ_REMOVE (&(q->pkts), first, pkt_train);
220 q->curr_count--;
221 }
222 return first;
223 }
224
225 unsigned int
226 bpacket_queue_length (struct bpacket_queue *q)
227 {
228 return q->curr_count - 1;
229 }
230
231 unsigned int
232 bpacket_queue_hwm_length (struct bpacket_queue *q)
233 {
234 return q->hwm_count - 1;
235 }
236
237 int
238 bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q)
239 {
240 if (q->curr_count >= bgp->default_subgroup_pkt_queue_max)
241 return 1;
242 return 0;
243 }
244
245 void
246 bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf)
247 {
248 if (!pkt || !paf)
249 return;
250
251 LIST_INSERT_HEAD (&(pkt->peers), paf, pkt_train);
252 paf->next_pkt_to_send = pkt;
253 }
254
255 /*
256 * bpacket_queue_cleanup
257 */
258 void
259 bpacket_queue_cleanup (struct bpacket_queue *q)
260 {
261 struct bpacket *pkt;
262
263 while ((pkt = bpacket_queue_remove (q)))
264 {
265 bpacket_free (pkt);
266 }
267 }
268
269 /*
270 * bpacket_queue_compact
271 *
272 * Delete packets that do not need to be transmitted to any peer from
273 * the queue.
274 *
275 * @return the number of packets deleted.
276 */
277 static int
278 bpacket_queue_compact (struct bpacket_queue *q)
279 {
280 int num_deleted;
281 struct bpacket *pkt, *removed_pkt;
282
283 num_deleted = 0;
284
285 while (1)
286 {
287 pkt = bpacket_queue_first (q);
288 if (!pkt)
289 break;
290
291 /*
292 * Don't delete the sentinel.
293 */
294 if (!pkt->buffer)
295 break;
296
297 if (!LIST_EMPTY (&(pkt->peers)))
298 break;
299
300 removed_pkt = bpacket_queue_remove (q);
301 assert (pkt == removed_pkt);
302 bpacket_free (removed_pkt);
303
304 num_deleted++;
305 }
306
307 bpacket_queue_sanity_check (q);
308 return num_deleted;
309 }
310
311 void
312 bpacket_queue_advance_peer (struct peer_af *paf)
313 {
314 struct bpacket *pkt;
315 struct bpacket *old_pkt;
316
317 old_pkt = paf->next_pkt_to_send;
318 if (old_pkt->buffer == NULL)
319 /* Already at end of list */
320 return;
321
322 LIST_REMOVE (paf, pkt_train);
323 pkt = TAILQ_NEXT (old_pkt, pkt_train);
324 bpacket_add_peer (pkt, paf);
325
326 if (!bpacket_queue_compact (PAF_PKTQ (paf)))
327 return;
328
329 /*
330 * Deleted one or more packets. Check if we can now merge this
331 * peer's subgroup into another subgroup.
332 */
333 update_subgroup_check_merge (paf->subgroup, "advanced peer in queue");
334 }
335
336 /*
337 * bpacket_queue_remove_peer
338 *
339 * Remove the peer from the packet queue of the subgroup it belongs
340 * to.
341 */
342 void
343 bpacket_queue_remove_peer (struct peer_af *paf)
344 {
345 struct bpacket_queue *q;
346
347 q = PAF_PKTQ (paf);
348 assert (q);
349 if (!q)
350 return;
351
352 LIST_REMOVE (paf, pkt_train);
353 paf->next_pkt_to_send = NULL;
354
355 bpacket_queue_compact (q);
356 }
357
358 unsigned int
359 bpacket_queue_virtual_length (struct peer_af *paf)
360 {
361 struct bpacket *pkt;
362 struct bpacket *last;
363 struct bpacket_queue *q;
364
365 pkt = paf->next_pkt_to_send;
366 if (!pkt || (pkt->buffer == NULL))
367 /* Already at end of list */
368 return 0;
369
370 q = PAF_PKTQ (paf);
371 if (TAILQ_EMPTY (&(q->pkts)))
372 return 0;
373
374 last = TAILQ_LAST (&(q->pkts), pkt_queue);
375 if (last->ver >= pkt->ver)
376 return last->ver - pkt->ver;
377
378 /* sequence # rolled over */
379 return (UINT_MAX - pkt->ver + 1) + last->ver;
380 }
381
382 /*
383 * Dump the bpacket queue
384 */
385 void
386 bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty)
387 {
388 struct bpacket *pkt;
389 struct peer_af *paf;
390
391 pkt = bpacket_queue_first (q);
392 while (pkt)
393 {
394 vty_out (vty, " Packet %p ver %u buffer %p%s", pkt, pkt->ver,
395 pkt->buffer, VTY_NEWLINE);
396
397 LIST_FOREACH (paf, &(pkt->peers), pkt_train)
398 {
399 vty_out (vty, " - %s%s", paf->peer->host, VTY_NEWLINE);
400 }
401 pkt = bpacket_next (pkt);
402 }
403 return;
404 }
405
406 struct stream *
407 bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
408 {
409 struct stream *s = NULL;
410 bpacket_attr_vec *vec;
411 struct peer *peer;
412 char buf[BUFSIZ];
413 char buf2[BUFSIZ];
414
415 s = stream_dup (pkt->buffer);
416 peer = PAF_PEER(paf);
417
418 vec = &pkt->arr.entries[BGP_ATTR_VEC_NH];
419 if (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED))
420 {
421 u_int8_t nhlen;
422 afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */
423 int route_map_sets_nh;
424 nhlen = stream_getc_from (s, vec->offset);
425 if (paf->afi == AFI_IP || paf->afi == AFI_IP6)
426 {
427 nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
428 if (peer_cap_enhe(peer))
429 nhafi = AFI_IP6;
430 if (paf->safi == SAFI_MPLS_VPN && /* if VPN && not global */
431 nhlen != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
432 nhafi = AFI_MAX; /* no change allowed */
433 }
434
435 if (nhafi == AFI_IP)
436 {
437 struct in_addr v4nh, *mod_v4nh;
438 int nh_modified = 0;
439
440 route_map_sets_nh =
441 (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED) ||
442 CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
443
444 stream_get_from (&v4nh, s, vec->offset + 1, 4);
445 mod_v4nh = &v4nh;
446
447 /*
448 * If route-map has set the nexthop, that is always used; if it is
449 * specified as peer-address, the peering address is picked up.
450 * Otherwise, if NH is unavailable from attribute, the peering addr
451 * is picked up; the "NH unavailable" case also covers next-hop-self
452 * and some other scenarios -- see subgroup_announce_check(). In
453 * all other cases, use the nexthop carried in the attribute unless
454 * it is EBGP non-multiaccess and there is no next-hop-unchanged setting.
455 * Note: It is assumed route-map cannot set the nexthop to an
456 * invalid value.
457 */
458 if (route_map_sets_nh)
459 {
460 if (CHECK_FLAG(vec->flags,
461 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))
462 {
463 mod_v4nh = &peer->nexthop.v4;
464 nh_modified = 1;
465 }
466 }
467 else if (!v4nh.s_addr)
468 {
469 mod_v4nh = &peer->nexthop.v4;
470 nh_modified = 1;
471 }
472 else if (peer->sort == BGP_PEER_EBGP &&
473 (bgp_multiaccess_check_v4 (v4nh, peer) == 0) &&
474 !CHECK_FLAG(vec->flags,
475 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
476 !peer_af_flag_check (peer, nhafi, paf->safi,
477 PEER_FLAG_NEXTHOP_UNCHANGED))
478 {
479 /* NOTE: not handling case where NH has new AFI */
480 mod_v4nh = &peer->nexthop.v4;
481 nh_modified = 1;
482 }
483
484 if (nh_modified) /* allow for VPN RD */
485 stream_put_in_addr_at (s, vec->offset + 1 + nhlen - 4, mod_v4nh);
486
487 if (bgp_debug_update(peer, NULL, NULL, 0))
488 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s%s",
489 PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id,
490 peer->host, inet_ntoa (*mod_v4nh),
491 (nhlen == 12 ? " and RD" : ""));
492 }
493 else if (nhafi == AFI_IP6)
494 {
495 struct in6_addr v6nhglobal, *mod_v6nhg;
496 struct in6_addr v6nhlocal, *mod_v6nhl;
497 int gnh_modified, lnh_modified;
498
499 gnh_modified = lnh_modified = 0;
500 mod_v6nhg = &v6nhglobal;
501 mod_v6nhl = &v6nhlocal;
502
503 route_map_sets_nh =
504 (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED) ||
505 CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS));
506
507 /*
508 * The logic here is rather similar to that for IPv4, the
509 * additional work being to handle 1 or 2 nexthops. Also, 3rd
510 * party nexthop is not propagated for EBGP right now.
511 */
512 stream_get_from (&v6nhglobal, s, vec->offset + 1, 16);
513 if (route_map_sets_nh)
514 {
515 if (CHECK_FLAG(vec->flags,
516 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS))
517 {
518 mod_v6nhg = &peer->nexthop.v6_global;
519 gnh_modified = 1;
520 }
521 }
522 else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal))
523 {
524 mod_v6nhg = &peer->nexthop.v6_global;
525 gnh_modified = 1;
526 }
527 else if (peer->sort == BGP_PEER_EBGP &&
528 !CHECK_FLAG(vec->flags,
529 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) &&
530 !peer_af_flag_check (peer, nhafi, paf->safi,
531 PEER_FLAG_NEXTHOP_UNCHANGED))
532 {
533 /* NOTE: not handling case where NH has new AFI */
534 mod_v6nhg = &peer->nexthop.v6_global;
535 gnh_modified = 1;
536 }
537
538
539 if (nhlen == 32 || nhlen == 48) /* 48 == VPN */
540 {
541 stream_get_from (&v6nhlocal, s, vec->offset + 1 + (nhlen-IPV6_MAX_BYTELEN), IPV6_MAX_BYTELEN);
542 if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal))
543 {
544 mod_v6nhl = &peer->nexthop.v6_local;
545 lnh_modified = 1;
546 }
547 }
548
549 if (gnh_modified)
550 stream_put_in6_addr_at (s, vec->offset + 1, mod_v6nhg);
551 if (lnh_modified)
552 stream_put_in6_addr_at (s, vec->offset + 1 + (nhlen-IPV6_MAX_BYTELEN), mod_v6nhl);
553
554 if (bgp_debug_update(peer, NULL, NULL, 0))
555 {
556 if (nhlen == 32 || nhlen == 48)
557 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthops %s, %s%s",
558 PAF_SUBGRP(paf)->update_group->id,
559 PAF_SUBGRP(paf)->id,
560 peer->host,
561 inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ),
562 inet_ntop (AF_INET6, mod_v6nhl, buf2, BUFSIZ),
563 (nhlen == 48 ? " and RD" : ""));
564 else
565 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthop %s%s",
566 PAF_SUBGRP(paf)->update_group->id,
567 PAF_SUBGRP(paf)->id,
568 peer->host,
569 inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ),
570 (nhlen == 24 ? " and RD" : ""));
571 }
572 }
573 }
574
575 bgp_packet_add (peer, s);
576 return s;
577 }
578
579 /*
580 * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos'
581 * to each offset.
582 */
583 static void
584 bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr *vecarr, size_t pos)
585 {
586 int i;
587
588 if (!vecarr)
589 return;
590
591 for (i = 0; i < BGP_ATTR_VEC_MAX; i++)
592 vecarr->entries[i].offset += pos;
593 }
594
595 /*
596 * Return if there are packets to build for this subgroup.
597 */
598 int
599 subgroup_packets_to_build (struct update_subgroup *subgrp)
600 {
601 struct bgp_advertise *adv;
602
603 if (!subgrp)
604 return 0;
605
606 adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw);
607 if (adv)
608 return 1;
609
610 adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update);
611 if (adv)
612 return 1;
613
614 return 0;
615 }
616
617 static void
618 bgp_info_addpath_tx_str (int addpath_encode, u_int32_t addpath_tx_id,
619 char *buf)
620 {
621 buf[0] = '\0';
622 if (addpath_encode)
623 sprintf(buf, " with addpath ID %d", addpath_tx_id);
624 else
625 buf[0] = '\0';
626 }
627
628 /* Make BGP update packet. */
629 struct bpacket *
630 subgroup_update_packet (struct update_subgroup *subgrp)
631 {
632 struct bpacket_attr_vec_arr vecarr;
633 struct bpacket *pkt;
634 struct peer *peer;
635 struct stream *s;
636 struct stream *snlri;
637 struct stream *packet;
638 struct bgp_adj_out *adj;
639 struct bgp_advertise *adv;
640 struct bgp_node *rn = NULL;
641 struct bgp_info *binfo = NULL;
642 bgp_size_t total_attr_len = 0;
643 unsigned long attrlen_pos = 0;
644 size_t mpattrlen_pos = 0;
645 size_t mpattr_pos = 0;
646 afi_t afi;
647 safi_t safi;
648 int space_remaining = 0;
649 int space_needed = 0;
650 char send_attr_str[BUFSIZ];
651 int send_attr_printed = 0;
652 int num_pfx = 0;
653 int addpath_encode = 0;
654 u_int32_t addpath_tx_id = 0;
655 struct prefix_rd *prd = NULL;
656
657 if (!subgrp)
658 return NULL;
659
660 if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
661 return NULL;
662
663
664 peer = SUBGRP_PEER (subgrp);
665 afi = SUBGRP_AFI (subgrp);
666 safi = SUBGRP_SAFI (subgrp);
667 s = subgrp->work;
668 stream_reset (s);
669 snlri = subgrp->scratch;
670 stream_reset (snlri);
671
672 bpacket_attr_vec_arr_reset (&vecarr);
673
674 addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
675
676 adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update);
677 while (adv)
678 {
679 assert (adv->rn);
680 rn = adv->rn;
681 adj = adv->adj;
682 addpath_tx_id = adj->addpath_tx_id;
683 binfo = adv->binfo;
684
685 space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
686 BGP_MAX_PACKET_SIZE_OVERFLOW;
687 space_needed = BGP_NLRI_LENGTH +
688 bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
689
690 /* When remaining space can't include NLRI and it's length. */
691 if (space_remaining < space_needed)
692 break;
693
694 /* If packet is empty, set attribute. */
695 if (stream_empty (s))
696 {
697 struct peer *from = NULL;
698
699 if (binfo)
700 from = binfo->peer;
701
702 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
703 * one byte message type.
704 */
705 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
706
707 /* 2: withdrawn routes length */
708 stream_putw (s, 0);
709
710 /* 3: total attributes length - attrlen_pos stores the position */
711 attrlen_pos = stream_get_endp (s);
712 stream_putw (s, 0);
713
714 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
715 * attribute, according to draft-ietf-idr-error-handling. Save the
716 * position.
717 */
718 mpattr_pos = stream_get_endp (s);
719
720 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
721 total_attr_len = bgp_packet_attribute (NULL, peer, s,
722 adv->baa->attr, &vecarr,
723 NULL, afi, safi,
724 from, NULL, NULL, 0, 0);
725
726 space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
727 BGP_MAX_PACKET_SIZE_OVERFLOW;
728 space_needed = BGP_NLRI_LENGTH +
729 bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
730
731 /* If the attributes alone do not leave any room for NLRI then
732 * return */
733 if (space_remaining < space_needed)
734 {
735 zlog_err ("u%" PRIu64 ":s%" PRIu64 " attributes too long, cannot send UPDATE",
736 subgrp->update_group->id, subgrp->id);
737
738 /* Flush the FIFO update queue */
739 while (adv)
740 adv = bgp_advertise_clean_subgroup (subgrp, adj);
741 return NULL;
742 }
743
744 if (BGP_DEBUG (update, UPDATE_OUT) ||
745 BGP_DEBUG (update, UPDATE_PREFIX))
746 {
747 memset (send_attr_str, 0, BUFSIZ);
748 send_attr_printed = 0;
749 bgp_dump_attr (peer, adv->baa->attr, send_attr_str, BUFSIZ);
750 }
751 }
752
753 if ((afi == AFI_IP && safi == SAFI_UNICAST) &&
754 !peer_cap_enhe(peer))
755 stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
756 else
757 {
758 /* Encode the prefix in MP_REACH_NLRI attribute */
759 u_char *tag = NULL;
760
761 if (rn->prn)
762 prd = (struct prefix_rd *) &rn->prn->p;
763 if (binfo && binfo->extra)
764 tag = binfo->extra->tag;
765
766 if (stream_empty (snlri))
767 mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi,
768 (peer_cap_enhe(peer) ? AFI_IP6 :
769 AFI_MAX), /* get from NH */
770 &vecarr, adv->baa->attr);
771
772 bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
773 tag, addpath_encode, addpath_tx_id, adv->baa->attr);
774 }
775
776 num_pfx++;
777
778 if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
779 {
780 char pfx_buf[BGP_PRD_PATH_STRLEN];
781
782 if (!send_attr_printed)
783 {
784 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE w/ attr: %s",
785 subgrp->update_group->id, subgrp->id, send_attr_str);
786 if (!stream_empty (snlri))
787 {
788 afi_t pkt_afi;
789 safi_t pkt_safi;
790
791 pkt_afi = afi_int2iana (afi);
792 pkt_safi = safi_int2iana (safi);
793 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_REACH for afi/safi %d/%d",
794 subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi);
795 }
796
797 send_attr_printed = 1;
798 }
799
800 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s",
801 subgrp->update_group->id, subgrp->id,
802 bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode,
803 addpath_tx_id,
804 pfx_buf, sizeof (pfx_buf)));
805 }
806
807 /* Synchnorize attribute. */
808 if (adj->attr)
809 bgp_attr_unintern (&adj->attr);
810 else
811 subgrp->scount++;
812
813 adj->attr = bgp_attr_intern (adv->baa->attr);
814
815 adv = bgp_advertise_clean_subgroup (subgrp, adj);
816 }
817
818 if (!stream_empty (s))
819 {
820 if (!stream_empty (snlri))
821 {
822 bgp_packet_mpattr_end (snlri, mpattrlen_pos);
823 total_attr_len += stream_get_endp (snlri);
824 }
825
826 /* set the total attribute length correctly */
827 stream_putw_at (s, attrlen_pos, total_attr_len);
828
829 if (!stream_empty (snlri))
830 {
831 packet = stream_dupcat (s, snlri, mpattr_pos);
832 bpacket_attr_vec_arr_update (&vecarr, mpattr_pos);
833 }
834 else
835 packet = stream_dup (s);
836 bgp_packet_set_size (packet);
837 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
838 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE len %zd numpfx %d",
839 subgrp->update_group->id, subgrp->id,
840 (stream_get_endp(packet) - stream_get_getp(packet)), num_pfx);
841 pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), packet, &vecarr);
842 stream_reset (s);
843 stream_reset (snlri);
844 return pkt;
845 }
846 return NULL;
847 }
848
849 /* Make BGP withdraw packet. */
850 /* For ipv4 unicast:
851 16-octet marker | 2-octet length | 1-octet type |
852 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
853 */
854 /* For other afi/safis:
855 16-octet marker | 2-octet length | 1-octet type |
856 2-octet withdrawn route length (=0) | 2-octet attrlen |
857 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
858 */
859 struct bpacket *
860 subgroup_withdraw_packet (struct update_subgroup *subgrp)
861 {
862 struct bpacket *pkt;
863 struct stream *s;
864 struct bgp_adj_out *adj;
865 struct bgp_advertise *adv;
866 struct peer *peer;
867 struct bgp_node *rn;
868 bgp_size_t unfeasible_len;
869 bgp_size_t total_attr_len;
870 size_t mp_start = 0;
871 size_t attrlen_pos = 0;
872 size_t mplen_pos = 0;
873 u_char first_time = 1;
874 afi_t afi;
875 safi_t safi;
876 int space_remaining = 0;
877 int space_needed = 0;
878 int num_pfx = 0;
879 int addpath_encode = 0;
880 u_int32_t addpath_tx_id = 0;
881 struct prefix_rd *prd = NULL;
882
883
884 if (!subgrp)
885 return NULL;
886
887 if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
888 return NULL;
889
890 peer = SUBGRP_PEER (subgrp);
891 afi = SUBGRP_AFI (subgrp);
892 safi = SUBGRP_SAFI (subgrp);
893 s = subgrp->work;
894 stream_reset (s);
895 addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
896
897 while ((adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw)) != NULL)
898 {
899 assert (adv->rn);
900 adj = adv->adj;
901 rn = adv->rn;
902 addpath_tx_id = adj->addpath_tx_id;
903
904 space_remaining = STREAM_REMAIN (s) -
905 BGP_MAX_PACKET_SIZE_OVERFLOW;
906 space_needed = BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN +
907 bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
908
909 if (space_remaining < space_needed)
910 break;
911
912 if (stream_empty (s))
913 {
914 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
915 stream_putw (s, 0); /* unfeasible routes length */
916 }
917 else
918 first_time = 0;
919
920 if (afi == AFI_IP && safi == SAFI_UNICAST &&
921 !peer_cap_enhe(peer))
922 stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
923 else
924 {
925 if (rn->prn)
926 prd = (struct prefix_rd *) &rn->prn->p;
927
928 /* If first time, format the MP_UNREACH header */
929 if (first_time)
930 {
931 afi_t pkt_afi;
932 safi_t pkt_safi;
933
934 pkt_afi = afi_int2iana (afi);
935 pkt_safi = safi_int2iana (safi);
936
937 attrlen_pos = stream_get_endp (s);
938 /* total attr length = 0 for now. reevaluate later */
939 stream_putw (s, 0);
940 mp_start = stream_get_endp (s);
941 mplen_pos = bgp_packet_mpunreach_start (s, afi, safi);
942 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
943 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_UNREACH for afi/safi %d/%d",
944 subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi);
945 }
946
947 bgp_packet_mpunreach_prefix (s, &rn->p, afi, safi, prd, NULL,
948 addpath_encode, addpath_tx_id, NULL);
949 }
950
951 num_pfx++;
952
953 if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0))
954 {
955 char pfx_buf[BGP_PRD_PATH_STRLEN];
956
957 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable",
958 subgrp->update_group->id, subgrp->id,
959 bgp_debug_rdpfxpath2str (prd, &rn->p,
960 addpath_encode, addpath_tx_id,
961 pfx_buf, sizeof (pfx_buf)));
962 }
963
964 subgrp->scount--;
965
966 bgp_adj_out_remove_subgroup (rn, adj, subgrp);
967 bgp_unlock_node (rn);
968 }
969
970 if (!stream_empty (s))
971 {
972 if (afi == AFI_IP && safi == SAFI_UNICAST &&
973 !peer_cap_enhe(peer))
974 {
975 unfeasible_len
976 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
977 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
978 stream_putw (s, 0);
979 }
980 else
981 {
982 /* Set the mp_unreach attr's length */
983 bgp_packet_mpunreach_end (s, mplen_pos);
984
985 /* Set total path attribute length. */
986 total_attr_len = stream_get_endp (s) - mp_start;
987 stream_putw_at (s, attrlen_pos, total_attr_len);
988 }
989 bgp_packet_set_size (s);
990 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
991 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE (withdraw) len %zd numpfx %d",
992 subgrp->update_group->id, subgrp->id,
993 (stream_get_endp(s) - stream_get_getp(s)), num_pfx);
994 pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), stream_dup (s), NULL);
995 stream_reset (s);
996 return pkt;
997 }
998
999 return NULL;
1000 }
1001
1002 void
1003 subgroup_default_update_packet (struct update_subgroup *subgrp,
1004 struct attr *attr, struct peer *from)
1005 {
1006 struct stream *s;
1007 struct peer *peer;
1008 struct prefix p;
1009 unsigned long pos;
1010 bgp_size_t total_attr_len;
1011 afi_t afi;
1012 safi_t safi;
1013 struct bpacket_attr_vec_arr vecarr;
1014 int addpath_encode = 0;
1015
1016 if (DISABLE_BGP_ANNOUNCE)
1017 return;
1018
1019 if (!subgrp)
1020 return;
1021
1022 peer = SUBGRP_PEER (subgrp);
1023 afi = SUBGRP_AFI (subgrp);
1024 safi = SUBGRP_SAFI (subgrp);
1025 bpacket_attr_vec_arr_reset (&vecarr);
1026 addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
1027
1028 if (afi == AFI_IP)
1029 str2prefix ("0.0.0.0/0", &p);
1030 else
1031 str2prefix ("::/0", &p);
1032
1033 /* Logging the attribute. */
1034 if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
1035 {
1036 char attrstr[BUFSIZ];
1037 char buf[PREFIX_STRLEN];
1038 char tx_id_buf[30];
1039 attrstr[0] = '\0';
1040
1041 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
1042 bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf);
1043 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s",
1044 (SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
1045 prefix2str (&p, buf, sizeof (buf)),
1046 tx_id_buf, attrstr);
1047 }
1048
1049 s = stream_new (BGP_MAX_PACKET_SIZE);
1050
1051 /* Make BGP update packet. */
1052 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
1053
1054 /* Unfeasible Routes Length. */
1055 stream_putw (s, 0);
1056
1057 /* Make place for total attribute length. */
1058 pos = stream_get_endp (s);
1059 stream_putw (s, 0);
1060 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &vecarr, &p,
1061 afi, safi, from, NULL, NULL,
1062 addpath_encode,
1063 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
1064
1065 /* Set Total Path Attribute Length. */
1066 stream_putw_at (s, pos, total_attr_len);
1067
1068 /* NLRI set. */
1069 if (p.family == AF_INET && safi == SAFI_UNICAST &&
1070 !peer_cap_enhe(peer))
1071 stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
1072
1073 /* Set size. */
1074 bgp_packet_set_size (s);
1075
1076 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, &vecarr);
1077 subgroup_trigger_write(subgrp);
1078 }
1079
1080 void
1081 subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
1082 {
1083 struct peer *peer;
1084 struct stream *s;
1085 struct prefix p;
1086 unsigned long attrlen_pos = 0;
1087 unsigned long cp;
1088 bgp_size_t unfeasible_len;
1089 bgp_size_t total_attr_len = 0;
1090 size_t mp_start = 0;
1091 size_t mplen_pos = 0;
1092 afi_t afi;
1093 safi_t safi;
1094 int addpath_encode = 0;
1095
1096 if (DISABLE_BGP_ANNOUNCE)
1097 return;
1098
1099 peer = SUBGRP_PEER (subgrp);
1100 afi = SUBGRP_AFI (subgrp);
1101 safi = SUBGRP_SAFI (subgrp);
1102 addpath_encode = bgp_addpath_encode_tx (peer, afi, safi);
1103
1104 if (afi == AFI_IP)
1105 str2prefix ("0.0.0.0/0", &p);
1106 else
1107 str2prefix ("::/0", &p);
1108
1109 if (bgp_debug_update(NULL, &p, subgrp->update_group, 0))
1110 {
1111 char buf[PREFIX_STRLEN];
1112 char tx_id_buf[INET6_BUFSIZ];
1113
1114 bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf);
1115 zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable",
1116 (SUBGRP_UPDGRP (subgrp))->id, subgrp->id,
1117 prefix2str (&p, buf, sizeof (buf)), tx_id_buf);
1118 }
1119
1120 s = stream_new (BGP_MAX_PACKET_SIZE);
1121
1122 /* Make BGP update packet. */
1123 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
1124
1125 /* Unfeasible Routes Length. */ ;
1126 cp = stream_get_endp (s);
1127 stream_putw (s, 0);
1128
1129 /* Withdrawn Routes. */
1130 if (p.family == AF_INET && safi == SAFI_UNICAST &&
1131 !peer_cap_enhe(peer))
1132 {
1133 stream_put_prefix_addpath (s, &p, addpath_encode,
1134 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
1135
1136 unfeasible_len = stream_get_endp (s) - cp - 2;
1137
1138 /* Set unfeasible len. */
1139 stream_putw_at (s, cp, unfeasible_len);
1140
1141 /* Set total path attribute length. */
1142 stream_putw (s, 0);
1143 }
1144 else
1145 {
1146 attrlen_pos = stream_get_endp (s);
1147 stream_putw (s, 0);
1148 mp_start = stream_get_endp (s);
1149 mplen_pos = bgp_packet_mpunreach_start (s, afi, safi);
1150 bgp_packet_mpunreach_prefix (s, &p, afi, safi, NULL, NULL,
1151 addpath_encode,
1152 BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL);
1153
1154 /* Set the mp_unreach attr's length */
1155 bgp_packet_mpunreach_end (s, mplen_pos);
1156
1157 /* Set total path attribute length. */
1158 total_attr_len = stream_get_endp (s) - mp_start;
1159 stream_putw_at (s, attrlen_pos, total_attr_len);
1160 }
1161
1162 bgp_packet_set_size (s);
1163
1164 (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, NULL);
1165 subgroup_trigger_write(subgrp);
1166 }
1167
1168 static void
1169 bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr *vecarr,
1170 bpacket_attr_vec_type type,
1171 struct attr *attr)
1172 {
1173 if (CHECK_FLAG (attr->rmap_change_flags,
1174 BATTR_RMAP_NEXTHOP_PEER_ADDRESS))
1175 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1176 BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS);
1177
1178 if (CHECK_FLAG (attr->rmap_change_flags, BATTR_REFLECTED))
1179 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1180 BPKT_ATTRVEC_FLAGS_REFLECTED);
1181
1182 if (CHECK_FLAG (attr->rmap_change_flags,
1183 BATTR_RMAP_NEXTHOP_UNCHANGED))
1184 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1185 BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED);
1186
1187 if (CHECK_FLAG (attr->rmap_change_flags,
1188 BATTR_RMAP_IPV4_NHOP_CHANGED))
1189 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1190 BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED);
1191
1192 if (CHECK_FLAG (attr->rmap_change_flags,
1193 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED))
1194 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1195 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED);
1196
1197 if (CHECK_FLAG (attr->rmap_change_flags,
1198 BATTR_RMAP_IPV6_LL_NHOP_CHANGED))
1199 SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags,
1200 BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED);
1201 }
1202
1203 /* Reset the Attributes vector array. The vector array is used to override
1204 * certain output parameters in the packet for a particular peer
1205 */
1206 void
1207 bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr)
1208 {
1209 int i;
1210
1211 if (!vecarr)
1212 return;
1213
1214 i = 0;
1215 while (i < BGP_ATTR_VEC_MAX)
1216 {
1217 vecarr->entries[i].flags = 0;
1218 vecarr->entries[i].offset = 0;
1219 i++;
1220 }
1221 }
1222
1223 /* Setup a particular node entry in the vecarr */
1224 void
1225 bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr,
1226 bpacket_attr_vec_type type, struct stream *s,
1227 struct attr *attr)
1228 {
1229 if (!vecarr)
1230 return;
1231 assert (type < BGP_ATTR_VEC_MAX);
1232
1233 SET_FLAG (vecarr->entries[type].flags, BPKT_ATTRVEC_FLAGS_UPDATED);
1234 vecarr->entries[type].offset = stream_get_endp (s);
1235 if (attr)
1236 bpacket_vec_arr_inherit_attr_flags(vecarr, type, attr);
1237 }